From 6d6ce8fba7aff23d15463213abb48c054c1df15d Mon Sep 17 00:00:00 2001 From: Michael Avila Date: Wed, 17 Apr 2019 10:08:08 -0700 Subject: [PATCH 001/671] Introduce first strategic provider: do nothing License: MIT Signed-off-by: Michael Avila --- core/builder.go | 5 +- core/commands/bitswap.go | 2 +- core/core.go | 4 +- core/coreapi/coreapi.go | 2 +- core/node/core.go | 4 +- core/node/groups.go | 58 +---- core/node/provider.go | 115 +++++++-- go.mod | 3 +- go.sum | 238 +----------------- provider/offline.go | 20 +- provider/provider.go | 70 +----- provider/{ => queue}/queue.go | 5 +- provider/{ => queue}/queue_test.go | 5 +- provider/simple/provider.go | 72 ++++++ provider/{ => simple}/provider_test.go | 14 +- provider/simple/reprovide.go | 225 +++++++++++++++++ .../simple}/reprovide_test.go | 11 +- provider/system.go | 47 ++++ reprovide/providers.go | 75 ------ reprovide/reprovide.go | 159 ------------ test/sharness/lib/iptb-lib.sh | 21 ++ test/sharness/t0175-provider.sh | 34 +++ test/sharness/t0175-reprovider.sh | 21 -- test/sharness/t0175-strategic-provider.sh | 34 +++ 24 files changed, 603 insertions(+), 641 deletions(-) rename provider/{ => queue}/queue.go (98%) rename provider/{ => queue}/queue_test.go (96%) create mode 100644 provider/simple/provider.go rename provider/{ => simple}/provider_test.go (86%) create mode 100644 provider/simple/reprovide.go rename {reprovide => provider/simple}/reprovide_test.go (85%) create mode 100644 provider/system.go delete mode 100644 reprovide/providers.go delete mode 100644 reprovide/reprovide.go create mode 100755 test/sharness/t0175-provider.sh create mode 100755 test/sharness/t0175-strategic-provider.sh diff --git a/core/builder.go b/core/builder.go index a048533b11c..24b987596ea 100644 --- a/core/builder.go +++ b/core/builder.go @@ -4,11 +4,10 @@ import ( "context" "sync" - "github.com/ipfs/go-metrics-interface" - "go.uber.org/fx" - "github.com/ipfs/go-ipfs/core/bootstrap" "github.com/ipfs/go-ipfs/core/node" + "github.com/ipfs/go-metrics-interface" + "go.uber.org/fx" ) type BuildCfg = node.BuildCfg // Alias for compatibility until we properly refactor the constructor interface diff --git a/core/commands/bitswap.go b/core/commands/bitswap.go index 1307414dbab..c2edf743cb5 100644 --- a/core/commands/bitswap.go +++ b/core/commands/bitswap.go @@ -233,7 +233,7 @@ Trigger reprovider to announce our data to network. return ErrNotOnline } - err = nd.Reprovider.Trigger(req.Context) + err = nd.Provider.Reprovide(req.Context) if err != nil { return err } diff --git a/core/core.go b/core/core.go index ab672e376bd..14b319330ad 100644 --- a/core/core.go +++ b/core/core.go @@ -25,7 +25,6 @@ import ( "github.com/ipfs/go-ipfs/pin" "github.com/ipfs/go-ipfs/provider" "github.com/ipfs/go-ipfs/repo" - rp "github.com/ipfs/go-ipfs/reprovide" bserv "github.com/ipfs/go-blockservice" bstore "github.com/ipfs/go-ipfs-blockstore" @@ -92,8 +91,7 @@ type IpfsNode struct { Routing routing.IpfsRouting `optional:"true"` // the routing system. recommend ipfs-dht Exchange exchange.Interface // the block exchange + strategy (bitswap) Namesys namesys.NameSystem // the name system, resolves paths to hashes - Provider provider.Provider // the value provider system - Reprovider *rp.Reprovider `optional:"true"` // the value reprovider system + Provider provider.System // the value provider system IpnsRepub *ipnsrp.Republisher `optional:"true"` AutoNAT *autonat.AutoNATService `optional:"true"` diff --git a/core/coreapi/coreapi.go b/core/coreapi/coreapi.go index eaf870ec808..dbbeba1fecd 100644 --- a/core/coreapi/coreapi.go +++ b/core/coreapi/coreapi.go @@ -68,7 +68,7 @@ type CoreAPI struct { namesys namesys.NameSystem routing routing.IpfsRouting - provider provider.Provider + provider provider.System pubSub *pubsub.PubSub diff --git a/core/node/core.go b/core/node/core.go index d7f3ba97ea8..8283447d2bb 100644 --- a/core/node/core.go +++ b/core/node/core.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/ipfs/go-ipfs-config" "github.com/ipfs/go-ipfs/core/node/helpers" "github.com/ipfs/go-ipfs/pin" "github.com/ipfs/go-ipfs/repo" @@ -59,8 +60,9 @@ func Dag(bs blockservice.BlockService) format.DAGService { } // OnlineExchange creates new LibP2P backed block exchange (BitSwap) -func OnlineExchange(mctx helpers.MetricsCtx, lc fx.Lifecycle, host host.Host, rt routing.IpfsRouting, bs blockstore.GCBlockstore) exchange.Interface { +func OnlineExchange(mctx helpers.MetricsCtx, lc fx.Lifecycle, cfg *config.Config, host host.Host, rt routing.IpfsRouting, bs blockstore.GCBlockstore) exchange.Interface { bitswapNetwork := network.NewFromIpfsHost(host, rt) + bitswap.ProvideEnabled = !cfg.Experimental.StrategicProviding exch := bitswap.New(helpers.LifecycleCtx(mctx, lc), bitswapNetwork, bs) lc.Append(fx.Hook{ OnStop: func(ctx context.Context) error { diff --git a/core/node/groups.go b/core/node/groups.go index be2174b9556..c9a4da43e96 100644 --- a/core/node/groups.go +++ b/core/node/groups.go @@ -14,12 +14,10 @@ import ( pubsub "github.com/libp2p/go-libp2p-pubsub" "github.com/ipfs/go-ipfs/core/node/libp2p" - "github.com/ipfs/go-ipfs/p2p" - "github.com/ipfs/go-ipfs/provider" - "github.com/ipfs/go-ipfs/reprovide" offline "github.com/ipfs/go-ipfs-exchange-offline" offroute "github.com/ipfs/go-ipfs-routing/offline" + "github.com/ipfs/go-ipfs/p2p" "github.com/ipfs/go-path/resolver" uio "github.com/ipfs/go-unixfs/io" "go.uber.org/fx" @@ -186,42 +184,6 @@ var IPNS = fx.Options( fx.Provide(RecordValidator), ) -// Providers groups units managing provider routing records -func Providers(cfg *config.Config) fx.Option { - reproviderInterval := kReprovideFrequency - if cfg.Reprovider.Interval != "" { - dur, err := time.ParseDuration(cfg.Reprovider.Interval) - if err != nil { - return fx.Error(err) - } - - reproviderInterval = dur - } - - var keyProvider fx.Option - switch cfg.Reprovider.Strategy { - case "all": - fallthrough - case "": - keyProvider = fx.Provide(reprovide.NewBlockstoreProvider) - case "roots": - keyProvider = fx.Provide(reprovide.NewPinnedProvider(true)) - case "pinned": - keyProvider = fx.Provide(reprovide.NewPinnedProvider(false)) - default: - return fx.Error(fmt.Errorf("unknown reprovider strategy '%s'", cfg.Reprovider.Strategy)) - } - - return fx.Options( - fx.Provide(ProviderQueue), - fx.Provide(ProviderCtor), - fx.Provide(ReproviderCtor(reproviderInterval)), - keyProvider, - - fx.Invoke(Reprovider), - ) -} - // Online groups online-only units func Online(bcfg *BuildCfg, cfg *config.Config) fx.Option { @@ -270,17 +232,19 @@ func Online(bcfg *BuildCfg, cfg *config.Config) fx.Option { fx.Provide(p2p.New), LibP2P(bcfg, cfg), - Providers(cfg), + OnlineProviders(cfg), ) } // Offline groups offline alternatives to Online units -var Offline = fx.Options( - fx.Provide(offline.Exchange), - fx.Provide(Namesys(0)), - fx.Provide(offroute.NewOfflineRouter), - fx.Provide(provider.NewOfflineProvider), -) +func Offline(cfg *config.Config) fx.Option { + return fx.Options( + fx.Provide(offline.Exchange), + fx.Provide(Namesys(0)), + fx.Provide(offroute.NewOfflineRouter), + OfflineProviders(cfg), + ) +} // Core groups basic IPFS services var Core = fx.Options( @@ -295,7 +259,7 @@ func Networked(bcfg *BuildCfg, cfg *config.Config) fx.Option { if bcfg.Online { return Online(bcfg, cfg) } - return Offline + return Offline(cfg) } // IPFS builds a group of fx Options based on the passed BuildCfg diff --git a/core/node/provider.go b/core/node/provider.go index e85a909141d..a5c62baa68b 100644 --- a/core/node/provider.go +++ b/core/node/provider.go @@ -2,50 +2,129 @@ package node import ( "context" + "fmt" "time" - "github.com/libp2p/go-libp2p-routing" "go.uber.org/fx" + "github.com/ipfs/go-ipfs-config" "github.com/ipfs/go-ipfs/core/node/helpers" "github.com/ipfs/go-ipfs/provider" + q "github.com/ipfs/go-ipfs/provider/queue" + "github.com/ipfs/go-ipfs/provider/simple" "github.com/ipfs/go-ipfs/repo" - "github.com/ipfs/go-ipfs/reprovide" + "github.com/libp2p/go-libp2p-routing" ) const kReprovideFrequency = time.Hour * 12 +// SIMPLE + // ProviderQueue creates new datastore backed provider queue -func ProviderQueue(mctx helpers.MetricsCtx, lc fx.Lifecycle, repo repo.Repo) (*provider.Queue, error) { - return provider.NewQueue(helpers.LifecycleCtx(mctx, lc), "provider-v1", repo.Datastore()) +func ProviderQueue(mctx helpers.MetricsCtx, lc fx.Lifecycle, repo repo.Repo) (*q.Queue, error) { + return q.NewQueue(helpers.LifecycleCtx(mctx, lc), "provider-v1", repo.Datastore()) } -// ProviderCtor creates new record provider -func ProviderCtor(mctx helpers.MetricsCtx, lc fx.Lifecycle, queue *provider.Queue, rt routing.IpfsRouting) provider.Provider { - p := provider.NewProvider(helpers.LifecycleCtx(mctx, lc), queue, rt) +// SimpleProviderCtor creates new record provider +func SimpleProviderCtor(mctx helpers.MetricsCtx, lc fx.Lifecycle, queue *q.Queue, rt routing.IpfsRouting) provider.Provider { + return simple.NewProvider(helpers.LifecycleCtx(mctx, lc), queue, rt) +} + +// SimpleReproviderCtor creates new reprovider +func SimpleReproviderCtor(reproviderInterval time.Duration) func(helpers.MetricsCtx, fx.Lifecycle, routing.IpfsRouting, simple.KeyChanFunc) (provider.Reprovider, error) { + return func(mctx helpers.MetricsCtx, lc fx.Lifecycle, rt routing.IpfsRouting, keyProvider simple.KeyChanFunc) (provider.Reprovider, error) { + return simple.NewReprovider(helpers.LifecycleCtx(mctx, lc), reproviderInterval, rt, keyProvider), nil + } +} +// SimpleProviderSysCtor creates new provider system +func SimpleProviderSysCtor(lc fx.Lifecycle, p provider.Provider, r provider.Reprovider) provider.System { + sys := provider.NewSystem(p, r) lc.Append(fx.Hook{ OnStart: func(ctx context.Context) error { - p.Run() + sys.Run() return nil }, OnStop: func(ctx context.Context) error { - return p.Close() + return sys.Close() }, }) + return sys +} + +// SimpleOfflineProviderSysCtor creates a new offline provider system +func SimpleOfflineProviderSysCtor(p provider.Provider, r provider.Reprovider) provider.System { + return provider.NewSystem(p, r) +} + +// STRATEGIC + +// StrategicProviderSysCtor creates new provider system +func StrategicProviderSysCtor() provider.System { + return provider.NewOfflineProvider() +} + +// StrategicOfflineProviderSysCtor creates a new offline provider system +func StrategicOfflineProviderSysCtor() provider.System { + return provider.NewOfflineProvider() +} + +// ONLINE/OFFLINE + +// OnlineProviders groups units managing provider routing records online +func OnlineProviders(cfg *config.Config) fx.Option { + if cfg.Experimental.StrategicProviding { + return fx.Provide(StrategicProviderSysCtor) + } - return p + return fx.Options( + SimpleProviders(cfg), + fx.Provide(SimpleProviderSysCtor), + ) } -// ReproviderCtor creates new reprovider -func ReproviderCtor(reproviderInterval time.Duration) func(helpers.MetricsCtx, fx.Lifecycle, routing.IpfsRouting, reprovide.KeyChanFunc) (*reprovide.Reprovider, error) { - return func(mctx helpers.MetricsCtx, lc fx.Lifecycle, rt routing.IpfsRouting, keyProvider reprovide.KeyChanFunc) (*reprovide.Reprovider, error) { - return reprovide.NewReprovider(helpers.LifecycleCtx(mctx, lc), reproviderInterval, rt, keyProvider), nil +// OfflineProviders groups units managing provider routing records offline +func OfflineProviders(cfg *config.Config) fx.Option { + if cfg.Experimental.StrategicProviding { + return fx.Provide(StrategicOfflineProviderSysCtor) } + + return fx.Options( + SimpleProviders(cfg), + fx.Provide(SimpleOfflineProviderSysCtor), + ) } -// Reprovider runs the reprovider service -func Reprovider(lp lcProcess, reprovider *reprovide.Reprovider) error { - lp.Append(reprovider.Run) - return nil +// SimpleProviders creates the simple provider/reprovider dependencies +func SimpleProviders(cfg *config.Config) fx.Option { + reproviderInterval := kReprovideFrequency + if cfg.Reprovider.Interval != "" { + dur, err := time.ParseDuration(cfg.Reprovider.Interval) + if err != nil { + return fx.Error(err) + } + + reproviderInterval = dur + } + + var keyProvider fx.Option + switch cfg.Reprovider.Strategy { + case "all": + fallthrough + case "": + keyProvider = fx.Provide(simple.NewBlockstoreProvider) + case "roots": + keyProvider = fx.Provide(simple.NewPinnedProvider(true)) + case "pinned": + keyProvider = fx.Provide(simple.NewPinnedProvider(false)) + default: + return fx.Error(fmt.Errorf("unknown reprovider strategy '%s'", cfg.Reprovider.Strategy)) + } + + return fx.Options( + fx.Provide(ProviderQueue), + fx.Provide(SimpleProviderCtor), + keyProvider, + fx.Provide(SimpleReproviderCtor(reproviderInterval)), + ) } diff --git a/go.mod b/go.mod index 9c94e261fb0..8600f1a62c5 100644 --- a/go.mod +++ b/go.mod @@ -35,7 +35,7 @@ require ( github.com/ipfs/go-ipfs-blocksutil v0.0.1 github.com/ipfs/go-ipfs-chunker v0.0.1 github.com/ipfs/go-ipfs-cmds v0.0.8 - github.com/ipfs/go-ipfs-config v0.0.3 + github.com/ipfs/go-ipfs-config v0.0.4 github.com/ipfs/go-ipfs-ds-help v0.0.1 github.com/ipfs/go-ipfs-exchange-interface v0.0.1 github.com/ipfs/go-ipfs-exchange-offline v0.0.1 @@ -122,6 +122,7 @@ require ( go.uber.org/multierr v1.1.0 // indirect go4.org v0.0.0-20190313082347-94abd6928b1d // indirect golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5 + google.golang.org/appengine v1.4.0 // indirect gopkg.in/cheggaaa/pb.v1 v1.0.28 gotest.tools/gotestsum v0.3.4 ) diff --git a/go.sum b/go.sum index 265c2e45750..1bc6861f292 100644 --- a/go.sum +++ b/go.sum @@ -3,78 +3,57 @@ bazil.org/fuse v0.0.0-20180421153158-65cc252bf669/go.mod h1:Xbm+BRKSBEpa4q4hTSxo cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7 h1:PqzgE6kAMi81xWQA2QIVxjWkFHptGgC547vchpUbtFo= github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Kubuxu/go-os-helper v0.0.1 h1:EJiD2VUQyh5A9hWJLmc6iWg6yIcJ7jpBcwC8GMGXfDk= github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y= -github.com/Kubuxu/gocovmerge v0.0.0-20161216165753-7ecaa51963cd h1:HNhzThEtZW714v8Eda8sWWRcu9WSzJC+oCyjRjvZgRA= github.com/Kubuxu/gocovmerge v0.0.0-20161216165753-7ecaa51963cd/go.mod h1:bqoB8kInrTeEtYAwaIXoSRqdwnjQmFhsfusnzyui6yY= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/OpenPeeDeeP/depguard v0.0.0-20180806142446-a69c782687b2 h1:HTOmFEEYrWi4MW5ZKUx6xfeyM10Sx3kQF65xiQJMPYA= github.com/OpenPeeDeeP/depguard v0.0.0-20180806142446-a69c782687b2/go.mod h1:7/4sitnI9YlQgTLLk734QlzXT8DuHVnAyztLplQjk+o= github.com/Quasilyte/go-consistent v0.0.0-20181230194409-8f8379e70f99/go.mod h1:ds1OLa3HF2x4OGKCx0pNTVL1s9Ii/2mT0Bg/8PtW6AM= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= -github.com/Stebalien/go-bitfield v0.0.0-20180330043415-076a62f9ce6e h1:2Z+EBRrOJsA3psnUPcEWMIH2EIga1xHflQcr/EZslx8= github.com/Stebalien/go-bitfield v0.0.0-20180330043415-076a62f9ce6e/go.mod h1:3oM7gXIttpYDAJXpVNnSCiUMYBLIZ6cb1t+Ip982MRo= github.com/Stebalien/go-bitfield v0.0.1 h1:X3kbSSPUaJK60wV2hjOPZwmpljr6VGCqdq4cBLhbQBo= github.com/Stebalien/go-bitfield v0.0.1/go.mod h1:GNjFpasyUVkHMsfEOk8EFLJ9syQ6SI+XWrX9Wf2XH0s= -github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/bifurcation/mint v0.0.0-20181105073638-824af6541065 h1:ArS0Fye/ZH2QmKVSj4JEf+9ARkXNe18jcFkmr4XPRiw= github.com/bifurcation/mint v0.0.0-20181105073638-824af6541065/go.mod h1:zVt7zX3K/aDCk9Tj+VM7YymsX66ERvzCJzw8rFCX2JU= 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/bren2010/proquint v0.0.0-20160323162903-38337c27106d h1:QgeLLoPD3kRVmeu/1al9iIpIANMi9O1zXFm8BnYGCJg= github.com/bren2010/proquint v0.0.0-20160323162903-38337c27106d/go.mod h1:Jbj8eKecMNwf0KFI75skSUZqMB4UCRcndUScVBTWyUI= -github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32 h1:qkOC5Gd33k54tobS36cXdAzJbeHaduLtnLQQwNoIi78= github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= github.com/btcsuite/btcd v0.0.0-20190427004231-96897255fd17 h1:m0N5Vg5nP3zEz8TREZpwX3gt4Biw3/8fbIf4A3hO96g= github.com/btcsuite/btcd v0.0.0-20190427004231-96897255fd17/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= -github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= -github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd h1:qdGvebPBDuYDPGi1WCPjy1tGyMpmDK8IEapSsszn7HE= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= -github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723 h1:ZA/jbKoGcVAnER6pCHPEkGdZOV7U1oLUedErBHCUMs0= github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= -github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= -github.com/btcsuite/winsvc v1.0.0 h1:J9B4L7e3oqhXOcm+2IuNApwzQec85lE+QaikUcCs+dk= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/cenkalti/backoff v2.1.1+incompatible h1:tKJnvO2kl0zmb/jA5UKAt4VoEVw1qxKWjE/Bpp46npY= github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= -github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/coreos/go-semver v0.2.0 h1:3Jm3tLmsgAYcjC+4Up7hJrFBPr+n7rAqYeSw/SZazuY= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.2.1-0.20180108230905-e214231b295a h1:U0BbGfKnviqVBJQB4etvm+mKx53KfkumNLBt6YeF/0Q= github.com/coreos/go-semver v0.2.1-0.20180108230905-e214231b295a/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/cskr/pubsub v1.0.2 h1:vlOzMhl6PFn60gRlTQQsIfVwaPB/B/8MziK8FhEPt/0= github.com/cskr/pubsub v1.0.2/go.mod h1:/8MzYXk/NJAz782G8RPkFzXTZVu63VotefPnR9TIRis= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018 h1:6xT9KW8zLC5IlbaIF5Q7JNieBoACT7iW0YTxQHR0in0= github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018/go.mod h1:rQYf4tfk5sSwFsnDg3qYaBxSjsD9S8+59vW0dKUgme4= -github.com/dgraph-io/badger v1.5.5-0.20190226225317-8115aed38f8f h1:6itBiEUtu+gOzXZWn46bM5/qm8LlV6/byR7Yflx/y6M= github.com/dgraph-io/badger v1.5.5-0.20190226225317-8115aed38f8f/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ= github.com/dgraph-io/badger v2.0.0-rc.2+incompatible h1:7KPp6xv5+wymkVUbkAnZZXvmDrJlf09m/7u1HG5lAYA= github.com/dgraph-io/badger v2.0.0-rc.2+incompatible/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ= @@ -87,113 +66,68 @@ github.com/elgris/jsondiff v0.0.0-20160530203242-765b5c24c302 h1:QV0ZrfBLpFc2KDk github.com/elgris/jsondiff v0.0.0-20160530203242-765b5c24c302/go.mod h1:qBlWZqWeVx9BjvqBsnC/8RUlAYpIFmPvgROcw0n1scE= github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 h1:BBso6MBKW8ncyZLv37o+KNyy0HrrHgfnOaGQC2qvN+A= github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5/go.mod h1:JpoxHjuQauoxiFMl1ie8Xc/7TfLuMZ5eOCONd1sUBHg= -github.com/fatih/color v1.6.0 h1:66qjqZk8kalYAvDRtM1AdAJQI0tj4Wrue3Eq3B3pmFU= github.com/fatih/color v1.6.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fd/go-nat v1.0.0 h1:DPyQ97sxA9ThrWYRPcWUz/z9TnpTIGRYODIQc/dy64M= github.com/fd/go-nat v1.0.0/go.mod h1:BTBu/CKvMmOMUPkKVef1pngt2WFH/lg7E6yQnulfp6E= -github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/go-check/check v0.0.0-20180628173108-788fd7840127 h1:0gkP6mzaMqkmpcJYCFOLkIBwI7xFExG03bbkOkCvUPI= github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= github.com/go-critic/go-critic v0.0.0-20181204210945-c3db6069acc5/go.mod h1:Jc75BZJv2dNy7opKH6bF29VveDQHfGZ6Asn/3phBesg= -github.com/go-critic/go-critic v0.0.0-20181204210945-ee9bf5809ead h1:qwmAYufKDopQnFdeMw+iHJVxAd2CbF+VFKHyJJwnPKk= github.com/go-critic/go-critic v0.0.0-20181204210945-ee9bf5809ead/go.mod h1:3MzXZKJdeXqdU9cj+rvZdNiN7SZ8V9OjybF8loZDmHU= -github.com/go-kit/kit v0.8.0 h1:Wz+5lgoB0kkuqLEc6NVmwRknTKP6dTGbSqvhZtBI/j0= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-lintpack/lintpack v0.5.2 h1:DI5mA3+eKdWeJ40nU4d6Wc26qmdG8RCi/btYq0TuRN0= github.com/go-lintpack/lintpack v0.5.2/go.mod h1:NwZuYi2nUHho8XEIZ6SIxihrnPoqBTDqfpXvXAN0sXM= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80nA= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= -github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-toolsmith/astcast v0.0.0-20181028201508-b7a89ed70af1 h1:h+1eMw+tZAlgTVclcVN0/rdPaBI/RUzG0peblT6df+Q= github.com/go-toolsmith/astcast v0.0.0-20181028201508-b7a89ed70af1/go.mod h1:TEo3Ghaj7PsZawQHxT/oBvo4HK/sl1RcuUHDKTTju+o= -github.com/go-toolsmith/astcopy v0.0.0-20180903214859-79b422d080c4 h1:wVs9OMjICHbAryp9hcIuWqUOi+NqEbUSZy9zMe3W//I= github.com/go-toolsmith/astcopy v0.0.0-20180903214859-79b422d080c4/go.mod h1:c9CPdq2AzM8oPomdlPniEfPAC6g1s7NqZzODt8y6ib8= -github.com/go-toolsmith/astequal v0.0.0-20180903214952-dcb477bfacd6 h1:aTBUNRTatDDU24gbOEKEoLiDwxtc98ga6K/iMTm6fvs= github.com/go-toolsmith/astequal v0.0.0-20180903214952-dcb477bfacd6/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= -github.com/go-toolsmith/astfmt v0.0.0-20180903215011-8f8ee99c3086 h1:EIMuvbE9fbtQtimdLe5yeXjuC5CeKbQt8zH6GwtIrhM= github.com/go-toolsmith/astfmt v0.0.0-20180903215011-8f8ee99c3086/go.mod h1:mP93XdblcopXwlyN4X4uodxXQhldPGZbcEJIimQHrkg= github.com/go-toolsmith/astinfo v0.0.0-20180906194353-9809ff7efb21/go.mod h1:dDStQCHtmZpYOmjRP/8gHHnCCch3Zz3oEgCdZVdtweU= -github.com/go-toolsmith/astp v0.0.0-20180903215135-0af7e3c24f30 h1:zRJPftZJNLPDiOtvYbFRwjSbaJAcVOf80TeEmWGe2kQ= github.com/go-toolsmith/astp v0.0.0-20180903215135-0af7e3c24f30/go.mod h1:SV2ur98SGypH1UjcPpCatrV5hPazG6+IfNHbkDXBRrk= -github.com/go-toolsmith/pkgload v0.0.0-20181119091011-e9e65178eee8 h1:vVouagbdmqTVlCIAxpyYsNNTbkKZ3V66VpKOLU/s6W4= github.com/go-toolsmith/pkgload v0.0.0-20181119091011-e9e65178eee8/go.mod h1:WoMrjiy4zvdS+Bg6z9jZH82QXwkcgCBX6nOfnmdaHks= -github.com/go-toolsmith/strparse v0.0.0-20180903215201-830b6daa1241 h1:ZRDeQioMGTBLeJxcPxXfFifEUgYxzR7fXw7w2WR+1bo= github.com/go-toolsmith/strparse v0.0.0-20180903215201-830b6daa1241/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= -github.com/go-toolsmith/typep v0.0.0-20181030061450-d63dc7650676 h1:6Qrsp0+25KEkaS2bB26UE0giFgRrIc8mYXboDL5OVMA= github.com/go-toolsmith/typep v0.0.0-20181030061450-d63dc7650676/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU= -github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.0 h1:kbxbvI4Un1LUWKxufD+BiE6AEExYYgkQLQmLFqA1LFk= github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 h1:23T5iq8rbUYlhpt5DB4XJkc6BU31uODLD1o1gKvZmD0= github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4= -github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a h1:w8hkcTqaFpzKqonE9uMCefW1WDie15eSP/4MssdenaM= github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk= -github.com/golangci/errcheck v0.0.0-20181003203344-ef45e06d44b6 h1:i2jIkQFb8RG45DuQs+ElyROY848cSJIoIkBM+7XXypA= github.com/golangci/errcheck v0.0.0-20181003203344-ef45e06d44b6/go.mod h1:DbHgvLiFKX1Sh2T1w8Q/h4NAI8MHIpzCdnBUDTXU3I0= -github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613 h1:9kfjN3AdxcbsZBf8NjltjWihK2QfBBBZuv91cMFfDHw= github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613/go.mod h1:SyvUF2NxV+sN8upjjeVYr5W7tyxaT1JVtvhKhOn2ii8= -github.com/golangci/go-tools v0.0.0-20180109140146-af6baa5dc196 h1:9rtVlONXLF1rJZzvLt4tfOXtnAFUEhxCJ64Ibzj6ECo= github.com/golangci/go-tools v0.0.0-20180109140146-af6baa5dc196/go.mod h1:unzUULGw35sjyOYjUt0jMTXqHlZPpPc6e+xfO4cd6mM= -github.com/golangci/goconst v0.0.0-20180610141641-041c5f2b40f3 h1:pe9JHs3cHHDQgOFXJJdYkK6fLz2PWyYtP4hthoCMvs8= github.com/golangci/goconst v0.0.0-20180610141641-041c5f2b40f3/go.mod h1:JXrF4TWy4tXYn62/9x8Wm/K/dm06p8tCKwFRDPZG/1o= -github.com/golangci/gocyclo v0.0.0-20180528134321-2becd97e67ee h1:J2XAy40+7yz70uaOiMbNnluTg7gyQhtGqLQncQh+4J8= github.com/golangci/gocyclo v0.0.0-20180528134321-2becd97e67ee/go.mod h1:ozx7R9SIwqmqf5pRP90DhR2Oay2UIjGuKheCBCNwAYU= -github.com/golangci/gofmt v0.0.0-20181105071733-0b8337e80d98 h1:ir6/L2ZOJfFrJlOTsuf/hlzdPuUwXV/VzkSlgS6f1vs= github.com/golangci/gofmt v0.0.0-20181105071733-0b8337e80d98/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU= -github.com/golangci/golangci-lint v1.16.1-0.20190425135923-692dacb773b7 h1:RfttK8W9qaF98OAdNFW2Mbr3ELn1Dyw1nnip6kYVc8M= github.com/golangci/golangci-lint v1.16.1-0.20190425135923-692dacb773b7/go.mod h1:kSe2pu2LlcsMT5Dr95yNKUT5RNfMkwif9MZqtOW5NEs= -github.com/golangci/gosec v0.0.0-20180901114220-66fb7fc33547 h1:qMomh8bv+kDazm1dSLZ9S3zZ2PJZMHL4ilfBjxFOlmI= github.com/golangci/gosec v0.0.0-20180901114220-66fb7fc33547/go.mod h1:0qUabqiIQgfmlAmulqxyiGkkyF6/tOGSnY2cnPVwrzU= -github.com/golangci/ineffassign v0.0.0-20180808204949-2ee8f2867dde h1:qEGp3ZF1Qw6TkbWKn6GdJ12Ssu/CpJBaBcJ4hrUjrSo= github.com/golangci/ineffassign v0.0.0-20180808204949-2ee8f2867dde/go.mod h1:e5tpTHCfVze+7EpLEozzMB3eafxo2KT5veNg1k6byQU= -github.com/golangci/lint-1 v0.0.0-20180610141402-ee948d087217 h1:r7vyX+SN24x6+5AnpnrRn/bdwBb7U+McZqCHOVtXDuk= github.com/golangci/lint-1 v0.0.0-20180610141402-ee948d087217/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg= -github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca h1:kNY3/svz5T29MYHubXix4aDDuE3RWHkPvopM/EDv/MA= github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o= -github.com/golangci/misspell v0.0.0-20180809174111-950f5d19e770 h1:EL/O5HGrF7Jaq0yNhBLucz9hTuRzj2LdwGBOaENgxIk= github.com/golangci/misspell v0.0.0-20180809174111-950f5d19e770/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA= -github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21 h1:leSNB7iYzLYSSx3J/s5sVf4Drkc68W2wm4Ixh/mr0us= github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21/go.mod h1:tf5+bzsHdTM0bsB7+8mt0GUMvjCgwLpTapNZHU8AajI= -github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0 h1:HVfrLniijszjS1aiNg8JbBMO2+E1WIQ+j/gL4SQqGPg= github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0/go.mod h1:qOQCunEYvmd/TLamH+7LlVccLvUH5kZNhbCgTHoBbp4= -github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 h1:zwtduBRr5SSWhqsYNgcuWO2kFlpdOZbP0+yRjmvPGys= github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ= -github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gxed/go-shellwords v1.0.3 h1:2TP32H4TAklZUdz84oj95BJhVnIrRasyx2j1cqH5K38= github.com/gxed/go-shellwords v1.0.3/go.mod h1:N7paucT91ByIjmVJHhvoarjoQnmsi3Jd3vH7VqgtMxQ= -github.com/gxed/hashland/keccakpg v0.0.1 h1:wrk3uMNaMxbXiHibbPO4S0ymqJMm41WiudyFSs7UnsU= github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU= -github.com/gxed/hashland/murmur3 v0.0.1 h1:SheiaIt0sda5K+8FLz952/1iWS9zrnKsEJaOJu4ZbSc= github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= -github.com/gxed/pubsub v0.0.0-20180201040156-26ebdf44f824 h1:TF4mX7zXpeyz/xintezebSa7ZDxAGBnqDwcoobvaz2o= github.com/gxed/pubsub v0.0.0-20180201040156-26ebdf44f824/go.mod h1:OiEWyHgK+CWrmOlVquHaIK1vhpUJydC9m0Je6mhaiNE= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -202,27 +136,21 @@ github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHh github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce h1:xdsDDbiBDQTKASoGEZ+pEmF1OnWuu8AQ9I8iNbHNeno= github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w= -github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hsanjuan/go-libp2p-gostream v0.0.31 h1:9dIgHQPR0VWxhOyTZrbgLzTx0xvZ5rTpmhG9huGEPjY= github.com/hsanjuan/go-libp2p-gostream v0.0.31/go.mod h1:cWvV5/NQ5XWi0eQZnX/svsAk6NLc4U26pItvj0eDeRk= github.com/hsanjuan/go-libp2p-http v0.0.2 h1:hviJbUD3h1Ez2FYTUdnRjrkAzn/9i2V/cLZpFPgnuP8= github.com/hsanjuan/go-libp2p-http v0.0.2/go.mod h1:MynY94gfOZxrw/0lVF4o7vbV2Zr84IC8sLBXmj8F5IE= -github.com/huin/goupnp v0.0.0-20180415215157-1395d1447324 h1:PV190X5/DzQ/tbFFG5YpT5mH6q+cHlfgqI5JuRnH9oE= github.com/huin/goupnp v0.0.0-20180415215157-1395d1447324/go.mod h1:MZ2ZmwcBpvOoJ22IJsc7va19ZwoheaBk43rKg12SKag= github.com/huin/goupnp v1.0.0 h1:wg75sLpL6DZqwHQN6E1Cfk6mtfzS45z8OV+ic+DtHRo= github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= -github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150 h1:vlNjIqmUZ9CMAWsbURYl3a6wZbw7q5RHVvlXTNS/Bs8= github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= -github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/ipfs/bbloom v0.0.1 h1:s7KkiBPfxCeDVo47KySjK0ACPc5GJRUxFpdyWEuDjhw= github.com/ipfs/bbloom v0.0.1/go.mod h1:oqo8CVWsJFMOZqTglBG4wydCE4IQA/G2/SEofB0rjUI= github.com/ipfs/dir-index-html v1.0.3 h1:cKdOjJBKJgewgcv97zOlqsNOle52N91d3nAkbQadnuY= github.com/ipfs/dir-index-html v1.0.3/go.mod h1:TG9zbaH/+4MnkGel0xF4SLNhk+YZvBNo6jjBkO/LaWc= -github.com/ipfs/go-bitswap v0.0.3 h1:uFcSI9dkjUn67S7IM60vr2wA27aAvn8o9xYjaQCug3o= github.com/ipfs/go-bitswap v0.0.3/go.mod h1:jadAZYsP/tcRMl47ZhFxhaNuDQoXawT8iHMg+iFoQbg= github.com/ipfs/go-bitswap v0.0.7 h1:BJwx7Kh5W845l10bOckkAJiNrT6XXWNaE8neK7H57q4= github.com/ipfs/go-bitswap v0.0.7/go.mod h1:++LZRc+e1/ZxYsZq7QLKIPQvybh+70TMgeGuX+WB0pY= @@ -231,27 +159,21 @@ github.com/ipfs/go-block-format v0.0.2 h1:qPDvcP19izTjU8rgo6p7gTXZlkMkF5bz5G3fqI github.com/ipfs/go-block-format v0.0.2/go.mod h1:AWR46JfpcObNfg3ok2JHDUfdiHRgWhJgCQF+KIgOPJY= github.com/ipfs/go-blockservice v0.0.3 h1:40OvwrxeudTAlUGUAKNYnNPcwQeLtXedjzTWecnUinQ= github.com/ipfs/go-blockservice v0.0.3/go.mod h1:/NNihwTi6V2Yr6g8wBI+BSwPuURpBRMtYNGrlxZ8KuI= -github.com/ipfs/go-cid v0.0.1 h1:GBjWPktLnNyX0JiQCNFpUuUSoMw5KMyqrsejHYlILBE= github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= github.com/ipfs/go-cid v0.0.2 h1:tuuKaZPU1M6HcejsO3AcYWW8sZ8MTvyxfc4uqB4eFE8= github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= github.com/ipfs/go-cidutil v0.0.2 h1:CNOboQf1t7Qp0nuNh8QMmhJs0+Q//bRL1axtCnIB1Yo= github.com/ipfs/go-cidutil v0.0.2/go.mod h1:ewllrvrxG6AMYStla3GD7Cqn+XYSLqjK0vc+086tB6s= -github.com/ipfs/go-datastore v0.0.1 h1:AW/KZCScnBWlSb5JbnEnLKFWXL224LBEh/9KXXOrUms= github.com/ipfs/go-datastore v0.0.1/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= -github.com/ipfs/go-datastore v0.0.3 h1:/eP3nMDmLzMJNoWSSYvEkmMTTrm9FFCN+JraP9NdlwU= github.com/ipfs/go-datastore v0.0.3/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= github.com/ipfs/go-datastore v0.0.5 h1:q3OfiOZV5rlsK1H5V8benjeUApRfMGs4Mrhmr6NriQo= github.com/ipfs/go-datastore v0.0.5/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= -github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk= github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= -github.com/ipfs/go-ds-badger v0.0.2 h1:7ToQt7QByBhOTuZF2USMv+PGlMcBC7FW7FdgQ4FCsoo= github.com/ipfs/go-ds-badger v0.0.2/go.mod h1:Y3QpeSFWQf6MopLTiZD+VT6IC1yZqaGmjvRcKeSGij8= github.com/ipfs/go-ds-badger v0.0.3 h1:sVYE2YlCzltznTZeAP1S+bp3qipz7VzogfZDtf6tGq0= github.com/ipfs/go-ds-badger v0.0.3/go.mod h1:7AzMKCsGav0u46HpdLiAEAOqizR1H6AZsjpHpQSPYCQ= github.com/ipfs/go-ds-flatfs v0.0.2 h1:1zujtU5bPBH6B8roE+TknKIbBCrpau865xUk0dH3x2A= github.com/ipfs/go-ds-flatfs v0.0.2/go.mod h1:YsMGWjUieue+smePAWeH/YhHtlmEMnEGhiwIn6K6rEM= -github.com/ipfs/go-ds-leveldb v0.0.1 h1:Z0lsTFciec9qYsyngAw1f/czhRU35qBLR2vhavPFgqA= github.com/ipfs/go-ds-leveldb v0.0.1/go.mod h1:feO8V3kubwsEF22n0YRQCffeb79OOYIykR4L04tMOYc= github.com/ipfs/go-ds-leveldb v0.0.2 h1:P5HB59Zblym0B5XYOeEyw3YtPtbpIqQCavCSWaWEEk8= github.com/ipfs/go-ds-leveldb v0.0.2/go.mod h1:CWFeBh5IAAscWyG/QRH+lJaAlnLWjsfPSNs4teyPUp0= @@ -263,18 +185,15 @@ github.com/ipfs/go-ipfs-addr v0.0.1 h1:DpDFybnho9v3/a1dzJ5KnWdThWD1HrFLpQ+tWIyBa github.com/ipfs/go-ipfs-addr v0.0.1/go.mod h1:uKTDljHT3Q3SUWzDLp3aYUi8MrY32fgNgogsIa0npjg= github.com/ipfs/go-ipfs-blockstore v0.0.1 h1:O9n3PbmTYZoNhkgkEyrXTznbmktIXif62xLX+8dPHzc= github.com/ipfs/go-ipfs-blockstore v0.0.1/go.mod h1:d3WClOmRQKFnJ0Jz/jj/zmksX0ma1gROTlovZKBmN08= -github.com/ipfs/go-ipfs-blocksutil v0.0.1 h1:Eh/H4pc1hsvhzsQoMEP3Bke/aW5P5rVM1IWFJMcGIPQ= github.com/ipfs/go-ipfs-blocksutil v0.0.1/go.mod h1:Yq4M86uIOmxmGPUHv/uI7uKqZNtLb449gwKqXjIsnRk= github.com/ipfs/go-ipfs-chunker v0.0.1 h1:cHUUxKFQ99pozdahi+uSC/3Y6HeRpi9oTeUHbE27SEw= github.com/ipfs/go-ipfs-chunker v0.0.1/go.mod h1:tWewYK0we3+rMbOh7pPFGDyypCtvGcBFymgY4rSDLAw= github.com/ipfs/go-ipfs-cmds v0.0.8 h1:ZMo0ZeQOr10ZKY4yxYA3lRHUbnF/ZYcV9cpU0IrlGFI= github.com/ipfs/go-ipfs-cmds v0.0.8/go.mod h1:TiK4e7/V31tuEb8YWDF8lN3qrnDH+BS7ZqWIeYJlAs8= -github.com/ipfs/go-ipfs-config v0.0.1 h1:6ED08emzI1imdsAjixFi2pEyZxTVD5ECKtCOxLBx+Uc= github.com/ipfs/go-ipfs-config v0.0.1/go.mod h1:KDbHjNyg4e6LLQSQpkgQMBz6Jf4LXiWAcmnkcwmH0DU= -github.com/ipfs/go-ipfs-config v0.0.3 h1:Ep4tRdP1iVK76BgOprD9B/qtOEdpno+1Xb57BqydgGk= -github.com/ipfs/go-ipfs-config v0.0.3/go.mod h1:KDbHjNyg4e6LLQSQpkgQMBz6Jf4LXiWAcmnkcwmH0DU= +github.com/ipfs/go-ipfs-config v0.0.4 h1:zOWk1gGvIOptjHvvu0qSC8psB2IBKO/FbQArFnmm0LM= +github.com/ipfs/go-ipfs-config v0.0.4/go.mod h1:KDbHjNyg4e6LLQSQpkgQMBz6Jf4LXiWAcmnkcwmH0DU= github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= -github.com/ipfs/go-ipfs-delay v0.0.1 h1:r/UXYyRcddO6thwOnhiznIAiSvxMECGgtv35Xs1IeRQ= github.com/ipfs/go-ipfs-delay v0.0.1/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= github.com/ipfs/go-ipfs-ds-help v0.0.1 h1:QBg+Ts2zgeemK/dB0saiF/ykzRGgfoFMT90Rzo0OnVU= github.com/ipfs/go-ipfs-ds-help v0.0.1/go.mod h1:gtP9xRaZXqIQRh1HRpp595KbBEdgqWFxefeVKOV8sxo= @@ -282,11 +201,9 @@ 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 h1:fEEjF4H+1t8SFOHqUGp0KqcwgIRlbD2bu8CAS2sIggE= github.com/ipfs/go-ipfs-files v0.0.2/go.mod h1:INEFm0LL2LWXBhNJ2PMIIb2w45hpXgPjNoE7yA8Y1d4= github.com/ipfs/go-ipfs-files v0.0.3 h1:ME+QnC3uOyla1ciRPezDW0ynQYK2ikOh9OCKAEg4uUA= github.com/ipfs/go-ipfs-files v0.0.3/go.mod h1:INEFm0LL2LWXBhNJ2PMIIb2w45hpXgPjNoE7yA8Y1d4= -github.com/ipfs/go-ipfs-flags v0.0.1 h1:OH5cEkJYL0QgA+bvD55TNG9ud8HA2Nqaav47b2c/UJk= github.com/ipfs/go-ipfs-flags v0.0.1/go.mod h1:RnXBb9WV53GSfTrSDVK61NLTFKvWc60n+K9EgCDh+rA= github.com/ipfs/go-ipfs-posinfo v0.0.1 h1:Esoxj+1JgSjX0+ylc0hUmJCOv6V2vFoZiETLR6OtpRs= github.com/ipfs/go-ipfs-posinfo v0.0.1/go.mod h1:SwyeVP+jCwiDu0C313l/8jg6ZxM0qqtlt2a0vILTc1A= @@ -296,11 +213,9 @@ github.com/ipfs/go-ipfs-routing v0.0.1 h1:394mZeTLcbM/LDO12PneBYvkZAUA+nRnmC0lAz github.com/ipfs/go-ipfs-routing v0.0.1/go.mod h1:k76lf20iKFxQTjcJokbPM9iBXVXVZhcOwc360N4nuKs= github.com/ipfs/go-ipfs-util v0.0.1 h1:Wz9bL2wB2YBJqggkA4dD7oSmqB4cAnpNbGrlHJulv50= github.com/ipfs/go-ipfs-util v0.0.1/go.mod h1:spsl5z8KUnrve+73pOhSVZND1SIxPW5RyBCNzQxlJBc= -github.com/ipfs/go-ipld-cbor v0.0.1 h1:g7yh27SznWP4CUbkFgjR+WQRjEeyxCpTR4iKVmXx1wA= github.com/ipfs/go-ipld-cbor v0.0.1/go.mod h1:RXHr8s4k0NE0TKhnrxqZC9M888QfsBN9rhS5NjfKzY8= github.com/ipfs/go-ipld-cbor v0.0.2 h1:amzFztBQQQ69UA5+f7JRfoXF/z2l//MGfEDHVkS20+s= github.com/ipfs/go-ipld-cbor v0.0.2/go.mod h1:wTBtrQZA3SoFKMVkp6cn6HMRteIB1VsmHA0AQFOn7Nc= -github.com/ipfs/go-ipld-format v0.0.1 h1:HCu4eB/Gh+KD/Q0M8u888RFkorTWNIL3da4oc5dwc80= github.com/ipfs/go-ipld-format v0.0.1/go.mod h1:kyJtbkDALmFHv3QR6et67i35QzO3S0dCDnkOJhcZkms= github.com/ipfs/go-ipld-format v0.0.2 h1:OVAGlyYT6JPZ0pEfGntFPS40lfrDmaDbQwNHEY2G9Zs= github.com/ipfs/go-ipld-format v0.0.2/go.mod h1:4B6+FM2u9OJ9zCV+kSbgFAZlOrv1Hqbf0INGQgiKf9k= @@ -318,7 +233,6 @@ 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.0.7 h1:Xjqk0jAhgwhMHO39oH4jqP1QkeAGqDelxa814voygN0= github.com/ipfs/go-mfs v0.0.7/go.mod h1:10Hdow7wUbSlIamnOduxeP6MEp58TozZmdnAhugOKz8= -github.com/ipfs/go-path v0.0.3 h1:G/VFcCMXtp36JUPPyytYQ1I3UsBUBf47M//uSdTLnFg= github.com/ipfs/go-path v0.0.3/go.mod h1:zIRQUez3LuQIU25zFjC2hpBTHimWx7VK5bjZgRLbbdo= github.com/ipfs/go-path v0.0.4 h1:zG/id80tV51XAfvCsRJIEGQSHGuTDBi8RWrtr3EfcfY= github.com/ipfs/go-path v0.0.4/go.mod h1:zIRQUez3LuQIU25zFjC2hpBTHimWx7VK5bjZgRLbbdo= @@ -326,131 +240,96 @@ github.com/ipfs/go-peertaskqueue v0.0.4 h1:i0JprfjjILYcWM1xguO/1MCS8XKVxLSl+ECEV github.com/ipfs/go-peertaskqueue v0.0.4/go.mod h1:03H8fhyeMfKNFWqzYEVyMbcPUeYrqP1MX6Kd+aN+rMQ= github.com/ipfs/go-todocounter v0.0.1 h1:kITWA5ZcQZfrUnDNkRn04Xzh0YFaDFXsoO2A81Eb6Lw= github.com/ipfs/go-todocounter v0.0.1/go.mod h1:l5aErvQc8qKE2r7NDMjmq5UNAvuZy0rC8BHOplkWvZ4= -github.com/ipfs/go-unixfs v0.0.4 h1:IApzQ+SnY0tfjqM7aU2b80CFYLZNHvhLmEZDIWr4e/E= github.com/ipfs/go-unixfs v0.0.4/go.mod h1:eIo/p9ADu/MFOuyxzwU+Th8D6xoxU//r590vUpWyfz8= github.com/ipfs/go-unixfs v0.0.6 h1:mQ6KS3NK4GA9hyUpGdGItqt5llzyIx0Qy2UxC/A7bEo= github.com/ipfs/go-unixfs v0.0.6/go.mod h1:g41FlHFM/qacA3jzMPOYKIwNwbgTQEKJH2hQiq19Zrc= github.com/ipfs/go-verifcid v0.0.1 h1:m2HI7zIuR5TFyQ1b79Da5N9dnnCP1vcu2QqawmWlK2E= github.com/ipfs/go-verifcid v0.0.1/go.mod h1:5Hrva5KBeIog4A+UpqlaIU+DEstipcJYQQZc0g37pY0= -github.com/ipfs/hang-fds v0.0.1 h1:KGAxiGtJPT3THVRNT6yxgpdFPeX4ZemUjENOt6NlOn4= github.com/ipfs/hang-fds v0.0.1/go.mod h1:U4JNbzwTpk/qP2Ms4VgrZ4HcgJGVosBJqMXvwe4udSY= github.com/ipfs/interface-go-ipfs-core v0.0.8 h1:nmEYOfK6QRf3VIdggoZ4rmbKXcC2g6cEdU13Z1CvmL4= github.com/ipfs/interface-go-ipfs-core v0.0.8/go.mod h1:RU+DSZXV+JdA7Yagu3OrSoB6hngSmMtK1w6ENOqmfQ8= -github.com/ipfs/iptb v1.4.0 h1:YFYTrCkLMRwk/35IMyC6+yjoQSHTEcNcefBStLJzgvo= github.com/ipfs/iptb v1.4.0/go.mod h1:1rzHpCYtNp87/+hTxG5TfCVn/yMY3dKnLn8tBiMfdmg= -github.com/ipfs/iptb-plugins v0.0.2 h1:JZp4h/+7f00dY4Epr8gzF+VqKITXmVGsZabvmZp7E9I= github.com/ipfs/iptb-plugins v0.0.2/go.mod h1:Vud+X6lHv5QlgVbqCPBHt91I0gPIRgmkD6/tMUsI07U= -github.com/jackpal/gateway v1.0.4 h1:LS5EHkLuQ6jzaHwULi0vL+JO0mU/n4yUtK8oUjHHOlM= github.com/jackpal/gateway v1.0.4/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= github.com/jackpal/gateway v1.0.5 h1:qzXWUJfuMdlLMtt0a3Dgt+xkWQiA5itDEITVJtuSwMc= github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= github.com/jackpal/go-nat-pmp v1.0.1 h1:i0LektDkO1QlrTm/cSuP+PyBCDnYvjPLGl4LdWEMiaA= github.com/jackpal/go-nat-pmp v1.0.1/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= -github.com/jbenet/go-cienv v0.0.0-20150120210510-1bb1476777ec h1:DQqZhhDvrTrEQ3Qod5yfavcA064e53xlQ+xajiorXgM= github.com/jbenet/go-cienv v0.0.0-20150120210510-1bb1476777ec/go.mod h1:rGaEvXB4uRSZMmzKNLoXvTu1sfx+1kv/DojUlPrSZGs= -github.com/jbenet/go-cienv v0.1.0 h1:Vc/s0QbQtoxX8MwwSLWWh+xNNZvM3Lw7NsTcHrvvhMc= github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jbenet/go-is-domain v1.0.2 h1:11r5MSptcNFZyBoqubBQnVMUKRWLuRjL1banaIk+iYo= github.com/jbenet/go-is-domain v1.0.2/go.mod h1:xbRLRb0S7FgzDBTJlguhDVwLYM/5yNtvktxj2Ttfy7Q= -github.com/jbenet/go-random v0.0.0-20190219211222-123a90aedc0c h1:uUx61FiAa1GI6ZmVd2wf2vULeQZIKG66eybjNXKYCz4= github.com/jbenet/go-random v0.0.0-20190219211222-123a90aedc0c/go.mod h1:sdx1xVM9UuLw1tXnhJWN3piypTUO3vCIHYmG15KE/dU= -github.com/jbenet/go-random-files v0.0.0-20190219210431-31b3f20ebded h1:fHCa28iw+qaRWZK4IqrntHxXALD5kKr/ESrpOCRRdrg= github.com/jbenet/go-random-files v0.0.0-20190219210431-31b3f20ebded/go.mod h1:FKvZrl5nnaGnTAMewcq0i7wM5zHD75e0lwlnF8q46uo= github.com/jbenet/go-temp-err-catcher v0.0.0-20150120210811-aac704a3f4f2 h1:vhC1OXXiT9R2pczegwz6moDvuRpggaroAXhPIseh57A= github.com/jbenet/go-temp-err-catcher v0.0.0-20150120210811-aac704a3f4f2/go.mod h1:8GXXJV31xl8whumTzdZsTt3RnUIiPqzkyf7mxToRCMs= -github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8 h1:bspPhN+oKYFk5fcGNuQzp6IGzYQSenLEgH3s6jkXrWw= github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8/go.mod h1:Ly/wlsjFq/qrU3Rar62tu1gASgGw6chQbSh/XgIIXCY= github.com/jbenet/goprocess v0.1.3 h1:YKyIEECS/XvcfHtBzxtjBBbWK+MbvA6dG8ASiqwvr10= github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= -github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89 h1:12K8AlpT0/6QUXSfV0yi4Q0jkbq8NDtIKFtF61AoqV0= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= -github.com/jtolds/gls v4.2.1+incompatible h1:fSuqC+Gmlu6l/ZYAoZzx2pyucC8Xza35fpRVWLVmUEE= github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/julienschmidt/httprouter v1.2.0 h1:TDTW5Yz1mjftljbcKqRcrYhd4XeOoI98t+9HbQbYf7g= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v0.0.0-20161130080628-0de1eaf82fa3/go.mod h1:jxZFDH7ILpTPQTk+E2s+z4CUas9lVNjIuKR4c5/zKgM= -github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 h1:FOOIBWrEkLgmlgGfMuZT83xIwfPDxEI2OHu6xUmJMFE= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/kkdai/bstream v0.0.0-20181106074824-b3251f7901ec/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= -github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/koron/go-ssdp v0.0.0-20180514024734-4a0ed625a78b h1:wxtKgYHEncAU00muMD06dzLiahtGM1eouRNOzVV7tdQ= github.com/koron/go-ssdp v0.0.0-20180514024734-4a0ed625a78b/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/libp2p/go-addr-util v0.0.1 h1:TpTQm9cXVRVSKsYbgQ7GKc3KbbHVTnbostgGaDEP+88= github.com/libp2p/go-addr-util v0.0.1/go.mod h1:4ac6O7n9rIAKB1dnd+s8IbbMXkt+oBpzX4/+RACcnlQ= -github.com/libp2p/go-buffer-pool v0.0.1 h1:9Rrn/H46cXjaA2HQ5Y8lyhOS1NhTkZ4yuEs2r3Eechg= github.com/libp2p/go-buffer-pool v0.0.1/go.mod h1:xtyIz9PMobb13WaxR6Zo1Pd1zXJKYg0a8KiIvDp3TzQ= github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOSqcmlfs= github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= github.com/libp2p/go-conn-security v0.0.1 h1:4kMMrqrt9EUNCNjX1xagSJC+bq16uqjMe9lk1KBMVNs= github.com/libp2p/go-conn-security v0.0.1/go.mod h1:bGmu51N0KU9IEjX7kl2PQjgZa40JQWnayTvNMgD/vyk= -github.com/libp2p/go-conn-security-multistream v0.0.1 h1:XefjAQRHcnUaxKb26RGupToucx3uU4ecbOZ3aACXlDU= github.com/libp2p/go-conn-security-multistream v0.0.1/go.mod h1:nc9vud7inQ+d6SO0I/6dSWrdMnHnzZNHeyUQqrAJulE= github.com/libp2p/go-conn-security-multistream v0.0.2 h1:Ykz0lnNjxk+0SdslUmlLNyrleqdpS1S/VW+dxFdt74Y= github.com/libp2p/go-conn-security-multistream v0.0.2/go.mod h1:nc9vud7inQ+d6SO0I/6dSWrdMnHnzZNHeyUQqrAJulE= github.com/libp2p/go-flow-metrics v0.0.1 h1:0gxuFd2GuK7IIP5pKljLwps6TvcuYgvG7Atqi3INF5s= github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8= -github.com/libp2p/go-libp2p v0.0.2 h1:+jvgi0Zy3y4TKXJKApchCk3pCBPZf1T54z3+vKie3gw= github.com/libp2p/go-libp2p v0.0.2/go.mod h1:Qu8bWqFXiocPloabFGUcVG4kk94fLvfC8mWTDdFC9wE= github.com/libp2p/go-libp2p v0.0.27/go.mod h1:kjeVlESxQisK2DvyKp38/UMHYd9gAMTj3C3XOB/DEZo= github.com/libp2p/go-libp2p v0.0.28 h1:tkDnM7iwrz9OSRRb8YAV4HYjv8TKsAxyxrV2sES9/Aw= github.com/libp2p/go-libp2p v0.0.28/go.mod h1:GBW0VbgEKe8ELXVpLQJduJYlJHRv/XfwP6Fo9TEcDJU= -github.com/libp2p/go-libp2p-autonat v0.0.2 h1:ilo9QPzNPf1hMkqaPG55yzvhILf5ZtijstJhcii+l3s= github.com/libp2p/go-libp2p-autonat v0.0.2/go.mod h1:fs71q5Xk+pdnKU014o2iq1RhMs9/PMaG5zXRFNnIIT4= -github.com/libp2p/go-libp2p-autonat v0.0.3 h1:PUD+pAx8Qs9hh+Bowzxq8RCkg/Vwrz5oCFC4peixXQk= github.com/libp2p/go-libp2p-autonat v0.0.3/go.mod h1:fs71q5Xk+pdnKU014o2iq1RhMs9/PMaG5zXRFNnIIT4= github.com/libp2p/go-libp2p-autonat v0.0.5/go.mod h1:cKt+qOSnWAZp0dqIuUk62v0/QAPw0vnLuVZnmzkOXRk= github.com/libp2p/go-libp2p-autonat v0.0.6 h1:OCStANLLpeyQeWFUuqZJ7aS9+Bx0/uoVb1PtLA9fGTQ= github.com/libp2p/go-libp2p-autonat v0.0.6/go.mod h1:uZneLdOkZHro35xIhpbtTzLlgYturpu4J5+0cZK3MqE= -github.com/libp2p/go-libp2p-autonat-svc v0.0.2 h1:beAUwqt3wHWlguz1EYdG+bVOKyf5SIQpXfTSnfGoW7k= github.com/libp2p/go-libp2p-autonat-svc v0.0.2/go.mod h1:j4iMiw0d3diRm5iB0noXumtb0mPvWrM1qAyh640cp8w= github.com/libp2p/go-libp2p-autonat-svc v0.0.5 h1:bTom7QFAkJMXiA8ibSsKQ2+LKEHsXZz2IAWYolg/YYg= github.com/libp2p/go-libp2p-autonat-svc v0.0.5/go.mod h1:6aLiQelA0CKEcPR0TvE9bqJ7U8Mc0nVdwCoho3ROdck= -github.com/libp2p/go-libp2p-blankhost v0.0.1 h1:/mZuuiwntNR8RywnCFlGHLKrKLYne+qciBpQXWqp5fk= github.com/libp2p/go-libp2p-blankhost v0.0.1/go.mod h1:Ibpbw/7cPPYwFb7PACIWdvxxv0t0XCCI10t7czjAjTc= -github.com/libp2p/go-libp2p-circuit v0.0.1 h1:DYbjyQ5ZY3QVAVYZWG4uzBQ6Wmcd1C82Bk8Q/pJlM1I= github.com/libp2p/go-libp2p-circuit v0.0.1/go.mod h1:Dqm0s/BiV63j8EEAs8hr1H5HudqvCAeXxDyic59lCwE= github.com/libp2p/go-libp2p-circuit v0.0.7/go.mod h1:DFCgZ2DklFGTUIZIhSvbbWXTErUgjyNrJGfDHOrTKIA= github.com/libp2p/go-libp2p-circuit v0.0.8 h1:vd9vZDy+LDssTvUuxIqnYUOAK2hfHoSQO2xjWhPVEmc= github.com/libp2p/go-libp2p-circuit v0.0.8/go.mod h1:DFCgZ2DklFGTUIZIhSvbbWXTErUgjyNrJGfDHOrTKIA= -github.com/libp2p/go-libp2p-connmgr v0.0.1 h1:9KP7UbP4a6fauLw954LhTGfovhkmMwvJsIf8G4CCons= github.com/libp2p/go-libp2p-connmgr v0.0.1/go.mod h1:eUBBlbuwBBTd/eim7KV5x0fOD2UHDjSwhzmBL6miIx8= github.com/libp2p/go-libp2p-connmgr v0.0.6 h1:oEUriPO/qWTvfHRPEU4HdNlNhYigdueOs2X3UZCdbYM= github.com/libp2p/go-libp2p-connmgr v0.0.6/go.mod h1:uwDfgdgqB5248sQYib1xo603cSsMg9PgAKu0Z+Y65Qk= -github.com/libp2p/go-libp2p-crypto v0.0.1 h1:JNQd8CmoGTohO/akqrH16ewsqZpci2CbgYH/LmYl8gw= github.com/libp2p/go-libp2p-crypto v0.0.1/go.mod h1:yJkNyDmO341d5wwXxDUGO0LykUVT72ImHNUqh5D/dBE= github.com/libp2p/go-libp2p-crypto v0.0.2 h1:TTdJ4y6Uoa6NxQcuEaVkQfFRcQeCE2ReDk8Ok4I0Fyw= github.com/libp2p/go-libp2p-crypto v0.0.2/go.mod h1:eETI5OUfBnvARGOHrJz2eWNyTUxEGZnBxMcbUjfIj4I= github.com/libp2p/go-libp2p-daemon v0.0.6/go.mod h1:nkhjsjSzkF+tg6iScsTTgq9m+VfyMtXNpycYG4CFvC8= -github.com/libp2p/go-libp2p-discovery v0.0.1 h1:VkjCKmJQMwpDUwtA8Qc1z3TQAHJgQ5nGQ6cdN0wQXOw= github.com/libp2p/go-libp2p-discovery v0.0.1/go.mod h1:ZkkF9xIFRLA1xCc7bstYFkd80gBGK8Fc1JqGoU2i+zI= github.com/libp2p/go-libp2p-discovery v0.0.4 h1:/kZwOVmcUHvB94zegSJYnUA9EvT1g8APoQJb5FHyT1c= github.com/libp2p/go-libp2p-discovery v0.0.4/go.mod h1:ReQGiv7QTtza8FUWzewfuMmRDVOQVp+lxHlJJA8YQCM= -github.com/libp2p/go-libp2p-host v0.0.1 h1:dnqusU+DheGcdxrE718kG4XgHNuL2n9eEv8Rg5zy8hQ= github.com/libp2p/go-libp2p-host v0.0.1/go.mod h1:qWd+H1yuU0m5CwzAkvbSjqKairayEHdR5MMl7Cwa7Go= github.com/libp2p/go-libp2p-host v0.0.3 h1:BB/1Z+4X0rjKP5lbQTmjEjLbDVbrcmLOlA6QDsN5/j4= github.com/libp2p/go-libp2p-host v0.0.3/go.mod h1:Y/qPyA6C8j2coYyos1dfRm0I8+nvd4TGrDGt4tA7JR8= -github.com/libp2p/go-libp2p-interface-connmgr v0.0.1 h1:Q9EkNSLAOF+u90L88qmE9z/fTdjLh8OsJwGw74mkwk4= github.com/libp2p/go-libp2p-interface-connmgr v0.0.1/go.mod h1:GarlRLH0LdeWcLnYM/SaBykKFl9U5JFnbBGruAk/D5k= -github.com/libp2p/go-libp2p-interface-connmgr v0.0.4 h1:/LngXETpII5qOD7YjAcQiIxhVtdAk/NQe5t9sC6BR0E= github.com/libp2p/go-libp2p-interface-connmgr v0.0.4/go.mod h1:GarlRLH0LdeWcLnYM/SaBykKFl9U5JFnbBGruAk/D5k= github.com/libp2p/go-libp2p-interface-connmgr v0.0.5 h1:KG/KNYL2tYzXAfMvQN5K1aAGTYSYUMJ1prgYa2/JI1E= github.com/libp2p/go-libp2p-interface-connmgr v0.0.5/go.mod h1:GarlRLH0LdeWcLnYM/SaBykKFl9U5JFnbBGruAk/D5k= @@ -459,7 +338,6 @@ github.com/libp2p/go-libp2p-interface-pnet v0.0.1/go.mod h1:el9jHpQAXK5dnTpKA4yf github.com/libp2p/go-libp2p-kad-dht v0.0.4/go.mod h1:oaBflOQcuC8H+SVV0YN26H6AS+wcUEJyjUGV66vXuSY= github.com/libp2p/go-libp2p-kad-dht v0.0.13 h1:ReMb41jJrngvXnU5Tirf74bBkXx4M9ne5QyFQPeNYtw= github.com/libp2p/go-libp2p-kad-dht v0.0.13/go.mod h1:3A4xaZJeJ3zD3jCg17mtI+rA7uuXiiQdKVyAZOhZo1U= -github.com/libp2p/go-libp2p-kbucket v0.0.1 h1:7H5hM851hkEpLOFjrVNSrrxo6J4bWrUQxxv+z1JW9xk= github.com/libp2p/go-libp2p-kbucket v0.0.1/go.mod h1:Y0iQDHRTk/ZgM8PC4jExoF+E4j+yXWwRkdldkMa5Xm4= github.com/libp2p/go-libp2p-kbucket v0.1.1 h1:ZrvW3qCM+lAuv7nrNts/zfEiClq+GZe8OIzX4Vb3Dwo= github.com/libp2p/go-libp2p-kbucket v0.1.1/go.mod h1:Y0iQDHRTk/ZgM8PC4jExoF+E4j+yXWwRkdldkMa5Xm4= @@ -469,23 +347,18 @@ github.com/libp2p/go-libp2p-metrics v0.0.1 h1:yumdPC/P2VzINdmcKZd0pciSUCpou+s0lw github.com/libp2p/go-libp2p-metrics v0.0.1/go.mod h1:jQJ95SXXA/K1VZi13h52WZMa9ja78zjyy5rspMsC/08= github.com/libp2p/go-libp2p-mplex v0.1.1 h1:lSPS1VJ36P01gGO//KgcsmSah5uoC3X9r7WY5j+iP4c= github.com/libp2p/go-libp2p-mplex v0.1.1/go.mod h1:KUQWpGkCzfV7UIpi8SKsAVxyBgz1c9R5EvxgnwLsb/I= -github.com/libp2p/go-libp2p-nat v0.0.2 h1:sKI5hiCsGFhuEKdXMsF9mywQu2qhfoIGX6a+VG6zelE= github.com/libp2p/go-libp2p-nat v0.0.2/go.mod h1:QrjXQSD5Dj4IJOdEcjHRkWTSomyxRo6HnUkf/TfQpLQ= github.com/libp2p/go-libp2p-nat v0.0.4 h1:+KXK324yaY701On8a0aGjTnw8467kW3ExKcqW2wwmyw= github.com/libp2p/go-libp2p-nat v0.0.4/go.mod h1:N9Js/zVtAXqaeT99cXgTV9e75KpnWCvVOiGzlcHmBbY= github.com/libp2p/go-libp2p-net v0.0.0-20190226201932-e71fff5ba6e9/go.mod h1:8W6Wx3AZbTRTe8zSMLoAmT3mGyau+w6kGIRk+Z+MZ7Q= -github.com/libp2p/go-libp2p-net v0.0.1 h1:xJ4Vh4yKF/XKb8fd1Ev0ebAGzVjMxXzrxG2kjtU+F5Q= github.com/libp2p/go-libp2p-net v0.0.1/go.mod h1:Yt3zgmlsHOgUWSXmt5V/Jpz9upuJBE8EgNU9DrCcR8c= github.com/libp2p/go-libp2p-net v0.0.2 h1:qP06u4TYXfl7uW/hzqPhlVVTSA2nw1B/bHBJaUnbh6M= github.com/libp2p/go-libp2p-net v0.0.2/go.mod h1:Yt3zgmlsHOgUWSXmt5V/Jpz9upuJBE8EgNU9DrCcR8c= -github.com/libp2p/go-libp2p-netutil v0.0.1 h1:LgD6+skofkOx8z6odD9+MZHKjupv3ng1u6KRhaADTnA= github.com/libp2p/go-libp2p-netutil v0.0.1/go.mod h1:GdusFvujWZI9Vt0X5BKqwWWmZFxecf9Gt03cKxm2f/Q= -github.com/libp2p/go-libp2p-peer v0.0.1 h1:0qwAOljzYewINrU+Kndoc+1jAL7vzY/oY2Go4DCGfyY= github.com/libp2p/go-libp2p-peer v0.0.1/go.mod h1:nXQvOBbwVqoP+T5Y5nCjeH4sP9IX/J0AMzcDUVruVoo= github.com/libp2p/go-libp2p-peer v0.1.1 h1:qGCWD1a+PyZcna6htMPo26jAtqirVnJ5NvBQIKV7rRY= github.com/libp2p/go-libp2p-peer v0.1.1/go.mod h1:jkF12jGB4Gk/IOo+yomm+7oLWxF278F7UnrYUQ1Q8es= github.com/libp2p/go-libp2p-peerstore v0.0.0-20190226201924-e2df3e49eabf/go.mod h1:lLfgn0N3z2t+ER57a88K7NTZjMO27ez5TyWSURd428E= -github.com/libp2p/go-libp2p-peerstore v0.0.1 h1:twKovq8YK5trLrd3nB7PD2Zu9JcyAIdm7Bz9yBWjhq8= github.com/libp2p/go-libp2p-peerstore v0.0.1/go.mod h1:RabLyPVJLuNQ+GFyoEkfi8H4Ti6k/HtZJ7YKgtSq+20= github.com/libp2p/go-libp2p-peerstore v0.0.6 h1:RgX/djPFXqZGktW0j2eF4NAX0pzDsCot45jO2GewC+g= github.com/libp2p/go-libp2p-peerstore v0.0.6/go.mod h1:RabLyPVJLuNQ+GFyoEkfi8H4Ti6k/HtZJ7YKgtSq+20= @@ -494,7 +367,6 @@ github.com/libp2p/go-libp2p-pnet v0.0.1/go.mod h1:bWN8HqdpgCdKnXSCsJhbWjiU3UZFa/ github.com/libp2p/go-libp2p-protocol v0.0.0-20171212212132-b29f3d97e3a2/go.mod h1:Af9n4PiruirSDjHycM1QuiMi/1VZNHYcK8cLgFJLZ4s= github.com/libp2p/go-libp2p-protocol v0.0.1 h1:+zkEmZ2yFDi5adpVE3t9dqh/N9TbpFWywowzeEzBbLM= github.com/libp2p/go-libp2p-protocol v0.0.1/go.mod h1:Af9n4PiruirSDjHycM1QuiMi/1VZNHYcK8cLgFJLZ4s= -github.com/libp2p/go-libp2p-pubsub v0.0.1 h1:iJWpvBDZiZOoRBGqEifu9yUHti9ptnSODHt6tgrBC6c= github.com/libp2p/go-libp2p-pubsub v0.0.1/go.mod h1:fYKlZBOF2yrJzYlgeEVFSbYWfbS+E8Zix6gMZ0A6WgE= github.com/libp2p/go-libp2p-pubsub v0.0.3 h1:DKVoDac2u1Dr8gX7B1HFjCrXkMxr8tfbnt0Fk1mmkgk= github.com/libp2p/go-libp2p-pubsub v0.0.3/go.mod h1:fYKlZBOF2yrJzYlgeEVFSbYWfbS+E8Zix6gMZ0A6WgE= @@ -509,13 +381,10 @@ github.com/libp2p/go-libp2p-routing v0.0.1 h1:hPMAWktf9rYi3ME4MG48qE7dq1ofJxiQbf github.com/libp2p/go-libp2p-routing v0.0.1/go.mod h1:N51q3yTr4Zdr7V8Jt2JIktVU+3xBBylx1MZeVA6t1Ys= github.com/libp2p/go-libp2p-routing-helpers v0.0.2 h1:SLX7eDQE8Xo197NwNM/hM7WnH3w6fSGY9+G9HkiYwqQ= github.com/libp2p/go-libp2p-routing-helpers v0.0.2/go.mod h1:zf1ook9HoOQpfnVXrF4gGorkPrGGf1g25vgH5+4SRNU= -github.com/libp2p/go-libp2p-secio v0.0.1 h1:CqE/RdsizOwItdgLe632iyft/w0tshDLmZGAiKDcUAI= github.com/libp2p/go-libp2p-secio v0.0.1/go.mod h1:IdG6iQybdcYmbTzxp4J5dwtUEDTOvZrT0opIDVNPrJs= github.com/libp2p/go-libp2p-secio v0.0.3 h1:h3fPeDrej7bvvARnC2oSjAfcLZOaS4REZKgWCRQNpE4= github.com/libp2p/go-libp2p-secio v0.0.3/go.mod h1:hS7HQ00MgLhRO/Wyu1bTX6ctJKhVpm+j2/S2A5UqYb0= -github.com/libp2p/go-libp2p-swarm v0.0.1 h1:Vne+hjaDwXqzgNwQ2vb2YKbnbOTyXjtS47stT66Apc4= github.com/libp2p/go-libp2p-swarm v0.0.1/go.mod h1:mh+KZxkbd3lQnveQ3j2q60BM1Cw2mX36XXQqwfPOShs= -github.com/libp2p/go-libp2p-swarm v0.0.5 h1:oue1c+NbyFTuwCkWulX+ouyQoaZsdYeYcAzQ/slfxXY= github.com/libp2p/go-libp2p-swarm v0.0.5/go.mod h1:+nkJir4feiXtWQjb/4CQHMEK8Vw+c5nVVxT8R5bs0yY= github.com/libp2p/go-libp2p-swarm v0.0.6 h1:gE0P/v2h+KEXtAi9YTw2UBOSODJ4m9VuuJ+ktc2LVUo= github.com/libp2p/go-libp2p-swarm v0.0.6/go.mod h1:s5GZvzg9xXe8sbeESuFpjt8CJPTCa8mhEusweJqyFy8= @@ -523,31 +392,23 @@ github.com/libp2p/go-libp2p-tls v0.0.1 h1:UIslpmpKDbjEymuidtP2D9up00GfWrOs6eyTKf github.com/libp2p/go-libp2p-tls v0.0.1/go.mod h1:DInSFKxm9XHHSbCdJRbcWctRYkmtPGnqiaUtgjiEa7g= github.com/libp2p/go-libp2p-transport v0.0.0-20190226201958-e8580c8a519d/go.mod h1:lcwgOszllbhvQXul37Kv5YbSYXPoUhRB2Z+Nr3jaBmo= github.com/libp2p/go-libp2p-transport v0.0.1/go.mod h1:UzbUs9X+PHOSw7S3ZmeOxfnwaQY5vGDzZmKPod3N3tk= -github.com/libp2p/go-libp2p-transport v0.0.4 h1:/CPHQMN75/IQwkhBxxIo6p6PtL3rwFZtlzBROT3e8mw= github.com/libp2p/go-libp2p-transport v0.0.4/go.mod h1:StoY3sx6IqsP6XKoabsPnHCwqKXWUMWU7Rfcsubee/A= github.com/libp2p/go-libp2p-transport v0.0.5 h1:pV6+UlRxyDpASSGD+60vMvdifSCby6JkJDfi+yUMHac= github.com/libp2p/go-libp2p-transport v0.0.5/go.mod h1:StoY3sx6IqsP6XKoabsPnHCwqKXWUMWU7Rfcsubee/A= -github.com/libp2p/go-libp2p-transport-upgrader v0.0.1 h1:rNtXkY6dty46mxYOHHAZQchI7gQdJStF683FhVnei/k= github.com/libp2p/go-libp2p-transport-upgrader v0.0.1/go.mod h1:NJpUAgQab/8K6K0m+JmZCe5RUXG10UMEx4kWe9Ipj5c= -github.com/libp2p/go-libp2p-transport-upgrader v0.0.3 h1:ZcXhGEMnv8f+ycqVl/9mnIe6uhUYy0aj/vEYQUoG7xU= github.com/libp2p/go-libp2p-transport-upgrader v0.0.3/go.mod h1:Ng1HzfMIopyYscMHNFmJqiMMcpgDlj0t+NyjVWW89ws= github.com/libp2p/go-libp2p-transport-upgrader v0.0.4 h1:uGMOd14BL1oFlfb/cGfOxPjiTKBhzWV4aMjjoCF1Z1o= github.com/libp2p/go-libp2p-transport-upgrader v0.0.4/go.mod h1:RGq+tupk+oj7PzL2kn/m1w6YXxcIAYJYeI90h6BGgUc= -github.com/libp2p/go-libp2p-yamux v0.1.2 h1:DgGItlrWi0j9y1OhRMC8qqL4zj2MEPWeKJTHb55R16Q= github.com/libp2p/go-libp2p-yamux v0.1.2/go.mod h1:xUoV/RmYkg6BW/qGxA9XJyg+HzXFYkeXbnhjmnYzKp8= github.com/libp2p/go-libp2p-yamux v0.1.3 h1:HmKvv2jWJ4GEm3iP7cEKjuw0POa6rK+Hcsu1FBKzpLc= github.com/libp2p/go-libp2p-yamux v0.1.3/go.mod h1:VGSQVrqkh6y4nm0189qqxMtvyBft44MOYYPpYKXiVt4= -github.com/libp2p/go-maddr-filter v0.0.1 h1:apvYTg0aIxxQyBX+XHKOR+0+lYhGs1Yv+JmTH9nyl5I= github.com/libp2p/go-maddr-filter v0.0.1/go.mod h1:6eT12kSQMA9x2pvFQa+xesMKUBlj9VImZbj3B9FBH/Q= github.com/libp2p/go-maddr-filter v0.0.4 h1:hx8HIuuwk34KePddrp2mM5ivgPkZ09JH4AvsALRbFUs= github.com/libp2p/go-maddr-filter v0.0.4/go.mod h1:6eT12kSQMA9x2pvFQa+xesMKUBlj9VImZbj3B9FBH/Q= -github.com/libp2p/go-mplex v0.0.1 h1:dn2XGSrUxLtz3/8u85bGrwhUEKPX8MOF3lpmcWBZCWc= github.com/libp2p/go-mplex v0.0.1/go.mod h1:pK5yMLmOoBR1pNCqDlA2GQrdAVTMkqFalaTWe7l4Yd0= -github.com/libp2p/go-mplex v0.0.3 h1:YiMaevQcZtFU6DmKIF8xEO0vaui5kM5HJ1V1xkWQv14= github.com/libp2p/go-mplex v0.0.3/go.mod h1:pK5yMLmOoBR1pNCqDlA2GQrdAVTMkqFalaTWe7l4Yd0= github.com/libp2p/go-mplex v0.0.4 h1:043XJ3Zr7/Oz5cfyUaJwxUZyP02TngTpt4oq8R5UizQ= github.com/libp2p/go-mplex v0.0.4/go.mod h1:pK5yMLmOoBR1pNCqDlA2GQrdAVTMkqFalaTWe7l4Yd0= -github.com/libp2p/go-msgio v0.0.1 h1:znj97n5FtXGCLDwe9x8jpHmY770SW4WStBGcCDh6GJw= github.com/libp2p/go-msgio v0.0.1/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= github.com/libp2p/go-msgio v0.0.2 h1:ivPvEKHxmVkTClHzg6RXTYHqaJQ0V9cDbq+6lKb3UV0= github.com/libp2p/go-msgio v0.0.2/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= @@ -555,7 +416,6 @@ github.com/libp2p/go-nat v0.0.3 h1:l6fKV+p0Xa354EqQOQP+d8CivdLM4kl5GxC1hSc/UeI= github.com/libp2p/go-nat v0.0.3/go.mod h1:88nUEt0k0JD45Bk93NIwDqjlhiOwOoV36GchpcVc1yI= github.com/libp2p/go-reuseport v0.0.1 h1:7PhkfH73VXfPJYKQ6JwS5I/eVcoyYi9IMNGc6FWpFLw= github.com/libp2p/go-reuseport v0.0.1/go.mod h1:jn6RmB1ufnQwl0Q1f+YxAj8isJgDCQzaaxIFYDhcYEA= -github.com/libp2p/go-reuseport-transport v0.0.1 h1:UIRneNxLDmEGNjGHpIiWzSWkZ5bhxMCP9x3Vh7BSc7E= github.com/libp2p/go-reuseport-transport v0.0.1/go.mod h1:YkbSDrvjUVDL6b8XqriyA20obEtsW9BLkuOUyQAOCbs= github.com/libp2p/go-reuseport-transport v0.0.2 h1:WglMwyXyBu61CMkjCCtnmqNqnjib0GIEjMiHTwR/KN4= github.com/libp2p/go-reuseport-transport v0.0.2/go.mod h1:YkbSDrvjUVDL6b8XqriyA20obEtsW9BLkuOUyQAOCbs= @@ -564,35 +424,25 @@ github.com/libp2p/go-stream-muxer v0.0.1 h1:Ce6e2Pyu+b5MC1k3eeFtAax0pW4gc6MosYSL github.com/libp2p/go-stream-muxer v0.0.1/go.mod h1:bAo8x7YkSpadMTbtTaxGVHWUQsR/l5MEaHbKaliuT14= github.com/libp2p/go-stream-muxer-multistream v0.1.1 h1:DhHqb4nu1fQv/vQKeLAaZGmhLsUA4SF77IdYJiWE1d4= github.com/libp2p/go-stream-muxer-multistream v0.1.1/go.mod h1:zmGdfkQ1AzOECIAcccoL8L//laqawOsO03zX8Sa+eGw= -github.com/libp2p/go-tcp-transport v0.0.1 h1:WyvJVw2lYAnr6CU+GZZ4oCt06fvORlmvBlFX2+ZpZDM= github.com/libp2p/go-tcp-transport v0.0.1/go.mod h1:mnjg0o0O5TmXUaUIanYPUqkW4+u6mK0en8rlpA6BBTs= -github.com/libp2p/go-tcp-transport v0.0.3 h1:ZDMczeg+6uvvlxnShYFY0wGjQqStFhWAYT7769utxuM= github.com/libp2p/go-tcp-transport v0.0.3/go.mod h1:f11C2zvCaGDkE8aFPUKmuYZwd3pP6HI24LeLMWhJnkQ= github.com/libp2p/go-tcp-transport v0.0.4 h1:2iRu994wCT/iEz62F+c60FUoSkijNEQ0q2Itc+79XlQ= github.com/libp2p/go-tcp-transport v0.0.4/go.mod h1:+E8HvC8ezEVOxIo3V5vCK9l1y/19K427vCzQ+xHKH/o= -github.com/libp2p/go-testutil v0.0.1 h1:Xg+O0G2HIMfHqBOBDcMS1iSZJ3GEcId4qOxCQvsGZHk= github.com/libp2p/go-testutil v0.0.1/go.mod h1:iAcJc/DKJQanJ5ws2V+u5ywdL2n12X1WbbEG+Jjy69I= -github.com/libp2p/go-ws-transport v0.0.1 h1:9ytMqq86Xvp8rcnC/1ZNuH612eXLDglvcu4ZHseJl8s= github.com/libp2p/go-ws-transport v0.0.1/go.mod h1:p3bKjDWHEgtuKKj+2OdPYs5dAPIjtpQGHF2tJfGz7Ww= github.com/libp2p/go-ws-transport v0.0.3/go.mod h1:iU0kzfMcO4tBVIk3z+7srp1YG/RFLWTSuO4enpivw8g= github.com/libp2p/go-ws-transport v0.0.4 h1:3wt9ed0gIUrne627XHvPMTwG4/AUpsLDy4TGQi2EyQ0= github.com/libp2p/go-ws-transport v0.0.4/go.mod h1:X9wfEcm2LAJYMox9x2VHAMHAZZSQMFC9mIa/UF6OuZk= -github.com/libp2p/go-yamux v1.2.1 h1:VumHkMhJ2iFk1lzAeoDRgekiZSylGc6NnAEihVdBCiw= github.com/libp2p/go-yamux v1.2.1/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= -github.com/libp2p/go-yamux v1.2.2 h1:s6J6o7+ajoQMjHe7BEnq+EynOj5D2EoG8CuQgL3F2vg= github.com/libp2p/go-yamux v1.2.2/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= github.com/libp2p/go-yamux v1.2.3 h1:xX8A36vpXb59frIzWFdEgptLMsOANMFq2K7fPRlunYI= github.com/libp2p/go-yamux v1.2.3/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= -github.com/lucas-clemente/aes12 v0.0.0-20171027163421-cd47fb39b79f h1:sSeNEkJrs+0F9TUau0CgWTTNEwF23HST3Eq0A+QIx+A= github.com/lucas-clemente/aes12 v0.0.0-20171027163421-cd47fb39b79f/go.mod h1:JpH9J1c9oX6otFSgdUHwUBUizmKlrMjxWnIAjff4m04= -github.com/lucas-clemente/quic-go v0.10.0 h1:xEF+pSHYAOcu+U10Meunf+DTtc8vhQDRqlA0BJ6hufc= github.com/lucas-clemente/quic-go v0.10.0/go.mod h1:wuD+2XqEx8G9jtwx5ou2BEYBsE+whgQmlj0Vz/77PrY= github.com/lucas-clemente/quic-go v0.11.1 h1:zasajC848Dqq/+WqfqBCkmPw+YHNe1MBts/z7y7nXf4= github.com/lucas-clemente/quic-go v0.11.1/go.mod h1:PpMmPfPKO9nKJ/psF49ESTAGQSdfXxlg1otPbEB2nOw= -github.com/lucas-clemente/quic-go-certificates v0.0.0-20160823095156-d2f86524cced h1:zqEC1GJZFbGZA0tRyNZqRjep92K5fujFtFsu5ZW7Aug= github.com/lucas-clemente/quic-go-certificates v0.0.0-20160823095156-d2f86524cced/go.mod h1:NCcRLrOTZbzhZvixZLlERbJtDtYsmMw8Jc4vS8Z0g58= -github.com/magiconair/properties v1.7.6 h1:U+1DqNen04MdEPgFiIwdOUiqZ8qPa37xgogX/sd3+54= github.com/magiconair/properties v1.7.6/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/marten-seemann/qtls v0.2.3 h1:0yWJ43C62LsZt08vuQJDK1uC1czUc3FJeCLPoNAI4vA= github.com/marten-seemann/qtls v0.2.3/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk= @@ -600,45 +450,36 @@ github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaO github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/goveralls v0.0.2 h1:7eJB6EqsPhRVxvwEXGnqdO2sJI0PTsrWoTMXEk9/OQc= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= -github.com/miekg/dns v1.1.4 h1:rCMZsU2ScVSYcAsOXgmC6+AKOK+6pmQTOcw03nfwYV0= github.com/miekg/dns v1.1.4/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.12 h1:WMhc1ik4LNkTg8U9l3hI1LvxKmIL+f1+WV/SZtCbDDA= github.com/miekg/dns v1.1.12/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= -github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16 h1:5W7KhL8HVF3XCFOweFD3BNESdnO8ewyYTFT2R+/b8FQ= github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5 h1:l16XLUUJ34wIz+RIvLhSwGvLvKyy+W598b135bJN6mg= github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-ps v0.0.0-20170309133038-4fdf99ab2936 h1:kw1v0NlnN+GZcU8Ma8CLF2Zzgjfx95gs3/GN3vYAPpo= github.com/mitchellh/go-ps v0.0.0-20170309133038-4fdf99ab2936/go.mod h1:r1VsdOzOPt1ZSrGZWFoNhsAedKnEd6r9Np1+5blZCWk= -github.com/mitchellh/mapstructure v0.0.0-20180220230111-00c29f56e238 h1:+MZW2uvHgN8kYvksEN3f7eFL2wpzk0GxmlFsMybWc7E= github.com/mitchellh/mapstructure v0.0.0-20180220230111-00c29f56e238/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mozilla/tls-observatory v0.0.0-20180409132520-8791a200eb40/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk= -github.com/mr-tron/base58 v1.1.0 h1:Y51FGVJ91WBqCEabAi5OPUz38eAx8DakuAm5svLcsfQ= github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= github.com/mr-tron/base58 v1.1.2 h1:ZEw4I2EgPKDJ2iEw0cNmLB3ROrEmkOtXIkaG7wZg+78= github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/multiformats/go-base32 v0.0.3 h1:tw5+NhuwaOjJCC5Pp82QuXbrmLzWg7uxlMFp8Nq/kkI= github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= -github.com/multiformats/go-multiaddr v0.0.1 h1:/QUV3VBMDI6pi6xfiw7lr6xhDWWvQKn9udPn68kLSdY= github.com/multiformats/go-multiaddr v0.0.1/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= -github.com/multiformats/go-multiaddr v0.0.2 h1:RBysRCv5rv3FWlhKWKoXv8tnsCUpEpIZpCmqAGZos2s= github.com/multiformats/go-multiaddr v0.0.2/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= github.com/multiformats/go-multiaddr v0.0.4 h1:WgMSI84/eRLdbptXMkMWDXPjPq7SPLIgGUVm2eroyU4= github.com/multiformats/go-multiaddr v0.0.4/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= @@ -651,63 +492,48 @@ github.com/multiformats/go-multibase v0.0.1 h1:PN9/v21eLywrFWdFNsFKaU04kLJzuYzmr github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= github.com/multiformats/go-multicodec v0.1.6 h1:4u6lcjbE4VVVoigU4QJSSVYsGVP4j2jtDkR8lPwOrLE= github.com/multiformats/go-multicodec v0.1.6/go.mod h1:lliaRHbcG8q33yf4Ot9BGD7JqR/Za9HE7HTyVyKwrUQ= -github.com/multiformats/go-multihash v0.0.1 h1:HHwN1K12I+XllBCrqKnhX949Orn4oawPkegHMu2vDqQ= github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= github.com/multiformats/go-multihash v0.0.5 h1:1wxmCvTXAifAepIMyF39vZinRw5sbqjPs/UIi93+uik= github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po= -github.com/multiformats/go-multistream v0.0.1 h1:JV4VfSdY9n7ECTtY59/TlSyFCzRILvYx4T4Ws8ZgihU= github.com/multiformats/go-multistream v0.0.1/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= github.com/multiformats/go-multistream v0.0.4 h1:rNgWgFyzRSTI9L+xISrz7kN5MdNXoEcoIeeCH05wLKA= github.com/multiformats/go-multistream v0.0.4/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223 h1:F9x/1yl3T2AeKLr2AMdilSD8+f9bvMnNN8VS5iDtovc= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nbutton23/zxcvbn-go v0.0.0-20160627004424-a22cb81b2ecd/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU= -github.com/nbutton23/zxcvbn-go v0.0.0-20171102151520-eafdab6b0663 h1:Ri1EhipkbhWsffPJ3IPlrb4SkTOPa2PfRXp3jchBczw= github.com/nbutton23/zxcvbn-go v0.0.0-20171102151520-eafdab6b0663/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/opentracing/opentracing-go v1.0.2 h1:3jA2P6O1F9UOrWVpwrIo17pu01KWvNWg4X946/Y5Zwg= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= -github.com/pelletier/go-toml v1.1.0 h1:cmiOvKzEunMsAxyhXSzpL5Q1CRKpVv0KQsnAIcSEVYM= github.com/pelletier/go-toml v1.1.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/polydawn/refmt v0.0.0-20190221155625-df39d6c2d992 h1:bzMe+2coZJYHnhGgVlcQKuRy4FSny4ds8dLQjw5P1XE= github.com/polydawn/refmt v0.0.0-20190221155625-df39d6c2d992/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.2 h1:awm861/B8OKDd2I/6o1dy3ra4BamzKhYOiGItCeZ740= github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= github.com/prometheus/client_golang v0.9.3 h1:9iH4JKXLzFbOAdtqv/a+j8aewx2Y8lAjAydhbaScPF8= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.0.0-20181126121408-4724e9255275 h1:PnBWHBf+6L0jOqq0gIVUe6Yk0/QMZ640k6NvkxcBf+8= github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0 h1:7etb9YClo3a6HjLzfl6rIQaU+FDfi0VSX39io3aQ+DM= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a h1:9a8MnZMP0X2nLJdBg+pBmGgkJlSaKC2KaQmTCk1XDtE= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.0-20190519111021-9935e8e0588d h1:Z5QMcUKnQw7ouB1wDuyZM6TL/rm+brJcNk6Ai8ut3zM= @@ -718,54 +544,34 @@ github.com/rs/cors v1.6.0 h1:G9tHG9lebljV9mfp9SNPDL36nCDxmo3zTlAf1YgvzmI= github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/shirou/gopsutil v0.0.0-20180427012116-c95755e4bcd7/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 h1:udFKJ0aHUL60LboW/A+DfgoHVedieIzIXE8uylPue0U= github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc= -github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e h1:MZM7FHLqUHYI0Y/mQAt3d2aYa0SiNms/hFqC9qJYolM= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= -github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041 h1:llrF3Fs4018ePo4+G/HV/uQUqEI1HMDjCeOf2V6puPc= github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= -github.com/sirupsen/logrus v1.0.5 h1:8c8b5uO0zS4X6RPl/sd1ENwSkIc0/H2PaHxE3udaE8I= github.com/sirupsen/logrus v1.0.5/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= -github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v0.0.0-20190222223459-a17d461953aa h1:E+gaaifzi2xF65PbDmuKI3PhLWY6G5opMLniFq8vmXA= github.com/smartystreets/goconvey v0.0.0-20190222223459-a17d461953aa/go.mod h1:2RVY1rIf+2J2o/IM9+vPq9RzmHDSseB7FoXiSNIUsoU= -github.com/sourcegraph/go-diff v0.5.1 h1:gO6i5zugwzo1RVTvgvfwCOSVegNuvnNi6bAD1QCmkHs= github.com/sourcegraph/go-diff v0.5.1/go.mod h1:j2dHj3m8aZgQO8lMTcTnBcXkRRRqi34cd2MNlA9u1mE= -github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a h1:/eS3yfGjQKG+9kayBkj0ip1BGhq6zJ3eaVksphxAaek= github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0= -github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.0 h1:bopulORc2JeYaxfHLvJa5NzxviA9PoWhpiiJkru7Ji4= github.com/spf13/afero v1.1.0/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/cast v1.2.0 h1:HHl1DSRbEQN2i8tJmtS6ViPyHx35+p51amrdsiTCrkg= github.com/spf13/cast v1.2.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg= -github.com/spf13/cobra v0.0.2 h1:NfkwRbgViGoyjBKsLI0QMDcuMnhM+SBg3T0cGfpvKDE= github.com/spf13/cobra v0.0.2/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/jwalterweatherman v0.0.0-20180109140146-7c0cea34c8ec h1:2ZXvIUGghLpdTVHR1UfvfrzoVlZaE/yOWC5LueIHZig= github.com/spf13/jwalterweatherman v0.0.0-20180109140146-7c0cea34c8ec/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v1.0.1 h1:aCvUg6QPl3ibpQUxyLkrEkCHtPqYJL4x9AuhqVqFis4= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/viper v1.0.2 h1:Ncr3ZIuJn322w2k1qmzXDnkLAdQMlJqBa9kfAH+irso= github.com/spf13/viper v1.0.2/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e h1:T5PdfK/M1xyrHwynxMIVMWLS7f/qHwfslZphxtGnw7s= github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e/go.mod h1:XDKHRm5ThF8YJjx001LtgelzsoaEcvnA7lVWz9EeX3g= -github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/warpfork/go-wish v0.0.0-20180510122957-5ad1f5abf436 h1:qOpVTI+BrstcjTZLm2Yz/3sOnqkzj3FQoh0g+E5s3Gc= github.com/warpfork/go-wish v0.0.0-20180510122957-5ad1f5abf436/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc h1:BCPnHtcboadS0DvysUuJXZ4lWVv5Bh5i7+tbIyi+ck4= github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc/go.mod h1:r45hJU7yEoA81k6MWNhpMj/kms0n14dkzkxYHoB96UM= @@ -773,7 +579,6 @@ github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11 h1:5HZfQkwe0mIf github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11/go.mod h1:Wlo/SzPmxVp6vXpGt/zaXhHH0fn4IxgqZc82aKg6bpQ= github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f h1:jQa4QT2UP9WYv2nzyawpKMOCl+Z/jW7djv2/J50lj9E= github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f/go.mod h1:p9UJB6dDgdPgMJZs7UjUOdulKyRr9fqkS+6JKAInPy8= -github.com/whyrusleeping/go-ctrlnet v0.0.0-20180313164037-f564fbbdaa95 h1:c23eYhe7i8MG6dUSPzyIDDy5+cWOoZMovPamBKqrjYQ= github.com/whyrusleeping/go-ctrlnet v0.0.0-20180313164037-f564fbbdaa95/go.mod h1:SJqKCCPXRfBFCwXjfNT/skfsceF7+MBFLI2OrvuRA7g= github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 h1:EKhdznlJHPMoKr0XTrX+IlJs1LH3lyx2nfr1dOlZ79k= github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc= @@ -782,15 +587,11 @@ github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1 github.com/whyrusleeping/go-notifier v0.0.0-20170827234753-097c5d47330f h1:M/lL30eFZTKnomXY6huvM6G0+gVquFNf6mxghaWlFUg= github.com/whyrusleeping/go-notifier v0.0.0-20170827234753-097c5d47330f/go.mod h1:cZNvX9cFybI01GriPRMXDtczuvUhgbcYr9iCGaNlRv8= github.com/whyrusleeping/go-smux-multiplex v0.1.0/go.mod h1:OXL5hggHNZSsadXDlBJDD4eD3IQYEB3Yu6xpovd6pPw= -github.com/whyrusleeping/go-smux-multiplex v3.0.16+incompatible h1:iqksILj8STw03EJQe7Laj4ubnw+ojOyik18cd5vPL1o= github.com/whyrusleeping/go-smux-multiplex v3.0.16+incompatible/go.mod h1:34LEDbeKFZInPUrAG+bjuJmUXONGdEFW7XL0SpTY1y4= github.com/whyrusleeping/go-smux-multistream v0.1.0/go.mod h1:/usW3LIBirW4h9ko1PnoF7tExBnbxPBszG0n4wylJr8= -github.com/whyrusleeping/go-smux-multistream v2.0.2+incompatible h1:BdYHctE9HJZLquG9tpTdwWcbG4FaX6tVKPGjCGgiVxo= github.com/whyrusleeping/go-smux-multistream v2.0.2+incompatible/go.mod h1:dRWHHvc4HDQSHh9gbKEBbUZ+f2Q8iZTPG3UOGYODxSQ= github.com/whyrusleeping/go-smux-yamux v0.1.1/go.mod h1:Yw+ayOEKERDHXLJ4GiE5AnBmldJW4QRLDzGFC9do8G0= -github.com/whyrusleeping/go-smux-yamux v2.0.8+incompatible h1:IGm/UP/JpEFS6D787sZnZg7RA6fZIR9c/Ms9DeAVNuk= github.com/whyrusleeping/go-smux-yamux v2.0.8+incompatible/go.mod h1:6qHUzBXUbB9MXmw3AUdB52L8sEb/hScCqOdW2kj/wuI= -github.com/whyrusleeping/go-smux-yamux v2.0.9+incompatible h1:nVkExQ7pYlN9e45LcqTCOiDD0904fjtm0flnHZGbXkw= github.com/whyrusleeping/go-smux-yamux v2.0.9+incompatible/go.mod h1:6qHUzBXUbB9MXmw3AUdB52L8sEb/hScCqOdW2kj/wuI= github.com/whyrusleeping/go-sysinfo v0.0.0-20190219211824-4a357d4b90b1 h1:ctS9Anw/KozviCCtK6VWMz5kPL9nbQzbQY4yfqlIV4M= github.com/whyrusleeping/go-sysinfo v0.0.0-20190219211824-4a357d4b90b1/go.mod h1:tKH72zYNt/exx6/5IQO6L9LoQ0rEjd5SbbWaDTs9Zso= @@ -804,9 +605,7 @@ github.com/whyrusleeping/tar-utils v0.0.0-20180509141711-8c6c8ba81d5c h1:GGsyl0d github.com/whyrusleeping/tar-utils v0.0.0-20180509141711-8c6c8ba81d5c/go.mod h1:xxcJeBb7SIUl/Wzkz1eVKJE/CB34YNrqX2TQI6jY9zs= github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee h1:lYbXeSvJi5zk5GLKVuid9TVjS9a0OmLIDKTfoZBL6Ow= github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee/go.mod h1:m2aV4LZI4Aez7dP5PMyVKEHhUyEJ/RjmPEDOpDvudHg= -github.com/whyrusleeping/yamux v1.1.5 h1:4CK3aUUJQu0qpKZv5gEWJjNOQtdbdDhVVS6PJ+HimdE= github.com/whyrusleeping/yamux v1.1.5/go.mod h1:E8LnQQ8HKx5KD29HZFUwM1PxCOdPRzGwur1mcYhXcD8= -github.com/whyrusleeping/yamux v1.2.0 h1:PzUrk7/Z0g/N5V4/+DesmKXYcCToALgj+SbATgs0B34= github.com/whyrusleeping/yamux v1.2.0/go.mod h1:Cgw3gpb4DrDZ1FrP/5pxg/cpiY54Gr5uCXwUylwi2GE= go.opencensus.io v0.21.0 h1:mU6zScU4U1YAFPHEHYk+3JC4SY7JxgkqS10ZOSyksNg= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= @@ -816,11 +615,9 @@ go.uber.org/dig v1.7.0 h1:E5/L92iQTNJTjfgJF2KgU+/JpMaiuvK2DHLBj0+kSZk= go.uber.org/dig v1.7.0/go.mod h1:z+dSd2TP9Usi48jL8M3v63iSBVkiwtVyMKxMZYYauPg= go.uber.org/fx v1.9.0 h1:7OAz8ucp35AU8eydejpYG7QrbE8rLKzGhHbZlJi5LYY= go.uber.org/fx v1.9.0/go.mod h1:mFdUyAUuJ3w4jAckiKSKbldsxy1ojpAMJ+dVZg5Y0Aw= -go.uber.org/goleak v0.10.0 h1:G3eWbSNIskeRqtsN/1uI5B+eP73y3JUuBsv9AZjehb4= go.uber.org/goleak v0.10.0/go.mod h1:VCZuO8V8mFPlL0F5J5GK1rtHV3DrFcQ1R8ryq7FK0aI= go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go4.org v0.0.0-20190218023631-ce4c26f7be8e h1:m9LfARr2VIOW0vsV19kEKp/sWQvZnGobA8JHui/XJoY= go4.org v0.0.0-20190218023631-ce4c26f7be8e/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= go4.org v0.0.0-20190313082347-94abd6928b1d h1:JkRdGP3zvTtTbabWSAC6n67ka30y7gOzWAah4XYJSfw= go4.org v0.0.0-20190313082347-94abd6928b1d/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= @@ -829,12 +626,9 @@ golang.org/x/crypto v0.0.0-20180426230345-b49d69b5da94/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25 h1:jsG6UpNLt9iAsb0S2AGW28DveNzzgmbXR+ENoPjUeIU= golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734 h1:p/H982KKEjUnLJkM3tt/LemDnOc1GiZL5FCVlORJ5zo= golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f h1:R423Cnkcp5JABoeemiGEPlt9tHXFfw5kvc0yqlxRPWo= golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -852,11 +646,8 @@ golang.org/x/net v0.0.0-20181102091132-c10e9556a7bc/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190227160552-c95aed5357e7 h1:C2F/nMkR/9sfUTpvR3QrjBuTdvMUC/cFajkphs1YLQo= golang.org/x/net v0.0.0-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190310074541-c10a0554eabf h1:J7RqX9u0J9ZB37CGaFc2VC+QZZT6E6jnDbrboEFVo0U= golang.org/x/net v0.0.0-20190310074541-c10a0554eabf/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -864,12 +655,9 @@ golang.org/x/net v0.0.0-20190522135303-fa69b94a3b58 h1:AZ8FNE2w7DVDFDK6u/iC9/Mqh golang.org/x/net v0.0.0-20190522135303-fa69b94a3b58/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f h1:Bl/8QSvNqXvPGPGXa2z5xUTmV7VDcZyvRZ+QQXkXTZQ= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20171026204733-164713f0dfce/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -881,7 +669,6 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190302025703-b6889370fb10 h1:xQJI9OEiErEQ++DoXOHqEpzsGMrAv2Q2jyCpi7DmfpQ= golang.org/x/sys v0.0.0-20190302025703-b6889370fb10/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190310054646-10058d7d4faa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -889,14 +676,11 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5 h1:f005F/Jl5JLP036x7QIvUVhNTqxvSYwFIiyOh2q12iU= golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.0.0-20170915090833-1cbadb444a80/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2 h1:z99zHgr7hKfrUcX/KsoJk5FJfjTceCKIp96+biqP4To= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/tools v0.0.0-20170915040203-e531a2a1c15f/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635 h1:2eB4G6bDQDeP69ZXbOKC00S2Kf6TIiRS+DzfKsKeQU0= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181024171208-a2dc47679d30/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -908,51 +692,33 @@ golang.org/x/tools v0.0.0-20190121143147-24cd39ecf745/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190420000508-685fecacd0a0/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190521203540-521d6ed310dd h1:7E3PabyysDSEjnaANKBgums/hyvMI/HoHQ50qZEzTrg= golang.org/x/tools v0.0.0-20190521203540-521d6ed310dd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/xerrors v0.0.0-20190212162355-a5947ffaace3 h1:P6iTFmrTQqWrqLZPX1VMzCUbCRCAUXSUsSpkEOvWzJ0= golang.org/x/xerrors v0.0.0-20190212162355-a5947ffaace3/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522 h1:bhOzK9QyoD0ogCnFro1m2mz41+Ib0oOhfJnBp5MR4K4= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -gopkg.in/airbrake/gobrake.v2 v2.0.9 h1:7z2uVWwn7oVeeugY1DtlPAy5H+KYgB1KeKTnqjNatLo= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= -gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/cheggaaa/pb.v1 v1.0.28 h1:n1tBJnnK2r7g9OW2btFH91V92STTUevLXYFb8gy9EMk= gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= -gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 h1:OAj3g0cR6Dx/R07QgQe8wkA9RNjB2u4i700xBkIT4e0= gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= -gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gotest.tools v2.1.0+incompatible h1:5USw7CrJBYKqjg9R7QlA6jzqZKEAtvW82aNmsxxGPxw= gotest.tools v2.1.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= -gotest.tools/gotestsum v0.3.4 h1:LdVJDg3RHrci4MbupUgSkwPCikz4kTzDHWtUahDAleY= gotest.tools/gotestsum v0.3.4/go.mod h1:Mnf3e5FUzXbkCfynWBGOwLssY7gTQgCHObK9tMpAriY= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed h1:WX1yoOaKQfddO/mLzdV4wptyWgoH/6hwLs7QHTixo0I= mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc= -mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphDJbHOQO1DFFFTeBo= mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= -mvdan.cc/unparam v0.0.0-20190124213536-fbb59629db34 h1:B1LAOfRqg2QUyCdzfjf46quTSYUTAK5OCwbh6pljHbM= mvdan.cc/unparam v0.0.0-20190124213536-fbb59629db34/go.mod h1:H6SUd1XjIs+qQCyskXg5OFSrilMRUkD8ePJpHKDPaeY= -sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4 h1:JPJh2pk3+X4lXAkZIk2RuE/7/FoK9maXw+TNPJhVS/c= sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= diff --git a/provider/offline.go b/provider/offline.go index 0c91ed2af77..eb1d1b9acda 100644 --- a/provider/offline.go +++ b/provider/offline.go @@ -1,20 +1,28 @@ package provider -import "github.com/ipfs/go-cid" +import ( + "context" + "github.com/ipfs/go-cid" +) type offlineProvider struct{} -// NewOfflineProvider creates a Provider that does nothing -func NewOfflineProvider() Provider { +// NewOfflineProvider creates a ProviderSystem that does nothing +func NewOfflineProvider() System { return &offlineProvider{} } -func (op *offlineProvider) Run() {} +func (op *offlineProvider) Run() { +} -func (op *offlineProvider) Provide(cid cid.Cid) error { +func (op *offlineProvider) Close() error { return nil } -func (op *offlineProvider) Close() error { +func (op *offlineProvider) Provide(_ cid.Cid) error { + return nil +} + +func (op *offlineProvider) Reprovide(_ context.Context) error { return nil } diff --git a/provider/provider.go b/provider/provider.go index 67c5c6b6b92..e8939ba6f7f 100644 --- a/provider/provider.go +++ b/provider/provider.go @@ -1,18 +1,18 @@ -// Package provider implements structures and methods to provide blocks, -// keep track of which blocks are provided, and to allow those blocks to -// be reprovided. package provider import ( "context" "github.com/ipfs/go-cid" logging "github.com/ipfs/go-log" - "github.com/libp2p/go-libp2p-routing" ) -var log = logging.Logger("provider") +var ( + // StrategicProvidingEnabled toggles between the original providing mechanism + // and the new strategic providing system + StrategicProvidingEnabled = false -const provideOutgoingWorkerLimit = 8 + log = logging.Logger("provider") +) // Provider announces blocks to the network type Provider interface { @@ -24,56 +24,10 @@ type Provider interface { Close() error } -type provider struct { - ctx context.Context - // the CIDs for which provide announcements should be made - queue *Queue - // used to announce providing to the network - contentRouting routing.ContentRouting -} - -// NewProvider creates a provider that announces blocks to the network using a content router -func NewProvider(ctx context.Context, queue *Queue, contentRouting routing.ContentRouting) Provider { - return &provider{ - ctx: ctx, - queue: queue, - contentRouting: contentRouting, - } -} - -// Close stops the provider -func (p *provider) Close() error { - p.queue.Close() - return nil -} - -// Start workers to handle provide requests. -func (p *provider) Run() { - p.handleAnnouncements() -} - -// Provide the given cid using specified strategy. -func (p *provider) Provide(root cid.Cid) error { - p.queue.Enqueue(root) - return nil -} - -// Handle all outgoing cids by providing (announcing) them -func (p *provider) handleAnnouncements() { - for workers := 0; workers < provideOutgoingWorkerLimit; workers++ { - go func() { - for p.ctx.Err() == nil { - select { - case <-p.ctx.Done(): - return - case c := <-p.queue.Dequeue(): - log.Info("announce - start - ", c) - if err := p.contentRouting.Provide(p.ctx, c, true); err != nil { - log.Warningf("Unable to provide entry: %s, %s", c, err) - } - log.Info("announce - end - ", c) - } - } - }() - } +// Reprovider reannounces blocks to the network +type Reprovider interface { + // Run is used to begin processing the reprovider work and waiting for reprovide triggers + Run() + // Trigger a reprovide + Trigger(context.Context) error } diff --git a/provider/queue.go b/provider/queue/queue.go similarity index 98% rename from provider/queue.go rename to provider/queue/queue.go index 8fdfca81521..2afbc81ee9b 100644 --- a/provider/queue.go +++ b/provider/queue/queue.go @@ -1,4 +1,4 @@ -package provider +package queue import ( "context" @@ -10,8 +10,11 @@ import ( datastore "github.com/ipfs/go-datastore" namespace "github.com/ipfs/go-datastore/namespace" query "github.com/ipfs/go-datastore/query" + logging "github.com/ipfs/go-log" ) +var log = logging.Logger("provider.queue") + // Queue provides a durable, FIFO interface to the datastore for storing cids // // Durability just means that cids in the process of being provided when a diff --git a/provider/queue_test.go b/provider/queue/queue_test.go similarity index 96% rename from provider/queue_test.go rename to provider/queue/queue_test.go index e151478d9f3..c8fb8682e31 100644 --- a/provider/queue_test.go +++ b/provider/queue/queue_test.go @@ -1,4 +1,4 @@ -package provider +package queue import ( "context" @@ -8,8 +8,11 @@ import ( cid "github.com/ipfs/go-cid" datastore "github.com/ipfs/go-datastore" sync "github.com/ipfs/go-datastore/sync" + "github.com/ipfs/go-ipfs-blocksutil" ) +var blockGenerator = blocksutil.NewBlockGenerator() + func makeCids(n int) []cid.Cid { cids := make([]cid.Cid, 0, n) for i := 0; i < n; i++ { diff --git a/provider/simple/provider.go b/provider/simple/provider.go new file mode 100644 index 00000000000..8310cebb3a4 --- /dev/null +++ b/provider/simple/provider.go @@ -0,0 +1,72 @@ +// Package simple implements structures and methods to provide blocks, +// keep track of which blocks are provided, and to allow those blocks to +// be reprovided. +package simple + +import ( + "context" + + cid "github.com/ipfs/go-cid" + q "github.com/ipfs/go-ipfs/provider/queue" + logging "github.com/ipfs/go-log" + routing "github.com/libp2p/go-libp2p-routing" +) + +var logP = logging.Logger("provider.simple") + +const provideOutgoingWorkerLimit = 8 + +// Provider announces blocks to the network +type Provider struct { + ctx context.Context + // the CIDs for which provide announcements should be made + queue *q.Queue + // used to announce providing to the network + contentRouting routing.ContentRouting +} + +// NewProvider creates a provider that announces blocks to the network using a content router +func NewProvider(ctx context.Context, queue *q.Queue, contentRouting routing.ContentRouting) *Provider { + return &Provider{ + ctx: ctx, + queue: queue, + contentRouting: contentRouting, + } +} + +// Close stops the provider +func (p *Provider) Close() error { + p.queue.Close() + return nil +} + +// Run workers to handle provide requests. +func (p *Provider) Run() { + p.handleAnnouncements() +} + +// Provide the given cid using specified strategy. +func (p *Provider) Provide(root cid.Cid) error { + p.queue.Enqueue(root) + return nil +} + +// Handle all outgoing cids by providing (announcing) them +func (p *Provider) handleAnnouncements() { + for workers := 0; workers < provideOutgoingWorkerLimit; workers++ { + go func() { + for p.ctx.Err() == nil { + select { + case <-p.ctx.Done(): + return + case c := <-p.queue.Dequeue(): + logP.Info("announce - start - ", c) + if err := p.contentRouting.Provide(p.ctx, c, true); err != nil { + logP.Warningf("Unable to provide entry: %s, %s", c, err) + } + logP.Info("announce - end - ", c) + } + } + }() + } +} diff --git a/provider/provider_test.go b/provider/simple/provider_test.go similarity index 86% rename from provider/provider_test.go rename to provider/simple/provider_test.go index 7ef007b03a7..6f70a41d722 100644 --- a/provider/provider_test.go +++ b/provider/simple/provider_test.go @@ -1,4 +1,4 @@ -package provider +package simple_test import ( "context" @@ -11,6 +11,10 @@ import ( sync "github.com/ipfs/go-datastore/sync" blocksutil "github.com/ipfs/go-ipfs-blocksutil" pstore "github.com/libp2p/go-libp2p-peerstore" + + q "github.com/ipfs/go-ipfs/provider/queue" + + . "github.com/ipfs/go-ipfs/provider/simple" ) var blockGenerator = blocksutil.NewBlockGenerator() @@ -39,15 +43,15 @@ func TestAnnouncement(t *testing.T) { defer ctx.Done() ds := sync.MutexWrap(datastore.NewMapDatastore()) - queue, err := NewQueue(ctx, "test", ds) + queue, err := q.NewQueue(ctx, "test", ds) if err != nil { t.Fatal(err) } r := mockContentRouting() - provider := NewProvider(ctx, queue, r) - provider.Run() + prov := NewProvider(ctx, queue, r) + prov.Run() cids := cid.NewSet() @@ -58,7 +62,7 @@ func TestAnnouncement(t *testing.T) { go func() { for _, c := range cids.Keys() { - err = provider.Provide(c) + err = prov.Provide(c) // A little goroutine stirring to exercise some different states r := rand.Intn(10) time.Sleep(time.Microsecond * time.Duration(r)) diff --git a/provider/simple/reprovide.go b/provider/simple/reprovide.go new file mode 100644 index 00000000000..73b733ce24a --- /dev/null +++ b/provider/simple/reprovide.go @@ -0,0 +1,225 @@ +package simple + +import ( + "context" + "fmt" + "time" + + backoff "github.com/cenkalti/backoff" + cid "github.com/ipfs/go-cid" + cidutil "github.com/ipfs/go-cidutil" + blocks "github.com/ipfs/go-ipfs-blockstore" + pin "github.com/ipfs/go-ipfs/pin" + ipld "github.com/ipfs/go-ipld-format" + logging "github.com/ipfs/go-log" + merkledag "github.com/ipfs/go-merkledag" + verifcid "github.com/ipfs/go-verifcid" + routing "github.com/libp2p/go-libp2p-routing" +) + +var logR = logging.Logger("reprovider.simple") + +//KeyChanFunc is function streaming CIDs to pass to content routing +type KeyChanFunc func(context.Context) (<-chan cid.Cid, error) +type doneFunc func(error) + +// Reprovider reannounces blocks to the network +type Reprovider struct { + ctx context.Context + trigger chan doneFunc + + // The routing system to provide values through + rsys routing.ContentRouting + + keyProvider KeyChanFunc + + tick time.Duration +} + +// NewReprovider creates new Reprovider instance. +func NewReprovider(ctx context.Context, reprovideIniterval time.Duration, rsys routing.ContentRouting, keyProvider KeyChanFunc) *Reprovider { + return &Reprovider{ + ctx: ctx, + trigger: make(chan doneFunc), + + rsys: rsys, + keyProvider: keyProvider, + tick: reprovideIniterval, + } +} + +// Close the reprovider +func (rp *Reprovider) Close() error { + return nil +} + +// Run re-provides keys with 'tick' interval or when triggered +func (rp *Reprovider) Run() { + // dont reprovide immediately. + // may have just started the daemon and shutting it down immediately. + // probability( up another minute | uptime ) increases with uptime. + after := time.After(time.Minute) + var done doneFunc + for { + if rp.tick == 0 { + after = make(chan time.Time) + } + + select { + case <-rp.ctx.Done(): + return + case done = <-rp.trigger: + case <-after: + } + + //'mute' the trigger channel so when `ipfs bitswap reprovide` is called + //a 'reprovider is already running' error is returned + unmute := rp.muteTrigger() + + err := rp.Reprovide() + if err != nil { + logR.Debug(err) + } + + if done != nil { + done(err) + } + + unmute() + + after = time.After(rp.tick) + } +} + +// Reprovide registers all keys given by rp.keyProvider to libp2p content routing +func (rp *Reprovider) Reprovide() error { + keychan, err := rp.keyProvider(rp.ctx) + if err != nil { + return fmt.Errorf("failed to get key chan: %s", err) + } + for c := range keychan { + // hash security + if err := verifcid.ValidateCid(c); err != nil { + logR.Errorf("insecure hash in reprovider, %s (%s)", c, err) + continue + } + op := func() error { + err := rp.rsys.Provide(rp.ctx, c, true) + if err != nil { + logR.Debugf("Failed to provide key: %s", err) + } + return err + } + + // TODO: this backoff library does not respect our context, we should + // eventually work contexts into it. low priority. + err := backoff.Retry(op, backoff.NewExponentialBackOff()) + if err != nil { + logR.Debugf("Providing failed after number of retries: %s", err) + return err + } + } + return nil +} + +// Trigger starts reprovision process in rp.Run and waits for it +func (rp *Reprovider) Trigger(ctx context.Context) error { + progressCtx, done := context.WithCancel(ctx) + + var err error + df := func(e error) { + err = e + done() + } + + select { + case <-rp.ctx.Done(): + return context.Canceled + case <-ctx.Done(): + return context.Canceled + case rp.trigger <- df: + <-progressCtx.Done() + return err + } +} + +func (rp *Reprovider) muteTrigger() context.CancelFunc { + ctx, cf := context.WithCancel(rp.ctx) + go func() { + defer cf() + for { + select { + case <-ctx.Done(): + return + case done := <-rp.trigger: + done(fmt.Errorf("reprovider is already running")) + } + } + }() + + return cf +} + +// Strategies + +// NewBlockstoreProvider returns key provider using bstore.AllKeysChan +func NewBlockstoreProvider(bstore blocks.Blockstore) KeyChanFunc { + return func(ctx context.Context) (<-chan cid.Cid, error) { + return bstore.AllKeysChan(ctx) + } +} + +// NewPinnedProvider returns provider supplying pinned keys +func NewPinnedProvider(onlyRoots bool) func(pin.Pinner, ipld.DAGService) KeyChanFunc { + return func(pinning pin.Pinner, dag ipld.DAGService) KeyChanFunc { + return func(ctx context.Context) (<-chan cid.Cid, error) { + set, err := pinSet(ctx, pinning, dag, onlyRoots) + if err != nil { + return nil, err + } + + outCh := make(chan cid.Cid) + go func() { + defer close(outCh) + for c := range set.New { + select { + case <-ctx.Done(): + return + case outCh <- c: + } + } + + }() + + return outCh, nil + } + } +} + +func pinSet(ctx context.Context, pinning pin.Pinner, dag ipld.DAGService, onlyRoots bool) (*cidutil.StreamingSet, error) { + set := cidutil.NewStreamingSet() + + go func() { + ctx, cancel := context.WithCancel(ctx) + defer cancel() + defer close(set.New) + + for _, key := range pinning.DirectKeys() { + set.Visitor(ctx)(key) + } + + for _, key := range pinning.RecursiveKeys() { + set.Visitor(ctx)(key) + + if !onlyRoots { + err := merkledag.EnumerateChildren(ctx, merkledag.GetLinksWithDAG(dag), key, set.Visitor(ctx)) + if err != nil { + logR.Errorf("reprovide indirect pins: %s", err) + return + } + } + } + }() + + return set, nil +} diff --git a/reprovide/reprovide_test.go b/provider/simple/reprovide_test.go similarity index 85% rename from reprovide/reprovide_test.go rename to provider/simple/reprovide_test.go index b9e9738b440..17c626c5b9e 100644 --- a/reprovide/reprovide_test.go +++ b/provider/simple/reprovide_test.go @@ -1,16 +1,19 @@ -package reprovide +package simple_test import ( "context" "testing" + "time" blocks "github.com/ipfs/go-block-format" ds "github.com/ipfs/go-datastore" dssync "github.com/ipfs/go-datastore/sync" - blockstore "github.com/ipfs/go-ipfs-blockstore" + "github.com/ipfs/go-ipfs-blockstore" mock "github.com/ipfs/go-ipfs-routing/mock" pstore "github.com/libp2p/go-libp2p-peerstore" "github.com/libp2p/go-testutil" + + . "github.com/ipfs/go-ipfs/provider/simple" ) func TestReprovide(t *testing.T) { @@ -34,8 +37,8 @@ func TestReprovide(t *testing.T) { } keyProvider := NewBlockstoreProvider(bstore) - reprov := NewReprovider(ctx, 0, clA, keyProvider) - err = reprov.reprovide(ctx) + reprov := NewReprovider(ctx, time.Hour, clA, keyProvider) + err = reprov.Reprovide() if err != nil { t.Fatal(err) } diff --git a/provider/system.go b/provider/system.go new file mode 100644 index 00000000000..6bc1d357cbc --- /dev/null +++ b/provider/system.go @@ -0,0 +1,47 @@ +package provider + +import ( + "context" + "github.com/ipfs/go-cid" +) + +// System defines the interface for interacting with the value +// provider system +type System interface { + Run() + Close() error + Provide(cid.Cid) error + Reprovide(context.Context) error +} + +type system struct { + provider Provider + reprovider Reprovider +} + +// NewSystem constructs a new provider system from a provider and reprovider +func NewSystem(provider Provider, reprovider Reprovider) System { + return &system{provider, reprovider} +} + +// Run the provider system by running the provider and reprovider +func (s *system) Run() { + go s.provider.Run() + go s.reprovider.Run() +} + +// Close the provider and reprovider +func (s *system) Close() error { + // TODO: Close reprovider here + return s.provider.Close() +} + +// Provide a value +func (s *system) Provide(cid cid.Cid) error { + return s.provider.Provide(cid) +} + +// Reprovide all the previously provided values +func (s *system) Reprovide(ctx context.Context) error { + return s.reprovider.Trigger(ctx) +} diff --git a/reprovide/providers.go b/reprovide/providers.go deleted file mode 100644 index bef56a0b720..00000000000 --- a/reprovide/providers.go +++ /dev/null @@ -1,75 +0,0 @@ -package reprovide - -import ( - "context" - - pin "github.com/ipfs/go-ipfs/pin" - - cid "github.com/ipfs/go-cid" - cidutil "github.com/ipfs/go-cidutil" - blocks "github.com/ipfs/go-ipfs-blockstore" - ipld "github.com/ipfs/go-ipld-format" - merkledag "github.com/ipfs/go-merkledag" -) - -// NewBlockstoreProvider returns key provider using bstore.AllKeysChan -func NewBlockstoreProvider(bstore blocks.Blockstore) KeyChanFunc { - return func(ctx context.Context) (<-chan cid.Cid, error) { - return bstore.AllKeysChan(ctx) - } -} - -// NewPinnedProvider returns provider supplying pinned keys -func NewPinnedProvider(onlyRoots bool) func(pinning pin.Pinner, dag ipld.DAGService) KeyChanFunc { - return func(pinning pin.Pinner, dag ipld.DAGService) KeyChanFunc { - return func(ctx context.Context) (<-chan cid.Cid, error) { - set, err := pinSet(ctx, pinning, dag, onlyRoots) - if err != nil { - return nil, err - } - - outCh := make(chan cid.Cid) - go func() { - defer close(outCh) - for c := range set.New { - select { - case <-ctx.Done(): - return - case outCh <- c: - } - } - - }() - - return outCh, nil - } - } -} - -func pinSet(ctx context.Context, pinning pin.Pinner, dag ipld.DAGService, onlyRoots bool) (*cidutil.StreamingSet, error) { - set := cidutil.NewStreamingSet() - - go func() { - ctx, cancel := context.WithCancel(ctx) - defer cancel() - defer close(set.New) - - for _, key := range pinning.DirectKeys() { - set.Visitor(ctx)(key) - } - - for _, key := range pinning.RecursiveKeys() { - set.Visitor(ctx)(key) - - if !onlyRoots { - err := merkledag.EnumerateChildren(ctx, merkledag.GetLinksWithDAG(dag), key, set.Visitor(ctx)) - if err != nil { - log.Errorf("reprovide indirect pins: %s", err) - return - } - } - } - }() - - return set, nil -} diff --git a/reprovide/reprovide.go b/reprovide/reprovide.go deleted file mode 100644 index 1a6f5bad3f0..00000000000 --- a/reprovide/reprovide.go +++ /dev/null @@ -1,159 +0,0 @@ -package reprovide - -import ( - "context" - "errors" - "fmt" - "time" - - "github.com/cenkalti/backoff" - "github.com/ipfs/go-cid" - logging "github.com/ipfs/go-log" - "github.com/ipfs/go-verifcid" - "github.com/jbenet/goprocess" - goprocessctx "github.com/jbenet/goprocess/context" - routing "github.com/libp2p/go-libp2p-routing" -) - -var log = logging.Logger("reprovider") - -// KeyChanFunc is function streaming CIDs to pass to content routing -type KeyChanFunc func(context.Context) (<-chan cid.Cid, error) -type doneFunc func(error) - -type Reprovider struct { - ctx context.Context - trigger chan doneFunc - closing chan struct{} - - // The routing system to provide values through - rsys routing.ContentRouting - - keyProvider KeyChanFunc - tick time.Duration -} - -// NewReprovider creates new Reprovider instance. -func NewReprovider(ctx context.Context, tick time.Duration, rsys routing.ContentRouting, keyProvider KeyChanFunc) *Reprovider { - return &Reprovider{ - ctx: ctx, - trigger: make(chan doneFunc), - closing: make(chan struct{}), - - rsys: rsys, - keyProvider: keyProvider, - tick: tick, - } -} - -// Run re-provides keys with 'tick' interval or when triggered -func (rp *Reprovider) Run(proc goprocess.Process) { - ctx := goprocessctx.WithProcessClosing(rp.ctx, proc) - defer close(rp.closing) - - // dont reprovide immediately. - // may have just started the daemon and shutting it down immediately. - // probability( up another minute | uptime ) increases with uptime. - after := time.After(time.Minute) - var done doneFunc - for { - if rp.tick == 0 { - after = make(chan time.Time) - } - - select { - case <-ctx.Done(): - return - case done = <-rp.trigger: - case <-after: - } - - // 'mute' the trigger channel so when `ipfs bitswap reprovide` is called - // a 'reprovider is already running' error is returned - unmute := rp.muteTrigger() - - err := rp.reprovide(ctx) - if err != nil { - log.Debug(err) - } - - if done != nil { - done(err) - } - - unmute() - - after = time.After(rp.tick) - } -} - -// reprovide registers all keys given by rp.keyProvider to libp2p content routing -func (rp *Reprovider) reprovide(ctx context.Context) error { - keychan, err := rp.keyProvider(ctx) - if err != nil { - return fmt.Errorf("failed to get key chan: %s", err) - } - for c := range keychan { - // hash security - if err := verifcid.ValidateCid(c); err != nil { - log.Errorf("insecure hash in reprovider, %s (%s)", c, err) - continue - } - op := func() error { - err := rp.rsys.Provide(ctx, c, true) - if err != nil { - log.Debugf("Failed to provide key: %s", err) - } - return err - } - - // TODO: this backoff library does not respect our context, we should - // eventually work contexts into it. low priority. - err := backoff.Retry(op, backoff.NewExponentialBackOff()) - if err != nil { - log.Debugf("Providing failed after number of retries: %s", err) - return err - } - } - return nil -} - -// Trigger starts reprovision process in rp.Run and waits for it -func (rp *Reprovider) Trigger(ctx context.Context) error { - progressCtx, done := context.WithCancel(ctx) - - var err error - df := func(e error) { - err = e - done() - } - - select { - case <-rp.closing: - return errors.New("reprovider is closed") - case <-rp.ctx.Done(): - return rp.ctx.Err() - case <-ctx.Done(): - return ctx.Err() - case rp.trigger <- df: - <-progressCtx.Done() - return err - } -} - -func (rp *Reprovider) muteTrigger() context.CancelFunc { - ctx, cf := context.WithCancel(rp.ctx) - go func() { - defer cf() - for { - select { - case <-ctx.Done(): - return - case done := <-rp.trigger: - done(fmt.Errorf("reprovider is already running")) - } - } - }() - - return cf -} diff --git a/test/sharness/lib/iptb-lib.sh b/test/sharness/lib/iptb-lib.sh index 6ee8fbd8b01..20a2ce7a68a 100644 --- a/test/sharness/lib/iptb-lib.sh +++ b/test/sharness/lib/iptb-lib.sh @@ -62,3 +62,24 @@ iptb_wait_stop() { go-sleep 10ms done } + +findprovs_empty() { + test_expect_success 'findprovs '$1' succeeds' ' + ipfsi 1 dht findprovs -n 1 '$1' > findprovsOut + ' + + test_expect_success "findprovs $1 output is empty" ' + test_must_be_empty findprovsOut + ' +} + +findprovs_expect() { + test_expect_success 'findprovs '$1' succeeds' ' + ipfsi 1 dht findprovs -n 1 '$1' > findprovsOut && + echo '$2' > expected + ' + + test_expect_success "findprovs $1 output looks good" ' + test_cmp findprovsOut expected + ' +} diff --git a/test/sharness/t0175-provider.sh b/test/sharness/t0175-provider.sh new file mode 100755 index 00000000000..364df60e91e --- /dev/null +++ b/test/sharness/t0175-provider.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash + +test_description="Test reprovider" + +. lib/test-lib.sh + +NUM_NODES=2 + +test_expect_success 'init iptb' ' + iptb testbed create -type localipfs -force -count $NUM_NODES -init +' + +test_expect_success 'peer ids' ' + PEERID_0=$(iptb attr get 0 id) && + PEERID_1=$(iptb attr get 1 id) +' + +test_expect_success 'use strategic providing' ' + iptb run -- ipfs config --json Experimental.StrategicProviding false +' + +startup_cluster ${NUM_NODES} + +test_expect_success 'add test object' ' + HASH_0=$(echo "foo" | ipfsi 0 add -q) +' + +findprovs_expect '$HASH_0' '$PEERID_0' + +test_expect_success 'stop node 1' ' + iptb stop +' + +test_done diff --git a/test/sharness/t0175-reprovider.sh b/test/sharness/t0175-reprovider.sh index 2df63fdfc0a..c00b25c0c3a 100755 --- a/test/sharness/t0175-reprovider.sh +++ b/test/sharness/t0175-reprovider.sh @@ -23,27 +23,6 @@ init_strategy() { startup_cluster ${NUM_NODES} } -findprovs_empty() { - test_expect_success 'findprovs '$1' succeeds' ' - ipfsi 1 dht findprovs -n 1 '$1' > findprovsOut - ' - - test_expect_success "findprovs $1 output is empty" ' - test_must_be_empty findprovsOut - ' -} - -findprovs_expect() { - test_expect_success 'findprovs '$1' succeeds' ' - ipfsi 1 dht findprovs -n 1 '$1' > findprovsOut && - echo '$2' > expected - ' - - test_expect_success "findprovs $1 output looks good" ' - test_cmp findprovsOut expected - ' -} - reprovide() { test_expect_success 'reprovide' ' # TODO: this hangs, though only after reprovision was done diff --git a/test/sharness/t0175-strategic-provider.sh b/test/sharness/t0175-strategic-provider.sh new file mode 100755 index 00000000000..7bad38838b6 --- /dev/null +++ b/test/sharness/t0175-strategic-provider.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash + +test_description="Test reprovider" + +. lib/test-lib.sh + +NUM_NODES=2 + +test_expect_success 'init iptb' ' + iptb testbed create -type localipfs -force -count $NUM_NODES -init +' + +test_expect_success 'peer ids' ' + PEERID_0=$(iptb attr get 0 id) && + PEERID_1=$(iptb attr get 1 id) +' + +test_expect_success 'use strategic providing' ' + iptb run -- ipfs config --json Experimental.StrategicProviding true +' + +startup_cluster ${NUM_NODES} + +test_expect_success 'add test object' ' + HASH_0=$(echo "foo" | ipfsi 0 add -q) +' + +findprovs_empty '$HASH_0' + +test_expect_success 'stop node 1' ' + iptb stop +' + +test_done From ce75f1c18fc7b4f0f59be87f9398bd15d62ad5f4 Mon Sep 17 00:00:00 2001 From: Michael Avila Date: Mon, 6 May 2019 11:03:40 -0700 Subject: [PATCH 002/671] Separate imports License: MIT Signed-off-by: Michael Avila --- core/builder.go | 1 + 1 file changed, 1 insertion(+) diff --git a/core/builder.go b/core/builder.go index 24b987596ea..ff8fbd3275a 100644 --- a/core/builder.go +++ b/core/builder.go @@ -6,6 +6,7 @@ import ( "github.com/ipfs/go-ipfs/core/bootstrap" "github.com/ipfs/go-ipfs/core/node" + "github.com/ipfs/go-metrics-interface" "go.uber.org/fx" ) From e8c9207da322d3e09aef51c10c27d5a3603e7936 Mon Sep 17 00:00:00 2001 From: Michael Avila Date: Mon, 6 May 2019 11:06:53 -0700 Subject: [PATCH 003/671] Move cfg out to groups License: MIT Signed-off-by: Michael Avila --- core/node/core.go | 24 +++++++++++++----------- core/node/groups.go | 2 +- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/core/node/core.go b/core/node/core.go index 8283447d2bb..0bd855cc8e5 100644 --- a/core/node/core.go +++ b/core/node/core.go @@ -4,7 +4,6 @@ import ( "context" "fmt" - "github.com/ipfs/go-ipfs-config" "github.com/ipfs/go-ipfs/core/node/helpers" "github.com/ipfs/go-ipfs/pin" "github.com/ipfs/go-ipfs/repo" @@ -60,16 +59,19 @@ func Dag(bs blockservice.BlockService) format.DAGService { } // OnlineExchange creates new LibP2P backed block exchange (BitSwap) -func OnlineExchange(mctx helpers.MetricsCtx, lc fx.Lifecycle, cfg *config.Config, host host.Host, rt routing.IpfsRouting, bs blockstore.GCBlockstore) exchange.Interface { - bitswapNetwork := network.NewFromIpfsHost(host, rt) - bitswap.ProvideEnabled = !cfg.Experimental.StrategicProviding - exch := bitswap.New(helpers.LifecycleCtx(mctx, lc), bitswapNetwork, bs) - lc.Append(fx.Hook{ - OnStop: func(ctx context.Context) error { - return exch.Close() - }, - }) - return exch +func OnlineExchange(provide bool) interface{} { + return func(mctx helpers.MetricsCtx, lc fx.Lifecycle, host host.Host, rt routing.IpfsRouting, bs blockstore.GCBlockstore) exchange.Interface { + bitswapNetwork := network.NewFromIpfsHost(host, rt) + bitswap.ProvideEnabled = provide + exch := bitswap.New(helpers.LifecycleCtx(mctx, lc), bitswapNetwork, bs) + lc.Append(fx.Hook{ + OnStop: func(ctx context.Context) error { + return exch.Close() + }, + }) + return exch + + } } // Files loads persisted MFS root diff --git a/core/node/groups.go b/core/node/groups.go index c9a4da43e96..2e55045757a 100644 --- a/core/node/groups.go +++ b/core/node/groups.go @@ -224,7 +224,7 @@ func Online(bcfg *BuildCfg, cfg *config.Config) fx.Option { } return fx.Options( - fx.Provide(OnlineExchange), + fx.Provide(OnlineExchange(!cfg.Experimental.StrategicProviding)), fx.Provide(Namesys(ipnsCacheSize)), fx.Invoke(IpnsRepublisher(repubPeriod, recordLifetime)), From a87558e02cc5c1cf4728c734e9c0566b3f1969e3 Mon Sep 17 00:00:00 2001 From: Michael Avila Date: Mon, 6 May 2019 11:18:28 -0700 Subject: [PATCH 004/671] Move more cfg out of groups License: MIT Signed-off-by: Michael Avila --- core/node/groups.go | 4 ++-- core/node/provider.go | 23 +++++++++++------------ 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/core/node/groups.go b/core/node/groups.go index 2e55045757a..5b37e1b38d9 100644 --- a/core/node/groups.go +++ b/core/node/groups.go @@ -232,7 +232,7 @@ func Online(bcfg *BuildCfg, cfg *config.Config) fx.Option { fx.Provide(p2p.New), LibP2P(bcfg, cfg), - OnlineProviders(cfg), + OnlineProviders(cfg.Experimental.StrategicProviding, cfg.Reprovider.Strategy, cfg.Reprovider.Interval), ) } @@ -242,7 +242,7 @@ func Offline(cfg *config.Config) fx.Option { fx.Provide(offline.Exchange), fx.Provide(Namesys(0)), fx.Provide(offroute.NewOfflineRouter), - OfflineProviders(cfg), + OfflineProviders(cfg.Experimental.StrategicProviding, cfg.Reprovider.Strategy, cfg.Reprovider.Interval), ) } diff --git a/core/node/provider.go b/core/node/provider.go index a5c62baa68b..783fb0ddf35 100644 --- a/core/node/provider.go +++ b/core/node/provider.go @@ -7,7 +7,6 @@ import ( "go.uber.org/fx" - "github.com/ipfs/go-ipfs-config" "github.com/ipfs/go-ipfs/core/node/helpers" "github.com/ipfs/go-ipfs/provider" q "github.com/ipfs/go-ipfs/provider/queue" @@ -72,34 +71,34 @@ func StrategicOfflineProviderSysCtor() provider.System { // ONLINE/OFFLINE // OnlineProviders groups units managing provider routing records online -func OnlineProviders(cfg *config.Config) fx.Option { - if cfg.Experimental.StrategicProviding { +func OnlineProviders(useStrategicProviding bool, reprovideStrategy string, reprovideInterval string) fx.Option { + if useStrategicProviding { return fx.Provide(StrategicProviderSysCtor) } return fx.Options( - SimpleProviders(cfg), + SimpleProviders(reprovideStrategy, reprovideInterval), fx.Provide(SimpleProviderSysCtor), ) } // OfflineProviders groups units managing provider routing records offline -func OfflineProviders(cfg *config.Config) fx.Option { - if cfg.Experimental.StrategicProviding { +func OfflineProviders(useStrategicProviding bool, reprovideStrategy string, reprovideInterval string) fx.Option { + if useStrategicProviding { return fx.Provide(StrategicOfflineProviderSysCtor) } return fx.Options( - SimpleProviders(cfg), + SimpleProviders(reprovideStrategy, reprovideInterval), fx.Provide(SimpleOfflineProviderSysCtor), ) } // SimpleProviders creates the simple provider/reprovider dependencies -func SimpleProviders(cfg *config.Config) fx.Option { +func SimpleProviders(reprovideStrategy string, reprovideInterval string) fx.Option { reproviderInterval := kReprovideFrequency - if cfg.Reprovider.Interval != "" { - dur, err := time.ParseDuration(cfg.Reprovider.Interval) + if reprovideInterval != "" { + dur, err := time.ParseDuration(reprovideInterval) if err != nil { return fx.Error(err) } @@ -108,7 +107,7 @@ func SimpleProviders(cfg *config.Config) fx.Option { } var keyProvider fx.Option - switch cfg.Reprovider.Strategy { + switch reprovideStrategy { case "all": fallthrough case "": @@ -118,7 +117,7 @@ func SimpleProviders(cfg *config.Config) fx.Option { case "pinned": keyProvider = fx.Provide(simple.NewPinnedProvider(false)) default: - return fx.Error(fmt.Errorf("unknown reprovider strategy '%s'", cfg.Reprovider.Strategy)) + return fx.Error(fmt.Errorf("unknown reprovider strategy '%s'", reprovideStrategy)) } return fx.Options( From 55676a0b86193aa71e91ad3cedeef1d3863df0d1 Mon Sep 17 00:00:00 2001 From: Michael Avila Date: Mon, 6 May 2019 11:20:43 -0700 Subject: [PATCH 005/671] Remove Ctor from names License: MIT Signed-off-by: Michael Avila --- core/node/provider.go | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/core/node/provider.go b/core/node/provider.go index 783fb0ddf35..c6703d617a1 100644 --- a/core/node/provider.go +++ b/core/node/provider.go @@ -24,20 +24,20 @@ func ProviderQueue(mctx helpers.MetricsCtx, lc fx.Lifecycle, repo repo.Repo) (*q return q.NewQueue(helpers.LifecycleCtx(mctx, lc), "provider-v1", repo.Datastore()) } -// SimpleProviderCtor creates new record provider -func SimpleProviderCtor(mctx helpers.MetricsCtx, lc fx.Lifecycle, queue *q.Queue, rt routing.IpfsRouting) provider.Provider { +// SimpleProvider creates new record provider +func SimpleProvider(mctx helpers.MetricsCtx, lc fx.Lifecycle, queue *q.Queue, rt routing.IpfsRouting) provider.Provider { return simple.NewProvider(helpers.LifecycleCtx(mctx, lc), queue, rt) } -// SimpleReproviderCtor creates new reprovider -func SimpleReproviderCtor(reproviderInterval time.Duration) func(helpers.MetricsCtx, fx.Lifecycle, routing.IpfsRouting, simple.KeyChanFunc) (provider.Reprovider, error) { +// SimpleReprovider creates new reprovider +func SimpleReprovider(reproviderInterval time.Duration) func(helpers.MetricsCtx, fx.Lifecycle, routing.IpfsRouting, simple.KeyChanFunc) (provider.Reprovider, error) { return func(mctx helpers.MetricsCtx, lc fx.Lifecycle, rt routing.IpfsRouting, keyProvider simple.KeyChanFunc) (provider.Reprovider, error) { return simple.NewReprovider(helpers.LifecycleCtx(mctx, lc), reproviderInterval, rt, keyProvider), nil } } -// SimpleProviderSysCtor creates new provider system -func SimpleProviderSysCtor(lc fx.Lifecycle, p provider.Provider, r provider.Reprovider) provider.System { +// SimpleProviderSys creates new provider system +func SimpleProviderSys(lc fx.Lifecycle, p provider.Provider, r provider.Reprovider) provider.System { sys := provider.NewSystem(p, r) lc.Append(fx.Hook{ OnStart: func(ctx context.Context) error { @@ -51,20 +51,20 @@ func SimpleProviderSysCtor(lc fx.Lifecycle, p provider.Provider, r provider.Repr return sys } -// SimpleOfflineProviderSysCtor creates a new offline provider system -func SimpleOfflineProviderSysCtor(p provider.Provider, r provider.Reprovider) provider.System { +// SimpleOfflineProviderSys creates a new offline provider system +func SimpleOfflineProviderSys(p provider.Provider, r provider.Reprovider) provider.System { return provider.NewSystem(p, r) } // STRATEGIC -// StrategicProviderSysCtor creates new provider system -func StrategicProviderSysCtor() provider.System { +// StrategicProviderSys creates new provider system +func StrategicProviderSys() provider.System { return provider.NewOfflineProvider() } -// StrategicOfflineProviderSysCtor creates a new offline provider system -func StrategicOfflineProviderSysCtor() provider.System { +// StrategicOfflineProviderSys creates a new offline provider system +func StrategicOfflineProviderSys() provider.System { return provider.NewOfflineProvider() } @@ -73,24 +73,24 @@ func StrategicOfflineProviderSysCtor() provider.System { // OnlineProviders groups units managing provider routing records online func OnlineProviders(useStrategicProviding bool, reprovideStrategy string, reprovideInterval string) fx.Option { if useStrategicProviding { - return fx.Provide(StrategicProviderSysCtor) + return fx.Provide(StrategicProviderSys) } return fx.Options( SimpleProviders(reprovideStrategy, reprovideInterval), - fx.Provide(SimpleProviderSysCtor), + fx.Provide(SimpleProviderSys), ) } // OfflineProviders groups units managing provider routing records offline func OfflineProviders(useStrategicProviding bool, reprovideStrategy string, reprovideInterval string) fx.Option { if useStrategicProviding { - return fx.Provide(StrategicOfflineProviderSysCtor) + return fx.Provide(StrategicOfflineProviderSys) } return fx.Options( SimpleProviders(reprovideStrategy, reprovideInterval), - fx.Provide(SimpleOfflineProviderSysCtor), + fx.Provide(SimpleOfflineProviderSys), ) } @@ -122,8 +122,8 @@ func SimpleProviders(reprovideStrategy string, reprovideInterval string) fx.Opti return fx.Options( fx.Provide(ProviderQueue), - fx.Provide(SimpleProviderCtor), + fx.Provide(SimpleProvider), keyProvider, - fx.Provide(SimpleReproviderCtor(reproviderInterval)), + fx.Provide(SimpleReprovider(reproviderInterval)), ) } From 0b8f0d3a845e0da0ee71845145ac50ecc0d31428 Mon Sep 17 00:00:00 2001 From: Michael Avila Date: Mon, 6 May 2019 11:21:57 -0700 Subject: [PATCH 006/671] Use interface{} for duplicated return type License: MIT Signed-off-by: Michael Avila --- core/node/provider.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/node/provider.go b/core/node/provider.go index c6703d617a1..a3f831417eb 100644 --- a/core/node/provider.go +++ b/core/node/provider.go @@ -30,7 +30,7 @@ func SimpleProvider(mctx helpers.MetricsCtx, lc fx.Lifecycle, queue *q.Queue, rt } // SimpleReprovider creates new reprovider -func SimpleReprovider(reproviderInterval time.Duration) func(helpers.MetricsCtx, fx.Lifecycle, routing.IpfsRouting, simple.KeyChanFunc) (provider.Reprovider, error) { +func SimpleReprovider(reproviderInterval time.Duration) interface{} { return func(mctx helpers.MetricsCtx, lc fx.Lifecycle, rt routing.IpfsRouting, keyProvider simple.KeyChanFunc) (provider.Reprovider, error) { return simple.NewReprovider(helpers.LifecycleCtx(mctx, lc), reproviderInterval, rt, keyProvider), nil } From cde21e9c551ab8e9d2949ad1f8a52c346e560fa2 Mon Sep 17 00:00:00 2001 From: Michael Avila Date: Mon, 6 May 2019 11:24:35 -0700 Subject: [PATCH 007/671] Remove unnecessary _ License: MIT Signed-off-by: Michael Avila --- provider/offline.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/provider/offline.go b/provider/offline.go index eb1d1b9acda..5511364ed74 100644 --- a/provider/offline.go +++ b/provider/offline.go @@ -19,10 +19,10 @@ func (op *offlineProvider) Close() error { return nil } -func (op *offlineProvider) Provide(_ cid.Cid) error { +func (op *offlineProvider) Provide(cid.Cid) error { return nil } -func (op *offlineProvider) Reprovide(_ context.Context) error { +func (op *offlineProvider) Reprovide(context.Context) error { return nil } From 8f03df805b519bd4976d55ed1e7665d59fcc6549 Mon Sep 17 00:00:00 2001 From: Michael Avila Date: Mon, 6 May 2019 11:29:03 -0700 Subject: [PATCH 008/671] Move sharness test helpers License: MIT Signed-off-by: Michael Avila --- test/sharness/lib/iptb-lib.sh | 21 --------------------- test/sharness/lib/test-lib.sh | 21 +++++++++++++++++++++ 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/test/sharness/lib/iptb-lib.sh b/test/sharness/lib/iptb-lib.sh index 20a2ce7a68a..6ee8fbd8b01 100644 --- a/test/sharness/lib/iptb-lib.sh +++ b/test/sharness/lib/iptb-lib.sh @@ -62,24 +62,3 @@ iptb_wait_stop() { go-sleep 10ms done } - -findprovs_empty() { - test_expect_success 'findprovs '$1' succeeds' ' - ipfsi 1 dht findprovs -n 1 '$1' > findprovsOut - ' - - test_expect_success "findprovs $1 output is empty" ' - test_must_be_empty findprovsOut - ' -} - -findprovs_expect() { - test_expect_success 'findprovs '$1' succeeds' ' - ipfsi 1 dht findprovs -n 1 '$1' > findprovsOut && - echo '$2' > expected - ' - - test_expect_success "findprovs $1 output looks good" ' - test_cmp findprovsOut expected - ' -} diff --git a/test/sharness/lib/test-lib.sh b/test/sharness/lib/test-lib.sh index f9ebae81e4c..8b8f26fb71e 100644 --- a/test/sharness/lib/test-lib.sh +++ b/test/sharness/lib/test-lib.sh @@ -437,3 +437,24 @@ convert_tcp_maddr() { port_from_maddr() { echo $1 | awk -F'/' '{ print $NF }' } + +findprovs_empty() { + test_expect_success 'findprovs '$1' succeeds' ' + ipfsi 1 dht findprovs -n 1 '$1' > findprovsOut + ' + + test_expect_success "findprovs $1 output is empty" ' + test_must_be_empty findprovsOut + ' +} + +findprovs_expect() { + test_expect_success 'findprovs '$1' succeeds' ' + ipfsi 1 dht findprovs -n 1 '$1' > findprovsOut && + echo '$2' > expected + ' + + test_expect_success "findprovs $1 output looks good" ' + test_cmp findprovsOut expected + ' +} From 16ed07b995c1183e47bae2e41a1b35c107c50a8d Mon Sep 17 00:00:00 2001 From: Michael Avila Date: Mon, 6 May 2019 11:46:26 -0700 Subject: [PATCH 009/671] Close reprovider in the provider system License: MIT Signed-off-by: Michael Avila --- provider/provider.go | 2 ++ provider/system.go | 16 ++++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/provider/provider.go b/provider/provider.go index e8939ba6f7f..689bfeb1b0c 100644 --- a/provider/provider.go +++ b/provider/provider.go @@ -30,4 +30,6 @@ type Reprovider interface { Run() // Trigger a reprovide Trigger(context.Context) error + // Close stops the reprovider + Close() error } diff --git a/provider/system.go b/provider/system.go index 6bc1d357cbc..b3e17ee40c5 100644 --- a/provider/system.go +++ b/provider/system.go @@ -32,8 +32,20 @@ func (s *system) Run() { // Close the provider and reprovider func (s *system) Close() error { - // TODO: Close reprovider here - return s.provider.Close() + var errs []error + + if err := s.provider.Close(); err != nil { + errs = append(errs, err) + } + + if err := s.reprovider.Close(); err != nil { + errs = append(errs, err) + } + + if len(errs) > 0 { + return errs[0] + } + return nil } // Provide a value From 4a4a61fb3951410586f411cd67557d9f86426a99 Mon Sep 17 00:00:00 2001 From: Michael Avila Date: Mon, 6 May 2019 14:54:41 -0700 Subject: [PATCH 010/671] Remove unused strategic providing feature flag License: MIT Signed-off-by: Michael Avila --- provider/provider.go | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/provider/provider.go b/provider/provider.go index 689bfeb1b0c..751d7cd6313 100644 --- a/provider/provider.go +++ b/provider/provider.go @@ -6,13 +6,7 @@ import ( logging "github.com/ipfs/go-log" ) -var ( - // StrategicProvidingEnabled toggles between the original providing mechanism - // and the new strategic providing system - StrategicProvidingEnabled = false - - log = logging.Logger("provider") -) +var log = logging.Logger("provider") // Provider announces blocks to the network type Provider interface { From 9587723911a31dfd0abf536f3fcb1a3cbfb6740d Mon Sep 17 00:00:00 2001 From: Michael Avila Date: Mon, 6 May 2019 16:13:01 -0700 Subject: [PATCH 011/671] Remove strategic provider sys constructors License: MIT Signed-off-by: Michael Avila --- core/node/provider.go | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/core/node/provider.go b/core/node/provider.go index a3f831417eb..dfea3b833fd 100644 --- a/core/node/provider.go +++ b/core/node/provider.go @@ -56,24 +56,12 @@ func SimpleOfflineProviderSys(p provider.Provider, r provider.Reprovider) provid return provider.NewSystem(p, r) } -// STRATEGIC - -// StrategicProviderSys creates new provider system -func StrategicProviderSys() provider.System { - return provider.NewOfflineProvider() -} - -// StrategicOfflineProviderSys creates a new offline provider system -func StrategicOfflineProviderSys() provider.System { - return provider.NewOfflineProvider() -} - // ONLINE/OFFLINE // OnlineProviders groups units managing provider routing records online func OnlineProviders(useStrategicProviding bool, reprovideStrategy string, reprovideInterval string) fx.Option { if useStrategicProviding { - return fx.Provide(StrategicProviderSys) + return fx.Provide(provider.NewOfflineProvider) } return fx.Options( @@ -85,7 +73,7 @@ func OnlineProviders(useStrategicProviding bool, reprovideStrategy string, repro // OfflineProviders groups units managing provider routing records offline func OfflineProviders(useStrategicProviding bool, reprovideStrategy string, reprovideInterval string) fx.Option { if useStrategicProviding { - return fx.Provide(StrategicOfflineProviderSys) + return fx.Provide(provider.NewOfflineProvider) } return fx.Options( From 23e1b1db3ac0cdf42653db0df4d126d79dcb8a43 Mon Sep 17 00:00:00 2001 From: Michael Avila Date: Mon, 6 May 2019 16:16:49 -0700 Subject: [PATCH 012/671] Use conditional for running provider online License: MIT Signed-off-by: Michael Avila --- core/node/provider.go | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/core/node/provider.go b/core/node/provider.go index dfea3b833fd..43540745bf6 100644 --- a/core/node/provider.go +++ b/core/node/provider.go @@ -37,23 +37,24 @@ func SimpleReprovider(reproviderInterval time.Duration) interface{} { } // SimpleProviderSys creates new provider system -func SimpleProviderSys(lc fx.Lifecycle, p provider.Provider, r provider.Reprovider) provider.System { - sys := provider.NewSystem(p, r) - lc.Append(fx.Hook{ - OnStart: func(ctx context.Context) error { - sys.Run() - return nil - }, - OnStop: func(ctx context.Context) error { - return sys.Close() - }, - }) - return sys -} +func SimpleProviderSys(isOnline bool) interface{} { + return func(lc fx.Lifecycle, p provider.Provider, r provider.Reprovider) provider.System { + sys := provider.NewSystem(p, r) + + if isOnline { + lc.Append(fx.Hook{ + OnStart: func(ctx context.Context) error { + sys.Run() + return nil + }, + OnStop: func(ctx context.Context) error { + return sys.Close() + }, + }) + } -// SimpleOfflineProviderSys creates a new offline provider system -func SimpleOfflineProviderSys(p provider.Provider, r provider.Reprovider) provider.System { - return provider.NewSystem(p, r) + return sys + } } // ONLINE/OFFLINE @@ -66,7 +67,7 @@ func OnlineProviders(useStrategicProviding bool, reprovideStrategy string, repro return fx.Options( SimpleProviders(reprovideStrategy, reprovideInterval), - fx.Provide(SimpleProviderSys), + fx.Provide(SimpleProviderSys(true)), ) } @@ -78,7 +79,7 @@ func OfflineProviders(useStrategicProviding bool, reprovideStrategy string, repr return fx.Options( SimpleProviders(reprovideStrategy, reprovideInterval), - fx.Provide(SimpleOfflineProviderSys), + fx.Provide(SimpleProviderSys(false)), ) } From 992ec291bc4531e217cb625fec1cc915cfd68477 Mon Sep 17 00:00:00 2001 From: Michael Avila Date: Tue, 14 May 2019 08:45:57 -0700 Subject: [PATCH 013/671] Give argument intent revealing name (and add comment) --- core/node/groups.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/node/groups.go b/core/node/groups.go index 5b37e1b38d9..8ccc3df505c 100644 --- a/core/node/groups.go +++ b/core/node/groups.go @@ -223,8 +223,11 @@ func Online(bcfg *BuildCfg, cfg *config.Config) fx.Option { recordLifetime = d } + /* don't provide from bitswap when the strategic provider service is active */ + shouldBitswapProvide := !cfg.Experimental.StrategicProviding + return fx.Options( - fx.Provide(OnlineExchange(!cfg.Experimental.StrategicProviding)), + fx.Provide(OnlineExchange(shouldBitswapProvide)), fx.Provide(Namesys(ipnsCacheSize)), fx.Invoke(IpnsRepublisher(repubPeriod, recordLifetime)), From 98df9143edeeb89848c6e2ea03fb78b9f4286d8c Mon Sep 17 00:00:00 2001 From: Michael Avila Date: Mon, 20 May 2019 12:03:38 -0700 Subject: [PATCH 014/671] Use ProvideEnabled option to construct Bitswap --- core/node/core.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/node/core.go b/core/node/core.go index 0bd855cc8e5..2445836cc2c 100644 --- a/core/node/core.go +++ b/core/node/core.go @@ -62,8 +62,7 @@ func Dag(bs blockservice.BlockService) format.DAGService { func OnlineExchange(provide bool) interface{} { return func(mctx helpers.MetricsCtx, lc fx.Lifecycle, host host.Host, rt routing.IpfsRouting, bs blockstore.GCBlockstore) exchange.Interface { bitswapNetwork := network.NewFromIpfsHost(host, rt) - bitswap.ProvideEnabled = provide - exch := bitswap.New(helpers.LifecycleCtx(mctx, lc), bitswapNetwork, bs) + exch := bitswap.New(helpers.LifecycleCtx(mctx, lc), bitswapNetwork, bs, bitswap.ProvideEnabled(provide)) lc.Append(fx.Hook{ OnStop: func(ctx context.Context) error { return exch.Close() From bc7c0c0f88f0f7eef497056c2edcf23d542550c6 Mon Sep 17 00:00:00 2001 From: Michael Avila Date: Mon, 20 May 2019 13:41:04 -0700 Subject: [PATCH 015/671] Add Strategic Providing to experimental features doc --- docs/experimental-features.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/docs/experimental-features.md b/docs/experimental-features.md index 9f25ef2a416..788ff5f033f 100644 --- a/docs/experimental-features.md +++ b/docs/experimental-features.md @@ -29,6 +29,7 @@ the above issue. - [QUIC](#quic) - [AutoRelay](#autorelay) - [TLS 1.3 Handshake](#tls-13-as-default-handshake-protocol) +- [Strategic Providing](#strategic-providing) --- @@ -674,3 +675,31 @@ ipfs config --json Experimental.PreferTLS true - [ ] needs testing - [ ] needs adoption + +--- + +## Strategic Providing + +### State + +Experimental, disabled by default. + +Replaces the existing provide mechanism with a robust, strategic provider system. + +### How to enable + +Modify your ipfs config: + +``` +ipfs config --json Experimental.StrategicProviding true +``` + +### Road to being a real feature + +- [ ] needs real world testing +- [ ] needs adoption +- [ ] needs to support all providing features + - [X] provide nothing + - [ ] provide roots + - [ ] provide all + - [ ] provide strategic From 4feff27a89de2f42b578d4b5e64ff65090076029 Mon Sep 17 00:00:00 2001 From: Michael Avila Date: Mon, 20 May 2019 14:33:53 -0700 Subject: [PATCH 016/671] Group imports correctly --- core/node/groups.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/node/groups.go b/core/node/groups.go index 8ccc3df505c..a66d0fb8aa4 100644 --- a/core/node/groups.go +++ b/core/node/groups.go @@ -14,10 +14,10 @@ import ( pubsub "github.com/libp2p/go-libp2p-pubsub" "github.com/ipfs/go-ipfs/core/node/libp2p" + "github.com/ipfs/go-ipfs/p2p" offline "github.com/ipfs/go-ipfs-exchange-offline" offroute "github.com/ipfs/go-ipfs-routing/offline" - "github.com/ipfs/go-ipfs/p2p" "github.com/ipfs/go-path/resolver" uio "github.com/ipfs/go-unixfs/io" "go.uber.org/fx" From d73ae305d2aaf2573341eb04a8860c745c01df4b Mon Sep 17 00:00:00 2001 From: Michael Avila Date: Wed, 22 May 2019 14:04:59 -0700 Subject: [PATCH 017/671] Remove unused logger in provider --- provider/provider.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/provider/provider.go b/provider/provider.go index 751d7cd6313..7dec4c172e6 100644 --- a/provider/provider.go +++ b/provider/provider.go @@ -3,11 +3,8 @@ package provider import ( "context" "github.com/ipfs/go-cid" - logging "github.com/ipfs/go-log" ) -var log = logging.Logger("provider") - // Provider announces blocks to the network type Provider interface { // Run is used to begin processing the provider work From 065d783c1d00d9ee98609f490459846c50713a8b Mon Sep 17 00:00:00 2001 From: Michael Avila Date: Tue, 28 May 2019 08:44:55 -0700 Subject: [PATCH 018/671] Add updated go.sum from after rebase --- go.sum | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/go.sum b/go.sum index 1bc6861f292..b9011632354 100644 --- a/go.sum +++ b/go.sum @@ -125,6 +125,7 @@ github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gxed/go-shellwords v1.0.3 h1:2TP32H4TAklZUdz84oj95BJhVnIrRasyx2j1cqH5K38= github.com/gxed/go-shellwords v1.0.3/go.mod h1:N7paucT91ByIjmVJHhvoarjoQnmsi3Jd3vH7VqgtMxQ= 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= @@ -245,10 +246,13 @@ github.com/ipfs/go-unixfs v0.0.6 h1:mQ6KS3NK4GA9hyUpGdGItqt5llzyIx0Qy2UxC/A7bEo= github.com/ipfs/go-unixfs v0.0.6/go.mod h1:g41FlHFM/qacA3jzMPOYKIwNwbgTQEKJH2hQiq19Zrc= github.com/ipfs/go-verifcid v0.0.1 h1:m2HI7zIuR5TFyQ1b79Da5N9dnnCP1vcu2QqawmWlK2E= github.com/ipfs/go-verifcid v0.0.1/go.mod h1:5Hrva5KBeIog4A+UpqlaIU+DEstipcJYQQZc0g37pY0= +github.com/ipfs/hang-fds v0.0.1 h1:KGAxiGtJPT3THVRNT6yxgpdFPeX4ZemUjENOt6NlOn4= github.com/ipfs/hang-fds v0.0.1/go.mod h1:U4JNbzwTpk/qP2Ms4VgrZ4HcgJGVosBJqMXvwe4udSY= github.com/ipfs/interface-go-ipfs-core v0.0.8 h1:nmEYOfK6QRf3VIdggoZ4rmbKXcC2g6cEdU13Z1CvmL4= github.com/ipfs/interface-go-ipfs-core v0.0.8/go.mod h1:RU+DSZXV+JdA7Yagu3OrSoB6hngSmMtK1w6ENOqmfQ8= +github.com/ipfs/iptb v1.4.0 h1:YFYTrCkLMRwk/35IMyC6+yjoQSHTEcNcefBStLJzgvo= github.com/ipfs/iptb v1.4.0/go.mod h1:1rzHpCYtNp87/+hTxG5TfCVn/yMY3dKnLn8tBiMfdmg= +github.com/ipfs/iptb-plugins v0.0.2 h1:JZp4h/+7f00dY4Epr8gzF+VqKITXmVGsZabvmZp7E9I= github.com/ipfs/iptb-plugins v0.0.2/go.mod h1:Vud+X6lHv5QlgVbqCPBHt91I0gPIRgmkD6/tMUsI07U= github.com/jackpal/gateway v1.0.4/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= github.com/jackpal/gateway v1.0.5 h1:qzXWUJfuMdlLMtt0a3Dgt+xkWQiA5itDEITVJtuSwMc= @@ -261,7 +265,9 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOl github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jbenet/go-is-domain v1.0.2 h1:11r5MSptcNFZyBoqubBQnVMUKRWLuRjL1banaIk+iYo= github.com/jbenet/go-is-domain v1.0.2/go.mod h1:xbRLRb0S7FgzDBTJlguhDVwLYM/5yNtvktxj2Ttfy7Q= +github.com/jbenet/go-random v0.0.0-20190219211222-123a90aedc0c h1:uUx61FiAa1GI6ZmVd2wf2vULeQZIKG66eybjNXKYCz4= github.com/jbenet/go-random v0.0.0-20190219211222-123a90aedc0c/go.mod h1:sdx1xVM9UuLw1tXnhJWN3piypTUO3vCIHYmG15KE/dU= +github.com/jbenet/go-random-files v0.0.0-20190219210431-31b3f20ebded h1:fHCa28iw+qaRWZK4IqrntHxXALD5kKr/ESrpOCRRdrg= github.com/jbenet/go-random-files v0.0.0-20190219210431-31b3f20ebded/go.mod h1:FKvZrl5nnaGnTAMewcq0i7wM5zHD75e0lwlnF8q46uo= github.com/jbenet/go-temp-err-catcher v0.0.0-20150120210811-aac704a3f4f2 h1:vhC1OXXiT9R2pczegwz6moDvuRpggaroAXhPIseh57A= github.com/jbenet/go-temp-err-catcher v0.0.0-20150120210811-aac704a3f4f2/go.mod h1:8GXXJV31xl8whumTzdZsTt3RnUIiPqzkyf7mxToRCMs= @@ -571,6 +577,7 @@ github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFd github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e h1:T5PdfK/M1xyrHwynxMIVMWLS7f/qHwfslZphxtGnw7s= github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e/go.mod h1:XDKHRm5ThF8YJjx001LtgelzsoaEcvnA7lVWz9EeX3g= +github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/warpfork/go-wish v0.0.0-20180510122957-5ad1f5abf436/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc h1:BCPnHtcboadS0DvysUuJXZ4lWVv5Bh5i7+tbIyi+ck4= From d4d24daaced8f0326d4eb8ea0285ec1bd18d50d3 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Thu, 30 May 2019 15:29:21 -0700 Subject: [PATCH 019/671] version: bump to 0.4.22-dev --- version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.go b/version.go index 9ce7d097026..5257125e2d9 100644 --- a/version.go +++ b/version.go @@ -4,6 +4,6 @@ package ipfs var CurrentCommit string // CurrentVersionNumber is the current application's version literal -const CurrentVersionNumber = "0.4.21" +const CurrentVersionNumber = "0.4.22-dev" const ApiVersion = "/go-ipfs/" + CurrentVersionNumber + "/" From 5cd15049ad7783ad03e00ea3b1064b7136f20b60 Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Fri, 31 May 2019 16:51:08 +0100 Subject: [PATCH 020/671] feat: update Web UI to v2.4.6 --- core/corehttp/webui.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/corehttp/webui.go b/core/corehttp/webui.go index 0df21d5f576..665e5c2403c 100644 --- a/core/corehttp/webui.go +++ b/core/corehttp/webui.go @@ -1,11 +1,12 @@ package corehttp // TODO: move to IPNS -const WebUIPath = "/ipfs/QmfQkD8pBSBCBxWEwFSu4XaDVSWK6bjnNuaWZjMyQbyDub" +const WebUIPath = "/ipfs/QmQNHd1suZTktPRhP7DD4nKWG46ZRSxkwHocycHVrK3dYW" // this is a list of all past webUI paths. var WebUIPaths = []string{ WebUIPath, + "/ipfs/QmfQkD8pBSBCBxWEwFSu4XaDVSWK6bjnNuaWZjMyQbyDub", "/ipfs/QmXc9raDM1M5G5fpBnVyQ71vR4gbnskwnB9iMEzBuLgvoZ", "/ipfs/QmenEBWcAk3tN94fSKpKFtUMwty1qNwSYw3DMDFV6cPBXA", "/ipfs/QmUnXcWZC5Ve21gUseouJsH5mLAyz5JPp8aHsg8qVUUK8e", From e8c2852179b03a95c8d198895b246b1e3ffaeed8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Tue, 28 May 2019 17:21:57 +0100 Subject: [PATCH 021/671] migrate to go-libp2p-core. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit closes #6391 License: MIT Signed-off-by: Raúl Kripalani --- cmd/seccat/seccat.go | 6 +- core/bootstrap/bootstrap.go | 38 +-- core/bootstrap/bootstrap_test.go | 12 +- core/commands/bitswap.go | 2 +- core/commands/dht.go | 120 ++++---- core/commands/dht_test.go | 4 +- core/commands/dns.go | 6 +- core/commands/id.go | 6 +- core/commands/name/ipnsps.go | 2 +- core/commands/p2p.go | 4 +- core/commands/ping.go | 4 +- core/commands/stat.go | 6 +- core/commands/swarm.go | 11 +- core/core.go | 28 +- core/coreapi/coreapi.go | 12 +- core/coreapi/dht.go | 17 +- core/coreapi/key.go | 4 +- core/coreapi/name.go | 7 +- core/coreapi/pubsub.go | 13 +- core/coreapi/swarm.go | 17 +- core/coreapi/test/api_test.go | 12 +- core/corehttp/gateway_handler.go | 2 +- core/corehttp/gateway_test.go | 2 +- core/corehttp/metrics_test.go | 2 +- core/corehttp/proxy.go | 2 +- core/corehttp/proxy_test.go | 2 +- core/mock/mock.go | 11 +- core/node/builder.go | 4 +- core/node/core.go | 6 +- core/node/groups.go | 2 +- core/node/identity.go | 4 +- core/node/ipns.go | 10 +- core/node/libp2p/addrs.go | 2 +- core/node/libp2p/discovery.go | 6 +- core/node/libp2p/host.go | 8 +- core/node/libp2p/hostopt.go | 6 +- core/node/libp2p/libp2p.go | 6 +- core/node/libp2p/nat.go | 2 +- core/node/libp2p/pnet.go | 2 +- core/node/libp2p/pubsub.go | 2 +- core/node/libp2p/routing.go | 32 +-- core/node/libp2p/routingopt.go | 10 +- core/node/libp2p/smux.go | 4 +- core/node/libp2p/transport.go | 2 +- core/node/provider.go | 9 +- fuse/ipns/common.go | 2 +- fuse/ipns/ipns_test.go | 2 +- fuse/ipns/ipns_unix.go | 4 +- fuse/node/mount_test.go | 2 +- fuse/readonly/ipfs_test.go | 2 +- go.mod | 74 ++--- go.sum | 335 ++++++++++++++-------- keystore/keystore.go | 2 +- keystore/keystore_test.go | 2 +- keystore/memkeystore.go | 2 +- namesys/interface.go | 2 +- namesys/ipns_resolver_validation_test.go | 17 +- namesys/namesys.go | 6 +- namesys/namesys_test.go | 4 +- namesys/publisher.go | 6 +- namesys/publisher_test.go | 6 +- namesys/republisher/repub.go | 4 +- namesys/republisher/repub_test.go | 4 +- namesys/resolve_test.go | 12 +- namesys/routing.go | 4 +- p2p/listener.go | 6 +- p2p/local.go | 6 +- p2p/p2p.go | 6 +- p2p/remote.go | 4 +- p2p/stream.go | 8 +- provider/simple/provider.go | 2 +- provider/simple/provider_test.go | 4 +- provider/simple/reprovide.go | 2 +- provider/simple/reprovide_test.go | 6 +- test/integration/addcat_test.go | 11 +- test/integration/bench_cat_test.go | 11 +- test/integration/bench_test.go | 2 +- test/integration/three_legged_cat_test.go | 6 +- 78 files changed, 563 insertions(+), 472 deletions(-) diff --git a/cmd/seccat/seccat.go b/cmd/seccat/seccat.go index 5a5ae49a244..22f7e00f685 100644 --- a/cmd/seccat/seccat.go +++ b/cmd/seccat/seccat.go @@ -20,9 +20,9 @@ import ( "syscall" logging "github.com/ipfs/go-log" - ci "github.com/libp2p/go-libp2p-crypto" - peer "github.com/libp2p/go-libp2p-peer" - pstore "github.com/libp2p/go-libp2p-peerstore" + ci "github.com/libp2p/go-libp2p-core/crypto" + peer "github.com/libp2p/go-libp2p-core/peer" + pstore "github.com/libp2p/go-libp2p-core/peerstore" pstoremem "github.com/libp2p/go-libp2p-peerstore/pstoremem" secio "github.com/libp2p/go-libp2p-secio" ) diff --git a/core/bootstrap/bootstrap.go b/core/bootstrap/bootstrap.go index d7c107690ea..b2cf1a811b9 100644 --- a/core/bootstrap/bootstrap.go +++ b/core/bootstrap/bootstrap.go @@ -14,12 +14,12 @@ import ( "github.com/jbenet/goprocess" "github.com/jbenet/goprocess/context" "github.com/jbenet/goprocess/periodic" - "github.com/libp2p/go-libp2p-host" + "github.com/libp2p/go-libp2p-core/host" + "github.com/libp2p/go-libp2p-core/network" + "github.com/libp2p/go-libp2p-core/peer" + "github.com/libp2p/go-libp2p-core/peerstore" + "github.com/libp2p/go-libp2p-core/routing" "github.com/libp2p/go-libp2p-loggables" - "github.com/libp2p/go-libp2p-net" - "github.com/libp2p/go-libp2p-peer" - "github.com/libp2p/go-libp2p-peerstore" - "github.com/libp2p/go-libp2p-routing" ) var log = logging.Logger("bootstrap") @@ -51,7 +51,7 @@ type BootstrapConfig struct { // BootstrapPeers is a function that returns a set of bootstrap peers // for the bootstrap process to use. This makes it possible for clients // to control the peers the process uses at any moment. - BootstrapPeers func() []peerstore.PeerInfo + BootstrapPeers func() []peer.AddrInfo } // DefaultBootstrapConfig specifies default sane parameters for bootstrapping. @@ -61,9 +61,9 @@ var DefaultBootstrapConfig = BootstrapConfig{ ConnectionTimeout: (30 * time.Second) / 3, // Perod / 3 } -func BootstrapConfigWithPeers(pis []peerstore.PeerInfo) BootstrapConfig { +func BootstrapConfigWithPeers(pis []peer.AddrInfo) BootstrapConfig { cfg := DefaultBootstrapConfig - cfg.BootstrapPeers = func() []peerstore.PeerInfo { + cfg.BootstrapPeers = func() []peer.AddrInfo { return pis } return cfg @@ -73,7 +73,7 @@ func BootstrapConfigWithPeers(pis []peerstore.PeerInfo) BootstrapConfig { // check the number of open connections and -- if there are too few -- initiate // connections to well-known bootstrap peers. It also kicks off subsystem // bootstrapping (i.e. routing). -func Bootstrap(id peer.ID, host host.Host, rt routing.IpfsRouting, cfg BootstrapConfig) (io.Closer, error) { +func Bootstrap(id peer.ID, host host.Host, rt routing.Routing, cfg BootstrapConfig) (io.Closer, error) { // make a signal to wait for one bootstrap round to complete. doneWithRound := make(chan struct{}) @@ -135,9 +135,9 @@ func bootstrapRound(ctx context.Context, host host.Host, cfg BootstrapConfig) er numToDial := cfg.MinPeerThreshold - len(connected) // filter out bootstrap nodes we are already connected to - var notConnected []peerstore.PeerInfo + var notConnected []peer.AddrInfo for _, p := range peers { - if host.Network().Connectedness(p.ID) != net.Connected { + if host.Network().Connectedness(p.ID) != network.Connected { notConnected = append(notConnected, p) } } @@ -156,7 +156,7 @@ func bootstrapRound(ctx context.Context, host host.Host, cfg BootstrapConfig) er return bootstrapConnect(ctx, host, randSubset) } -func bootstrapConnect(ctx context.Context, ph host.Host, peers []peerstore.PeerInfo) error { +func bootstrapConnect(ctx context.Context, ph host.Host, peers []peer.AddrInfo) error { if len(peers) < 1 { return ErrNotEnoughBootstrapPeers } @@ -171,7 +171,7 @@ func bootstrapConnect(ctx context.Context, ph host.Host, peers []peerstore.PeerI // Also, performed asynchronously for dial speed. wg.Add(1) - go func(p peerstore.PeerInfo) { + go func(p peer.AddrInfo) { defer wg.Done() defer log.EventBegin(ctx, "bootstrapDial", ph.ID(), p.ID).Done() log.Debugf("%s bootstrapping to %s", ph.ID(), p.ID) @@ -205,12 +205,12 @@ func bootstrapConnect(ctx context.Context, ph host.Host, peers []peerstore.PeerI return nil } -func randomSubsetOfPeers(in []peerstore.PeerInfo, max int) []peerstore.PeerInfo { +func randomSubsetOfPeers(in []peer.AddrInfo, max int) []peer.AddrInfo { if max > len(in) { max = len(in) } - out := make([]peerstore.PeerInfo, max) + out := make([]peer.AddrInfo, max) for i, val := range rand.Perm(len(in))[:max] { out[i] = in[val] } @@ -219,12 +219,12 @@ func randomSubsetOfPeers(in []peerstore.PeerInfo, max int) []peerstore.PeerInfo type Peers []config.BootstrapPeer -func (bpeers Peers) ToPeerInfos() []peerstore.PeerInfo { - pinfos := make(map[peer.ID]*peerstore.PeerInfo) +func (bpeers Peers) ToPeerInfos() []peer.AddrInfo { + pinfos := make(map[peer.ID]*peer.AddrInfo) for _, bootstrap := range bpeers { pinfo, ok := pinfos[bootstrap.ID()] if !ok { - pinfo = new(peerstore.PeerInfo) + pinfo = new(peer.AddrInfo) pinfos[bootstrap.ID()] = pinfo pinfo.ID = bootstrap.ID() } @@ -232,7 +232,7 @@ func (bpeers Peers) ToPeerInfos() []peerstore.PeerInfo { pinfo.Addrs = append(pinfo.Addrs, bootstrap.Transport()) } - var peers []peerstore.PeerInfo + var peers []peer.AddrInfo for _, pinfo := range pinfos { peers = append(peers, *pinfo) } diff --git a/core/bootstrap/bootstrap_test.go b/core/bootstrap/bootstrap_test.go index 0c779985847..e7e460b8781 100644 --- a/core/bootstrap/bootstrap_test.go +++ b/core/bootstrap/bootstrap_test.go @@ -5,20 +5,20 @@ import ( "testing" config "github.com/ipfs/go-ipfs-config" - pstore "github.com/libp2p/go-libp2p-peerstore" - testutil "github.com/libp2p/go-testutil" + "github.com/libp2p/go-libp2p-core/peer" + "github.com/libp2p/go-libp2p-core/test" ) func TestSubsetWhenMaxIsGreaterThanLengthOfSlice(t *testing.T) { - var ps []pstore.PeerInfo + var ps []peer.AddrInfo sizeofSlice := 100 for i := 0; i < sizeofSlice; i++ { - pid, err := testutil.RandPeerID() + pid, err := test.RandPeerID() if err != nil { t.Fatal(err) } - ps = append(ps, pstore.PeerInfo{ID: pid}) + ps = append(ps, peer.AddrInfo{ID: pid}) } out := randomSubsetOfPeers(ps, 2*sizeofSlice) if len(out) != len(ps) { @@ -29,7 +29,7 @@ func TestSubsetWhenMaxIsGreaterThanLengthOfSlice(t *testing.T) { func TestMultipleAddrsPerPeer(t *testing.T) { var bsps []config.BootstrapPeer for i := 0; i < 10; i++ { - pid, err := testutil.RandPeerID() + pid, err := test.RandPeerID() if err != nil { t.Fatal(err) } diff --git a/core/commands/bitswap.go b/core/commands/bitswap.go index c2edf743cb5..7f7b2e83481 100644 --- a/core/commands/bitswap.go +++ b/core/commands/bitswap.go @@ -12,7 +12,7 @@ import ( decision "github.com/ipfs/go-bitswap/decision" cidutil "github.com/ipfs/go-cidutil" cmds "github.com/ipfs/go-ipfs-cmds" - peer "github.com/libp2p/go-libp2p-peer" + peer "github.com/libp2p/go-libp2p-core/peer" ) var BitswapCmd = &cmds.Command{ diff --git a/core/commands/dht.go b/core/commands/dht.go index 4788f7cadf1..d1a2ffd462c 100644 --- a/core/commands/dht.go +++ b/core/commands/dht.go @@ -15,10 +15,8 @@ import ( ipld "github.com/ipfs/go-ipld-format" dag "github.com/ipfs/go-merkledag" path "github.com/ipfs/go-path" - peer "github.com/libp2p/go-libp2p-peer" - pstore "github.com/libp2p/go-libp2p-peerstore" - routing "github.com/libp2p/go-libp2p-routing" - notif "github.com/libp2p/go-libp2p-routing/notifications" + peer "github.com/libp2p/go-libp2p-core/peer" + routing "github.com/libp2p/go-libp2p-core/routing" b58 "github.com/mr-tron/base58/base58" ) @@ -75,7 +73,7 @@ var queryDhtCmd = &cmds.Command{ } ctx, cancel := context.WithCancel(req.Context) - ctx, events := notif.RegisterForQueryEvents(ctx) + ctx, events := routing.RegisterForQueryEvents(ctx) closestPeers, err := nd.DHT.GetClosestPeers(ctx, string(id)) if err != nil { @@ -86,9 +84,9 @@ var queryDhtCmd = &cmds.Command{ go func() { defer cancel() for p := range closestPeers { - notif.PublishQueryEvent(ctx, ¬if.QueryEvent{ + routing.PublishQueryEvent(ctx, &routing.QueryEvent{ ID: p, - Type: notif.FinalPeer, + Type: routing.FinalPeer, }) } }() @@ -102,9 +100,9 @@ var queryDhtCmd = &cmds.Command{ return nil }, Encoders: cmds.EncoderMap{ - cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *notif.QueryEvent) error { + cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *routing.QueryEvent) error { pfm := pfuncMap{ - notif.PeerResponse: func(obj *notif.QueryEvent, out io.Writer, verbose bool) error { + routing.PeerResponse: func(obj *routing.QueryEvent, out io.Writer, verbose bool) error { for _, p := range obj.Responses { fmt.Fprintf(out, "%s\n", p.ID.Pretty()) } @@ -115,7 +113,7 @@ var queryDhtCmd = &cmds.Command{ return printEvent(out, w, verbose, pfm) }), }, - Type: notif.QueryEvent{}, + Type: routing.QueryEvent{}, } const ( @@ -157,7 +155,7 @@ var findProvidersDhtCmd = &cmds.Command{ } ctx, cancel := context.WithCancel(req.Context) - ctx, events := notif.RegisterForQueryEvents(ctx) + ctx, events := routing.RegisterForQueryEvents(ctx) pchan := n.Routing.FindProvidersAsync(ctx, c, numProviders) @@ -165,9 +163,9 @@ var findProvidersDhtCmd = &cmds.Command{ defer cancel() for p := range pchan { np := p - notif.PublishQueryEvent(ctx, ¬if.QueryEvent{ - Type: notif.Provider, - Responses: []*pstore.PeerInfo{&np}, + routing.PublishQueryEvent(ctx, &routing.QueryEvent{ + Type: routing.Provider, + Responses: []*peer.AddrInfo{&np}, }) } }() @@ -180,15 +178,15 @@ var findProvidersDhtCmd = &cmds.Command{ return nil }, Encoders: cmds.EncoderMap{ - cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *notif.QueryEvent) error { + cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *routing.QueryEvent) error { pfm := pfuncMap{ - notif.FinalPeer: func(obj *notif.QueryEvent, out io.Writer, verbose bool) error { + routing.FinalPeer: func(obj *routing.QueryEvent, out io.Writer, verbose bool) error { if verbose { fmt.Fprintf(out, "* closest peer %s\n", obj.ID) } return nil }, - notif.Provider: func(obj *notif.QueryEvent, out io.Writer, verbose bool) error { + routing.Provider: func(obj *routing.QueryEvent, out io.Writer, verbose bool) error { prov := obj.Responses[0] if verbose { fmt.Fprintf(out, "provider: ") @@ -207,7 +205,7 @@ var findProvidersDhtCmd = &cmds.Command{ return printEvent(out, w, verbose, pfm) }), }, - Type: notif.QueryEvent{}, + Type: routing.QueryEvent{}, } const ( @@ -269,7 +267,7 @@ var provideRefDhtCmd = &cmds.Command{ } ctx, cancel := context.WithCancel(req.Context) - ctx, events := notif.RegisterForQueryEvents(ctx) + ctx, events := routing.RegisterForQueryEvents(ctx) var provideErr error go func() { @@ -280,8 +278,8 @@ var provideRefDhtCmd = &cmds.Command{ provideErr = provideKeys(ctx, nd.Routing, cids) } if provideErr != nil { - notif.PublishQueryEvent(ctx, ¬if.QueryEvent{ - Type: notif.QueryError, + routing.PublishQueryEvent(ctx, &routing.QueryEvent{ + Type: routing.QueryError, Extra: provideErr.Error(), }) } @@ -296,9 +294,9 @@ var provideRefDhtCmd = &cmds.Command{ return provideErr }, Encoders: cmds.EncoderMap{ - cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *notif.QueryEvent) error { + cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *routing.QueryEvent) error { pfm := pfuncMap{ - notif.FinalPeer: func(obj *notif.QueryEvent, out io.Writer, verbose bool) error { + routing.FinalPeer: func(obj *routing.QueryEvent, out io.Writer, verbose bool) error { if verbose { fmt.Fprintf(out, "sending provider record to peer %s\n", obj.ID) } @@ -310,10 +308,10 @@ var provideRefDhtCmd = &cmds.Command{ return printEvent(out, w, verbose, pfm) }), }, - Type: notif.QueryEvent{}, + Type: routing.QueryEvent{}, } -func provideKeys(ctx context.Context, r routing.IpfsRouting, cids []cid.Cid) error { +func provideKeys(ctx context.Context, r routing.Routing, cids []cid.Cid) error { for _, c := range cids { err := r.Provide(ctx, c, true) if err != nil { @@ -323,7 +321,7 @@ func provideKeys(ctx context.Context, r routing.IpfsRouting, cids []cid.Cid) err return nil } -func provideKeysRec(ctx context.Context, r routing.IpfsRouting, dserv ipld.DAGService, cids []cid.Cid) error { +func provideKeysRec(ctx context.Context, r routing.Routing, dserv ipld.DAGService, cids []cid.Cid) error { provided := cid.NewSet() for _, c := range cids { kset := cid.NewSet() @@ -377,24 +375,24 @@ var findPeerDhtCmd = &cmds.Command{ } ctx, cancel := context.WithCancel(req.Context) - ctx, events := notif.RegisterForQueryEvents(ctx) + ctx, events := routing.RegisterForQueryEvents(ctx) var findPeerErr error go func() { defer cancel() - var pi pstore.PeerInfo + var pi peer.AddrInfo pi, findPeerErr = nd.Routing.FindPeer(ctx, pid) if findPeerErr != nil { - notif.PublishQueryEvent(ctx, ¬if.QueryEvent{ - Type: notif.QueryError, + routing.PublishQueryEvent(ctx, &routing.QueryEvent{ + Type: routing.QueryError, Extra: findPeerErr.Error(), }) return } - notif.PublishQueryEvent(ctx, ¬if.QueryEvent{ - Type: notif.FinalPeer, - Responses: []*pstore.PeerInfo{&pi}, + routing.PublishQueryEvent(ctx, &routing.QueryEvent{ + Type: routing.FinalPeer, + Responses: []*peer.AddrInfo{&pi}, }) }() @@ -407,9 +405,9 @@ var findPeerDhtCmd = &cmds.Command{ return findPeerErr }, Encoders: cmds.EncoderMap{ - cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *notif.QueryEvent) error { + cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *routing.QueryEvent) error { pfm := pfuncMap{ - notif.FinalPeer: func(obj *notif.QueryEvent, out io.Writer, verbose bool) error { + routing.FinalPeer: func(obj *routing.QueryEvent, out io.Writer, verbose bool) error { pi := obj.Responses[0] for _, a := range pi.Addrs { fmt.Fprintf(out, "%s\n", a) @@ -422,7 +420,7 @@ var findPeerDhtCmd = &cmds.Command{ return printEvent(out, w, verbose, pfm) }), }, - Type: notif.QueryEvent{}, + Type: routing.QueryEvent{}, } var getValueDhtCmd = &cmds.Command{ @@ -461,7 +459,7 @@ Different key types can specify other 'best' rules. } ctx, cancel := context.WithCancel(req.Context) - ctx, events := notif.RegisterForQueryEvents(ctx) + ctx, events := routing.RegisterForQueryEvents(ctx) var getErr error go func() { @@ -469,13 +467,13 @@ Different key types can specify other 'best' rules. var val []byte val, getErr = nd.Routing.GetValue(ctx, dhtkey) if getErr != nil { - notif.PublishQueryEvent(ctx, ¬if.QueryEvent{ - Type: notif.QueryError, + routing.PublishQueryEvent(ctx, &routing.QueryEvent{ + Type: routing.QueryError, Extra: getErr.Error(), }) } else { - notif.PublishQueryEvent(ctx, ¬if.QueryEvent{ - Type: notif.Value, + routing.PublishQueryEvent(ctx, &routing.QueryEvent{ + Type: routing.Value, Extra: base64.StdEncoding.EncodeToString(val), }) } @@ -490,9 +488,9 @@ Different key types can specify other 'best' rules. return getErr }, Encoders: cmds.EncoderMap{ - cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *notif.QueryEvent) error { + cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *routing.QueryEvent) error { pfm := pfuncMap{ - notif.Value: func(obj *notif.QueryEvent, out io.Writer, verbose bool) error { + routing.Value: func(obj *routing.QueryEvent, out io.Writer, verbose bool) error { if verbose { _, err := fmt.Fprintf(out, "got value: '%s'\n", obj.Extra) return err @@ -510,7 +508,7 @@ Different key types can specify other 'best' rules. return printEvent(out, w, verbose, pfm) }), }, - Type: notif.QueryEvent{}, + Type: routing.QueryEvent{}, } var putValueDhtCmd = &cmds.Command{ @@ -566,15 +564,15 @@ NOTE: A value may not exceed 2048 bytes. data := req.Arguments[1] ctx, cancel := context.WithCancel(req.Context) - ctx, events := notif.RegisterForQueryEvents(ctx) + ctx, events := routing.RegisterForQueryEvents(ctx) var putErr error go func() { defer cancel() putErr = nd.Routing.PutValue(ctx, key, []byte(data)) if putErr != nil { - notif.PublishQueryEvent(ctx, ¬if.QueryEvent{ - Type: notif.QueryError, + routing.PublishQueryEvent(ctx, &routing.QueryEvent{ + Type: routing.QueryError, Extra: putErr.Error(), }) } @@ -589,15 +587,15 @@ NOTE: A value may not exceed 2048 bytes. return putErr }, Encoders: cmds.EncoderMap{ - cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *notif.QueryEvent) error { + cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *routing.QueryEvent) error { pfm := pfuncMap{ - notif.FinalPeer: func(obj *notif.QueryEvent, out io.Writer, verbose bool) error { + routing.FinalPeer: func(obj *routing.QueryEvent, out io.Writer, verbose bool) error { if verbose { fmt.Fprintf(out, "* closest peer %s\n", obj.ID) } return nil }, - notif.Value: func(obj *notif.QueryEvent, out io.Writer, verbose bool) error { + routing.Value: func(obj *routing.QueryEvent, out io.Writer, verbose bool) error { fmt.Fprintf(out, "%s\n", obj.ID.Pretty()) return nil }, @@ -608,13 +606,13 @@ NOTE: A value may not exceed 2048 bytes. return printEvent(out, w, verbose, pfm) }), }, - Type: notif.QueryEvent{}, + Type: routing.QueryEvent{}, } -type printFunc func(obj *notif.QueryEvent, out io.Writer, verbose bool) error -type pfuncMap map[notif.QueryEventType]printFunc +type printFunc func(obj *routing.QueryEvent, out io.Writer, verbose bool) error +type pfuncMap map[routing.QueryEventType]printFunc -func printEvent(obj *notif.QueryEvent, out io.Writer, verbose bool, override pfuncMap) error { +func printEvent(obj *routing.QueryEvent, out io.Writer, verbose bool, override pfuncMap) error { if verbose { fmt.Fprintf(out, "%s: ", time.Now().Format("15:04:05.000")) } @@ -626,17 +624,17 @@ func printEvent(obj *notif.QueryEvent, out io.Writer, verbose bool, override pfu } switch obj.Type { - case notif.SendingQuery: + case routing.SendingQuery: if verbose { fmt.Fprintf(out, "* querying %s\n", obj.ID) } - case notif.Value: + case routing.Value: if verbose { fmt.Fprintf(out, "got value: '%s'\n", obj.Extra) } else { fmt.Fprint(out, obj.Extra) } - case notif.PeerResponse: + case routing.PeerResponse: if verbose { fmt.Fprintf(out, "* %s says use ", obj.ID) for _, p := range obj.Responses { @@ -644,19 +642,19 @@ func printEvent(obj *notif.QueryEvent, out io.Writer, verbose bool, override pfu } fmt.Fprintln(out) } - case notif.QueryError: + case routing.QueryError: if verbose { fmt.Fprintf(out, "error: %s\n", obj.Extra) } - case notif.DialingPeer: + case routing.DialingPeer: if verbose { fmt.Fprintf(out, "dialing peer: %s\n", obj.ID) } - case notif.AddingPeer: + case routing.AddingPeer: if verbose { fmt.Fprintf(out, "adding peer to query: %s\n", obj.ID) } - case notif.FinalPeer: + case routing.FinalPeer: default: if verbose { fmt.Fprintf(out, "unrecognized event type: %d\n", obj.Type) diff --git a/core/commands/dht_test.go b/core/commands/dht_test.go index 51504649807..b32190a12e0 100644 --- a/core/commands/dht_test.go +++ b/core/commands/dht_test.go @@ -6,11 +6,11 @@ import ( "github.com/ipfs/go-ipfs/namesys" ipns "github.com/ipfs/go-ipns" - tu "github.com/libp2p/go-testutil" + "github.com/libp2p/go-libp2p-core/test" ) func TestKeyTranslation(t *testing.T) { - pid := tu.RandPeerIDFatal(t) + pid := test.RandPeerIDFatal(t) pkname := namesys.PkKeyForID(pid) ipnsname := ipns.RecordKey(pid) diff --git a/core/commands/dns.go b/core/commands/dns.go index 3db12ab95d8..a775f09db1f 100644 --- a/core/commands/dns.go +++ b/core/commands/dns.go @@ -64,12 +64,12 @@ The resolver can recursively resolve: name := req.Arguments[0] resolver := namesys.NewDNSResolver() - var ropts []nsopts.ResolveOpt + var routing []nsopts.ResolveOpt if !recursive { - ropts = append(ropts, nsopts.Depth(1)) + routing = append(routing, nsopts.Depth(1)) } - output, err := resolver.Resolve(req.Context, name, ropts...) + output, err := resolver.Resolve(req.Context, name, routing...) if err != nil && (recursive || err != namesys.ErrResolveRecursion) { return err } diff --git a/core/commands/id.go b/core/commands/id.go index f7607970cb1..fd59e4a20f8 100644 --- a/core/commands/id.go +++ b/core/commands/id.go @@ -12,10 +12,10 @@ import ( cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv" cmds "github.com/ipfs/go-ipfs-cmds" - ic "github.com/libp2p/go-libp2p-crypto" + ic "github.com/libp2p/go-libp2p-core/crypto" + peer "github.com/libp2p/go-libp2p-core/peer" + pstore "github.com/libp2p/go-libp2p-core/peerstore" kb "github.com/libp2p/go-libp2p-kbucket" - peer "github.com/libp2p/go-libp2p-peer" - pstore "github.com/libp2p/go-libp2p-peerstore" identify "github.com/libp2p/go-libp2p/p2p/protocol/identify" ) diff --git a/core/commands/name/ipnsps.go b/core/commands/name/ipnsps.go index c3a422327b7..07063bff38a 100644 --- a/core/commands/name/ipnsps.go +++ b/core/commands/name/ipnsps.go @@ -7,7 +7,7 @@ import ( "github.com/ipfs/go-ipfs-cmds" "github.com/ipfs/go-ipfs/core/commands/cmdenv" - "github.com/libp2p/go-libp2p-peer" + "github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-record" ) diff --git a/core/commands/p2p.go b/core/commands/p2p.go index 387b05c3707..687f16fd550 100644 --- a/core/commands/p2p.go +++ b/core/commands/p2p.go @@ -16,8 +16,8 @@ import ( ipfsaddr "github.com/ipfs/go-ipfs-addr" cmds "github.com/ipfs/go-ipfs-cmds" - pstore "github.com/libp2p/go-libp2p-peerstore" - protocol "github.com/libp2p/go-libp2p-protocol" + pstore "github.com/libp2p/go-libp2p-core/peerstore" + protocol "github.com/libp2p/go-libp2p-core/protocol" ma "github.com/multiformats/go-multiaddr" madns "github.com/multiformats/go-multiaddr-dns" ) diff --git a/core/commands/ping.go b/core/commands/ping.go index 15530448d52..7d2a615d5f3 100644 --- a/core/commands/ping.go +++ b/core/commands/ping.go @@ -12,8 +12,8 @@ import ( iaddr "github.com/ipfs/go-ipfs-addr" cmds "github.com/ipfs/go-ipfs-cmds" - "github.com/libp2p/go-libp2p-peer" - pstore "github.com/libp2p/go-libp2p-peerstore" + peer "github.com/libp2p/go-libp2p-core/peer" + pstore "github.com/libp2p/go-libp2p-core/peerstore" ping "github.com/libp2p/go-libp2p/p2p/protocol/ping" ma "github.com/multiformats/go-multiaddr" ) diff --git a/core/commands/stat.go b/core/commands/stat.go index 330217ebfe0..21098090f4a 100644 --- a/core/commands/stat.go +++ b/core/commands/stat.go @@ -10,9 +10,9 @@ import ( humanize "github.com/dustin/go-humanize" cmds "github.com/ipfs/go-ipfs-cmds" - metrics "github.com/libp2p/go-libp2p-metrics" - peer "github.com/libp2p/go-libp2p-peer" - protocol "github.com/libp2p/go-libp2p-protocol" + metrics "github.com/libp2p/go-libp2p-core/metrics" + peer "github.com/libp2p/go-libp2p-core/peer" + protocol "github.com/libp2p/go-libp2p-core/protocol" ) var StatsCmd = &cmds.Command{ diff --git a/core/commands/swarm.go b/core/commands/swarm.go index 56857104601..3a413a68451 100644 --- a/core/commands/swarm.go +++ b/core/commands/swarm.go @@ -18,9 +18,8 @@ import ( iaddr "github.com/ipfs/go-ipfs-addr" cmds "github.com/ipfs/go-ipfs-cmds" config "github.com/ipfs/go-ipfs-config" - inet "github.com/libp2p/go-libp2p-net" - peer "github.com/libp2p/go-libp2p-peer" - pstore "github.com/libp2p/go-libp2p-peerstore" + inet "github.com/libp2p/go-libp2p-core/network" + peer "github.com/libp2p/go-libp2p-core/peer" swarm "github.com/libp2p/go-libp2p-swarm" mafilter "github.com/libp2p/go-maddr-filter" ma "github.com/multiformats/go-multiaddr" @@ -467,7 +466,7 @@ func parseMultiaddrs(maddrs []ma.Multiaddr) (iaddrs []iaddr.IPFSAddr, err error) // peersWithAddresses is a function that takes in a slice of string peer addresses // (multiaddr + peerid) and returns a slice of properly constructed peers -func peersWithAddresses(ctx context.Context, addrs []string) ([]pstore.PeerInfo, error) { +func peersWithAddresses(ctx context.Context, addrs []string) ([]peer.AddrInfo, error) { // resolve addresses maddrs, err := resolveAddresses(ctx, addrs) if err != nil { @@ -489,9 +488,9 @@ func peersWithAddresses(ctx context.Context, addrs []string) ([]pstore.PeerInfo, peers[id] = nil } } - pis := make([]pstore.PeerInfo, 0, len(peers)) + pis := make([]peer.AddrInfo, 0, len(peers)) for id, maddrs := range peers { - pis = append(pis, pstore.PeerInfo{ + pis = append(pis, peer.AddrInfo{ ID: id, Addrs: maddrs, }) diff --git a/core/core.go b/core/core.go index 14b319330ad..8b411457155 100644 --- a/core/core.go +++ b/core/core.go @@ -31,21 +31,21 @@ import ( exchange "github.com/ipfs/go-ipfs-exchange-interface" ipld "github.com/ipfs/go-ipld-format" logging "github.com/ipfs/go-log" - "github.com/ipfs/go-mfs" - "github.com/ipfs/go-path/resolver" - "github.com/jbenet/goprocess" + mfs "github.com/ipfs/go-mfs" + resolver "github.com/ipfs/go-path/resolver" + goprocess "github.com/jbenet/goprocess" autonat "github.com/libp2p/go-libp2p-autonat-svc" - ic "github.com/libp2p/go-libp2p-crypto" - p2phost "github.com/libp2p/go-libp2p-host" - ifconnmgr "github.com/libp2p/go-libp2p-interface-connmgr" + connmgr "github.com/libp2p/go-libp2p-core/connmgr" + ic "github.com/libp2p/go-libp2p-core/crypto" + p2phost "github.com/libp2p/go-libp2p-core/host" + metrics "github.com/libp2p/go-libp2p-core/metrics" + peer "github.com/libp2p/go-libp2p-core/peer" + pstore "github.com/libp2p/go-libp2p-core/peerstore" + routing "github.com/libp2p/go-libp2p-core/routing" dht "github.com/libp2p/go-libp2p-kad-dht" - metrics "github.com/libp2p/go-libp2p-metrics" - peer "github.com/libp2p/go-libp2p-peer" - pstore "github.com/libp2p/go-libp2p-peerstore" pubsub "github.com/libp2p/go-libp2p-pubsub" psrouter "github.com/libp2p/go-libp2p-pubsub-router" record "github.com/libp2p/go-libp2p-record" - routing "github.com/libp2p/go-libp2p-routing" "github.com/libp2p/go-libp2p/p2p/discovery" p2pbhost "github.com/libp2p/go-libp2p/p2p/host/basic" "github.com/libp2p/go-libp2p/p2p/protocol/identify" @@ -88,7 +88,7 @@ type IpfsNode struct { // Online PeerHost p2phost.Host `optional:"true"` // the network host (server+client) Bootstrapper io.Closer `optional:"true"` // the periodic bootstrapper - Routing routing.IpfsRouting `optional:"true"` // the routing system. recommend ipfs-dht + Routing routing.Routing `optional:"true"` // the routing system. recommend ipfs-dht Exchange exchange.Interface // the block exchange + strategy (bitswap) Namesys namesys.NameSystem // the name system, resolves paths to hashes Provider provider.System // the value provider system @@ -145,7 +145,7 @@ func (n *IpfsNode) Bootstrap(cfg bootstrap.BootstrapConfig) error { // if the caller did not specify a bootstrap peer function, get the // freshest bootstrap peers from config. this responds to live changes. if cfg.BootstrapPeers == nil { - cfg.BootstrapPeers = func() []pstore.PeerInfo { + cfg.BootstrapPeers = func() []peer.AddrInfo { ps, err := n.loadBootstrapPeers() if err != nil { log.Warning("failed to parse bootstrap peers from config") @@ -160,7 +160,7 @@ func (n *IpfsNode) Bootstrap(cfg bootstrap.BootstrapConfig) error { return err } -func (n *IpfsNode) loadBootstrapPeers() ([]pstore.PeerInfo, error) { +func (n *IpfsNode) loadBootstrapPeers() ([]peer.AddrInfo, error) { cfg, err := n.Repo.Config() if err != nil { return nil, err @@ -178,5 +178,5 @@ type ConstructPeerHostOpts struct { DisableNatPortMap bool DisableRelay bool EnableRelayHop bool - ConnectionManager ifconnmgr.ConnManager + ConnectionManager connmgr.ConnManager } diff --git a/core/coreapi/coreapi.go b/core/coreapi/coreapi.go index dbbeba1fecd..85a2b24f602 100644 --- a/core/coreapi/coreapi.go +++ b/core/coreapi/coreapi.go @@ -35,13 +35,13 @@ import ( dag "github.com/ipfs/go-merkledag" coreiface "github.com/ipfs/interface-go-ipfs-core" "github.com/ipfs/interface-go-ipfs-core/options" - ci "github.com/libp2p/go-libp2p-crypto" - p2phost "github.com/libp2p/go-libp2p-host" - "github.com/libp2p/go-libp2p-peer" - pstore "github.com/libp2p/go-libp2p-peerstore" + ci "github.com/libp2p/go-libp2p-core/crypto" + p2phost "github.com/libp2p/go-libp2p-core/host" + peer "github.com/libp2p/go-libp2p-core/peer" + pstore "github.com/libp2p/go-libp2p-core/peerstore" + routing "github.com/libp2p/go-libp2p-core/routing" pubsub "github.com/libp2p/go-libp2p-pubsub" record "github.com/libp2p/go-libp2p-record" - "github.com/libp2p/go-libp2p-routing" ) var log = logging.Logger("core/coreapi") @@ -66,7 +66,7 @@ type CoreAPI struct { exchange exchange.Interface namesys namesys.NameSystem - routing routing.IpfsRouting + routing routing.Routing provider provider.System diff --git a/core/coreapi/dht.go b/core/coreapi/dht.go index c7e0ebc57ab..fcef6fdf927 100644 --- a/core/coreapi/dht.go +++ b/core/coreapi/dht.go @@ -13,28 +13,27 @@ import ( coreiface "github.com/ipfs/interface-go-ipfs-core" caopts "github.com/ipfs/interface-go-ipfs-core/options" path "github.com/ipfs/interface-go-ipfs-core/path" - peer "github.com/libp2p/go-libp2p-peer" - pstore "github.com/libp2p/go-libp2p-peerstore" - routing "github.com/libp2p/go-libp2p-routing" + peer "github.com/libp2p/go-libp2p-core/peer" + routing "github.com/libp2p/go-libp2p-core/routing" ) type DhtAPI CoreAPI -func (api *DhtAPI) FindPeer(ctx context.Context, p peer.ID) (pstore.PeerInfo, error) { +func (api *DhtAPI) FindPeer(ctx context.Context, p peer.ID) (peer.AddrInfo, error) { err := api.checkOnline(false) if err != nil { - return pstore.PeerInfo{}, err + return peer.AddrInfo{}, err } pi, err := api.routing.FindPeer(ctx, peer.ID(p)) if err != nil { - return pstore.PeerInfo{}, err + return peer.AddrInfo{}, err } return pi, nil } -func (api *DhtAPI) FindProviders(ctx context.Context, p path.Path, opts ...caopts.DhtFindProvidersOption) (<-chan pstore.PeerInfo, error) { +func (api *DhtAPI) FindProviders(ctx context.Context, p path.Path, opts ...caopts.DhtFindProvidersOption) (<-chan peer.AddrInfo, error) { settings, err := caopts.DhtFindProvidersOptions(opts...) if err != nil { return nil, err @@ -98,7 +97,7 @@ func (api *DhtAPI) Provide(ctx context.Context, path path.Path, opts ...caopts.D return nil } -func provideKeys(ctx context.Context, r routing.IpfsRouting, cids []cid.Cid) error { +func provideKeys(ctx context.Context, r routing.Routing, cids []cid.Cid) error { for _, c := range cids { err := r.Provide(ctx, c, true) if err != nil { @@ -108,7 +107,7 @@ func provideKeys(ctx context.Context, r routing.IpfsRouting, cids []cid.Cid) err return nil } -func provideKeysRec(ctx context.Context, r routing.IpfsRouting, bs blockstore.Blockstore, cids []cid.Cid) error { +func provideKeysRec(ctx context.Context, r routing.Routing, bs blockstore.Blockstore, cids []cid.Cid) error { provided := cidutil.NewStreamingSet() errCh := make(chan error) diff --git a/core/coreapi/key.go b/core/coreapi/key.go index 4fea3c5d405..e6fe7b124d1 100644 --- a/core/coreapi/key.go +++ b/core/coreapi/key.go @@ -11,8 +11,8 @@ import ( coreiface "github.com/ipfs/interface-go-ipfs-core" caopts "github.com/ipfs/interface-go-ipfs-core/options" path "github.com/ipfs/interface-go-ipfs-core/path" - crypto "github.com/libp2p/go-libp2p-crypto" - peer "github.com/libp2p/go-libp2p-peer" + crypto "github.com/libp2p/go-libp2p-core/crypto" + peer "github.com/libp2p/go-libp2p-core/peer" ) type KeyAPI CoreAPI diff --git a/core/coreapi/name.go b/core/coreapi/name.go index 43ed78b9f75..da38b929b18 100644 --- a/core/coreapi/name.go +++ b/core/coreapi/name.go @@ -13,9 +13,8 @@ import ( coreiface "github.com/ipfs/interface-go-ipfs-core" caopts "github.com/ipfs/interface-go-ipfs-core/options" path "github.com/ipfs/interface-go-ipfs-core/path" - "github.com/libp2p/go-libp2p-crypto" - ci "github.com/libp2p/go-libp2p-crypto" - "github.com/libp2p/go-libp2p-peer" + ci "github.com/libp2p/go-libp2p-core/crypto" + peer "github.com/libp2p/go-libp2p-core/peer" ) type NameAPI CoreAPI @@ -139,7 +138,7 @@ func (api *NameAPI) Resolve(ctx context.Context, name string, opts ...caopts.Nam return p, err } -func keylookup(self ci.PrivKey, kstore keystore.Keystore, k string) (crypto.PrivKey, error) { +func keylookup(self ci.PrivKey, kstore keystore.Keystore, k string) (ci.PrivKey, error) { if k == "self" { return self, nil } diff --git a/core/coreapi/pubsub.go b/core/coreapi/pubsub.go index 987d9d6c8ba..c36019342fc 100644 --- a/core/coreapi/pubsub.go +++ b/core/coreapi/pubsub.go @@ -10,11 +10,10 @@ import ( cid "github.com/ipfs/go-cid" coreiface "github.com/ipfs/interface-go-ipfs-core" caopts "github.com/ipfs/interface-go-ipfs-core/options" - p2phost "github.com/libp2p/go-libp2p-host" - peer "github.com/libp2p/go-libp2p-peer" - pstore "github.com/libp2p/go-libp2p-peerstore" + p2phost "github.com/libp2p/go-libp2p-core/host" + peer "github.com/libp2p/go-libp2p-core/peer" + routing "github.com/libp2p/go-libp2p-core/routing" pubsub "github.com/libp2p/go-libp2p-pubsub" - routing "github.com/libp2p/go-libp2p-routing" ) type PubSubAPI CoreAPI @@ -93,7 +92,7 @@ func (api *PubSubAPI) Subscribe(ctx context.Context, topic string, opts ...caopt return &pubSubSubscription{cancel, sub}, nil } -func connectToPubSubPeers(ctx context.Context, r routing.IpfsRouting, ph p2phost.Host, cid cid.Cid) { +func connectToPubSubPeers(ctx context.Context, r routing.Routing, ph p2phost.Host, cid cid.Cid) { ctx, cancel := context.WithCancel(ctx) defer cancel() @@ -101,7 +100,7 @@ func connectToPubSubPeers(ctx context.Context, r routing.IpfsRouting, ph p2phost var wg sync.WaitGroup for p := range provs { wg.Add(1) - go func(pi pstore.PeerInfo) { + go func(pi peer.AddrInfo) { defer wg.Done() ctx, cancel := context.WithTimeout(ctx, time.Second*10) defer cancel() @@ -117,7 +116,7 @@ func connectToPubSubPeers(ctx context.Context, r routing.IpfsRouting, ph p2phost wg.Wait() } -func (api *PubSubAPI) checkNode() (routing.IpfsRouting, error) { +func (api *PubSubAPI) checkNode() (routing.Routing, error) { if api.pubSub == nil { return nil, errors.New("experimental pubsub feature not enabled. Run daemon with --enable-pubsub-experiment to use.") } diff --git a/core/coreapi/swarm.go b/core/coreapi/swarm.go index 8b55e8278e3..8e2ea9a573a 100644 --- a/core/coreapi/swarm.go +++ b/core/coreapi/swarm.go @@ -7,11 +7,10 @@ import ( iaddr "github.com/ipfs/go-ipfs-addr" coreiface "github.com/ipfs/interface-go-ipfs-core" - inet "github.com/libp2p/go-libp2p-net" - net "github.com/libp2p/go-libp2p-net" - peer "github.com/libp2p/go-libp2p-peer" - pstore "github.com/libp2p/go-libp2p-peerstore" - protocol "github.com/libp2p/go-libp2p-protocol" + inet "github.com/libp2p/go-libp2p-core/network" + peer "github.com/libp2p/go-libp2p-core/peer" + pstore "github.com/libp2p/go-libp2p-core/peerstore" + protocol "github.com/libp2p/go-libp2p-core/protocol" swarm "github.com/libp2p/go-libp2p-swarm" ma "github.com/multiformats/go-multiaddr" ) @@ -20,8 +19,8 @@ type SwarmAPI CoreAPI type connInfo struct { peerstore pstore.Peerstore - conn net.Conn - dir net.Direction + conn inet.Conn + dir inet.Direction addr ma.Multiaddr peer peer.ID @@ -31,7 +30,7 @@ type connInfo struct { const connectionManagerTag = "user-connect" const connectionManagerWeight = 100 -func (api *SwarmAPI) Connect(ctx context.Context, pi pstore.PeerInfo) error { +func (api *SwarmAPI) Connect(ctx context.Context, pi peer.AddrInfo) error { if api.peerHost == nil { return coreiface.ErrOffline } @@ -159,7 +158,7 @@ func (ci *connInfo) Address() ma.Multiaddr { return ci.addr } -func (ci *connInfo) Direction() net.Direction { +func (ci *connInfo) Direction() inet.Direction { return ci.dir } diff --git a/core/coreapi/test/api_test.go b/core/coreapi/test/api_test.go index 399722a839a..f6700e1afa4 100644 --- a/core/coreapi/test/api_test.go +++ b/core/coreapi/test/api_test.go @@ -8,12 +8,11 @@ import ( "path/filepath" "testing" - "github.com/ipfs/go-ipfs/core/bootstrap" - "github.com/ipfs/go-ipfs/filestore" - "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/filestore" "github.com/ipfs/go-ipfs/keystore" "github.com/ipfs/go-ipfs/repo" @@ -22,9 +21,8 @@ import ( "github.com/ipfs/go-ipfs-config" coreiface "github.com/ipfs/interface-go-ipfs-core" "github.com/ipfs/interface-go-ipfs-core/tests" - ci "github.com/libp2p/go-libp2p-crypto" - "github.com/libp2p/go-libp2p-peer" - pstore "github.com/libp2p/go-libp2p-peerstore" + ci "github.com/libp2p/go-libp2p-core/crypto" + peer "github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p/p2p/net/mock" ) @@ -103,7 +101,7 @@ func (NodeProvider) MakeAPISwarm(ctx context.Context, fullIdentity bool, n int) } bsinf := bootstrap.BootstrapConfigWithPeers( - []pstore.PeerInfo{ + []peer.AddrInfo{ nodes[0].Peerstore.PeerInfo(nodes[0].Identity), }, ) diff --git a/core/corehttp/gateway_handler.go b/core/corehttp/gateway_handler.go index d3cca5d3db0..3f212d9180b 100644 --- a/core/corehttp/gateway_handler.go +++ b/core/corehttp/gateway_handler.go @@ -28,7 +28,7 @@ import ( "github.com/ipfs/go-unixfs/importer" coreiface "github.com/ipfs/interface-go-ipfs-core" ipath "github.com/ipfs/interface-go-ipfs-core/path" - routing "github.com/libp2p/go-libp2p-routing" + routing "github.com/libp2p/go-libp2p-core/routing" "github.com/multiformats/go-multibase" ) diff --git a/core/corehttp/gateway_test.go b/core/corehttp/gateway_test.go index 3578f33ad82..0e08ea2ff86 100644 --- a/core/corehttp/gateway_test.go +++ b/core/corehttp/gateway_test.go @@ -24,7 +24,7 @@ import ( iface "github.com/ipfs/interface-go-ipfs-core" nsopts "github.com/ipfs/interface-go-ipfs-core/options/namesys" ipath "github.com/ipfs/interface-go-ipfs-core/path" - ci "github.com/libp2p/go-libp2p-crypto" + ci "github.com/libp2p/go-libp2p-core/crypto" id "github.com/libp2p/go-libp2p/p2p/protocol/identify" ) diff --git a/core/corehttp/metrics_test.go b/core/corehttp/metrics_test.go index 49270a71a93..847d681a58c 100644 --- a/core/corehttp/metrics_test.go +++ b/core/corehttp/metrics_test.go @@ -7,7 +7,7 @@ import ( core "github.com/ipfs/go-ipfs/core" - inet "github.com/libp2p/go-libp2p-net" + inet "github.com/libp2p/go-libp2p-core/network" swarmt "github.com/libp2p/go-libp2p-swarm/testing" bhost "github.com/libp2p/go-libp2p/p2p/host/basic" ) diff --git a/core/corehttp/proxy.go b/core/corehttp/proxy.go index 02255d255ff..64d796cba5c 100644 --- a/core/corehttp/proxy.go +++ b/core/corehttp/proxy.go @@ -11,7 +11,7 @@ import ( core "github.com/ipfs/go-ipfs/core" p2phttp "github.com/hsanjuan/go-libp2p-http" - protocol "github.com/libp2p/go-libp2p-protocol" + protocol "github.com/libp2p/go-libp2p-core/protocol" ) // ProxyOption is an endpoint for proxying a HTTP request to another ipfs peer diff --git a/core/corehttp/proxy_test.go b/core/corehttp/proxy_test.go index 966f12c37d7..98d749e0c50 100644 --- a/core/corehttp/proxy_test.go +++ b/core/corehttp/proxy_test.go @@ -7,7 +7,7 @@ import ( "github.com/ipfs/go-ipfs/thirdparty/assert" - protocol "github.com/libp2p/go-libp2p-protocol" + protocol "github.com/libp2p/go-libp2p-core/protocol" ) type TestCase struct { diff --git a/core/mock/mock.go b/core/mock/mock.go index f8dbed7e09d..2867de1112a 100644 --- a/core/mock/mock.go +++ b/core/mock/mock.go @@ -2,6 +2,7 @@ package coremock import ( "context" + libp2p2 "github.com/ipfs/go-ipfs/core/node/libp2p" "github.com/ipfs/go-ipfs/commands" @@ -11,12 +12,14 @@ import ( "github.com/ipfs/go-datastore" syncds "github.com/ipfs/go-datastore/sync" config "github.com/ipfs/go-ipfs-config" + "github.com/libp2p/go-libp2p" - host "github.com/libp2p/go-libp2p-host" - peer "github.com/libp2p/go-libp2p-peer" - pstore "github.com/libp2p/go-libp2p-peerstore" + host "github.com/libp2p/go-libp2p-core/host" + peer "github.com/libp2p/go-libp2p-core/peer" + pstore "github.com/libp2p/go-libp2p-core/peerstore" + testutil "github.com/libp2p/go-libp2p-testing/net" + mocknet "github.com/libp2p/go-libp2p/p2p/net/mock" - "github.com/libp2p/go-testutil" ) // NewMockNode constructs an IpfsNode for use in tests. diff --git a/core/node/builder.go b/core/node/builder.go index 8424acbcd11..129ac0a3e40 100644 --- a/core/node/builder.go +++ b/core/node/builder.go @@ -15,8 +15,8 @@ import ( ds "github.com/ipfs/go-datastore" dsync "github.com/ipfs/go-datastore/sync" cfg "github.com/ipfs/go-ipfs-config" - ci "github.com/libp2p/go-libp2p-crypto" - peer "github.com/libp2p/go-libp2p-peer" + ci "github.com/libp2p/go-libp2p-core/crypto" + peer "github.com/libp2p/go-libp2p-core/peer" ) type BuildCfg struct { diff --git a/core/node/core.go b/core/node/core.go index 2445836cc2c..ddb42aff5c4 100644 --- a/core/node/core.go +++ b/core/node/core.go @@ -20,8 +20,8 @@ import ( "github.com/ipfs/go-merkledag" "github.com/ipfs/go-mfs" "github.com/ipfs/go-unixfs" - "github.com/libp2p/go-libp2p-host" - "github.com/libp2p/go-libp2p-routing" + "github.com/libp2p/go-libp2p-core/host" + "github.com/libp2p/go-libp2p-core/routing" "go.uber.org/fx" ) @@ -60,7 +60,7 @@ func Dag(bs blockservice.BlockService) format.DAGService { // OnlineExchange creates new LibP2P backed block exchange (BitSwap) func OnlineExchange(provide bool) interface{} { - return func(mctx helpers.MetricsCtx, lc fx.Lifecycle, host host.Host, rt routing.IpfsRouting, bs blockstore.GCBlockstore) exchange.Interface { + return func(mctx helpers.MetricsCtx, lc fx.Lifecycle, host host.Host, rt routing.Routing, bs blockstore.GCBlockstore) exchange.Interface { bitswapNetwork := network.NewFromIpfsHost(host, rt) exch := bitswap.New(helpers.LifecycleCtx(mctx, lc), bitswapNetwork, bs, bitswap.ProvideEnabled(provide)) lc.Append(fx.Hook{ diff --git a/core/node/groups.go b/core/node/groups.go index a66d0fb8aa4..5e84b9a5838 100644 --- a/core/node/groups.go +++ b/core/node/groups.go @@ -9,7 +9,7 @@ import ( blockstore "github.com/ipfs/go-ipfs-blockstore" "github.com/ipfs/go-ipfs-config" util "github.com/ipfs/go-ipfs-util" - peer "github.com/libp2p/go-libp2p-peer" + peer "github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-peerstore/pstoremem" pubsub "github.com/libp2p/go-libp2p-pubsub" diff --git a/core/node/identity.go b/core/node/identity.go index 46baa84942c..ad6eb2383f5 100644 --- a/core/node/identity.go +++ b/core/node/identity.go @@ -3,8 +3,8 @@ package node import ( "fmt" - "github.com/libp2p/go-libp2p-crypto" - "github.com/libp2p/go-libp2p-peer" + "github.com/libp2p/go-libp2p-core/crypto" + "github.com/libp2p/go-libp2p-core/peer" ) func PeerID(id peer.ID) func() peer.ID { diff --git a/core/node/ipns.go b/core/node/ipns.go index 1f245760331..11769d97f92 100644 --- a/core/node/ipns.go +++ b/core/node/ipns.go @@ -6,10 +6,10 @@ import ( "github.com/ipfs/go-ipfs-util" "github.com/ipfs/go-ipns" - "github.com/libp2p/go-libp2p-crypto" - "github.com/libp2p/go-libp2p-peerstore" + "github.com/libp2p/go-libp2p-core/crypto" + "github.com/libp2p/go-libp2p-core/peerstore" + "github.com/libp2p/go-libp2p-core/routing" "github.com/libp2p/go-libp2p-record" - "github.com/libp2p/go-libp2p-routing" "github.com/ipfs/go-ipfs/namesys" "github.com/ipfs/go-ipfs/namesys/republisher" @@ -27,8 +27,8 @@ func RecordValidator(ps peerstore.Peerstore) record.Validator { } // Namesys creates new name system -func Namesys(cacheSize int) func(rt routing.IpfsRouting, repo repo.Repo) (namesys.NameSystem, error) { - return func(rt routing.IpfsRouting, repo repo.Repo) (namesys.NameSystem, error) { +func Namesys(cacheSize int) func(rt routing.Routing, repo repo.Repo) (namesys.NameSystem, error) { + return func(rt routing.Routing, repo repo.Repo) (namesys.NameSystem, error) { return namesys.NewNameSystem(rt, repo.Datastore(), cacheSize), nil } } diff --git a/core/node/libp2p/addrs.go b/core/node/libp2p/addrs.go index d20417b70c5..703a959cbae 100644 --- a/core/node/libp2p/addrs.go +++ b/core/node/libp2p/addrs.go @@ -4,7 +4,7 @@ import ( "fmt" "github.com/libp2p/go-libp2p" - host "github.com/libp2p/go-libp2p-host" + host "github.com/libp2p/go-libp2p-core/host" p2pbhost "github.com/libp2p/go-libp2p/p2p/host/basic" mafilter "github.com/libp2p/go-maddr-filter" ma "github.com/multiformats/go-multiaddr" diff --git a/core/node/libp2p/discovery.go b/core/node/libp2p/discovery.go index f1351d6468f..7b0c8263470 100644 --- a/core/node/libp2p/discovery.go +++ b/core/node/libp2p/discovery.go @@ -4,8 +4,8 @@ import ( "context" "time" - "github.com/libp2p/go-libp2p-host" - "github.com/libp2p/go-libp2p-peerstore" + "github.com/libp2p/go-libp2p-core/host" + "github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p/p2p/discovery" "go.uber.org/fx" @@ -19,7 +19,7 @@ type discoveryHandler struct { host host.Host } -func (dh *discoveryHandler) HandlePeerFound(p peerstore.PeerInfo) { +func (dh *discoveryHandler) HandlePeerFound(p peer.AddrInfo) { log.Warning("trying peer info: ", p) ctx, cancel := context.WithTimeout(dh.ctx, discoveryConnTimeout) defer cancel() diff --git a/core/node/libp2p/host.go b/core/node/libp2p/host.go index f2a9069ce24..57475316e35 100644 --- a/core/node/libp2p/host.go +++ b/core/node/libp2p/host.go @@ -4,11 +4,11 @@ import ( "context" "github.com/libp2p/go-libp2p" - host "github.com/libp2p/go-libp2p-host" - peer "github.com/libp2p/go-libp2p-peer" - peerstore "github.com/libp2p/go-libp2p-peerstore" + host "github.com/libp2p/go-libp2p-core/host" + peer "github.com/libp2p/go-libp2p-core/peer" + peerstore "github.com/libp2p/go-libp2p-core/peerstore" + routing "github.com/libp2p/go-libp2p-core/routing" record "github.com/libp2p/go-libp2p-record" - routing "github.com/libp2p/go-libp2p-routing" routedhost "github.com/libp2p/go-libp2p/p2p/host/routed" "go.uber.org/fx" diff --git a/core/node/libp2p/hostopt.go b/core/node/libp2p/hostopt.go index 984c038bd51..26d6cad7066 100644 --- a/core/node/libp2p/hostopt.go +++ b/core/node/libp2p/hostopt.go @@ -5,9 +5,9 @@ import ( "fmt" "github.com/libp2p/go-libp2p" - host "github.com/libp2p/go-libp2p-host" - peer "github.com/libp2p/go-libp2p-peer" - peerstore "github.com/libp2p/go-libp2p-peerstore" + host "github.com/libp2p/go-libp2p-core/host" + peer "github.com/libp2p/go-libp2p-core/peer" + peerstore "github.com/libp2p/go-libp2p-core/peerstore" ) type HostOption func(ctx context.Context, id peer.ID, ps peerstore.Peerstore, options ...libp2p.Option) (host.Host, error) diff --git a/core/node/libp2p/libp2p.go b/core/node/libp2p/libp2p.go index 758994b5622..f0c840279ac 100644 --- a/core/node/libp2p/libp2p.go +++ b/core/node/libp2p/libp2p.go @@ -6,9 +6,9 @@ import ( logging "github.com/ipfs/go-log" "github.com/libp2p/go-libp2p" "github.com/libp2p/go-libp2p-connmgr" - "github.com/libp2p/go-libp2p-crypto" - "github.com/libp2p/go-libp2p-peer" - "github.com/libp2p/go-libp2p-peerstore" + "github.com/libp2p/go-libp2p-core/crypto" + "github.com/libp2p/go-libp2p-core/peer" + "github.com/libp2p/go-libp2p-core/peerstore" "go.uber.org/fx" ) diff --git a/core/node/libp2p/nat.go b/core/node/libp2p/nat.go index b4aadf68593..6367d311b99 100644 --- a/core/node/libp2p/nat.go +++ b/core/node/libp2p/nat.go @@ -3,7 +3,7 @@ package libp2p import ( "github.com/libp2p/go-libp2p" autonat "github.com/libp2p/go-libp2p-autonat-svc" - host "github.com/libp2p/go-libp2p-host" + host "github.com/libp2p/go-libp2p-core/host" libp2pquic "github.com/libp2p/go-libp2p-quic-transport" "go.uber.org/fx" diff --git a/core/node/libp2p/pnet.go b/core/node/libp2p/pnet.go index 5f7a3763269..bf4cc556e42 100644 --- a/core/node/libp2p/pnet.go +++ b/core/node/libp2p/pnet.go @@ -7,7 +7,7 @@ import ( "time" "github.com/libp2p/go-libp2p" - host "github.com/libp2p/go-libp2p-host" + host "github.com/libp2p/go-libp2p-core/host" pnet "github.com/libp2p/go-libp2p-pnet" "go.uber.org/fx" diff --git a/core/node/libp2p/pubsub.go b/core/node/libp2p/pubsub.go index 4dd3f096566..c065cd7ee40 100644 --- a/core/node/libp2p/pubsub.go +++ b/core/node/libp2p/pubsub.go @@ -1,7 +1,7 @@ package libp2p import ( - host "github.com/libp2p/go-libp2p-host" + host "github.com/libp2p/go-libp2p-core/host" pubsub "github.com/libp2p/go-libp2p-pubsub" "go.uber.org/fx" diff --git a/core/node/libp2p/routing.go b/core/node/libp2p/routing.go index 9dc518871d4..6a27373db7e 100644 --- a/core/node/libp2p/routing.go +++ b/core/node/libp2p/routing.go @@ -4,12 +4,12 @@ import ( "context" "sort" - host "github.com/libp2p/go-libp2p-host" + host "github.com/libp2p/go-libp2p-core/host" + routing "github.com/libp2p/go-libp2p-core/routing" dht "github.com/libp2p/go-libp2p-kad-dht" "github.com/libp2p/go-libp2p-pubsub" namesys "github.com/libp2p/go-libp2p-pubsub-router" record "github.com/libp2p/go-libp2p-record" - routing "github.com/libp2p/go-libp2p-routing" routinghelpers "github.com/libp2p/go-libp2p-routing-helpers" "go.uber.org/fx" @@ -17,10 +17,10 @@ import ( "github.com/ipfs/go-ipfs/repo" ) -type BaseIpfsRouting routing.IpfsRouting +type BaseIpfsRouting routing.Routing type Router struct { - routing.IpfsRouting + routing.Routing Priority int // less = more important } @@ -44,8 +44,8 @@ func BaseRouting(lc fx.Lifecycle, in BaseIpfsRouting) (out p2pRouterOut, dr *dht return p2pRouterOut{ Router: Router{ - Priority: 1000, - IpfsRouting: in, + Priority: 1000, + Routing: in, }, }, dr } @@ -57,16 +57,16 @@ type p2pOnlineRoutingIn struct { Validator record.Validator } -func Routing(in p2pOnlineRoutingIn) routing.IpfsRouting { +func Routing(in p2pOnlineRoutingIn) routing.Routing { routers := in.Routers sort.SliceStable(routers, func(i, j int) bool { return routers[i].Priority < routers[j].Priority }) - irouters := make([]routing.IpfsRouting, len(routers)) + irouters := make([]routing.Routing, len(routers)) for i, v := range routers { - irouters[i] = v.IpfsRouting + irouters[i] = v.Routing } return routinghelpers.Tiered{ @@ -78,25 +78,25 @@ func Routing(in p2pOnlineRoutingIn) routing.IpfsRouting { type p2pPSRoutingIn struct { fx.In - BaseRouting BaseIpfsRouting - Repo repo.Repo - Validator record.Validator - Host host.Host - PubSub *pubsub.PubSub `optional:"true"` + BaseIpfsRouting BaseIpfsRouting + Repo repo.Repo + Validator record.Validator + Host host.Host + PubSub *pubsub.PubSub `optional:"true"` } func PubsubRouter(mctx helpers.MetricsCtx, lc fx.Lifecycle, in p2pPSRoutingIn) (p2pRouterOut, *namesys.PubsubValueStore) { psRouter := namesys.NewPubsubValueStore( helpers.LifecycleCtx(mctx, lc), in.Host, - in.BaseRouting, + in.BaseIpfsRouting, in.PubSub, in.Validator, ) return p2pRouterOut{ Router: Router{ - IpfsRouting: &routinghelpers.Compose{ + Routing: &routinghelpers.Compose{ ValueStore: &routinghelpers.LimitedValueStore{ ValueStore: psRouter, Namespaces: []string{"ipns"}, diff --git a/core/node/libp2p/routingopt.go b/core/node/libp2p/routingopt.go index 5c756743668..35389d857f5 100644 --- a/core/node/libp2p/routingopt.go +++ b/core/node/libp2p/routingopt.go @@ -5,16 +5,16 @@ import ( "github.com/ipfs/go-datastore" nilrouting "github.com/ipfs/go-ipfs-routing/none" - host "github.com/libp2p/go-libp2p-host" + host "github.com/libp2p/go-libp2p-core/host" + routing "github.com/libp2p/go-libp2p-core/routing" dht "github.com/libp2p/go-libp2p-kad-dht" dhtopts "github.com/libp2p/go-libp2p-kad-dht/opts" record "github.com/libp2p/go-libp2p-record" - routing "github.com/libp2p/go-libp2p-routing" ) -type RoutingOption func(context.Context, host.Host, datastore.Batching, record.Validator) (routing.IpfsRouting, error) +type RoutingOption func(context.Context, host.Host, datastore.Batching, record.Validator) (routing.Routing, error) -func constructDHTRouting(ctx context.Context, host host.Host, dstore datastore.Batching, validator record.Validator) (routing.IpfsRouting, error) { +func constructDHTRouting(ctx context.Context, host host.Host, dstore datastore.Batching, validator record.Validator) (routing.Routing, error) { return dht.New( ctx, host, dhtopts.Datastore(dstore), @@ -22,7 +22,7 @@ func constructDHTRouting(ctx context.Context, host host.Host, dstore datastore.B ) } -func constructClientDHTRouting(ctx context.Context, host host.Host, dstore datastore.Batching, validator record.Validator) (routing.IpfsRouting, error) { +func constructClientDHTRouting(ctx context.Context, host host.Host, dstore datastore.Batching, validator record.Validator) (routing.Routing, error) { return dht.New( ctx, host, dhtopts.Client(true), diff --git a/core/node/libp2p/smux.go b/core/node/libp2p/smux.go index 2792de6752f..95e599ec200 100644 --- a/core/node/libp2p/smux.go +++ b/core/node/libp2p/smux.go @@ -5,9 +5,9 @@ import ( "strings" "github.com/libp2p/go-libp2p" + smux "github.com/libp2p/go-libp2p-core/mux" mplex "github.com/libp2p/go-libp2p-mplex" yamux "github.com/libp2p/go-libp2p-yamux" - smux "github.com/libp2p/go-stream-muxer" ) func makeSmuxTransportOption(mplexExp bool) libp2p.Option { @@ -21,7 +21,7 @@ func makeSmuxTransportOption(mplexExp bool) libp2p.Option { ymxtpt.LogOutput = os.Stderr } - muxers := map[string]smux.Transport{yamuxID: &ymxtpt} + muxers := map[string]smux.Multiplexer{yamuxID: &ymxtpt} if mplexExp { muxers[mplexID] = mplex.DefaultTransport } diff --git a/core/node/libp2p/transport.go b/core/node/libp2p/transport.go index c4572724eaa..526776ab3e6 100644 --- a/core/node/libp2p/transport.go +++ b/core/node/libp2p/transport.go @@ -2,7 +2,7 @@ package libp2p import ( "github.com/libp2p/go-libp2p" - metrics "github.com/libp2p/go-libp2p-metrics" + metrics "github.com/libp2p/go-libp2p-core/metrics" libp2pquic "github.com/libp2p/go-libp2p-quic-transport" secio "github.com/libp2p/go-libp2p-secio" tls "github.com/libp2p/go-libp2p-tls" diff --git a/core/node/provider.go b/core/node/provider.go index 43540745bf6..c87e2ac58d5 100644 --- a/core/node/provider.go +++ b/core/node/provider.go @@ -5,14 +5,13 @@ import ( "fmt" "time" - "go.uber.org/fx" - "github.com/ipfs/go-ipfs/core/node/helpers" "github.com/ipfs/go-ipfs/provider" q "github.com/ipfs/go-ipfs/provider/queue" "github.com/ipfs/go-ipfs/provider/simple" "github.com/ipfs/go-ipfs/repo" - "github.com/libp2p/go-libp2p-routing" + "github.com/libp2p/go-libp2p-core/routing" + "go.uber.org/fx" ) const kReprovideFrequency = time.Hour * 12 @@ -25,13 +24,13 @@ func ProviderQueue(mctx helpers.MetricsCtx, lc fx.Lifecycle, repo repo.Repo) (*q } // SimpleProvider creates new record provider -func SimpleProvider(mctx helpers.MetricsCtx, lc fx.Lifecycle, queue *q.Queue, rt routing.IpfsRouting) provider.Provider { +func SimpleProvider(mctx helpers.MetricsCtx, lc fx.Lifecycle, queue *q.Queue, rt routing.Routing) provider.Provider { return simple.NewProvider(helpers.LifecycleCtx(mctx, lc), queue, rt) } // SimpleReprovider creates new reprovider func SimpleReprovider(reproviderInterval time.Duration) interface{} { - return func(mctx helpers.MetricsCtx, lc fx.Lifecycle, rt routing.IpfsRouting, keyProvider simple.KeyChanFunc) (provider.Reprovider, error) { + return func(mctx helpers.MetricsCtx, lc fx.Lifecycle, rt routing.Routing, keyProvider simple.KeyChanFunc) (provider.Reprovider, error) { return simple.NewReprovider(helpers.LifecycleCtx(mctx, lc), reproviderInterval, rt, keyProvider), nil } } diff --git a/fuse/ipns/common.go b/fuse/ipns/common.go index c626dac94a2..182236aabf3 100644 --- a/fuse/ipns/common.go +++ b/fuse/ipns/common.go @@ -7,7 +7,7 @@ import ( nsys "github.com/ipfs/go-ipfs/namesys" path "github.com/ipfs/go-path" ft "github.com/ipfs/go-unixfs" - ci "github.com/libp2p/go-libp2p-crypto" + ci "github.com/libp2p/go-libp2p-core/crypto" ) // InitializeKeyspace sets the ipns record for the given key to diff --git a/fuse/ipns/ipns_test.go b/fuse/ipns/ipns_test.go index 80ab4a52ecf..cf59f65a715 100644 --- a/fuse/ipns/ipns_test.go +++ b/fuse/ipns/ipns_test.go @@ -20,7 +20,7 @@ import ( fstest "bazil.org/fuse/fs/fstestutil" racedet "github.com/ipfs/go-detect-race" u "github.com/ipfs/go-ipfs-util" - ci "github.com/libp2p/go-testutil/ci" + ci "github.com/libp2p/go-libp2p-testing/ci" ) func maybeSkipFuseTests(t *testing.T) { diff --git a/fuse/ipns/ipns_unix.go b/fuse/ipns/ipns_unix.go index a662ab22e78..f625f25a0e6 100644 --- a/fuse/ipns/ipns_unix.go +++ b/fuse/ipns/ipns_unix.go @@ -24,8 +24,8 @@ import ( cid "github.com/ipfs/go-cid" logging "github.com/ipfs/go-log" mfs "github.com/ipfs/go-mfs" - ci "github.com/libp2p/go-libp2p-crypto" - peer "github.com/libp2p/go-libp2p-peer" + ci "github.com/libp2p/go-libp2p-core/crypto" + peer "github.com/libp2p/go-libp2p-core/peer" ) func init() { diff --git a/fuse/node/mount_test.go b/fuse/node/mount_test.go index 9c8783901ac..a57d638199f 100644 --- a/fuse/node/mount_test.go +++ b/fuse/node/mount_test.go @@ -17,7 +17,7 @@ import ( ipns "github.com/ipfs/go-ipfs/fuse/ipns" mount "github.com/ipfs/go-ipfs/fuse/mount" - ci "github.com/libp2p/go-testutil/ci" + ci "github.com/libp2p/go-libp2p-testing/ci" ) func maybeSkipFuseTests(t *testing.T) { diff --git a/fuse/readonly/ipfs_test.go b/fuse/readonly/ipfs_test.go index 3f03779ad1b..bea43d2920e 100644 --- a/fuse/readonly/ipfs_test.go +++ b/fuse/readonly/ipfs_test.go @@ -31,7 +31,7 @@ import ( importer "github.com/ipfs/go-unixfs/importer" uio "github.com/ipfs/go-unixfs/io" ipath "github.com/ipfs/interface-go-ipfs-core/path" - ci "github.com/libp2p/go-testutil/ci" + ci "github.com/libp2p/go-libp2p-testing/ci" ) func maybeSkipFuseTests(t *testing.T) { diff --git a/go.mod b/go.mod index 8600f1a62c5..5714e958e9d 100644 --- a/go.mod +++ b/go.mod @@ -16,11 +16,11 @@ require ( github.com/golangci/golangci-lint v1.16.1-0.20190425135923-692dacb773b7 github.com/hashicorp/go-multierror v1.0.0 github.com/hashicorp/golang-lru v0.5.1 - github.com/hsanjuan/go-libp2p-http v0.0.2 + github.com/hsanjuan/go-libp2p-http v0.1.0 github.com/ipfs/dir-index-html v1.0.3 - github.com/ipfs/go-bitswap v0.0.7 + github.com/ipfs/go-bitswap v0.1.1 github.com/ipfs/go-block-format v0.0.2 - github.com/ipfs/go-blockservice v0.0.3 + github.com/ipfs/go-blockservice v0.1.0 github.com/ipfs/go-cid v0.0.2 github.com/ipfs/go-cidutil v0.0.2 github.com/ipfs/go-datastore v0.0.5 @@ -41,22 +41,22 @@ require ( github.com/ipfs/go-ipfs-exchange-offline v0.0.1 github.com/ipfs/go-ipfs-files v0.0.3 github.com/ipfs/go-ipfs-posinfo v0.0.1 - github.com/ipfs/go-ipfs-routing v0.0.1 + github.com/ipfs/go-ipfs-routing v0.1.0 github.com/ipfs/go-ipfs-util v0.0.1 github.com/ipfs/go-ipld-cbor v0.0.2 github.com/ipfs/go-ipld-format v0.0.2 github.com/ipfs/go-ipld-git v0.0.2 github.com/ipfs/go-ipns v0.0.1 github.com/ipfs/go-log v0.0.1 - github.com/ipfs/go-merkledag v0.0.3 + github.com/ipfs/go-merkledag v0.1.0 github.com/ipfs/go-metrics-interface v0.0.1 github.com/ipfs/go-metrics-prometheus v0.0.2 - github.com/ipfs/go-mfs v0.0.7 - github.com/ipfs/go-path v0.0.4 - github.com/ipfs/go-unixfs v0.0.6 + github.com/ipfs/go-mfs v0.1.0 + github.com/ipfs/go-path v0.0.7 + github.com/ipfs/go-unixfs v0.0.8 github.com/ipfs/go-verifcid v0.0.1 github.com/ipfs/hang-fds v0.0.1 - github.com/ipfs/interface-go-ipfs-core v0.0.8 + github.com/ipfs/interface-go-ipfs-core v0.1.0 github.com/ipfs/iptb v1.4.0 github.com/ipfs/iptb-plugins v0.0.2 github.com/jbenet/go-is-domain v1.0.2 @@ -64,39 +64,28 @@ require ( github.com/jbenet/go-random-files v0.0.0-20190219210431-31b3f20ebded github.com/jbenet/go-temp-err-catcher v0.0.0-20150120210811-aac704a3f4f2 github.com/jbenet/goprocess v0.1.3 - github.com/libp2p/go-libp2p v0.0.28 - github.com/libp2p/go-libp2p-autonat-svc v0.0.5 - github.com/libp2p/go-libp2p-circuit v0.0.8 - github.com/libp2p/go-libp2p-connmgr v0.0.6 - github.com/libp2p/go-libp2p-crypto v0.0.2 - github.com/libp2p/go-libp2p-host v0.0.3 - github.com/libp2p/go-libp2p-interface-connmgr v0.0.5 - github.com/libp2p/go-libp2p-kad-dht v0.0.13 - github.com/libp2p/go-libp2p-kbucket v0.1.1 - github.com/libp2p/go-libp2p-loggables v0.0.1 - github.com/libp2p/go-libp2p-metrics v0.0.1 - github.com/libp2p/go-libp2p-mplex v0.1.1 - github.com/libp2p/go-libp2p-net v0.0.2 - github.com/libp2p/go-libp2p-peer v0.1.1 - github.com/libp2p/go-libp2p-peerstore v0.0.6 - github.com/libp2p/go-libp2p-pnet v0.0.1 - github.com/libp2p/go-libp2p-protocol v0.0.1 - github.com/libp2p/go-libp2p-pubsub v0.0.3 - github.com/libp2p/go-libp2p-pubsub-router v0.0.3 - github.com/libp2p/go-libp2p-quic-transport v0.0.3 - github.com/libp2p/go-libp2p-record v0.0.1 - github.com/libp2p/go-libp2p-routing v0.0.1 - github.com/libp2p/go-libp2p-routing-helpers v0.0.2 - github.com/libp2p/go-libp2p-secio v0.0.3 - github.com/libp2p/go-libp2p-swarm v0.0.6 - github.com/libp2p/go-libp2p-tls v0.0.1 - github.com/libp2p/go-libp2p-yamux v0.1.3 + github.com/libp2p/go-libp2p v0.1.0 + github.com/libp2p/go-libp2p-autonat-svc v0.1.0 + github.com/libp2p/go-libp2p-circuit v0.1.0 + github.com/libp2p/go-libp2p-connmgr v0.1.0 + github.com/libp2p/go-libp2p-core v0.0.2 + github.com/libp2p/go-libp2p-kad-dht v0.1.0 + github.com/libp2p/go-libp2p-kbucket v0.2.0 + github.com/libp2p/go-libp2p-loggables v0.1.0 + github.com/libp2p/go-libp2p-mplex v0.2.1 + github.com/libp2p/go-libp2p-peerstore v0.1.0 + github.com/libp2p/go-libp2p-pnet v0.1.0 + github.com/libp2p/go-libp2p-pubsub v0.1.0 + github.com/libp2p/go-libp2p-pubsub-router v0.1.0 + github.com/libp2p/go-libp2p-quic-transport v0.1.1 + github.com/libp2p/go-libp2p-record v0.1.0 + github.com/libp2p/go-libp2p-routing-helpers v0.1.0 + github.com/libp2p/go-libp2p-secio v0.1.0 + github.com/libp2p/go-libp2p-swarm v0.1.0 + github.com/libp2p/go-libp2p-testing v0.0.3 + github.com/libp2p/go-libp2p-tls v0.1.0 + github.com/libp2p/go-libp2p-yamux v0.2.0 github.com/libp2p/go-maddr-filter v0.0.4 - github.com/libp2p/go-mplex v0.0.4 // indirect - github.com/libp2p/go-stream-muxer v0.0.1 - github.com/libp2p/go-testutil v0.0.1 - github.com/libp2p/go-yamux v1.2.3 // indirect - github.com/mattn/go-isatty v0.0.7 // indirect github.com/mattn/go-runewidth v0.0.4 // indirect github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect github.com/mitchellh/go-homedir v1.1.0 @@ -121,8 +110,7 @@ require ( go.uber.org/goleak v0.10.0 // indirect go.uber.org/multierr v1.1.0 // indirect go4.org v0.0.0-20190313082347-94abd6928b1d // indirect - golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5 - google.golang.org/appengine v1.4.0 // indirect + golang.org/x/sys v0.0.0-20190526052359-791d8a0f4d09 gopkg.in/cheggaaa/pb.v1 v1.0.28 gotest.tools/gotestsum v0.3.4 ) diff --git a/go.sum b/go.sum index b9011632354..b9cb4bcdeef 100644 --- a/go.sum +++ b/go.sum @@ -3,11 +3,14 @@ bazil.org/fuse v0.0.0-20180421153158-65cc252bf669/go.mod h1:Xbm+BRKSBEpa4q4hTSxo cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7 h1:PqzgE6kAMi81xWQA2QIVxjWkFHptGgC547vchpUbtFo= github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Kubuxu/go-os-helper v0.0.1 h1:EJiD2VUQyh5A9hWJLmc6iWg6yIcJ7jpBcwC8GMGXfDk= github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y= +github.com/Kubuxu/gocovmerge v0.0.0-20161216165753-7ecaa51963cd h1:HNhzThEtZW714v8Eda8sWWRcu9WSzJC+oCyjRjvZgRA= github.com/Kubuxu/gocovmerge v0.0.0-20161216165753-7ecaa51963cd/go.mod h1:bqoB8kInrTeEtYAwaIXoSRqdwnjQmFhsfusnzyui6yY= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/OpenPeeDeeP/depguard v0.0.0-20180806142446-a69c782687b2 h1:HTOmFEEYrWi4MW5ZKUx6xfeyM10Sx3kQF65xiQJMPYA= github.com/OpenPeeDeeP/depguard v0.0.0-20180806142446-a69c782687b2/go.mod h1:7/4sitnI9YlQgTLLk734QlzXT8DuHVnAyztLplQjk+o= github.com/Quasilyte/go-consistent v0.0.0-20181230194409-8f8379e70f99/go.mod h1:ds1OLa3HF2x4OGKCx0pNTVL1s9Ii/2mT0Bg/8PtW6AM= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= @@ -26,16 +29,14 @@ github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnweb 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-20190427004231-96897255fd17 h1:m0N5Vg5nP3zEz8TREZpwX3gt4Biw3/8fbIf4A3hO96g= -github.com/btcsuite/btcd v0.0.0-20190427004231-96897255fd17/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= +github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c h1:aEbSeNALREWXk0G7UdNhR3ayBV7tZ4M2PNmnrCAph6Q= +github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= -github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= -github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/cenkalti/backoff v2.1.1+incompatible h1:tKJnvO2kl0zmb/jA5UKAt4VoEVw1qxKWjE/Bpp46npY= @@ -45,12 +46,14 @@ github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitf github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-semver v0.2.1-0.20180108230905-e214231b295a h1:U0BbGfKnviqVBJQB4etvm+mKx53KfkumNLBt6YeF/0Q= github.com/coreos/go-semver v0.2.1-0.20180108230905-e214231b295a/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/cskr/pubsub v1.0.2 h1:vlOzMhl6PFn60gRlTQQsIfVwaPB/B/8MziK8FhEPt/0= github.com/cskr/pubsub v1.0.2/go.mod h1:/8MzYXk/NJAz782G8RPkFzXTZVu63VotefPnR9TIRis= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018 h1:6xT9KW8zLC5IlbaIF5Q7JNieBoACT7iW0YTxQHR0in0= github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018/go.mod h1:rQYf4tfk5sSwFsnDg3qYaBxSjsD9S8+59vW0dKUgme4= @@ -67,33 +70,48 @@ github.com/elgris/jsondiff v0.0.0-20160530203242-765b5c24c302/go.mod h1:qBlWZqWe github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 h1:BBso6MBKW8ncyZLv37o+KNyy0HrrHgfnOaGQC2qvN+A= github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5/go.mod h1:JpoxHjuQauoxiFMl1ie8Xc/7TfLuMZ5eOCONd1sUBHg= github.com/fatih/color v1.6.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fd/go-nat v1.0.0/go.mod h1:BTBu/CKvMmOMUPkKVef1pngt2WFH/lg7E6yQnulfp6E= +github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/go-check/check v0.0.0-20180628173108-788fd7840127 h1:0gkP6mzaMqkmpcJYCFOLkIBwI7xFExG03bbkOkCvUPI= github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= github.com/go-critic/go-critic v0.0.0-20181204210945-c3db6069acc5/go.mod h1:Jc75BZJv2dNy7opKH6bF29VveDQHfGZ6Asn/3phBesg= +github.com/go-critic/go-critic v0.0.0-20181204210945-ee9bf5809ead h1:qwmAYufKDopQnFdeMw+iHJVxAd2CbF+VFKHyJJwnPKk= github.com/go-critic/go-critic v0.0.0-20181204210945-ee9bf5809ead/go.mod h1:3MzXZKJdeXqdU9cj+rvZdNiN7SZ8V9OjybF8loZDmHU= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-lintpack/lintpack v0.5.2 h1:DI5mA3+eKdWeJ40nU4d6Wc26qmdG8RCi/btYq0TuRN0= github.com/go-lintpack/lintpack v0.5.2/go.mod h1:NwZuYi2nUHho8XEIZ6SIxihrnPoqBTDqfpXvXAN0sXM= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-toolsmith/astcast v0.0.0-20181028201508-b7a89ed70af1 h1:h+1eMw+tZAlgTVclcVN0/rdPaBI/RUzG0peblT6df+Q= github.com/go-toolsmith/astcast v0.0.0-20181028201508-b7a89ed70af1/go.mod h1:TEo3Ghaj7PsZawQHxT/oBvo4HK/sl1RcuUHDKTTju+o= +github.com/go-toolsmith/astcopy v0.0.0-20180903214859-79b422d080c4 h1:wVs9OMjICHbAryp9hcIuWqUOi+NqEbUSZy9zMe3W//I= github.com/go-toolsmith/astcopy v0.0.0-20180903214859-79b422d080c4/go.mod h1:c9CPdq2AzM8oPomdlPniEfPAC6g1s7NqZzODt8y6ib8= +github.com/go-toolsmith/astequal v0.0.0-20180903214952-dcb477bfacd6 h1:aTBUNRTatDDU24gbOEKEoLiDwxtc98ga6K/iMTm6fvs= github.com/go-toolsmith/astequal v0.0.0-20180903214952-dcb477bfacd6/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= +github.com/go-toolsmith/astfmt v0.0.0-20180903215011-8f8ee99c3086 h1:EIMuvbE9fbtQtimdLe5yeXjuC5CeKbQt8zH6GwtIrhM= github.com/go-toolsmith/astfmt v0.0.0-20180903215011-8f8ee99c3086/go.mod h1:mP93XdblcopXwlyN4X4uodxXQhldPGZbcEJIimQHrkg= github.com/go-toolsmith/astinfo v0.0.0-20180906194353-9809ff7efb21/go.mod h1:dDStQCHtmZpYOmjRP/8gHHnCCch3Zz3oEgCdZVdtweU= +github.com/go-toolsmith/astp v0.0.0-20180903215135-0af7e3c24f30 h1:zRJPftZJNLPDiOtvYbFRwjSbaJAcVOf80TeEmWGe2kQ= github.com/go-toolsmith/astp v0.0.0-20180903215135-0af7e3c24f30/go.mod h1:SV2ur98SGypH1UjcPpCatrV5hPazG6+IfNHbkDXBRrk= +github.com/go-toolsmith/pkgload v0.0.0-20181119091011-e9e65178eee8 h1:vVouagbdmqTVlCIAxpyYsNNTbkKZ3V66VpKOLU/s6W4= github.com/go-toolsmith/pkgload v0.0.0-20181119091011-e9e65178eee8/go.mod h1:WoMrjiy4zvdS+Bg6z9jZH82QXwkcgCBX6nOfnmdaHks= +github.com/go-toolsmith/strparse v0.0.0-20180903215201-830b6daa1241 h1:ZRDeQioMGTBLeJxcPxXfFifEUgYxzR7fXw7w2WR+1bo= github.com/go-toolsmith/strparse v0.0.0-20180903215201-830b6daa1241/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= +github.com/go-toolsmith/typep v0.0.0-20181030061450-d63dc7650676 h1:6Qrsp0+25KEkaS2bB26UE0giFgRrIc8mYXboDL5OVMA= github.com/go-toolsmith/typep v0.0.0-20181030061450-d63dc7650676/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= @@ -101,27 +119,46 @@ github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 h1:23T5iq8rbUYlhpt5DB4XJkc6BU31uODLD1o1gKvZmD0= github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4= +github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a h1:w8hkcTqaFpzKqonE9uMCefW1WDie15eSP/4MssdenaM= github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk= +github.com/golangci/errcheck v0.0.0-20181003203344-ef45e06d44b6 h1:i2jIkQFb8RG45DuQs+ElyROY848cSJIoIkBM+7XXypA= github.com/golangci/errcheck v0.0.0-20181003203344-ef45e06d44b6/go.mod h1:DbHgvLiFKX1Sh2T1w8Q/h4NAI8MHIpzCdnBUDTXU3I0= +github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613 h1:9kfjN3AdxcbsZBf8NjltjWihK2QfBBBZuv91cMFfDHw= github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613/go.mod h1:SyvUF2NxV+sN8upjjeVYr5W7tyxaT1JVtvhKhOn2ii8= +github.com/golangci/go-tools v0.0.0-20180109140146-af6baa5dc196 h1:9rtVlONXLF1rJZzvLt4tfOXtnAFUEhxCJ64Ibzj6ECo= github.com/golangci/go-tools v0.0.0-20180109140146-af6baa5dc196/go.mod h1:unzUULGw35sjyOYjUt0jMTXqHlZPpPc6e+xfO4cd6mM= +github.com/golangci/goconst v0.0.0-20180610141641-041c5f2b40f3 h1:pe9JHs3cHHDQgOFXJJdYkK6fLz2PWyYtP4hthoCMvs8= github.com/golangci/goconst v0.0.0-20180610141641-041c5f2b40f3/go.mod h1:JXrF4TWy4tXYn62/9x8Wm/K/dm06p8tCKwFRDPZG/1o= +github.com/golangci/gocyclo v0.0.0-20180528134321-2becd97e67ee h1:J2XAy40+7yz70uaOiMbNnluTg7gyQhtGqLQncQh+4J8= github.com/golangci/gocyclo v0.0.0-20180528134321-2becd97e67ee/go.mod h1:ozx7R9SIwqmqf5pRP90DhR2Oay2UIjGuKheCBCNwAYU= +github.com/golangci/gofmt v0.0.0-20181105071733-0b8337e80d98 h1:ir6/L2ZOJfFrJlOTsuf/hlzdPuUwXV/VzkSlgS6f1vs= github.com/golangci/gofmt v0.0.0-20181105071733-0b8337e80d98/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU= +github.com/golangci/golangci-lint v1.16.1-0.20190425135923-692dacb773b7 h1:RfttK8W9qaF98OAdNFW2Mbr3ELn1Dyw1nnip6kYVc8M= github.com/golangci/golangci-lint v1.16.1-0.20190425135923-692dacb773b7/go.mod h1:kSe2pu2LlcsMT5Dr95yNKUT5RNfMkwif9MZqtOW5NEs= +github.com/golangci/gosec v0.0.0-20180901114220-66fb7fc33547 h1:qMomh8bv+kDazm1dSLZ9S3zZ2PJZMHL4ilfBjxFOlmI= github.com/golangci/gosec v0.0.0-20180901114220-66fb7fc33547/go.mod h1:0qUabqiIQgfmlAmulqxyiGkkyF6/tOGSnY2cnPVwrzU= +github.com/golangci/ineffassign v0.0.0-20180808204949-2ee8f2867dde h1:qEGp3ZF1Qw6TkbWKn6GdJ12Ssu/CpJBaBcJ4hrUjrSo= github.com/golangci/ineffassign v0.0.0-20180808204949-2ee8f2867dde/go.mod h1:e5tpTHCfVze+7EpLEozzMB3eafxo2KT5veNg1k6byQU= +github.com/golangci/lint-1 v0.0.0-20180610141402-ee948d087217 h1:r7vyX+SN24x6+5AnpnrRn/bdwBb7U+McZqCHOVtXDuk= github.com/golangci/lint-1 v0.0.0-20180610141402-ee948d087217/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg= +github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca h1:kNY3/svz5T29MYHubXix4aDDuE3RWHkPvopM/EDv/MA= github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o= +github.com/golangci/misspell v0.0.0-20180809174111-950f5d19e770 h1:EL/O5HGrF7Jaq0yNhBLucz9hTuRzj2LdwGBOaENgxIk= github.com/golangci/misspell v0.0.0-20180809174111-950f5d19e770/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA= +github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21 h1:leSNB7iYzLYSSx3J/s5sVf4Drkc68W2wm4Ixh/mr0us= github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21/go.mod h1:tf5+bzsHdTM0bsB7+8mt0GUMvjCgwLpTapNZHU8AajI= +github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0 h1:HVfrLniijszjS1aiNg8JbBMO2+E1WIQ+j/gL4SQqGPg= github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0/go.mod h1:qOQCunEYvmd/TLamH+7LlVccLvUH5kZNhbCgTHoBbp4= +github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 h1:zwtduBRr5SSWhqsYNgcuWO2kFlpdOZbP0+yRjmvPGys= github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ= +github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= @@ -137,29 +174,39 @@ github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHh github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce h1:xdsDDbiBDQTKASoGEZ+pEmF1OnWuu8AQ9I8iNbHNeno= github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w= +github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/hsanjuan/go-libp2p-gostream v0.0.31 h1:9dIgHQPR0VWxhOyTZrbgLzTx0xvZ5rTpmhG9huGEPjY= -github.com/hsanjuan/go-libp2p-gostream v0.0.31/go.mod h1:cWvV5/NQ5XWi0eQZnX/svsAk6NLc4U26pItvj0eDeRk= -github.com/hsanjuan/go-libp2p-http v0.0.2 h1:hviJbUD3h1Ez2FYTUdnRjrkAzn/9i2V/cLZpFPgnuP8= -github.com/hsanjuan/go-libp2p-http v0.0.2/go.mod h1:MynY94gfOZxrw/0lVF4o7vbV2Zr84IC8sLBXmj8F5IE= +github.com/hsanjuan/go-libp2p-gostream v0.1.0 h1:Fk2j4UbUFsCvX9y66iL/8AqU4Il+QGnq73595eMoUX4= +github.com/hsanjuan/go-libp2p-gostream v0.1.0/go.mod h1:+mgB1KPi3ACeWxwwBKaJKxnCh4RTWDfIRqKqWwatvLI= +github.com/hsanjuan/go-libp2p-http v0.1.0 h1:O3t+2R/kqD4pTQUJJQdZlc/sMqub2ZMe+37SpQMGAn8= +github.com/hsanjuan/go-libp2p-http v0.1.0/go.mod h1:cI7XxaacYXbUv6WXkScPgo5EOc1eU1ktw6bVkygjsnk= 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= +github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/ipfs/bbloom v0.0.1 h1:s7KkiBPfxCeDVo47KySjK0ACPc5GJRUxFpdyWEuDjhw= github.com/ipfs/bbloom v0.0.1/go.mod h1:oqo8CVWsJFMOZqTglBG4wydCE4IQA/G2/SEofB0rjUI= github.com/ipfs/dir-index-html v1.0.3 h1:cKdOjJBKJgewgcv97zOlqsNOle52N91d3nAkbQadnuY= github.com/ipfs/dir-index-html v1.0.3/go.mod h1:TG9zbaH/+4MnkGel0xF4SLNhk+YZvBNo6jjBkO/LaWc= github.com/ipfs/go-bitswap v0.0.3/go.mod h1:jadAZYsP/tcRMl47ZhFxhaNuDQoXawT8iHMg+iFoQbg= -github.com/ipfs/go-bitswap v0.0.7 h1:BJwx7Kh5W845l10bOckkAJiNrT6XXWNaE8neK7H57q4= -github.com/ipfs/go-bitswap v0.0.7/go.mod h1:++LZRc+e1/ZxYsZq7QLKIPQvybh+70TMgeGuX+WB0pY= +github.com/ipfs/go-bitswap v0.0.9 h1:Dy0qvYlaOd2E2FOL2gApJ21qVjepJsGNNfstLrGf+0I= +github.com/ipfs/go-bitswap v0.0.9/go.mod h1:kAPf5qgn2W2DrgAcscZ3HrM9qh4pH+X8Fkk3UPrwvis= +github.com/ipfs/go-bitswap v0.1.0 h1:28YsHYw9ut6wootnImPXH0WpnU5Dbo3qm6cvQ6e6wYY= +github.com/ipfs/go-bitswap v0.1.0/go.mod h1:FFJEf18E9izuCqUtHxbWEvq+reg7o4CW5wSAE1wsxj0= +github.com/ipfs/go-bitswap v0.1.1 h1:5cNAqH8I7pRmgCIrEaPErWewxbUnLru2BCliegnN/5w= +github.com/ipfs/go-bitswap v0.1.1/go.mod h1:Eb5r34ftg4R38fGnQDlojCLZwZyr+WDsvBH5uLUQsjg= github.com/ipfs/go-block-format v0.0.1/go.mod h1:DK/YYcsSUIVAFNwo/KZCdIIbpN0ROH/baNLgayt4pFc= github.com/ipfs/go-block-format v0.0.2 h1:qPDvcP19izTjU8rgo6p7gTXZlkMkF5bz5G3fqIsSCPE= github.com/ipfs/go-block-format v0.0.2/go.mod h1:AWR46JfpcObNfg3ok2JHDUfdiHRgWhJgCQF+KIgOPJY= -github.com/ipfs/go-blockservice v0.0.3 h1:40OvwrxeudTAlUGUAKNYnNPcwQeLtXedjzTWecnUinQ= github.com/ipfs/go-blockservice v0.0.3/go.mod h1:/NNihwTi6V2Yr6g8wBI+BSwPuURpBRMtYNGrlxZ8KuI= +github.com/ipfs/go-blockservice v0.0.7 h1:VRRVjgahs7r//MdO7yY5DJ2/i2fmkKOnxfSyfuPjTm0= +github.com/ipfs/go-blockservice v0.0.7/go.mod h1:EOfb9k/Y878ZTRY/CH0x5+ATtaipfbRhbvNSdgc/7So= +github.com/ipfs/go-blockservice v0.1.0 h1:dh2i7xjMbCtf0ZSMyQAF2qpV/pEEmM7yVpQ00+gik6U= +github.com/ipfs/go-blockservice v0.1.0/go.mod h1:hzmMScl1kXHg3M2BjTymbVPjv627N7sYcvYaKbop39M= github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= github.com/ipfs/go-cid v0.0.2 h1:tuuKaZPU1M6HcejsO3AcYWW8sZ8MTvyxfc4uqB4eFE8= github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= @@ -169,6 +216,7 @@ github.com/ipfs/go-datastore v0.0.1/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAK github.com/ipfs/go-datastore v0.0.3/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= github.com/ipfs/go-datastore v0.0.5 h1:q3OfiOZV5rlsK1H5V8benjeUApRfMGs4Mrhmr6NriQo= github.com/ipfs/go-datastore v0.0.5/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= +github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk= github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= github.com/ipfs/go-ds-badger v0.0.2/go.mod h1:Y3QpeSFWQf6MopLTiZD+VT6IC1yZqaGmjvRcKeSGij8= github.com/ipfs/go-ds-badger v0.0.3 h1:sVYE2YlCzltznTZeAP1S+bp3qipz7VzogfZDtf6tGq0= @@ -186,6 +234,7 @@ github.com/ipfs/go-ipfs-addr v0.0.1 h1:DpDFybnho9v3/a1dzJ5KnWdThWD1HrFLpQ+tWIyBa github.com/ipfs/go-ipfs-addr v0.0.1/go.mod h1:uKTDljHT3Q3SUWzDLp3aYUi8MrY32fgNgogsIa0npjg= github.com/ipfs/go-ipfs-blockstore v0.0.1 h1:O9n3PbmTYZoNhkgkEyrXTznbmktIXif62xLX+8dPHzc= github.com/ipfs/go-ipfs-blockstore v0.0.1/go.mod h1:d3WClOmRQKFnJ0Jz/jj/zmksX0ma1gROTlovZKBmN08= +github.com/ipfs/go-ipfs-blocksutil v0.0.1 h1:Eh/H4pc1hsvhzsQoMEP3Bke/aW5P5rVM1IWFJMcGIPQ= github.com/ipfs/go-ipfs-blocksutil v0.0.1/go.mod h1:Yq4M86uIOmxmGPUHv/uI7uKqZNtLb449gwKqXjIsnRk= github.com/ipfs/go-ipfs-chunker v0.0.1 h1:cHUUxKFQ99pozdahi+uSC/3Y6HeRpi9oTeUHbE27SEw= github.com/ipfs/go-ipfs-chunker v0.0.1/go.mod h1:tWewYK0we3+rMbOh7pPFGDyypCtvGcBFymgY4rSDLAw= @@ -195,6 +244,7 @@ github.com/ipfs/go-ipfs-config v0.0.1/go.mod h1:KDbHjNyg4e6LLQSQpkgQMBz6Jf4LXiWA github.com/ipfs/go-ipfs-config v0.0.4 h1:zOWk1gGvIOptjHvvu0qSC8psB2IBKO/FbQArFnmm0LM= github.com/ipfs/go-ipfs-config v0.0.4/go.mod h1:KDbHjNyg4e6LLQSQpkgQMBz6Jf4LXiWAcmnkcwmH0DU= github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= +github.com/ipfs/go-ipfs-delay v0.0.1 h1:r/UXYyRcddO6thwOnhiznIAiSvxMECGgtv35Xs1IeRQ= github.com/ipfs/go-ipfs-delay v0.0.1/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= github.com/ipfs/go-ipfs-ds-help v0.0.1 h1:QBg+Ts2zgeemK/dB0saiF/ykzRGgfoFMT90Rzo0OnVU= github.com/ipfs/go-ipfs-ds-help v0.0.1/go.mod h1:gtP9xRaZXqIQRh1HRpp595KbBEdgqWFxefeVKOV8sxo= @@ -210,8 +260,9 @@ github.com/ipfs/go-ipfs-posinfo v0.0.1 h1:Esoxj+1JgSjX0+ylc0hUmJCOv6V2vFoZiETLR6 github.com/ipfs/go-ipfs-posinfo v0.0.1/go.mod h1:SwyeVP+jCwiDu0C313l/8jg6ZxM0qqtlt2a0vILTc1A= github.com/ipfs/go-ipfs-pq v0.0.1 h1:zgUotX8dcAB/w/HidJh1zzc1yFq6Vm8J7T2F4itj/RU= github.com/ipfs/go-ipfs-pq v0.0.1/go.mod h1:LWIqQpqfRG3fNc5XsnIhz/wQ2XXGyugQwls7BgUmUfY= -github.com/ipfs/go-ipfs-routing v0.0.1 h1:394mZeTLcbM/LDO12PneBYvkZAUA+nRnmC0lAzDXKOY= github.com/ipfs/go-ipfs-routing v0.0.1/go.mod h1:k76lf20iKFxQTjcJokbPM9iBXVXVZhcOwc360N4nuKs= +github.com/ipfs/go-ipfs-routing v0.1.0 h1:gAJTT1cEeeLj6/DlLX6t+NxD9fQe2ymTO6qWRDI/HQQ= +github.com/ipfs/go-ipfs-routing v0.1.0/go.mod h1:hYoUkJLyAUKhF58tysKpids8RNDPO42BVMgK5dNsoqY= github.com/ipfs/go-ipfs-util v0.0.1 h1:Wz9bL2wB2YBJqggkA4dD7oSmqB4cAnpNbGrlHJulv50= github.com/ipfs/go-ipfs-util v0.0.1/go.mod h1:spsl5z8KUnrve+73pOhSVZND1SIxPW5RyBCNzQxlJBc= github.com/ipfs/go-ipld-cbor v0.0.1/go.mod h1:RXHr8s4k0NE0TKhnrxqZC9M888QfsBN9rhS5NjfKzY8= @@ -226,30 +277,34 @@ github.com/ipfs/go-ipns v0.0.1 h1:5vX0+ehF55YWxE8Pmf4eB8szcP+fh24AXnvCkOmSLCc= github.com/ipfs/go-ipns v0.0.1/go.mod h1:HOiAXgGiH0wCSwsFM1IKdOy6YGT4iZafcsUKni703/g= github.com/ipfs/go-log v0.0.1 h1:9XTUN/rW64BCG1YhPK9Hoy3q8nr4gOmHHBpgFdfw6Lc= github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM= -github.com/ipfs/go-merkledag v0.0.3 h1:A5DlOMzqTRDVmdgkf3dzCKCFmVWH4Zqwb0cbYXUs+Ro= github.com/ipfs/go-merkledag v0.0.3/go.mod h1:Oc5kIXLHokkE1hWGMBHw+oxehkAaTOqtEb7Zbh6BhLA= +github.com/ipfs/go-merkledag v0.0.6 h1:rYZc0yzhO7y1cKi3Rw425a2HhEJDdLvNOWsqtmO3PF0= +github.com/ipfs/go-merkledag v0.0.6/go.mod h1:QYPdnlvkOg7GnQRofu9XZimC5ZW5Wi3bKys/4GQQfto= +github.com/ipfs/go-merkledag v0.1.0 h1:CAEXjRFEDPvealQj3TgEjV1IJckwjvmxAqtq5QSXJrg= +github.com/ipfs/go-merkledag v0.1.0/go.mod h1:SQiXrtSts3KGNmgOzMICy5c0POOpUNQLvB3ClKnBAlk= github.com/ipfs/go-metrics-interface v0.0.1 h1:j+cpbjYvu4R8zbleSs36gvB7jR+wsL2fGD6n0jO4kdg= github.com/ipfs/go-metrics-interface v0.0.1/go.mod h1:6s6euYU4zowdslK0GKHmqaIZ3j/b/tL7HTWtJ4VPgWY= github.com/ipfs/go-metrics-prometheus v0.0.2 h1:9i2iljLg12S78OhC6UAiXi176xvQGiZaGVF1CUVdE+s= github.com/ipfs/go-metrics-prometheus v0.0.2/go.mod h1:ELLU99AQQNi+zX6GCGm2lAgnzdSH3u5UVlCdqSXnEks= -github.com/ipfs/go-mfs v0.0.7 h1:Xjqk0jAhgwhMHO39oH4jqP1QkeAGqDelxa814voygN0= -github.com/ipfs/go-mfs v0.0.7/go.mod h1:10Hdow7wUbSlIamnOduxeP6MEp58TozZmdnAhugOKz8= +github.com/ipfs/go-mfs v0.1.0 h1:XVAdaMQtLV0KCNC7CnZlLAFiIU23RD/3Tvb8h6KDLaY= +github.com/ipfs/go-mfs v0.1.0/go.mod h1:/oADRI/at3cfIHqL4BTAF5n0nvWO4XpMi5nmHoxwhrQ= github.com/ipfs/go-path v0.0.3/go.mod h1:zIRQUez3LuQIU25zFjC2hpBTHimWx7VK5bjZgRLbbdo= -github.com/ipfs/go-path v0.0.4 h1:zG/id80tV51XAfvCsRJIEGQSHGuTDBi8RWrtr3EfcfY= -github.com/ipfs/go-path v0.0.4/go.mod h1:zIRQUez3LuQIU25zFjC2hpBTHimWx7VK5bjZgRLbbdo= -github.com/ipfs/go-peertaskqueue v0.0.4 h1:i0JprfjjILYcWM1xguO/1MCS8XKVxLSl+ECEVr6i8nw= +github.com/ipfs/go-path v0.0.7 h1:H06hKMquQ0aYtHiHryOMLpQC1qC3QwXwkahcEVD51Ho= +github.com/ipfs/go-path v0.0.7/go.mod h1:6KTKmeRnBXgqrTvzFrPV3CamxcgvXX/4z79tfAd2Sno= github.com/ipfs/go-peertaskqueue v0.0.4/go.mod h1:03H8fhyeMfKNFWqzYEVyMbcPUeYrqP1MX6Kd+aN+rMQ= +github.com/ipfs/go-peertaskqueue v0.1.0 h1:bpRbgv76eT4avutNPDFZuCPOQus6qTgurEYxfulgZW4= +github.com/ipfs/go-peertaskqueue v0.1.0/go.mod h1:Jmk3IyCcfl1W3jTW3YpghSwSEC6IJ3Vzz/jUmWw8Z0U= github.com/ipfs/go-todocounter v0.0.1 h1:kITWA5ZcQZfrUnDNkRn04Xzh0YFaDFXsoO2A81Eb6Lw= github.com/ipfs/go-todocounter v0.0.1/go.mod h1:l5aErvQc8qKE2r7NDMjmq5UNAvuZy0rC8BHOplkWvZ4= github.com/ipfs/go-unixfs v0.0.4/go.mod h1:eIo/p9ADu/MFOuyxzwU+Th8D6xoxU//r590vUpWyfz8= -github.com/ipfs/go-unixfs v0.0.6 h1:mQ6KS3NK4GA9hyUpGdGItqt5llzyIx0Qy2UxC/A7bEo= -github.com/ipfs/go-unixfs v0.0.6/go.mod h1:g41FlHFM/qacA3jzMPOYKIwNwbgTQEKJH2hQiq19Zrc= +github.com/ipfs/go-unixfs v0.0.8 h1:AHahQ+gdNZd9BhKVLf8XP1EWeKa78eTzYgCygp7N/Pg= +github.com/ipfs/go-unixfs v0.0.8/go.mod h1:cK2vDJ7L4YnWB6oLefpVNesgx0x/zPTRVDw6B4Y+03U= github.com/ipfs/go-verifcid v0.0.1 h1:m2HI7zIuR5TFyQ1b79Da5N9dnnCP1vcu2QqawmWlK2E= github.com/ipfs/go-verifcid v0.0.1/go.mod h1:5Hrva5KBeIog4A+UpqlaIU+DEstipcJYQQZc0g37pY0= github.com/ipfs/hang-fds v0.0.1 h1:KGAxiGtJPT3THVRNT6yxgpdFPeX4ZemUjENOt6NlOn4= github.com/ipfs/hang-fds v0.0.1/go.mod h1:U4JNbzwTpk/qP2Ms4VgrZ4HcgJGVosBJqMXvwe4udSY= -github.com/ipfs/interface-go-ipfs-core v0.0.8 h1:nmEYOfK6QRf3VIdggoZ4rmbKXcC2g6cEdU13Z1CvmL4= -github.com/ipfs/interface-go-ipfs-core v0.0.8/go.mod h1:RU+DSZXV+JdA7Yagu3OrSoB6hngSmMtK1w6ENOqmfQ8= +github.com/ipfs/interface-go-ipfs-core v0.1.0 h1:4LD2TJThswXVMJgAji9k9PyPsOGNtmdcx7U9RM1xH84= +github.com/ipfs/interface-go-ipfs-core v0.1.0/go.mod h1:h1zJvvfh9dcNU0bK+Jag516LputHLKQkHsDP+z0dz4A= github.com/ipfs/iptb v1.4.0 h1:YFYTrCkLMRwk/35IMyC6+yjoQSHTEcNcefBStLJzgvo= github.com/ipfs/iptb v1.4.0/go.mod h1:1rzHpCYtNp87/+hTxG5TfCVn/yMY3dKnLn8tBiMfdmg= github.com/ipfs/iptb-plugins v0.0.2 h1:JZp4h/+7f00dY4Epr8gzF+VqKITXmVGsZabvmZp7E9I= @@ -260,8 +315,8 @@ github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQ github.com/jackpal/go-nat-pmp v1.0.1 h1:i0LektDkO1QlrTm/cSuP+PyBCDnYvjPLGl4LdWEMiaA= github.com/jackpal/go-nat-pmp v1.0.1/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jbenet/go-cienv v0.0.0-20150120210510-1bb1476777ec/go.mod h1:rGaEvXB4uRSZMmzKNLoXvTu1sfx+1kv/DojUlPrSZGs= +github.com/jbenet/go-cienv v0.1.0 h1:Vc/s0QbQtoxX8MwwSLWWh+xNNZvM3Lw7NsTcHrvvhMc= github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jbenet/go-is-domain v1.0.2 h1:11r5MSptcNFZyBoqubBQnVMUKRWLuRjL1banaIk+iYo= github.com/jbenet/go-is-domain v1.0.2/go.mod h1:xbRLRb0S7FgzDBTJlguhDVwLYM/5yNtvktxj2Ttfy7Q= @@ -275,63 +330,72 @@ github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8/go.mod h1:Ly/wlsj github.com/jbenet/goprocess v0.1.3 h1:YKyIEECS/XvcfHtBzxtjBBbWK+MbvA6dG8ASiqwvr10= github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/jtolds/gls v4.2.1+incompatible h1:fSuqC+Gmlu6l/ZYAoZzx2pyucC8Xza35fpRVWLVmUEE= github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v0.0.0-20161130080628-0de1eaf82fa3/go.mod h1:jxZFDH7ILpTPQTk+E2s+z4CUas9lVNjIuKR4c5/zKgM= +github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= -github.com/kkdai/bstream v0.0.0-20181106074824-b3251f7901ec/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/koron/go-ssdp v0.0.0-20180514024734-4a0ed625a78b h1:wxtKgYHEncAU00muMD06dzLiahtGM1eouRNOzVV7tdQ= github.com/koron/go-ssdp v0.0.0-20180514024734-4a0ed625a78b/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/libp2p/go-addr-util v0.0.1 h1:TpTQm9cXVRVSKsYbgQ7GKc3KbbHVTnbostgGaDEP+88= github.com/libp2p/go-addr-util v0.0.1/go.mod h1:4ac6O7n9rIAKB1dnd+s8IbbMXkt+oBpzX4/+RACcnlQ= github.com/libp2p/go-buffer-pool v0.0.1/go.mod h1:xtyIz9PMobb13WaxR6Zo1Pd1zXJKYg0a8KiIvDp3TzQ= github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOSqcmlfs= github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= -github.com/libp2p/go-conn-security v0.0.1 h1:4kMMrqrt9EUNCNjX1xagSJC+bq16uqjMe9lk1KBMVNs= github.com/libp2p/go-conn-security v0.0.1/go.mod h1:bGmu51N0KU9IEjX7kl2PQjgZa40JQWnayTvNMgD/vyk= github.com/libp2p/go-conn-security-multistream v0.0.1/go.mod h1:nc9vud7inQ+d6SO0I/6dSWrdMnHnzZNHeyUQqrAJulE= -github.com/libp2p/go-conn-security-multistream v0.0.2 h1:Ykz0lnNjxk+0SdslUmlLNyrleqdpS1S/VW+dxFdt74Y= github.com/libp2p/go-conn-security-multistream v0.0.2/go.mod h1:nc9vud7inQ+d6SO0I/6dSWrdMnHnzZNHeyUQqrAJulE= +github.com/libp2p/go-conn-security-multistream v0.1.0 h1:aqGmto+ttL/uJgX0JtQI0tD21CIEy5eYd1Hlp0juHY0= +github.com/libp2p/go-conn-security-multistream v0.1.0/go.mod h1:aw6eD7LOsHEX7+2hJkDxw1MteijaVcI+/eP2/x3J1xc= github.com/libp2p/go-flow-metrics v0.0.1 h1:0gxuFd2GuK7IIP5pKljLwps6TvcuYgvG7Atqi3INF5s= github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8= github.com/libp2p/go-libp2p v0.0.2/go.mod h1:Qu8bWqFXiocPloabFGUcVG4kk94fLvfC8mWTDdFC9wE= -github.com/libp2p/go-libp2p v0.0.27/go.mod h1:kjeVlESxQisK2DvyKp38/UMHYd9gAMTj3C3XOB/DEZo= -github.com/libp2p/go-libp2p v0.0.28 h1:tkDnM7iwrz9OSRRb8YAV4HYjv8TKsAxyxrV2sES9/Aw= -github.com/libp2p/go-libp2p v0.0.28/go.mod h1:GBW0VbgEKe8ELXVpLQJduJYlJHRv/XfwP6Fo9TEcDJU= +github.com/libp2p/go-libp2p v0.0.30/go.mod h1:XWT8FGHlhptAv1+3V/+J5mEpzyui/5bvFsNuWYs611A= +github.com/libp2p/go-libp2p v0.1.0 h1:8VXadcPNni74ODoZ+7326LMAppFYmz1fRQOUuT5iZvQ= +github.com/libp2p/go-libp2p v0.1.0/go.mod h1:6D/2OBauqLUoqcADOJpn9WbKqvaM07tDw68qHM0BxUM= github.com/libp2p/go-libp2p-autonat v0.0.2/go.mod h1:fs71q5Xk+pdnKU014o2iq1RhMs9/PMaG5zXRFNnIIT4= -github.com/libp2p/go-libp2p-autonat v0.0.3/go.mod h1:fs71q5Xk+pdnKU014o2iq1RhMs9/PMaG5zXRFNnIIT4= -github.com/libp2p/go-libp2p-autonat v0.0.5/go.mod h1:cKt+qOSnWAZp0dqIuUk62v0/QAPw0vnLuVZnmzkOXRk= -github.com/libp2p/go-libp2p-autonat v0.0.6 h1:OCStANLLpeyQeWFUuqZJ7aS9+Bx0/uoVb1PtLA9fGTQ= github.com/libp2p/go-libp2p-autonat v0.0.6/go.mod h1:uZneLdOkZHro35xIhpbtTzLlgYturpu4J5+0cZK3MqE= +github.com/libp2p/go-libp2p-autonat v0.1.0 h1:aCWAu43Ri4nU0ZPO7NyLzUvvfqd0nE3dX0R/ZGYVgOU= +github.com/libp2p/go-libp2p-autonat v0.1.0/go.mod h1:1tLf2yXxiE/oKGtDwPYWTSYG3PtvYlJmg7NeVtPRqH8= github.com/libp2p/go-libp2p-autonat-svc v0.0.2/go.mod h1:j4iMiw0d3diRm5iB0noXumtb0mPvWrM1qAyh640cp8w= -github.com/libp2p/go-libp2p-autonat-svc v0.0.5 h1:bTom7QFAkJMXiA8ibSsKQ2+LKEHsXZz2IAWYolg/YYg= -github.com/libp2p/go-libp2p-autonat-svc v0.0.5/go.mod h1:6aLiQelA0CKEcPR0TvE9bqJ7U8Mc0nVdwCoho3ROdck= +github.com/libp2p/go-libp2p-autonat-svc v0.1.0 h1:28IM7iWMDclZeVkpiFQaWVANwXwE7zLlpbnS7yXxrfs= +github.com/libp2p/go-libp2p-autonat-svc v0.1.0/go.mod h1:fqi8Obl/z3R4PFVLm8xFtZ6PBL9MlV/xumymRFkKq5A= github.com/libp2p/go-libp2p-blankhost v0.0.1/go.mod h1:Ibpbw/7cPPYwFb7PACIWdvxxv0t0XCCI10t7czjAjTc= +github.com/libp2p/go-libp2p-blankhost v0.1.1 h1:X919sCh+KLqJcNRApj43xCSiQRYqOSI88Fdf55ngf78= +github.com/libp2p/go-libp2p-blankhost v0.1.1/go.mod h1:pf2fvdLJPsC1FsVrNP3DUUvMzUts2dsLLBEpo1vW1ro= github.com/libp2p/go-libp2p-circuit v0.0.1/go.mod h1:Dqm0s/BiV63j8EEAs8hr1H5HudqvCAeXxDyic59lCwE= -github.com/libp2p/go-libp2p-circuit v0.0.7/go.mod h1:DFCgZ2DklFGTUIZIhSvbbWXTErUgjyNrJGfDHOrTKIA= -github.com/libp2p/go-libp2p-circuit v0.0.8 h1:vd9vZDy+LDssTvUuxIqnYUOAK2hfHoSQO2xjWhPVEmc= -github.com/libp2p/go-libp2p-circuit v0.0.8/go.mod h1:DFCgZ2DklFGTUIZIhSvbbWXTErUgjyNrJGfDHOrTKIA= +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 h1:eniLL3Y9aq/sryfyV1IAHj5rlvuyj3b7iz8tSiZpdhY= +github.com/libp2p/go-libp2p-circuit v0.1.0/go.mod h1:Ahq4cY3V9VJcHcn1SBXjr78AbFkZeIRmfunbA7pmFh8= github.com/libp2p/go-libp2p-connmgr v0.0.1/go.mod h1:eUBBlbuwBBTd/eim7KV5x0fOD2UHDjSwhzmBL6miIx8= -github.com/libp2p/go-libp2p-connmgr v0.0.6 h1:oEUriPO/qWTvfHRPEU4HdNlNhYigdueOs2X3UZCdbYM= -github.com/libp2p/go-libp2p-connmgr v0.0.6/go.mod h1:uwDfgdgqB5248sQYib1xo603cSsMg9PgAKu0Z+Y65Qk= +github.com/libp2p/go-libp2p-connmgr v0.1.0 h1:vp0t0F0EuT3rrlTtnMnIyyzCnly7nIlRoEbhJpgp0qU= +github.com/libp2p/go-libp2p-connmgr v0.1.0/go.mod h1:wZxh8veAmU5qdrfJ0ZBLcU8oJe9L82ciVP/fl1VHjXk= +github.com/libp2p/go-libp2p-core v0.0.1/go.mod h1:g/VxnTZ/1ygHxH3dKok7Vno1VfpvGcGip57wjTU4fco= +github.com/libp2p/go-libp2p-core v0.0.2 h1:86uOwW+O6Uc7NbaK4diuLZo2/Ikvqw2rgyV03VcSbLE= +github.com/libp2p/go-libp2p-core v0.0.2/go.mod h1:9dAcntw/n46XycV4RnlBq3BpgrmyUi9LuoTNdPrbUco= github.com/libp2p/go-libp2p-crypto v0.0.1/go.mod h1:yJkNyDmO341d5wwXxDUGO0LykUVT72ImHNUqh5D/dBE= -github.com/libp2p/go-libp2p-crypto v0.0.2 h1:TTdJ4y6Uoa6NxQcuEaVkQfFRcQeCE2ReDk8Ok4I0Fyw= github.com/libp2p/go-libp2p-crypto v0.0.2/go.mod h1:eETI5OUfBnvARGOHrJz2eWNyTUxEGZnBxMcbUjfIj4I= +github.com/libp2p/go-libp2p-crypto v0.1.0 h1:k9MFy+o2zGDNGsaoZl0MA3iZ75qXxr9OOoAZF+sD5OQ= +github.com/libp2p/go-libp2p-crypto v0.1.0/go.mod h1:sPUokVISZiy+nNuTTH/TY+leRSxnFj/2GLjtOTW90hI= github.com/libp2p/go-libp2p-daemon v0.0.6/go.mod h1:nkhjsjSzkF+tg6iScsTTgq9m+VfyMtXNpycYG4CFvC8= github.com/libp2p/go-libp2p-discovery v0.0.1/go.mod h1:ZkkF9xIFRLA1xCc7bstYFkd80gBGK8Fc1JqGoU2i+zI= -github.com/libp2p/go-libp2p-discovery v0.0.4 h1:/kZwOVmcUHvB94zegSJYnUA9EvT1g8APoQJb5FHyT1c= -github.com/libp2p/go-libp2p-discovery v0.0.4/go.mod h1:ReQGiv7QTtza8FUWzewfuMmRDVOQVp+lxHlJJA8YQCM= +github.com/libp2p/go-libp2p-discovery v0.0.5/go.mod h1:YtF20GUxjgoKZ4zmXj8j3Nb2TUSBHFlOCetzYdbZL5I= +github.com/libp2p/go-libp2p-discovery v0.1.0 h1:j+R6cokKcGbnZLf4kcNwpx6mDEUPF3N6SrqMymQhmvs= +github.com/libp2p/go-libp2p-discovery v0.1.0/go.mod h1:4F/x+aldVHjHDHuX85x1zWoFTGElt8HnoDzwkFZm29g= github.com/libp2p/go-libp2p-host v0.0.1/go.mod h1:qWd+H1yuU0m5CwzAkvbSjqKairayEHdR5MMl7Cwa7Go= github.com/libp2p/go-libp2p-host v0.0.3 h1:BB/1Z+4X0rjKP5lbQTmjEjLbDVbrcmLOlA6QDsN5/j4= github.com/libp2p/go-libp2p-host v0.0.3/go.mod h1:Y/qPyA6C8j2coYyos1dfRm0I8+nvd4TGrDGt4tA7JR8= @@ -339,20 +403,21 @@ github.com/libp2p/go-libp2p-interface-connmgr v0.0.1/go.mod h1:GarlRLH0LdeWcLnYM github.com/libp2p/go-libp2p-interface-connmgr v0.0.4/go.mod h1:GarlRLH0LdeWcLnYM/SaBykKFl9U5JFnbBGruAk/D5k= github.com/libp2p/go-libp2p-interface-connmgr v0.0.5 h1:KG/KNYL2tYzXAfMvQN5K1aAGTYSYUMJ1prgYa2/JI1E= github.com/libp2p/go-libp2p-interface-connmgr v0.0.5/go.mod h1:GarlRLH0LdeWcLnYM/SaBykKFl9U5JFnbBGruAk/D5k= -github.com/libp2p/go-libp2p-interface-pnet v0.0.1 h1:7GnzRrBTJHEsofi1ahFdPN9Si6skwXQE9UqR2S+Pkh8= github.com/libp2p/go-libp2p-interface-pnet v0.0.1/go.mod h1:el9jHpQAXK5dnTpKA4yfCNBZXvrzdOU75zz+C6ryp3k= github.com/libp2p/go-libp2p-kad-dht v0.0.4/go.mod h1:oaBflOQcuC8H+SVV0YN26H6AS+wcUEJyjUGV66vXuSY= -github.com/libp2p/go-libp2p-kad-dht v0.0.13 h1:ReMb41jJrngvXnU5Tirf74bBkXx4M9ne5QyFQPeNYtw= -github.com/libp2p/go-libp2p-kad-dht v0.0.13/go.mod h1:3A4xaZJeJ3zD3jCg17mtI+rA7uuXiiQdKVyAZOhZo1U= +github.com/libp2p/go-libp2p-kad-dht v0.1.0 h1:cupGornmncdQCnjArAv9Txkqy43wgQCxoe/5pfIDF/4= +github.com/libp2p/go-libp2p-kad-dht v0.1.0/go.mod h1:EiH74cOsCxcu2Yh1XxQMpf1uHcLNm/hYEJBOIRlzHNE= github.com/libp2p/go-libp2p-kbucket v0.0.1/go.mod h1:Y0iQDHRTk/ZgM8PC4jExoF+E4j+yXWwRkdldkMa5Xm4= -github.com/libp2p/go-libp2p-kbucket v0.1.1 h1:ZrvW3qCM+lAuv7nrNts/zfEiClq+GZe8OIzX4Vb3Dwo= -github.com/libp2p/go-libp2p-kbucket v0.1.1/go.mod h1:Y0iQDHRTk/ZgM8PC4jExoF+E4j+yXWwRkdldkMa5Xm4= -github.com/libp2p/go-libp2p-loggables v0.0.1 h1:HVww9oAnINIxbt69LJNkxD8lnbfgteXR97Xm4p3l9ps= +github.com/libp2p/go-libp2p-kbucket v0.2.0 h1:FB2a0VkOTNGTP5gu/I444u4WabNM9V1zCkQcWb7zajI= +github.com/libp2p/go-libp2p-kbucket v0.2.0/go.mod h1:JNymBToym3QXKBMKGy3m29+xprg0EVr/GJFHxFEdgh8= github.com/libp2p/go-libp2p-loggables v0.0.1/go.mod h1:lDipDlBNYbpyqyPX/KcoO+eq0sJYEVR2JgOexcivchg= -github.com/libp2p/go-libp2p-metrics v0.0.1 h1:yumdPC/P2VzINdmcKZd0pciSUCpou+s0lwYCjBbzQZU= +github.com/libp2p/go-libp2p-loggables v0.1.0 h1:h3w8QFfCt2UJl/0/NW4K829HX/0S4KD31PQ7m8UXXO8= +github.com/libp2p/go-libp2p-loggables v0.1.0/go.mod h1:EyumB2Y6PrYjr55Q3/tiJ/o3xoDasoRYM7nOzEpoa90= github.com/libp2p/go-libp2p-metrics v0.0.1/go.mod h1:jQJ95SXXA/K1VZi13h52WZMa9ja78zjyy5rspMsC/08= -github.com/libp2p/go-libp2p-mplex v0.1.1 h1:lSPS1VJ36P01gGO//KgcsmSah5uoC3X9r7WY5j+iP4c= github.com/libp2p/go-libp2p-mplex v0.1.1/go.mod h1:KUQWpGkCzfV7UIpi8SKsAVxyBgz1c9R5EvxgnwLsb/I= +github.com/libp2p/go-libp2p-mplex v0.2.0/go.mod h1:Ejl9IyjvXJ0T9iqUTE1jpYATQ9NM3g+OtR+EMMODbKo= +github.com/libp2p/go-libp2p-mplex v0.2.1 h1:E1xaJBQnbSiTHGI1gaBKmKhu1TUKkErKJnE8iGvirYI= +github.com/libp2p/go-libp2p-mplex v0.2.1/go.mod h1:SC99Rxs8Vuzrf/6WhmH41kNn13TiYdAWNYHrwImKLnE= github.com/libp2p/go-libp2p-nat v0.0.2/go.mod h1:QrjXQSD5Dj4IJOdEcjHRkWTSomyxRo6HnUkf/TfQpLQ= github.com/libp2p/go-libp2p-nat v0.0.4 h1:+KXK324yaY701On8a0aGjTnw8467kW3ExKcqW2wwmyw= github.com/libp2p/go-libp2p-nat v0.0.4/go.mod h1:N9Js/zVtAXqaeT99cXgTV9e75KpnWCvVOiGzlcHmBbY= @@ -361,60 +426,73 @@ github.com/libp2p/go-libp2p-net v0.0.1/go.mod h1:Yt3zgmlsHOgUWSXmt5V/Jpz9upuJBE8 github.com/libp2p/go-libp2p-net v0.0.2 h1:qP06u4TYXfl7uW/hzqPhlVVTSA2nw1B/bHBJaUnbh6M= github.com/libp2p/go-libp2p-net v0.0.2/go.mod h1:Yt3zgmlsHOgUWSXmt5V/Jpz9upuJBE8EgNU9DrCcR8c= github.com/libp2p/go-libp2p-netutil v0.0.1/go.mod h1:GdusFvujWZI9Vt0X5BKqwWWmZFxecf9Gt03cKxm2f/Q= +github.com/libp2p/go-libp2p-netutil v0.1.0 h1:zscYDNVEcGxyUpMd0JReUZTrpMfia8PmLKcKF72EAMQ= +github.com/libp2p/go-libp2p-netutil v0.1.0/go.mod h1:3Qv/aDqtMLTUyQeundkKsA+YCThNdbQD54k3TqjpbFU= github.com/libp2p/go-libp2p-peer v0.0.1/go.mod h1:nXQvOBbwVqoP+T5Y5nCjeH4sP9IX/J0AMzcDUVruVoo= -github.com/libp2p/go-libp2p-peer v0.1.1 h1:qGCWD1a+PyZcna6htMPo26jAtqirVnJ5NvBQIKV7rRY= github.com/libp2p/go-libp2p-peer v0.1.1/go.mod h1:jkF12jGB4Gk/IOo+yomm+7oLWxF278F7UnrYUQ1Q8es= +github.com/libp2p/go-libp2p-peer v0.2.0 h1:EQ8kMjaCUwt/Y5uLgjT8iY2qg0mGUT0N1zUjer50DsY= +github.com/libp2p/go-libp2p-peer v0.2.0/go.mod h1:RCffaCvUyW2CJmG2gAWVqwePwW7JMgxjsHm7+J5kjWY= github.com/libp2p/go-libp2p-peerstore v0.0.0-20190226201924-e2df3e49eabf/go.mod h1:lLfgn0N3z2t+ER57a88K7NTZjMO27ez5TyWSURd428E= github.com/libp2p/go-libp2p-peerstore v0.0.1/go.mod h1:RabLyPVJLuNQ+GFyoEkfi8H4Ti6k/HtZJ7YKgtSq+20= -github.com/libp2p/go-libp2p-peerstore v0.0.6 h1:RgX/djPFXqZGktW0j2eF4NAX0pzDsCot45jO2GewC+g= github.com/libp2p/go-libp2p-peerstore v0.0.6/go.mod h1:RabLyPVJLuNQ+GFyoEkfi8H4Ti6k/HtZJ7YKgtSq+20= -github.com/libp2p/go-libp2p-pnet v0.0.1 h1:2e5d15M8XplUKsU4Fqrll5eDfqGg/7mHUufLkhbfKHM= -github.com/libp2p/go-libp2p-pnet v0.0.1/go.mod h1:bWN8HqdpgCdKnXSCsJhbWjiU3UZFa/tIe4no5jCmHVw= +github.com/libp2p/go-libp2p-peerstore v0.1.0 h1:MKh7pRNPHSh1fLPj8u/M/s/napdmeNpoi9BRy9lPN0E= +github.com/libp2p/go-libp2p-peerstore v0.1.0/go.mod h1:2CeHkQsr8svp4fZ+Oi9ykN1HBb6u0MOvdJ7YIsmcwtY= +github.com/libp2p/go-libp2p-pnet v0.1.0 h1:kRUES28dktfnHNIRW4Ro78F7rKBHBiw5MJpl0ikrLIA= +github.com/libp2p/go-libp2p-pnet v0.1.0/go.mod h1:ZkyZw3d0ZFOex71halXRihWf9WH/j3OevcJdTmD0lyE= github.com/libp2p/go-libp2p-protocol v0.0.0-20171212212132-b29f3d97e3a2/go.mod h1:Af9n4PiruirSDjHycM1QuiMi/1VZNHYcK8cLgFJLZ4s= -github.com/libp2p/go-libp2p-protocol v0.0.1 h1:+zkEmZ2yFDi5adpVE3t9dqh/N9TbpFWywowzeEzBbLM= github.com/libp2p/go-libp2p-protocol v0.0.1/go.mod h1:Af9n4PiruirSDjHycM1QuiMi/1VZNHYcK8cLgFJLZ4s= +github.com/libp2p/go-libp2p-protocol v0.1.0 h1:HdqhEyhg0ToCaxgMhnOmUO8snQtt/kQlcjVk3UoJU3c= +github.com/libp2p/go-libp2p-protocol v0.1.0/go.mod h1:KQPHpAabB57XQxGrXCNvbL6UEXfQqUgC/1adR2Xtflk= github.com/libp2p/go-libp2p-pubsub v0.0.1/go.mod h1:fYKlZBOF2yrJzYlgeEVFSbYWfbS+E8Zix6gMZ0A6WgE= -github.com/libp2p/go-libp2p-pubsub v0.0.3 h1:DKVoDac2u1Dr8gX7B1HFjCrXkMxr8tfbnt0Fk1mmkgk= -github.com/libp2p/go-libp2p-pubsub v0.0.3/go.mod h1:fYKlZBOF2yrJzYlgeEVFSbYWfbS+E8Zix6gMZ0A6WgE= -github.com/libp2p/go-libp2p-pubsub-router v0.0.3 h1:2EF+8nueIsA9Unpj1MxdlS9+dX29kwCxSttchMMfXsI= -github.com/libp2p/go-libp2p-pubsub-router v0.0.3/go.mod h1:h5z0kyMFRu2J46tt15eEuLHKEmu1MrFghsGHqTc/iII= +github.com/libp2p/go-libp2p-pubsub v0.1.0 h1:SmQeMa7IUv5vadh0fYgYsafWCBA1sCy5d/68kIYqGcU= +github.com/libp2p/go-libp2p-pubsub v0.1.0/go.mod h1:ZwlKzRSe1eGvSIdU5bD7+8RZN/Uzw0t1Bp9R1znpR/Q= +github.com/libp2p/go-libp2p-pubsub-router v0.1.0 h1:xA5B8Sdx64tNlSRIcay2QUngtlu8LpUJClaUk/dYYrg= +github.com/libp2p/go-libp2p-pubsub-router v0.1.0/go.mod h1:PnHOshBr/2I2ZxVfEsqfgCQPsVg09zo+DhSlWkOhPFM= github.com/libp2p/go-libp2p-quic-transport v0.0.0-20190301030811-862195d91de1/go.mod h1:bw/6H57fSVn44ldP1Js6hnzpoiUm9YgBDKSv+ch+hWc= -github.com/libp2p/go-libp2p-quic-transport v0.0.3 h1:FGEPXsjpY9K6P3iMtJQPKGl45eXickBY1+xSJ84lVVI= -github.com/libp2p/go-libp2p-quic-transport v0.0.3/go.mod h1:v2oVuaFLkxlFpkFbXUty3dfEYSlNb0sCzvf8cRi1m/k= -github.com/libp2p/go-libp2p-record v0.0.1 h1:zN7AS3X46qmwsw5JLxdDuI43cH5UYwovKxHPjKBYQxw= +github.com/libp2p/go-libp2p-quic-transport v0.1.1 h1:MFMJzvsxIEDEVKzO89BnB/FgvMj9WI4GDGUW2ArDPUA= +github.com/libp2p/go-libp2p-quic-transport v0.1.1/go.mod h1:wqG/jzhF3Pu2NrhJEvE+IE0NTHNXslOPn9JQzyCAxzU= github.com/libp2p/go-libp2p-record v0.0.1/go.mod h1:grzqg263Rug/sRex85QrDOLntdFAymLDLm7lxMgU79Q= -github.com/libp2p/go-libp2p-routing v0.0.1 h1:hPMAWktf9rYi3ME4MG48qE7dq1ofJxiQbfdvpNntjhc= +github.com/libp2p/go-libp2p-record v0.1.0 h1:wHwBGbFzymoIl69BpgwIu0O6ta3TXGcMPvHUAcodzRc= +github.com/libp2p/go-libp2p-record v0.1.0/go.mod h1:ujNc8iuE5dlKWVy6wuL6dd58t0n7xI4hAIl8pE6wu5Q= github.com/libp2p/go-libp2p-routing v0.0.1/go.mod h1:N51q3yTr4Zdr7V8Jt2JIktVU+3xBBylx1MZeVA6t1Ys= -github.com/libp2p/go-libp2p-routing-helpers v0.0.2 h1:SLX7eDQE8Xo197NwNM/hM7WnH3w6fSGY9+G9HkiYwqQ= -github.com/libp2p/go-libp2p-routing-helpers v0.0.2/go.mod h1:zf1ook9HoOQpfnVXrF4gGorkPrGGf1g25vgH5+4SRNU= +github.com/libp2p/go-libp2p-routing v0.1.0 h1:hFnj3WR3E2tOcKaGpyzfP4gvFZ3t8JkQmbapN0Ct+oU= +github.com/libp2p/go-libp2p-routing v0.1.0/go.mod h1:zfLhI1RI8RLEzmEaaPwzonRvXeeSHddONWkcTcB54nE= +github.com/libp2p/go-libp2p-routing-helpers v0.1.0 h1:BaFvpyv8TyhCN7TihawTiKuzeu8/Pyw7ZnMA4IvqIN8= +github.com/libp2p/go-libp2p-routing-helpers v0.1.0/go.mod h1:oUs0h39vNwYtYXnQWOTU5BaafbedSyWCCal3gqHuoOQ= github.com/libp2p/go-libp2p-secio v0.0.1/go.mod h1:IdG6iQybdcYmbTzxp4J5dwtUEDTOvZrT0opIDVNPrJs= -github.com/libp2p/go-libp2p-secio v0.0.3 h1:h3fPeDrej7bvvARnC2oSjAfcLZOaS4REZKgWCRQNpE4= github.com/libp2p/go-libp2p-secio v0.0.3/go.mod h1:hS7HQ00MgLhRO/Wyu1bTX6ctJKhVpm+j2/S2A5UqYb0= +github.com/libp2p/go-libp2p-secio v0.1.0 h1:NNP5KLxuP97sE5Bu3iuwOWyT/dKEGMN5zSLMWdB7GTQ= +github.com/libp2p/go-libp2p-secio v0.1.0/go.mod h1:tMJo2w7h3+wN4pgU2LSYeiKPrfqBgkOsdiKK77hE7c8= github.com/libp2p/go-libp2p-swarm v0.0.1/go.mod h1:mh+KZxkbd3lQnveQ3j2q60BM1Cw2mX36XXQqwfPOShs= -github.com/libp2p/go-libp2p-swarm v0.0.5/go.mod h1:+nkJir4feiXtWQjb/4CQHMEK8Vw+c5nVVxT8R5bs0yY= -github.com/libp2p/go-libp2p-swarm v0.0.6 h1:gE0P/v2h+KEXtAi9YTw2UBOSODJ4m9VuuJ+ktc2LVUo= github.com/libp2p/go-libp2p-swarm v0.0.6/go.mod h1:s5GZvzg9xXe8sbeESuFpjt8CJPTCa8mhEusweJqyFy8= -github.com/libp2p/go-libp2p-tls v0.0.1 h1:UIslpmpKDbjEymuidtP2D9up00GfWrOs6eyTKf83uBA= -github.com/libp2p/go-libp2p-tls v0.0.1/go.mod h1:DInSFKxm9XHHSbCdJRbcWctRYkmtPGnqiaUtgjiEa7g= +github.com/libp2p/go-libp2p-swarm v0.1.0 h1:HrFk2p0awrGEgch9JXK/qp/hfjqQfgNxpLWnCiWPg5s= +github.com/libp2p/go-libp2p-swarm v0.1.0/go.mod h1:wQVsCdjsuZoc730CgOvh5ox6K8evllckjebkdiY5ta4= +github.com/libp2p/go-libp2p-testing v0.0.1/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= +github.com/libp2p/go-libp2p-testing v0.0.2/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= +github.com/libp2p/go-libp2p-testing v0.0.3 h1:bdij4bKaaND7tCsaXVjRfYkMpvoOeKj9AVQGJllA6jM= +github.com/libp2p/go-libp2p-testing v0.0.3/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= +github.com/libp2p/go-libp2p-tls v0.1.0 h1:o4bjjAdnUjNgJoPoDd0wUaZH7K+EenlNWJpgyXB3ulA= +github.com/libp2p/go-libp2p-tls v0.1.0/go.mod h1:VZdoSWQDeNpIIAFJFv+6uqTqpnIIDHcqZQSTC/A1TT0= github.com/libp2p/go-libp2p-transport v0.0.0-20190226201958-e8580c8a519d/go.mod h1:lcwgOszllbhvQXul37Kv5YbSYXPoUhRB2Z+Nr3jaBmo= 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 h1:pV6+UlRxyDpASSGD+60vMvdifSCby6JkJDfi+yUMHac= github.com/libp2p/go-libp2p-transport v0.0.5/go.mod h1:StoY3sx6IqsP6XKoabsPnHCwqKXWUMWU7Rfcsubee/A= github.com/libp2p/go-libp2p-transport-upgrader v0.0.1/go.mod h1:NJpUAgQab/8K6K0m+JmZCe5RUXG10UMEx4kWe9Ipj5c= -github.com/libp2p/go-libp2p-transport-upgrader v0.0.3/go.mod h1:Ng1HzfMIopyYscMHNFmJqiMMcpgDlj0t+NyjVWW89ws= -github.com/libp2p/go-libp2p-transport-upgrader v0.0.4 h1:uGMOd14BL1oFlfb/cGfOxPjiTKBhzWV4aMjjoCF1Z1o= github.com/libp2p/go-libp2p-transport-upgrader v0.0.4/go.mod h1:RGq+tupk+oj7PzL2kn/m1w6YXxcIAYJYeI90h6BGgUc= +github.com/libp2p/go-libp2p-transport-upgrader v0.1.1 h1:PZMS9lhjK9VytzMCW3tWHAXtKXmlURSc3ZdvwEcKCzw= +github.com/libp2p/go-libp2p-transport-upgrader v0.1.1/go.mod h1:IEtA6or8JUbsV07qPW4r01GnTenLW4oi3lOPbUMGJJA= github.com/libp2p/go-libp2p-yamux v0.1.2/go.mod h1:xUoV/RmYkg6BW/qGxA9XJyg+HzXFYkeXbnhjmnYzKp8= -github.com/libp2p/go-libp2p-yamux v0.1.3 h1:HmKvv2jWJ4GEm3iP7cEKjuw0POa6rK+Hcsu1FBKzpLc= github.com/libp2p/go-libp2p-yamux v0.1.3/go.mod h1:VGSQVrqkh6y4nm0189qqxMtvyBft44MOYYPpYKXiVt4= +github.com/libp2p/go-libp2p-yamux v0.2.0 h1:TSPZ5cMMz/wdoYsye/wU1TE4G3LDGMoeEN0xgnCKU/I= +github.com/libp2p/go-libp2p-yamux v0.2.0/go.mod h1:Db2gU+XfLpm6E4rG5uGCFX6uXA8MEXOxFcRoXUODaK8= github.com/libp2p/go-maddr-filter v0.0.1/go.mod h1:6eT12kSQMA9x2pvFQa+xesMKUBlj9VImZbj3B9FBH/Q= github.com/libp2p/go-maddr-filter v0.0.4 h1:hx8HIuuwk34KePddrp2mM5ivgPkZ09JH4AvsALRbFUs= github.com/libp2p/go-maddr-filter v0.0.4/go.mod h1:6eT12kSQMA9x2pvFQa+xesMKUBlj9VImZbj3B9FBH/Q= github.com/libp2p/go-mplex v0.0.1/go.mod h1:pK5yMLmOoBR1pNCqDlA2GQrdAVTMkqFalaTWe7l4Yd0= github.com/libp2p/go-mplex v0.0.3/go.mod h1:pK5yMLmOoBR1pNCqDlA2GQrdAVTMkqFalaTWe7l4Yd0= -github.com/libp2p/go-mplex v0.0.4 h1:043XJ3Zr7/Oz5cfyUaJwxUZyP02TngTpt4oq8R5UizQ= github.com/libp2p/go-mplex v0.0.4/go.mod h1:pK5yMLmOoBR1pNCqDlA2GQrdAVTMkqFalaTWe7l4Yd0= +github.com/libp2p/go-mplex v0.1.0 h1:/nBTy5+1yRyY82YaO6HXQRnO5IAGsXTjEJaR3LdTPc0= +github.com/libp2p/go-mplex v0.1.0/go.mod h1:SXgmdki2kwCUlCCbfGLEgHjC4pFqhTp0ZoV6aiKgxDU= github.com/libp2p/go-msgio v0.0.1/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= github.com/libp2p/go-msgio v0.0.2 h1:ivPvEKHxmVkTClHzg6RXTYHqaJQ0V9cDbq+6lKb3UV0= github.com/libp2p/go-msgio v0.0.2/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= @@ -426,19 +504,24 @@ github.com/libp2p/go-reuseport-transport v0.0.1/go.mod h1:YkbSDrvjUVDL6b8XqriyA2 github.com/libp2p/go-reuseport-transport v0.0.2 h1:WglMwyXyBu61CMkjCCtnmqNqnjib0GIEjMiHTwR/KN4= github.com/libp2p/go-reuseport-transport v0.0.2/go.mod h1:YkbSDrvjUVDL6b8XqriyA20obEtsW9BLkuOUyQAOCbs= github.com/libp2p/go-stream-muxer v0.0.0-20190218175335-a3f82916c8ad/go.mod h1:bAo8x7YkSpadMTbtTaxGVHWUQsR/l5MEaHbKaliuT14= -github.com/libp2p/go-stream-muxer v0.0.1 h1:Ce6e2Pyu+b5MC1k3eeFtAax0pW4gc6MosYSLV05UeLw= github.com/libp2p/go-stream-muxer v0.0.1/go.mod h1:bAo8x7YkSpadMTbtTaxGVHWUQsR/l5MEaHbKaliuT14= -github.com/libp2p/go-stream-muxer-multistream v0.1.1 h1:DhHqb4nu1fQv/vQKeLAaZGmhLsUA4SF77IdYJiWE1d4= +github.com/libp2p/go-stream-muxer v0.1.0 h1:3ToDXUzx8pDC6RfuOzGsUYP5roMDthbUKRdMRRhqAqY= +github.com/libp2p/go-stream-muxer v0.1.0/go.mod h1:8JAVsjeRBCWwPoZeH0W1imLOcriqXJyFvB0mR4A04sQ= github.com/libp2p/go-stream-muxer-multistream v0.1.1/go.mod h1:zmGdfkQ1AzOECIAcccoL8L//laqawOsO03zX8Sa+eGw= +github.com/libp2p/go-stream-muxer-multistream v0.2.0 h1:714bRJ4Zy9mdhyTLJ+ZKiROmAFwUHpeRidG+q7LTQOg= +github.com/libp2p/go-stream-muxer-multistream v0.2.0/go.mod h1:j9eyPol/LLRqT+GPLSxvimPhNph4sfYfMoDPd7HkzIc= github.com/libp2p/go-tcp-transport v0.0.1/go.mod h1:mnjg0o0O5TmXUaUIanYPUqkW4+u6mK0en8rlpA6BBTs= -github.com/libp2p/go-tcp-transport v0.0.3/go.mod h1:f11C2zvCaGDkE8aFPUKmuYZwd3pP6HI24LeLMWhJnkQ= -github.com/libp2p/go-tcp-transport v0.0.4 h1:2iRu994wCT/iEz62F+c60FUoSkijNEQ0q2Itc+79XlQ= github.com/libp2p/go-tcp-transport v0.0.4/go.mod h1:+E8HvC8ezEVOxIo3V5vCK9l1y/19K427vCzQ+xHKH/o= +github.com/libp2p/go-tcp-transport v0.1.0 h1:IGhowvEqyMFknOar4FWCKSWE0zL36UFKQtiRQD60/8o= +github.com/libp2p/go-tcp-transport v0.1.0/go.mod h1:oJ8I5VXryj493DEJ7OsBieu8fcg2nHGctwtInJVpipc= +github.com/libp2p/go-testutil v0.0.1 h1:Xg+O0G2HIMfHqBOBDcMS1iSZJ3GEcId4qOxCQvsGZHk= github.com/libp2p/go-testutil v0.0.1/go.mod h1:iAcJc/DKJQanJ5ws2V+u5ywdL2n12X1WbbEG+Jjy69I= +github.com/libp2p/go-testutil v0.1.0 h1:4QhjaWGO89udplblLVpgGDOQjzFlRavZOjuEnz2rLMc= +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.3/go.mod h1:iU0kzfMcO4tBVIk3z+7srp1YG/RFLWTSuO4enpivw8g= -github.com/libp2p/go-ws-transport v0.0.4 h1:3wt9ed0gIUrne627XHvPMTwG4/AUpsLDy4TGQi2EyQ0= -github.com/libp2p/go-ws-transport v0.0.4/go.mod h1:X9wfEcm2LAJYMox9x2VHAMHAZZSQMFC9mIa/UF6OuZk= +github.com/libp2p/go-ws-transport v0.0.5/go.mod h1:Qbl4BxPfXXhhd/o0wcrgoaItHqA9tnZjoFZnxykuaXU= +github.com/libp2p/go-ws-transport v0.1.0 h1:F+0OvvdmPTDsVc4AjPHjV7L7Pk1B7D5QwtDcKE2oag4= +github.com/libp2p/go-ws-transport v0.1.0/go.mod h1:rjw1MG1LU9YDC6gzmwObkPd/Sqwhw7yT74kj3raBFuo= github.com/libp2p/go-yamux v1.2.1/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= github.com/libp2p/go-yamux v1.2.2/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= github.com/libp2p/go-yamux v1.2.3 h1:xX8A36vpXb59frIzWFdEgptLMsOANMFq2K7fPRlunYI= @@ -446,19 +529,21 @@ github.com/libp2p/go-yamux v1.2.3/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZ github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= github.com/lucas-clemente/aes12 v0.0.0-20171027163421-cd47fb39b79f/go.mod h1:JpH9J1c9oX6otFSgdUHwUBUizmKlrMjxWnIAjff4m04= github.com/lucas-clemente/quic-go v0.10.0/go.mod h1:wuD+2XqEx8G9jtwx5ou2BEYBsE+whgQmlj0Vz/77PrY= -github.com/lucas-clemente/quic-go v0.11.1 h1:zasajC848Dqq/+WqfqBCkmPw+YHNe1MBts/z7y7nXf4= -github.com/lucas-clemente/quic-go v0.11.1/go.mod h1:PpMmPfPKO9nKJ/psF49ESTAGQSdfXxlg1otPbEB2nOw= +github.com/lucas-clemente/quic-go v0.11.2 h1:Mop0ac3zALaBR3wGs6j8OYe/tcFvFsxTUFMkE/7yUOI= +github.com/lucas-clemente/quic-go v0.11.2/go.mod h1:PpMmPfPKO9nKJ/psF49ESTAGQSdfXxlg1otPbEB2nOw= github.com/lucas-clemente/quic-go-certificates v0.0.0-20160823095156-d2f86524cced/go.mod h1:NCcRLrOTZbzhZvixZLlERbJtDtYsmMw8Jc4vS8Z0g58= +github.com/magiconair/properties v1.7.6 h1:U+1DqNen04MdEPgFiIwdOUiqZ8qPa37xgogX/sd3+54= github.com/magiconair/properties v1.7.6/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/marten-seemann/qtls v0.2.3 h1:0yWJ43C62LsZt08vuQJDK1uC1czUc3FJeCLPoNAI4vA= github.com/marten-seemann/qtls v0.2.3/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc= -github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= @@ -472,15 +557,18 @@ github.com/miekg/dns v1.1.12/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3N github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= -github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5 h1:l16XLUUJ34wIz+RIvLhSwGvLvKyy+W598b135bJN6mg= github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= +github.com/minio/sha256-simd v0.1.0 h1:U41/2erhAKcmSI14xh/ZTUdBPOzDOIfS93ibzUSl8KM= +github.com/minio/sha256-simd v0.1.0/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-ps v0.0.0-20170309133038-4fdf99ab2936/go.mod h1:r1VsdOzOPt1ZSrGZWFoNhsAedKnEd6r9Np1+5blZCWk= +github.com/mitchellh/mapstructure v0.0.0-20180220230111-00c29f56e238 h1:+MZW2uvHgN8kYvksEN3f7eFL2wpzk0GxmlFsMybWc7E= github.com/mitchellh/mapstructure v0.0.0-20180220230111-00c29f56e238/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mozilla/tls-observatory v0.0.0-20180409132520-8791a200eb40/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk= github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= +github.com/mr-tron/base58 v1.1.1/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= github.com/mr-tron/base58 v1.1.2 h1:ZEw4I2EgPKDJ2iEw0cNmLB3ROrEmkOtXIkaG7wZg+78= github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/multiformats/go-base32 v0.0.3 h1:tw5+NhuwaOjJCC5Pp82QuXbrmLzWg7uxlMFp8Nq/kkI= @@ -492,39 +580,44 @@ github.com/multiformats/go-multiaddr v0.0.4/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lg github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= github.com/multiformats/go-multiaddr-dns v0.0.2 h1:/Bbsgsy3R6e3jf2qBahzNHzww6usYaZ0NhNH3sqdFS8= github.com/multiformats/go-multiaddr-dns v0.0.2/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= +github.com/multiformats/go-multiaddr-fmt v0.0.1 h1:5YjeOIzbX8OTKVaN72aOzGIYW7PnrZrnkDyOfAWRSMA= +github.com/multiformats/go-multiaddr-fmt v0.0.1/go.mod h1:aBYjqL4T/7j4Qx+R73XSv/8JsgnRFlf0w2KGLCmXl3Q= github.com/multiformats/go-multiaddr-net v0.0.1 h1:76O59E3FavvHqNg7jvzWzsPSW5JSi/ek0E4eiDVbg9g= github.com/multiformats/go-multiaddr-net v0.0.1/go.mod h1:nw6HSxNmCIQH27XPGBuX+d1tnvM7ihcFwHMSstNAVUU= github.com/multiformats/go-multibase v0.0.1 h1:PN9/v21eLywrFWdFNsFKaU04kLJzuYzmrJR+ubhT9qA= github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= -github.com/multiformats/go-multicodec v0.1.6 h1:4u6lcjbE4VVVoigU4QJSSVYsGVP4j2jtDkR8lPwOrLE= -github.com/multiformats/go-multicodec v0.1.6/go.mod h1:lliaRHbcG8q33yf4Ot9BGD7JqR/Za9HE7HTyVyKwrUQ= github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= github.com/multiformats/go-multihash v0.0.5 h1:1wxmCvTXAifAepIMyF39vZinRw5sbqjPs/UIi93+uik= github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po= github.com/multiformats/go-multistream v0.0.1/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= -github.com/multiformats/go-multistream v0.0.4 h1:rNgWgFyzRSTI9L+xISrz7kN5MdNXoEcoIeeCH05wLKA= github.com/multiformats/go-multistream v0.0.4/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= +github.com/multiformats/go-multistream v0.1.0 h1:UpO6jrsjqs46mqAK3n6wKRYFhugss9ArzbyUzU+4wkQ= +github.com/multiformats/go-multistream v0.1.0/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nbutton23/zxcvbn-go v0.0.0-20160627004424-a22cb81b2ecd/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU= +github.com/nbutton23/zxcvbn-go v0.0.0-20171102151520-eafdab6b0663 h1:Ri1EhipkbhWsffPJ3IPlrb4SkTOPa2PfRXp3jchBczw= github.com/nbutton23/zxcvbn-go v0.0.0-20171102151520-eafdab6b0663/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/pelletier/go-toml v1.1.0 h1:cmiOvKzEunMsAxyhXSzpL5Q1CRKpVv0KQsnAIcSEVYM= github.com/pelletier/go-toml v1.1.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/polydawn/refmt v0.0.0-20190221155625-df39d6c2d992 h1:bzMe+2coZJYHnhGgVlcQKuRy4FSny4ds8dLQjw5P1XE= github.com/polydawn/refmt v0.0.0-20190221155625-df39d6c2d992/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= @@ -551,27 +644,42 @@ github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/shirou/gopsutil v0.0.0-20180427012116-c95755e4bcd7/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc= +github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e h1:MZM7FHLqUHYI0Y/mQAt3d2aYa0SiNms/hFqC9qJYolM= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= +github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041 h1:llrF3Fs4018ePo4+G/HV/uQUqEI1HMDjCeOf2V6puPc= github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= github.com/sirupsen/logrus v1.0.5/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= +github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v0.0.0-20190222223459-a17d461953aa h1:E+gaaifzi2xF65PbDmuKI3PhLWY6G5opMLniFq8vmXA= github.com/smartystreets/goconvey v0.0.0-20190222223459-a17d461953aa/go.mod h1:2RVY1rIf+2J2o/IM9+vPq9RzmHDSseB7FoXiSNIUsoU= +github.com/sourcegraph/go-diff v0.5.1 h1:gO6i5zugwzo1RVTvgvfwCOSVegNuvnNi6bAD1QCmkHs= github.com/sourcegraph/go-diff v0.5.1/go.mod h1:j2dHj3m8aZgQO8lMTcTnBcXkRRRqi34cd2MNlA9u1mE= +github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a h1:/eS3yfGjQKG+9kayBkj0ip1BGhq6zJ3eaVksphxAaek= github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0= +github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.0 h1:bopulORc2JeYaxfHLvJa5NzxviA9PoWhpiiJkru7Ji4= github.com/spf13/afero v1.1.0/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.2.0 h1:HHl1DSRbEQN2i8tJmtS6ViPyHx35+p51amrdsiTCrkg= github.com/spf13/cast v1.2.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg= +github.com/spf13/cobra v0.0.2 h1:NfkwRbgViGoyjBKsLI0QMDcuMnhM+SBg3T0cGfpvKDE= github.com/spf13/cobra v0.0.2/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/jwalterweatherman v0.0.0-20180109140146-7c0cea34c8ec h1:2ZXvIUGghLpdTVHR1UfvfrzoVlZaE/yOWC5LueIHZig= github.com/spf13/jwalterweatherman v0.0.0-20180109140146-7c0cea34c8ec/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.1 h1:aCvUg6QPl3ibpQUxyLkrEkCHtPqYJL4x9AuhqVqFis4= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/viper v1.0.2 h1:Ncr3ZIuJn322w2k1qmzXDnkLAdQMlJqBa9kfAH+irso= github.com/spf13/viper v1.0.2/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= @@ -579,11 +687,10 @@ github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e h1: github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e/go.mod h1:XDKHRm5ThF8YJjx001LtgelzsoaEcvnA7lVWz9EeX3g= github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/warpfork/go-wish v0.0.0-20180510122957-5ad1f5abf436 h1:qOpVTI+BrstcjTZLm2Yz/3sOnqkzj3FQoh0g+E5s3Gc= github.com/warpfork/go-wish v0.0.0-20180510122957-5ad1f5abf436/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc h1:BCPnHtcboadS0DvysUuJXZ4lWVv5Bh5i7+tbIyi+ck4= github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc/go.mod h1:r45hJU7yEoA81k6MWNhpMj/kms0n14dkzkxYHoB96UM= -github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11 h1:5HZfQkwe0mIfyDmc1Em5GqlNRzcdtlv4HTNmdpt7XH0= -github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11/go.mod h1:Wlo/SzPmxVp6vXpGt/zaXhHH0fn4IxgqZc82aKg6bpQ= github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f h1:jQa4QT2UP9WYv2nzyawpKMOCl+Z/jW7djv2/J50lj9E= github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f/go.mod h1:p9UJB6dDgdPgMJZs7UjUOdulKyRr9fqkS+6JKAInPy8= github.com/whyrusleeping/go-ctrlnet v0.0.0-20180313164037-f564fbbdaa95/go.mod h1:SJqKCCPXRfBFCwXjfNT/skfsceF7+MBFLI2OrvuRA7g= @@ -593,11 +700,8 @@ github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc h1:9lDbC6 github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM= github.com/whyrusleeping/go-notifier v0.0.0-20170827234753-097c5d47330f h1:M/lL30eFZTKnomXY6huvM6G0+gVquFNf6mxghaWlFUg= github.com/whyrusleeping/go-notifier v0.0.0-20170827234753-097c5d47330f/go.mod h1:cZNvX9cFybI01GriPRMXDtczuvUhgbcYr9iCGaNlRv8= -github.com/whyrusleeping/go-smux-multiplex v0.1.0/go.mod h1:OXL5hggHNZSsadXDlBJDD4eD3IQYEB3Yu6xpovd6pPw= github.com/whyrusleeping/go-smux-multiplex v3.0.16+incompatible/go.mod h1:34LEDbeKFZInPUrAG+bjuJmUXONGdEFW7XL0SpTY1y4= -github.com/whyrusleeping/go-smux-multistream v0.1.0/go.mod h1:/usW3LIBirW4h9ko1PnoF7tExBnbxPBszG0n4wylJr8= github.com/whyrusleeping/go-smux-multistream v2.0.2+incompatible/go.mod h1:dRWHHvc4HDQSHh9gbKEBbUZ+f2Q8iZTPG3UOGYODxSQ= -github.com/whyrusleeping/go-smux-yamux v0.1.1/go.mod h1:Yw+ayOEKERDHXLJ4GiE5AnBmldJW4QRLDzGFC9do8G0= 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= @@ -613,7 +717,6 @@ github.com/whyrusleeping/tar-utils v0.0.0-20180509141711-8c6c8ba81d5c/go.mod h1: 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/whyrusleeping/yamux v1.2.0/go.mod h1:Cgw3gpb4DrDZ1FrP/5pxg/cpiY54Gr5uCXwUylwi2GE= go.opencensus.io v0.21.0 h1:mU6zScU4U1YAFPHEHYk+3JC4SY7JxgkqS10ZOSyksNg= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= @@ -622,6 +725,7 @@ go.uber.org/dig v1.7.0 h1:E5/L92iQTNJTjfgJF2KgU+/JpMaiuvK2DHLBj0+kSZk= go.uber.org/dig v1.7.0/go.mod h1:z+dSd2TP9Usi48jL8M3v63iSBVkiwtVyMKxMZYYauPg= go.uber.org/fx v1.9.0 h1:7OAz8ucp35AU8eydejpYG7QrbE8rLKzGhHbZlJi5LYY= go.uber.org/fx v1.9.0/go.mod h1:mFdUyAUuJ3w4jAckiKSKbldsxy1ojpAMJ+dVZg5Y0Aw= +go.uber.org/goleak v0.10.0 h1:G3eWbSNIskeRqtsN/1uI5B+eP73y3JUuBsv9AZjehb4= go.uber.org/goleak v0.10.0/go.mod h1:VCZuO8V8mFPlL0F5J5GK1rtHV3DrFcQ1R8ryq7FK0aI= go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= @@ -644,7 +748,6 @@ golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTk golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/net v0.0.0-20170915142106-8351a756f30f/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180524181706-dfa909b99c79/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -654,18 +757,17 @@ golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190310074541-c10a0554eabf/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190522135303-fa69b94a3b58 h1:AZ8FNE2w7DVDFDK6u/iC9/Mqh73UupjaqSd/2qMoECQ= -golang.org/x/net v0.0.0-20190522135303-fa69b94a3b58/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092 h1:4QSRKanuywn15aTZvI/mIDEgPQpswuFndXpOj3rKEco= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20171026204733-164713f0dfce/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -677,29 +779,28 @@ golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190302025703-b6889370fb10/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190310054646-10058d7d4faa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5 h1:f005F/Jl5JLP036x7QIvUVhNTqxvSYwFIiyOh2q12iU= -golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190524122548-abf6ff778158/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190524152521-dbbf3f1254d4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190526052359-791d8a0f4d09 h1:IlD35wZE03o2qJy2o37WIskL33b7PT6cHdGnE8bieZs= +golang.org/x/sys v0.0.0-20190526052359-791d8a0f4d09/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.0.0-20170915090833-1cbadb444a80/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/tools v0.0.0-20170915040203-e531a2a1c15f/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181024171208-a2dc47679d30/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181117154741-2ddaf7f79a09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181205014116-22934f0fdb62/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190121143147-24cd39ecf745/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190420000508-685fecacd0a0 h1:pa1CyBALPFjblgkNQp7T7gEcFcG/GOG5Ck8IcnSVWGs= golang.org/x/tools v0.0.0-20190420000508-685fecacd0a0/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190521203540-521d6ed310dd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/xerrors v0.0.0-20190212162355-a5947ffaace3/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522 h1:bhOzK9QyoD0ogCnFro1m2mz41+Ib0oOhfJnBp5MR4K4= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -712,20 +813,30 @@ google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZi gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/cheggaaa/pb.v1 v1.0.28 h1:n1tBJnnK2r7g9OW2btFH91V92STTUevLXYFb8gy9EMk= gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gotest.tools v2.1.0+incompatible h1:5USw7CrJBYKqjg9R7QlA6jzqZKEAtvW82aNmsxxGPxw= gotest.tools v2.1.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +gotest.tools/gotestsum v0.3.4 h1:LdVJDg3RHrci4MbupUgSkwPCikz4kTzDHWtUahDAleY= gotest.tools/gotestsum v0.3.4/go.mod h1:Mnf3e5FUzXbkCfynWBGOwLssY7gTQgCHObK9tMpAriY= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed h1:WX1yoOaKQfddO/mLzdV4wptyWgoH/6hwLs7QHTixo0I= mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc= +mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphDJbHOQO1DFFFTeBo= mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= +mvdan.cc/unparam v0.0.0-20190124213536-fbb59629db34 h1:B1LAOfRqg2QUyCdzfjf46quTSYUTAK5OCwbh6pljHbM= mvdan.cc/unparam v0.0.0-20190124213536-fbb59629db34/go.mod h1:H6SUd1XjIs+qQCyskXg5OFSrilMRUkD8ePJpHKDPaeY= +sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4 h1:JPJh2pk3+X4lXAkZIk2RuE/7/FoK9maXw+TNPJhVS/c= sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= diff --git a/keystore/keystore.go b/keystore/keystore.go index d9467f263cb..237d4b05c3a 100644 --- a/keystore/keystore.go +++ b/keystore/keystore.go @@ -8,7 +8,7 @@ import ( "strings" logging "github.com/ipfs/go-log" - ci "github.com/libp2p/go-libp2p-crypto" + ci "github.com/libp2p/go-libp2p-core/crypto" ) var log = logging.Logger("keystore") diff --git a/keystore/keystore_test.go b/keystore/keystore_test.go index d7118d7564b..37f59ebffff 100644 --- a/keystore/keystore_test.go +++ b/keystore/keystore_test.go @@ -9,7 +9,7 @@ import ( "sort" "testing" - ci "github.com/libp2p/go-libp2p-crypto" + ci "github.com/libp2p/go-libp2p-core/crypto" ) type rr struct{} diff --git a/keystore/memkeystore.go b/keystore/memkeystore.go index 4f505a995b5..4067bbce29a 100644 --- a/keystore/memkeystore.go +++ b/keystore/memkeystore.go @@ -1,6 +1,6 @@ package keystore -import ci "github.com/libp2p/go-libp2p-crypto" +import ci "github.com/libp2p/go-libp2p-core/crypto" // MemKeystore is an in memory keystore implementation that is not persisted to // any backing storage. diff --git a/namesys/interface.go b/namesys/interface.go index 4db95ab3ca1..ecd80943be8 100644 --- a/namesys/interface.go +++ b/namesys/interface.go @@ -37,7 +37,7 @@ import ( path "github.com/ipfs/go-path" opts "github.com/ipfs/interface-go-ipfs-core/options/namesys" - ci "github.com/libp2p/go-libp2p-crypto" + ci "github.com/libp2p/go-libp2p-core/crypto" ) // ErrResolveFailed signals an error when attempting to resolve. diff --git a/namesys/ipns_resolver_validation_test.go b/namesys/ipns_resolver_validation_test.go index 71335b52239..9eed8375bbb 100644 --- a/namesys/ipns_resolver_validation_test.go +++ b/namesys/ipns_resolver_validation_test.go @@ -13,14 +13,13 @@ import ( ipns "github.com/ipfs/go-ipns" path "github.com/ipfs/go-path" opts "github.com/ipfs/interface-go-ipfs-core/options/namesys" - ci "github.com/libp2p/go-libp2p-crypto" - peer "github.com/libp2p/go-libp2p-peer" - pstore "github.com/libp2p/go-libp2p-peerstore" + ci "github.com/libp2p/go-libp2p-core/crypto" + peer "github.com/libp2p/go-libp2p-core/peer" + pstore "github.com/libp2p/go-libp2p-core/peerstore" + routing "github.com/libp2p/go-libp2p-core/routing" pstoremem "github.com/libp2p/go-libp2p-peerstore/pstoremem" record "github.com/libp2p/go-libp2p-record" - routing "github.com/libp2p/go-libp2p-routing" - ropts "github.com/libp2p/go-libp2p-routing/options" - testutil "github.com/libp2p/go-testutil" + testutil "github.com/libp2p/go-libp2p-testing/net" ) func TestResolverValidation(t *testing.T) { @@ -168,11 +167,11 @@ func newMockValueStore(id testutil.Identity, dstore ds.Datastore, kbook pstore.K } } -func (m *mockValueStore) GetValue(ctx context.Context, k string, opts ...ropts.Option) ([]byte, error) { +func (m *mockValueStore) GetValue(ctx context.Context, k string, opts ...routing.Option) ([]byte, error) { return m.r.GetValue(ctx, k, opts...) } -func (m *mockValueStore) SearchValue(ctx context.Context, k string, opts ...ropts.Option) (<-chan []byte, error) { +func (m *mockValueStore) SearchValue(ctx context.Context, k string, opts ...routing.Option) (<-chan []byte, error) { return m.r.SearchValue(ctx, k, opts...) } @@ -196,6 +195,6 @@ func (m *mockValueStore) GetPublicKey(ctx context.Context, p peer.ID) (ci.PubKey return pk, m.kbook.AddPubKey(p, pk) } -func (m *mockValueStore) PutValue(ctx context.Context, k string, d []byte, opts ...ropts.Option) error { +func (m *mockValueStore) PutValue(ctx context.Context, k string, d []byte, opts ...routing.Option) error { return m.r.PutValue(ctx, k, d, opts...) } diff --git a/namesys/namesys.go b/namesys/namesys.go index f8b8c6d12e8..6d59c62e334 100644 --- a/namesys/namesys.go +++ b/namesys/namesys.go @@ -10,9 +10,9 @@ import ( path "github.com/ipfs/go-path" opts "github.com/ipfs/interface-go-ipfs-core/options/namesys" isd "github.com/jbenet/go-is-domain" - ci "github.com/libp2p/go-libp2p-crypto" - peer "github.com/libp2p/go-libp2p-peer" - routing "github.com/libp2p/go-libp2p-routing" + ci "github.com/libp2p/go-libp2p-core/crypto" + peer "github.com/libp2p/go-libp2p-core/peer" + routing "github.com/libp2p/go-libp2p-core/routing" mh "github.com/multiformats/go-multihash" ) diff --git a/namesys/namesys_test.go b/namesys/namesys_test.go index 2cf316cf32c..031ae833ac6 100644 --- a/namesys/namesys_test.go +++ b/namesys/namesys_test.go @@ -12,8 +12,8 @@ import ( path "github.com/ipfs/go-path" "github.com/ipfs/go-unixfs" opts "github.com/ipfs/interface-go-ipfs-core/options/namesys" - ci "github.com/libp2p/go-libp2p-crypto" - peer "github.com/libp2p/go-libp2p-peer" + ci "github.com/libp2p/go-libp2p-core/crypto" + peer "github.com/libp2p/go-libp2p-core/peer" pstoremem "github.com/libp2p/go-libp2p-peerstore/pstoremem" record "github.com/libp2p/go-libp2p-record" ) diff --git a/namesys/publisher.go b/namesys/publisher.go index e43858d02f6..c06deb795ae 100644 --- a/namesys/publisher.go +++ b/namesys/publisher.go @@ -15,9 +15,9 @@ import ( pb "github.com/ipfs/go-ipns/pb" path "github.com/ipfs/go-path" ft "github.com/ipfs/go-unixfs" - ci "github.com/libp2p/go-libp2p-crypto" - peer "github.com/libp2p/go-libp2p-peer" - routing "github.com/libp2p/go-libp2p-routing" + ci "github.com/libp2p/go-libp2p-core/crypto" + peer "github.com/libp2p/go-libp2p-core/peer" + routing "github.com/libp2p/go-libp2p-core/routing" base32 "github.com/whyrusleeping/base32" ) diff --git a/namesys/publisher_test.go b/namesys/publisher_test.go index 53cc6735eee..0b7b2c93999 100644 --- a/namesys/publisher_test.go +++ b/namesys/publisher_test.go @@ -11,9 +11,9 @@ import ( dshelp "github.com/ipfs/go-ipfs-ds-help" mockrouting "github.com/ipfs/go-ipfs-routing/mock" ipns "github.com/ipfs/go-ipns" - ci "github.com/libp2p/go-libp2p-crypto" - peer "github.com/libp2p/go-libp2p-peer" - testutil "github.com/libp2p/go-testutil" + ci "github.com/libp2p/go-libp2p-core/crypto" + peer "github.com/libp2p/go-libp2p-core/peer" + testutil "github.com/libp2p/go-libp2p-testing/net" ma "github.com/multiformats/go-multiaddr" ) diff --git a/namesys/republisher/repub.go b/namesys/republisher/repub.go index 1092ba3a57c..9e7272d32e0 100644 --- a/namesys/republisher/repub.go +++ b/namesys/republisher/repub.go @@ -15,8 +15,8 @@ import ( logging "github.com/ipfs/go-log" goprocess "github.com/jbenet/goprocess" gpctx "github.com/jbenet/goprocess/context" - ic "github.com/libp2p/go-libp2p-crypto" - peer "github.com/libp2p/go-libp2p-peer" + ic "github.com/libp2p/go-libp2p-core/crypto" + peer "github.com/libp2p/go-libp2p-core/peer" ) var errNoEntry = errors.New("no previous entry") diff --git a/namesys/republisher/repub_test.go b/namesys/republisher/repub_test.go index 48a0b086f0c..5fedc3907a2 100644 --- a/namesys/republisher/repub_test.go +++ b/namesys/republisher/repub_test.go @@ -14,7 +14,7 @@ import ( path "github.com/ipfs/go-path" goprocess "github.com/jbenet/goprocess" - pstore "github.com/libp2p/go-libp2p-peerstore" + peer "github.com/libp2p/go-libp2p-core/peer" mocknet "github.com/libp2p/go-libp2p/p2p/net/mock" ) @@ -47,7 +47,7 @@ func TestRepublish(t *testing.T) { } bsinf := bootstrap.BootstrapConfigWithPeers( - []pstore.PeerInfo{ + []peer.AddrInfo{ nodes[0].Peerstore.PeerInfo(nodes[0].Identity), }, ) diff --git a/namesys/resolve_test.go b/namesys/resolve_test.go index 88206144868..814bf59730a 100644 --- a/namesys/resolve_test.go +++ b/namesys/resolve_test.go @@ -11,8 +11,10 @@ import ( mockrouting "github.com/ipfs/go-ipfs-routing/mock" ipns "github.com/ipfs/go-ipns" path "github.com/ipfs/go-path" - peer "github.com/libp2p/go-libp2p-peer" - testutil "github.com/libp2p/go-testutil" + ci "github.com/libp2p/go-libp2p-core/crypto" + peer "github.com/libp2p/go-libp2p-core/peer" + test "github.com/libp2p/go-libp2p-core/test" + testutil "github.com/libp2p/go-libp2p-testing/net" ) func TestRoutingResolve(t *testing.T) { @@ -24,7 +26,7 @@ func TestRoutingResolve(t *testing.T) { resolver := NewIpnsResolver(d) publisher := NewIpnsPublisher(d, dstore) - privk, pubk, err := testutil.RandTestKeyPair(512) + privk, pubk, err := test.RandTestKeyPair(ci.RSA, 512) if err != nil { t.Fatal(err) } @@ -57,7 +59,7 @@ func TestPrexistingExpiredRecord(t *testing.T) { resolver := NewIpnsResolver(d) publisher := NewIpnsPublisher(d, dstore) - privk, pubk, err := testutil.RandTestKeyPair(512) + privk, pubk, err := test.RandTestKeyPair(ci.RSA, 512) if err != nil { t.Fatal(err) } @@ -99,7 +101,7 @@ func TestPrexistingRecord(t *testing.T) { resolver := NewIpnsResolver(d) publisher := NewIpnsPublisher(d, dstore) - privk, pubk, err := testutil.RandTestKeyPair(512) + privk, pubk, err := test.RandTestKeyPair(ci.RSA, 512) if err != nil { t.Fatal(err) } diff --git a/namesys/routing.go b/namesys/routing.go index e89dd9c9d4f..94c12a72617 100644 --- a/namesys/routing.go +++ b/namesys/routing.go @@ -12,9 +12,9 @@ import ( logging "github.com/ipfs/go-log" path "github.com/ipfs/go-path" opts "github.com/ipfs/interface-go-ipfs-core/options/namesys" + peer "github.com/libp2p/go-libp2p-core/peer" + routing "github.com/libp2p/go-libp2p-core/routing" dht "github.com/libp2p/go-libp2p-kad-dht" - peer "github.com/libp2p/go-libp2p-peer" - routing "github.com/libp2p/go-libp2p-routing" mh "github.com/multiformats/go-multihash" ) diff --git a/p2p/listener.go b/p2p/listener.go index ff7859b0310..65fe87c2040 100644 --- a/p2p/listener.go +++ b/p2p/listener.go @@ -4,9 +4,9 @@ import ( "errors" "sync" - p2phost "github.com/libp2p/go-libp2p-host" - net "github.com/libp2p/go-libp2p-net" - "github.com/libp2p/go-libp2p-protocol" + p2phost "github.com/libp2p/go-libp2p-core/host" + net "github.com/libp2p/go-libp2p-core/network" + "github.com/libp2p/go-libp2p-core/protocol" ma "github.com/multiformats/go-multiaddr" ) diff --git a/p2p/local.go b/p2p/local.go index b96afa91987..bff25e20014 100644 --- a/p2p/local.go +++ b/p2p/local.go @@ -5,9 +5,9 @@ import ( "time" tec "github.com/jbenet/go-temp-err-catcher" - "github.com/libp2p/go-libp2p-net" - "github.com/libp2p/go-libp2p-peer" - "github.com/libp2p/go-libp2p-protocol" + net "github.com/libp2p/go-libp2p-core/network" + "github.com/libp2p/go-libp2p-core/peer" + "github.com/libp2p/go-libp2p-core/protocol" ma "github.com/multiformats/go-multiaddr" "github.com/multiformats/go-multiaddr-net" ) diff --git a/p2p/p2p.go b/p2p/p2p.go index 21132120a00..078ba51c477 100644 --- a/p2p/p2p.go +++ b/p2p/p2p.go @@ -2,9 +2,9 @@ package p2p import ( logging "github.com/ipfs/go-log" - p2phost "github.com/libp2p/go-libp2p-host" - peer "github.com/libp2p/go-libp2p-peer" - pstore "github.com/libp2p/go-libp2p-peerstore" + p2phost "github.com/libp2p/go-libp2p-core/host" + peer "github.com/libp2p/go-libp2p-core/peer" + pstore "github.com/libp2p/go-libp2p-core/peerstore" ) var log = logging.Logger("p2p-mount") diff --git a/p2p/remote.go b/p2p/remote.go index f6b956829f8..a89b2f2f656 100644 --- a/p2p/remote.go +++ b/p2p/remote.go @@ -4,8 +4,8 @@ import ( "context" "fmt" - net "github.com/libp2p/go-libp2p-net" - protocol "github.com/libp2p/go-libp2p-protocol" + net "github.com/libp2p/go-libp2p-core/network" + protocol "github.com/libp2p/go-libp2p-core/protocol" ma "github.com/multiformats/go-multiaddr" manet "github.com/multiformats/go-multiaddr-net" ) diff --git a/p2p/stream.go b/p2p/stream.go index e29c965b024..137f14c114c 100644 --- a/p2p/stream.go +++ b/p2p/stream.go @@ -4,10 +4,10 @@ import ( "io" "sync" - ifconnmgr "github.com/libp2p/go-libp2p-interface-connmgr" - net "github.com/libp2p/go-libp2p-net" - peer "github.com/libp2p/go-libp2p-peer" - protocol "github.com/libp2p/go-libp2p-protocol" + ifconnmgr "github.com/libp2p/go-libp2p-core/connmgr" + net "github.com/libp2p/go-libp2p-core/network" + peer "github.com/libp2p/go-libp2p-core/peer" + protocol "github.com/libp2p/go-libp2p-core/protocol" ma "github.com/multiformats/go-multiaddr" manet "github.com/multiformats/go-multiaddr-net" ) diff --git a/provider/simple/provider.go b/provider/simple/provider.go index 8310cebb3a4..abe13ce5986 100644 --- a/provider/simple/provider.go +++ b/provider/simple/provider.go @@ -9,7 +9,7 @@ import ( cid "github.com/ipfs/go-cid" q "github.com/ipfs/go-ipfs/provider/queue" logging "github.com/ipfs/go-log" - routing "github.com/libp2p/go-libp2p-routing" + routing "github.com/libp2p/go-libp2p-core/routing" ) var logP = logging.Logger("provider.simple") diff --git a/provider/simple/provider_test.go b/provider/simple/provider_test.go index 6f70a41d722..4922958c8c9 100644 --- a/provider/simple/provider_test.go +++ b/provider/simple/provider_test.go @@ -10,7 +10,7 @@ import ( datastore "github.com/ipfs/go-datastore" sync "github.com/ipfs/go-datastore/sync" blocksutil "github.com/ipfs/go-ipfs-blocksutil" - pstore "github.com/libp2p/go-libp2p-peerstore" + peer "github.com/libp2p/go-libp2p-core/peer" q "github.com/ipfs/go-ipfs/provider/queue" @@ -28,7 +28,7 @@ func (r *mockRouting) Provide(ctx context.Context, cid cid.Cid, recursive bool) return nil } -func (r *mockRouting) FindProvidersAsync(ctx context.Context, cid cid.Cid, timeout int) <-chan pstore.PeerInfo { +func (r *mockRouting) FindProvidersAsync(ctx context.Context, cid cid.Cid, timeout int) <-chan peer.AddrInfo { return nil } diff --git a/provider/simple/reprovide.go b/provider/simple/reprovide.go index 73b733ce24a..ce5c71812fd 100644 --- a/provider/simple/reprovide.go +++ b/provider/simple/reprovide.go @@ -14,7 +14,7 @@ import ( logging "github.com/ipfs/go-log" merkledag "github.com/ipfs/go-merkledag" verifcid "github.com/ipfs/go-verifcid" - routing "github.com/libp2p/go-libp2p-routing" + routing "github.com/libp2p/go-libp2p-core/routing" ) var logR = logging.Logger("reprovider.simple") diff --git a/provider/simple/reprovide_test.go b/provider/simple/reprovide_test.go index 17c626c5b9e..e9925e55ec8 100644 --- a/provider/simple/reprovide_test.go +++ b/provider/simple/reprovide_test.go @@ -10,8 +10,8 @@ import ( dssync "github.com/ipfs/go-datastore/sync" "github.com/ipfs/go-ipfs-blockstore" mock "github.com/ipfs/go-ipfs-routing/mock" - pstore "github.com/libp2p/go-libp2p-peerstore" - "github.com/libp2p/go-testutil" + peer "github.com/libp2p/go-libp2p-core/peer" + testutil "github.com/libp2p/go-libp2p-testing/net" . "github.com/ipfs/go-ipfs/provider/simple" ) @@ -43,7 +43,7 @@ func TestReprovide(t *testing.T) { t.Fatal(err) } - var providers []pstore.PeerInfo + var providers []peer.AddrInfo maxProvs := 100 provChan := clB.FindProvidersAsync(ctx, blk.Cid(), maxProvs) diff --git a/test/integration/addcat_test.go b/test/integration/addcat_test.go index 98e6936ee82..eebc1f63f76 100644 --- a/test/integration/addcat_test.go +++ b/test/integration/addcat_test.go @@ -11,18 +11,17 @@ import ( "testing" "time" + files "github.com/ipfs/go-ipfs-files" "github.com/ipfs/go-ipfs/core" "github.com/ipfs/go-ipfs/core/bootstrap" "github.com/ipfs/go-ipfs/core/coreapi" mock "github.com/ipfs/go-ipfs/core/mock" "github.com/ipfs/go-ipfs/thirdparty/unit" - - files "github.com/ipfs/go-ipfs-files" logging "github.com/ipfs/go-log" random "github.com/jbenet/go-random" - pstore "github.com/libp2p/go-libp2p-peerstore" + peer "github.com/libp2p/go-libp2p-core/peer" + testutil "github.com/libp2p/go-libp2p-testing/net" mocknet "github.com/libp2p/go-libp2p/p2p/net/mock" - testutil "github.com/libp2p/go-testutil" ) var log = logging.Logger("epictest") @@ -138,8 +137,8 @@ func DirectAddCat(data []byte, conf testutil.LatencyConfig) error { return err } - bs1 := []pstore.PeerInfo{adder.Peerstore.PeerInfo(adder.Identity)} - bs2 := []pstore.PeerInfo{catter.Peerstore.PeerInfo(catter.Identity)} + bs1 := []peer.AddrInfo{adder.Peerstore.PeerInfo(adder.Identity)} + bs2 := []peer.AddrInfo{catter.Peerstore.PeerInfo(catter.Identity)} if err := catter.Bootstrap(bootstrap.BootstrapConfigWithPeers(bs1)); err != nil { return err diff --git a/test/integration/bench_cat_test.go b/test/integration/bench_cat_test.go index a40fcfe37b1..6115b5b54dd 100644 --- a/test/integration/bench_cat_test.go +++ b/test/integration/bench_cat_test.go @@ -8,16 +8,15 @@ import ( "math" "testing" + files "github.com/ipfs/go-ipfs-files" "github.com/ipfs/go-ipfs/core" "github.com/ipfs/go-ipfs/core/bootstrap" "github.com/ipfs/go-ipfs/core/coreapi" mock "github.com/ipfs/go-ipfs/core/mock" "github.com/ipfs/go-ipfs/thirdparty/unit" - - files "github.com/ipfs/go-ipfs-files" - pstore "github.com/libp2p/go-libp2p-peerstore" + peer "github.com/libp2p/go-libp2p-core/peer" + testutil "github.com/libp2p/go-libp2p-testing/net" mocknet "github.com/libp2p/go-libp2p/p2p/net/mock" - testutil "github.com/libp2p/go-testutil" ) func BenchmarkCat1MB(b *testing.B) { benchmarkVarCat(b, unit.MB*1) } @@ -81,8 +80,8 @@ func benchCat(b *testing.B, data []byte, conf testutil.LatencyConfig) error { return err } - bs1 := []pstore.PeerInfo{adder.Peerstore.PeerInfo(adder.Identity)} - bs2 := []pstore.PeerInfo{catter.Peerstore.PeerInfo(catter.Identity)} + bs1 := []peer.AddrInfo{adder.Peerstore.PeerInfo(adder.Identity)} + bs2 := []peer.AddrInfo{catter.Peerstore.PeerInfo(catter.Identity)} if err := catter.Bootstrap(bootstrap.BootstrapConfigWithPeers(bs1)); err != nil { return err diff --git a/test/integration/bench_test.go b/test/integration/bench_test.go index 78e78eb57d0..bc5a22ea91d 100644 --- a/test/integration/bench_test.go +++ b/test/integration/bench_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/ipfs/go-ipfs/thirdparty/unit" - testutil "github.com/libp2p/go-testutil" + testutil "github.com/libp2p/go-libp2p-testing/net" ) func benchmarkAddCat(numBytes int64, conf testutil.LatencyConfig, b *testing.B) { diff --git a/test/integration/three_legged_cat_test.go b/test/integration/three_legged_cat_test.go index 1fc0e7bf253..ab9b857c59f 100644 --- a/test/integration/three_legged_cat_test.go +++ b/test/integration/three_legged_cat_test.go @@ -16,9 +16,9 @@ import ( "github.com/ipfs/go-ipfs/thirdparty/unit" files "github.com/ipfs/go-ipfs-files" - pstore "github.com/libp2p/go-libp2p-peerstore" + peer "github.com/libp2p/go-libp2p-core/peer" + testutil "github.com/libp2p/go-libp2p-testing/net" mocknet "github.com/libp2p/go-libp2p/p2p/net/mock" - testutil "github.com/libp2p/go-testutil" ) func TestThreeLeggedCatTransfer(t *testing.T) { @@ -119,7 +119,7 @@ func RunThreeLeggedCat(data []byte, conf testutil.LatencyConfig) error { } bis := bootstrap.Peerstore.PeerInfo(bootstrap.PeerHost.ID()) - bcfg := bootstrap2.BootstrapConfigWithPeers([]pstore.PeerInfo{bis}) + bcfg := bootstrap2.BootstrapConfigWithPeers([]peer.AddrInfo{bis}) if err := adder.Bootstrap(bcfg); err != nil { return err } From 5d468e23ea315811018c3af46e0b29f4355f7d37 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Fri, 31 May 2019 17:06:52 -0700 Subject: [PATCH 022/671] chore: deprecate go-ipfs-addr --- core/bootstrap/bootstrap.go | 24 ------ core/bootstrap/bootstrap_test.go | 31 -------- core/commands/bootstrap.go | 130 ++++++++++++++++++------------- core/commands/p2p.go | 60 +++++++------- core/commands/ping.go | 9 ++- core/commands/swarm.go | 90 +++++++-------------- core/core.go | 6 +- core/coreapi/swarm.go | 30 +++---- go.mod | 7 +- go.sum | 49 ++++-------- 10 files changed, 176 insertions(+), 260 deletions(-) diff --git a/core/bootstrap/bootstrap.go b/core/bootstrap/bootstrap.go index b2cf1a811b9..02669036633 100644 --- a/core/bootstrap/bootstrap.go +++ b/core/bootstrap/bootstrap.go @@ -9,7 +9,6 @@ import ( "sync" "time" - config "github.com/ipfs/go-ipfs-config" logging "github.com/ipfs/go-log" "github.com/jbenet/goprocess" "github.com/jbenet/goprocess/context" @@ -216,26 +215,3 @@ func randomSubsetOfPeers(in []peer.AddrInfo, max int) []peer.AddrInfo { } return out } - -type Peers []config.BootstrapPeer - -func (bpeers Peers) ToPeerInfos() []peer.AddrInfo { - pinfos := make(map[peer.ID]*peer.AddrInfo) - for _, bootstrap := range bpeers { - pinfo, ok := pinfos[bootstrap.ID()] - if !ok { - pinfo = new(peer.AddrInfo) - pinfos[bootstrap.ID()] = pinfo - pinfo.ID = bootstrap.ID() - } - - pinfo.Addrs = append(pinfo.Addrs, bootstrap.Transport()) - } - - var peers []peer.AddrInfo - for _, pinfo := range pinfos { - peers = append(peers, *pinfo) - } - - return peers -} diff --git a/core/bootstrap/bootstrap_test.go b/core/bootstrap/bootstrap_test.go index e7e460b8781..23128c31f26 100644 --- a/core/bootstrap/bootstrap_test.go +++ b/core/bootstrap/bootstrap_test.go @@ -1,10 +1,8 @@ package bootstrap import ( - "fmt" "testing" - config "github.com/ipfs/go-ipfs-config" "github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/test" ) @@ -25,32 +23,3 @@ func TestSubsetWhenMaxIsGreaterThanLengthOfSlice(t *testing.T) { t.Fail() } } - -func TestMultipleAddrsPerPeer(t *testing.T) { - var bsps []config.BootstrapPeer - for i := 0; i < 10; i++ { - pid, err := test.RandPeerID() - if err != nil { - t.Fatal(err) - } - - addr := fmt.Sprintf("/ip4/127.0.0.1/tcp/5001/ipfs/%s", pid.Pretty()) - bsp1, err := config.ParseBootstrapPeer(addr) - if err != nil { - t.Fatal(err) - } - - addr = fmt.Sprintf("/ip4/127.0.0.1/udp/5002/utp/ipfs/%s", pid.Pretty()) - bsp2, err := config.ParseBootstrapPeer(addr) - if err != nil { - t.Fatal(err) - } - - bsps = append(bsps, bsp1, bsp2) - } - - pinfos := Peers.ToPeerInfos(bsps) - if len(pinfos) != len(bsps)/2 { - t.Fatal("expected fewer peers") - } -} diff --git a/core/commands/bootstrap.go b/core/commands/bootstrap.go index 1b21fbd0053..1aaa6456501 100644 --- a/core/commands/bootstrap.go +++ b/core/commands/bootstrap.go @@ -2,6 +2,7 @@ package commands import ( "errors" + "fmt" "io" "sort" @@ -11,6 +12,8 @@ import ( cmds "github.com/ipfs/go-ipfs-cmds" config "github.com/ipfs/go-ipfs-config" + peer "github.com/libp2p/go-libp2p-core/peer" + ma "github.com/multiformats/go-multiaddr" ) type BootstrapOutput struct { @@ -64,26 +67,13 @@ in the bootstrap list). Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { deflt, _ := req.Options[defaultOptionName].(bool) - var inputPeers []config.BootstrapPeer - if deflt { - // parse separately for meaningful, correct error. - defltPeers, err := config.DefaultBootstrapPeers() - if err != nil { - return err - } - - inputPeers = defltPeers - } else { + inputPeers := config.DefaultBootstrapAddresses + if !deflt { if err := req.ParseBodyArgs(); err != nil { return err } - parsedPeers, err := config.ParseBootstrapPeers(req.Arguments) - if err != nil { - return err - } - - inputPeers = parsedPeers + inputPeers = req.Arguments } if len(inputPeers) == 0 { @@ -110,7 +100,7 @@ in the bootstrap list). return err } - return cmds.EmitOnce(res, &BootstrapOutput{config.BootstrapPeerStrings(added)}) + return cmds.EmitOnce(res, &BootstrapOutput{added}) }, Type: BootstrapOutput{}, Encoders: cmds.EncoderMap{ @@ -127,11 +117,6 @@ var bootstrapAddDefaultCmd = &cmds.Command{ in the bootstrap list).`, }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { - defltPeers, err := config.DefaultBootstrapPeers() - if err != nil { - return err - } - cfgRoot, err := cmdenv.GetConfigRoot(env) if err != nil { return err @@ -148,12 +133,12 @@ in the bootstrap list).`, return err } - added, err := bootstrapAdd(r, cfg, defltPeers) + added, err := bootstrapAdd(r, cfg, config.DefaultBootstrapAddresses) if err != nil { return err } - return cmds.EmitOnce(res, &BootstrapOutput{config.BootstrapPeerStrings(added)}) + return cmds.EmitOnce(res, &BootstrapOutput{added}) }, Type: BootstrapOutput{}, Encoders: cmds.EncoderMap{ @@ -201,26 +186,20 @@ var bootstrapRemoveCmd = &cmds.Command{ return err } - var removed []config.BootstrapPeer + var removed []string if all { removed, err = bootstrapRemoveAll(r, cfg) } else { if err := req.ParseBodyArgs(); err != nil { return err } - - input, perr := config.ParseBootstrapPeers(req.Arguments) - if perr != nil { - return perr - } - - removed, err = bootstrapRemove(r, cfg, input) + removed, err = bootstrapRemove(r, cfg, req.Arguments) } if err != nil { return err } - return cmds.EmitOnce(res, &BootstrapOutput{config.BootstrapPeerStrings(removed)}) + return cmds.EmitOnce(res, &BootstrapOutput{removed}) }, Type: BootstrapOutput{}, Encoders: cmds.EncoderMap{ @@ -257,7 +236,7 @@ var bootstrapRemoveAllCmd = &cmds.Command{ return err } - return cmds.EmitOnce(res, &BootstrapOutput{config.BootstrapPeerStrings(removed)}) + return cmds.EmitOnce(res, &BootstrapOutput{removed}) }, Type: BootstrapOutput{}, Encoders: cmds.EncoderMap{ @@ -315,23 +294,36 @@ func bootstrapWritePeers(w io.Writer, prefix string, peers []string) error { return nil } -func bootstrapAdd(r repo.Repo, cfg *config.Config, peers []config.BootstrapPeer) ([]config.BootstrapPeer, error) { +func bootstrapAdd(r repo.Repo, cfg *config.Config, peers []string) ([]string, error) { + for _, p := range peers { + m, err := ma.NewMultiaddr(p) + if err != nil { + return nil, err + } + tpt, p2ppart := ma.SplitLast(m) + if p2ppart == nil || p2ppart.Protocol().Code != ma.P_P2P { + return nil, fmt.Errorf("invalid bootstrap address: %s", p) + } + if tpt == nil { + return nil, fmt.Errorf("bootstrap address without a transport: %s", p) + } + } + addedMap := map[string]struct{}{} - addedList := make([]config.BootstrapPeer, 0, len(peers)) + addedList := make([]string, 0, len(peers)) // re-add cfg bootstrap peers to rm dupes bpeers := cfg.Bootstrap cfg.Bootstrap = nil // add new peers - for _, peer := range peers { - s := peer.String() + for _, s := range peers { if _, found := addedMap[s]; found { continue } cfg.Bootstrap = append(cfg.Bootstrap, s) - addedList = append(addedList, peer) + addedList = append(addedList, s) addedMap[s] = struct{}{} } @@ -352,27 +344,56 @@ func bootstrapAdd(r repo.Repo, cfg *config.Config, peers []config.BootstrapPeer) return addedList, nil } -func bootstrapRemove(r repo.Repo, cfg *config.Config, toRemove []config.BootstrapPeer) ([]config.BootstrapPeer, error) { - removed := make([]config.BootstrapPeer, 0, len(toRemove)) - keep := make([]config.BootstrapPeer, 0, len(cfg.Bootstrap)) +func bootstrapRemove(r repo.Repo, cfg *config.Config, toRemove []string) ([]string, error) { + removed := make([]peer.AddrInfo, 0, len(toRemove)) + keep := make([]peer.AddrInfo, 0, len(cfg.Bootstrap)) + + toRemoveAddr, err := config.ParseBootstrapPeers(toRemove) + if err != nil { + return nil, err + } + toRemoveMap := make(map[peer.ID][]ma.Multiaddr, len(toRemoveAddr)) + for _, addr := range toRemoveAddr { + toRemoveMap[addr.ID] = addr.Addrs + } peers, err := cfg.BootstrapPeers() if err != nil { return nil, err } - for _, peer := range peers { - found := false - for _, peer2 := range toRemove { - if peer.Equal(peer2) { - found = true - removed = append(removed, peer) - break + for _, p := range peers { + addrs, ok := toRemoveMap[p.ID] + // not in the remove set? + if !ok { + keep = append(keep, p) + continue + } + // remove the entire peer? + if len(addrs) == 0 { + removed = append(removed, p) + continue + } + var ( + keptAddrs, removedAddrs []ma.Multiaddr + ) + // remove specific addresses + filter: + for _, addr := range p.Addrs { + for _, addr2 := range addrs { + if addr.Equal(addr2) { + removedAddrs = append(removedAddrs, addr) + continue filter + } } + keptAddrs = append(keptAddrs, addr) + } + if len(removedAddrs) > 0 { + removed = append(removed, peer.AddrInfo{ID: p.ID, Addrs: removedAddrs}) } - if !found { - keep = append(keep, peer) + if len(keptAddrs) > 0 { + keep = append(keep, peer.AddrInfo{ID: p.ID, Addrs: keptAddrs}) } } cfg.SetBootstrapPeers(keep) @@ -381,10 +402,10 @@ func bootstrapRemove(r repo.Repo, cfg *config.Config, toRemove []config.Bootstra return nil, err } - return removed, nil + return config.BootstrapPeerStrings(removed), nil } -func bootstrapRemoveAll(r repo.Repo, cfg *config.Config) ([]config.BootstrapPeer, error) { +func bootstrapRemoveAll(r repo.Repo, cfg *config.Config) ([]string, error) { removed, err := cfg.BootstrapPeers() if err != nil { return nil, err @@ -394,8 +415,7 @@ func bootstrapRemoveAll(r repo.Repo, cfg *config.Config) ([]config.BootstrapPeer if err := r.SetConfig(cfg); err != nil { return nil, err } - - return removed, nil + return config.BootstrapPeerStrings(removed), nil } const bootstrapSecurityWarning = ` diff --git a/core/commands/p2p.go b/core/commands/p2p.go index 687f16fd550..c84c8e3bc7a 100644 --- a/core/commands/p2p.go +++ b/core/commands/p2p.go @@ -14,8 +14,8 @@ import ( cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv" p2p "github.com/ipfs/go-ipfs/p2p" - ipfsaddr "github.com/ipfs/go-ipfs-addr" cmds "github.com/ipfs/go-ipfs-cmds" + peer "github.com/libp2p/go-libp2p-core/peer" pstore "github.com/libp2p/go-libp2p-core/peerstore" protocol "github.com/libp2p/go-libp2p-core/protocol" ma "github.com/multiformats/go-multiaddr" @@ -133,37 +133,49 @@ Example: } // parseIpfsAddr is a function that takes in addr string and return ipfsAddrs -func parseIpfsAddr(addr string) ([]ipfsaddr.IPFSAddr, error) { - mutiladdr, err := ma.NewMultiaddr(addr) +func parseIpfsAddr(addr string) (*peer.AddrInfo, error) { + multiaddr, err := ma.NewMultiaddr(addr) if err != nil { return nil, err } - if _, err := mutiladdr.ValueForProtocol(ma.P_IPFS); err == nil { - iaddrs := make([]ipfsaddr.IPFSAddr, 1) - iaddrs[0], err = ipfsaddr.ParseMultiaddr(mutiladdr) - if err != nil { - return nil, err - } - return iaddrs, nil + + pi, err := peer.AddrInfoFromP2pAddr(multiaddr) + if err == nil { + return pi, nil } - // resolve mutiladdr whose protocol is not ma.P_IPFS + + // resolve multiaddr whose protocol is not ma.P_IPFS ctx, cancel := context.WithTimeout(context.Background(), resolveTimeout) defer cancel() - addrs, err := madns.Resolve(ctx, mutiladdr) + addrs, err := madns.Resolve(ctx, multiaddr) if err != nil { return nil, err } if len(addrs) == 0 { - return nil, errors.New("fail to resolve the multiaddr:" + mutiladdr.String()) + return nil, errors.New("fail to resolve the multiaddr:" + multiaddr.String()) } - iaddrs := make([]ipfsaddr.IPFSAddr, len(addrs)) - for i, addr := range addrs { - iaddrs[i], err = ipfsaddr.ParseMultiaddr(addr) - if err != nil { - return nil, err + var info peer.AddrInfo + for _, addr := range addrs { + taddr, id := peer.SplitAddr(addr) + if id == "" { + // not an ipfs addr, skipping. + continue + } + switch info.ID { + case "": + info.ID = id + case id: + default: + return nil, fmt.Errorf( + "ambiguous multiaddr %s could refer to %s or %s", + multiaddr, + info.ID, + id, + ) } + info.Addrs = append(info.Addrs, taddr) } - return iaddrs, nil + return &info, nil } var p2pListenCmd = &cmds.Command{ @@ -256,14 +268,10 @@ func checkPort(target ma.Multiaddr) error { } // forwardLocal forwards local connections to a libp2p service -func forwardLocal(ctx context.Context, p *p2p.P2P, ps pstore.Peerstore, proto protocol.ID, bindAddr ma.Multiaddr, addrs []ipfsaddr.IPFSAddr) error { - for _, addr := range addrs { - ps.AddAddr(addr.ID(), addr.Multiaddr(), pstore.TempAddrTTL) - } +func forwardLocal(ctx context.Context, p *p2p.P2P, ps pstore.Peerstore, proto protocol.ID, bindAddr ma.Multiaddr, addr *peer.AddrInfo) error { + ps.AddAddrs(addr.ID, addr.Addrs, pstore.TempAddrTTL) // TODO: return some info - // the length of the addrs must large than 0 - // peerIDs in addr must be the same and choose addr[0] to connect - _, err := p.ForwardLocal(ctx, addrs[0].ID(), proto, bindAddr) + _, err := p.ForwardLocal(ctx, addr.ID, proto, bindAddr) return err } diff --git a/core/commands/ping.go b/core/commands/ping.go index 7d2a615d5f3..89352ad1b34 100644 --- a/core/commands/ping.go +++ b/core/commands/ping.go @@ -10,7 +10,6 @@ import ( "github.com/ipfs/go-ipfs/core/commands/cmdenv" - iaddr "github.com/ipfs/go-ipfs-addr" cmds "github.com/ipfs/go-ipfs-cmds" peer "github.com/libp2p/go-libp2p-core/peer" pstore "github.com/libp2p/go-libp2p-core/peerstore" @@ -207,11 +206,15 @@ trip latency information. func ParsePeerParam(text string) (ma.Multiaddr, peer.ID, error) { // Multiaddr if strings.HasPrefix(text, "/") { - a, err := iaddr.ParseString(text) + maddr, err := ma.NewMultiaddr(text) if err != nil { return nil, "", err } - return a.Transport(), a.ID(), nil + transport, id := peer.SplitAddr(maddr) + if id == "" { + return nil, "", peer.ErrInvalidAddr + } + return transport, id, nil } // Raw peer ID p, err := peer.IDB58Decode(text) diff --git a/core/commands/swarm.go b/core/commands/swarm.go index 3a413a68451..db9122f3d7a 100644 --- a/core/commands/swarm.go +++ b/core/commands/swarm.go @@ -15,7 +15,6 @@ import ( repo "github.com/ipfs/go-ipfs/repo" fsrepo "github.com/ipfs/go-ipfs/repo/fsrepo" - iaddr "github.com/ipfs/go-ipfs-addr" cmds "github.com/ipfs/go-ipfs-cmds" config "github.com/ipfs/go-ipfs-config" inet "github.com/libp2p/go-libp2p-core/network" @@ -369,7 +368,7 @@ ipfs swarm connect /ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3 addrs := req.Arguments - pis, err := peersWithAddresses(req.Context, addrs) + pis, err := parseAddresses(req.Context, addrs) if err != nil { return err } @@ -415,19 +414,34 @@ it will reconnect. return err } - iaddrs, err := parseAddresses(req.Arguments) + addrs, err := parseAddresses(req.Context, req.Arguments) if err != nil { return err } - output := make([]string, len(iaddrs)) - for i, addr := range iaddrs { - output[i] = "disconnect " + addr.ID().Pretty() - - if err := api.Swarm().Disconnect(req.Context, addr.Multiaddr()); err != nil { - output[i] += " failure: " + err.Error() - } else { - output[i] += " success" + output := make([]string, 0, len(addrs)) + for _, ainfo := range addrs { + maddrs, err := peer.AddrInfoToP2pAddrs(&ainfo) + if err != nil { + return err + } + // FIXME: This will print: + // + // disconnect QmFoo success + // disconnect QmFoo success + // ... + // + // Once per address specified. However, I'm not sure of + // a good backwards compat solution. Right now, I'm just + // preserving the current behavior. + for _, addr := range maddrs { + msg := "disconnect " + ainfo.ID.Pretty() + if err := api.Swarm().Disconnect(req.Context, addr); err != nil { + msg += " failure: " + err.Error() + } else { + msg += " success" + } + output = append(output, msg) } } return cmds.EmitOnce(res, &stringList{output}) @@ -439,63 +453,15 @@ it will reconnect. } // parseAddresses is a function that takes in a slice of string peer addresses -// (multiaddr + peerid) and returns slices of multiaddrs and peerids. -func parseAddresses(addrs []string) (iaddrs []iaddr.IPFSAddr, err error) { - iaddrs = make([]iaddr.IPFSAddr, len(addrs)) - for i, saddr := range addrs { - iaddrs[i], err = iaddr.ParseString(saddr) - if err != nil { - return nil, cmds.ClientError("invalid peer address: " + err.Error()) - } - } - return -} - -// parseMultiaddrs is a function that takes in a slice of peer multiaddr -// and returns slices of multiaddrs and peerids -func parseMultiaddrs(maddrs []ma.Multiaddr) (iaddrs []iaddr.IPFSAddr, err error) { - iaddrs = make([]iaddr.IPFSAddr, len(maddrs)) - for i, maddr := range maddrs { - iaddrs[i], err = iaddr.ParseMultiaddr(maddr) - if err != nil { - return nil, cmds.ClientError("invalid peer address: " + err.Error()) - } - } - return -} - -// peersWithAddresses is a function that takes in a slice of string peer addresses // (multiaddr + peerid) and returns a slice of properly constructed peers -func peersWithAddresses(ctx context.Context, addrs []string) ([]peer.AddrInfo, error) { +func parseAddresses(ctx context.Context, addrs []string) ([]peer.AddrInfo, error) { // resolve addresses maddrs, err := resolveAddresses(ctx, addrs) if err != nil { return nil, err } - iaddrs, err := parseMultiaddrs(maddrs) - if err != nil { - return nil, err - } - - peers := make(map[peer.ID][]ma.Multiaddr, len(iaddrs)) - for _, iaddr := range iaddrs { - id := iaddr.ID() - current, ok := peers[id] - if tpt := iaddr.Transport(); tpt != nil { - peers[id] = append(current, tpt) - } else if !ok { - peers[id] = nil - } - } - pis := make([]peer.AddrInfo, 0, len(peers)) - for id, maddrs := range peers { - pis = append(pis, peer.AddrInfo{ - ID: id, - Addrs: maddrs, - }) - } - return pis, nil + return peer.AddrInfosFromP2pAddrs(maddrs...) } // resolveAddresses resolves addresses parallelly @@ -531,7 +497,7 @@ func resolveAddresses(ctx context.Context, addrs []string) ([]ma.Multiaddr, erro // filter out addresses that still doesn't end in `ipfs/Qm...` found := 0 for _, raddr := range raddrs { - if _, last := ma.SplitLast(raddr); last.Protocol().Code == ma.P_IPFS { + if _, last := ma.SplitLast(raddr); last != nil && last.Protocol().Code == ma.P_IPFS { maddrC <- raddr found++ } diff --git a/core/core.go b/core/core.go index 8b411457155..24535208dbf 100644 --- a/core/core.go +++ b/core/core.go @@ -166,11 +166,7 @@ func (n *IpfsNode) loadBootstrapPeers() ([]peer.AddrInfo, error) { return nil, err } - parsed, err := cfg.BootstrapPeers() - if err != nil { - return nil, err - } - return bootstrap.Peers.ToPeerInfos(parsed), nil + return cfg.BootstrapPeers() } type ConstructPeerHostOpts struct { diff --git a/core/coreapi/swarm.go b/core/coreapi/swarm.go index 8e2ea9a573a..641b4c526f2 100644 --- a/core/coreapi/swarm.go +++ b/core/coreapi/swarm.go @@ -5,7 +5,6 @@ import ( "sort" "time" - iaddr "github.com/ipfs/go-ipfs-addr" coreiface "github.com/ipfs/interface-go-ipfs-core" inet "github.com/libp2p/go-libp2p-core/network" peer "github.com/libp2p/go-libp2p-core/peer" @@ -52,34 +51,29 @@ func (api *SwarmAPI) Disconnect(ctx context.Context, addr ma.Multiaddr) error { return coreiface.ErrOffline } - ia, err := iaddr.ParseMultiaddr(ma.Multiaddr(addr)) - if err != nil { - return err + taddr, id := peer.SplitAddr(addr) + if id == "" { + return peer.ErrInvalidAddr } - taddr := ia.Transport() - id := ia.ID() net := api.peerHost.Network() - if taddr == nil { if net.Connectedness(id) != inet.Connected { return coreiface.ErrNotConnected - } else if err := net.ClosePeer(id); err != nil { + } + if err := net.ClosePeer(id); err != nil { return err } - } else { - for _, conn := range net.ConnsToPeer(id) { - if !conn.RemoteMultiaddr().Equal(taddr) { - continue - } - - return conn.Close() + return nil + } + for _, conn := range net.ConnsToPeer(id) { + if !conn.RemoteMultiaddr().Equal(taddr) { + continue } - return coreiface.ErrConnNotFound + return conn.Close() } - - return nil + return coreiface.ErrConnNotFound } func (api *SwarmAPI) KnownAddrs(context.Context) (map[peer.ID][]ma.Multiaddr, error) { diff --git a/go.mod b/go.mod index 5714e958e9d..374f157a96f 100644 --- a/go.mod +++ b/go.mod @@ -30,12 +30,11 @@ require ( github.com/ipfs/go-ds-leveldb v0.0.2 github.com/ipfs/go-ds-measure v0.0.1 github.com/ipfs/go-fs-lock v0.0.1 - github.com/ipfs/go-ipfs-addr v0.0.1 github.com/ipfs/go-ipfs-blockstore v0.0.1 github.com/ipfs/go-ipfs-blocksutil v0.0.1 github.com/ipfs/go-ipfs-chunker v0.0.1 github.com/ipfs/go-ipfs-cmds v0.0.8 - github.com/ipfs/go-ipfs-config v0.0.4 + github.com/ipfs/go-ipfs-config v0.0.5 github.com/ipfs/go-ipfs-ds-help v0.0.1 github.com/ipfs/go-ipfs-exchange-interface v0.0.1 github.com/ipfs/go-ipfs-exchange-offline v0.0.1 @@ -58,7 +57,7 @@ require ( github.com/ipfs/hang-fds v0.0.1 github.com/ipfs/interface-go-ipfs-core v0.1.0 github.com/ipfs/iptb v1.4.0 - github.com/ipfs/iptb-plugins v0.0.2 + github.com/ipfs/iptb-plugins v0.1.0 github.com/jbenet/go-is-domain v1.0.2 github.com/jbenet/go-random v0.0.0-20190219211222-123a90aedc0c github.com/jbenet/go-random-files v0.0.0-20190219210431-31b3f20ebded @@ -68,7 +67,7 @@ require ( github.com/libp2p/go-libp2p-autonat-svc v0.1.0 github.com/libp2p/go-libp2p-circuit v0.1.0 github.com/libp2p/go-libp2p-connmgr v0.1.0 - github.com/libp2p/go-libp2p-core v0.0.2 + github.com/libp2p/go-libp2p-core v0.0.3 github.com/libp2p/go-libp2p-kad-dht v0.1.0 github.com/libp2p/go-libp2p-kbucket v0.2.0 github.com/libp2p/go-libp2p-loggables v0.1.0 diff --git a/go.sum b/go.sum index b9cb4bcdeef..319330449b0 100644 --- a/go.sum +++ b/go.sum @@ -23,7 +23,6 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/bifurcation/mint v0.0.0-20181105073638-824af6541065/go.mod h1:zVt7zX3K/aDCk9Tj+VM7YymsX66ERvzCJzw8rFCX2JU= 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/bren2010/proquint v0.0.0-20160323162903-38337c27106d h1:QgeLLoPD3kRVmeu/1al9iIpIANMi9O1zXFm8BnYGCJg= @@ -193,7 +192,6 @@ github.com/ipfs/bbloom v0.0.1/go.mod h1:oqo8CVWsJFMOZqTglBG4wydCE4IQA/G2/SEofB0r github.com/ipfs/dir-index-html v1.0.3 h1:cKdOjJBKJgewgcv97zOlqsNOle52N91d3nAkbQadnuY= github.com/ipfs/dir-index-html v1.0.3/go.mod h1:TG9zbaH/+4MnkGel0xF4SLNhk+YZvBNo6jjBkO/LaWc= github.com/ipfs/go-bitswap v0.0.3/go.mod h1:jadAZYsP/tcRMl47ZhFxhaNuDQoXawT8iHMg+iFoQbg= -github.com/ipfs/go-bitswap v0.0.9 h1:Dy0qvYlaOd2E2FOL2gApJ21qVjepJsGNNfstLrGf+0I= github.com/ipfs/go-bitswap v0.0.9/go.mod h1:kAPf5qgn2W2DrgAcscZ3HrM9qh4pH+X8Fkk3UPrwvis= github.com/ipfs/go-bitswap v0.1.0 h1:28YsHYw9ut6wootnImPXH0WpnU5Dbo3qm6cvQ6e6wYY= github.com/ipfs/go-bitswap v0.1.0/go.mod h1:FFJEf18E9izuCqUtHxbWEvq+reg7o4CW5wSAE1wsxj0= @@ -230,8 +228,6 @@ github.com/ipfs/go-ds-measure v0.0.1 h1:PrCueug+yZLkDCOthZTXKinuoCal/GvlAT7cNxzr github.com/ipfs/go-ds-measure v0.0.1/go.mod h1:wiH6bepKsgyNKpz3nyb4erwhhIVpIxnZbsjN1QpVbbE= github.com/ipfs/go-fs-lock v0.0.1 h1:XHX8uW4jQBYWHj59XXcjg7BHlHxV9ZOYs6Y43yb7/l0= github.com/ipfs/go-fs-lock v0.0.1/go.mod h1:DNBekbboPKcxs1aukPSaOtFA3QfSdi5C855v0i9XJ8Y= -github.com/ipfs/go-ipfs-addr v0.0.1 h1:DpDFybnho9v3/a1dzJ5KnWdThWD1HrFLpQ+tWIyBaFI= -github.com/ipfs/go-ipfs-addr v0.0.1/go.mod h1:uKTDljHT3Q3SUWzDLp3aYUi8MrY32fgNgogsIa0npjg= github.com/ipfs/go-ipfs-blockstore v0.0.1 h1:O9n3PbmTYZoNhkgkEyrXTznbmktIXif62xLX+8dPHzc= github.com/ipfs/go-ipfs-blockstore v0.0.1/go.mod h1:d3WClOmRQKFnJ0Jz/jj/zmksX0ma1gROTlovZKBmN08= github.com/ipfs/go-ipfs-blocksutil v0.0.1 h1:Eh/H4pc1hsvhzsQoMEP3Bke/aW5P5rVM1IWFJMcGIPQ= @@ -240,9 +236,8 @@ github.com/ipfs/go-ipfs-chunker v0.0.1 h1:cHUUxKFQ99pozdahi+uSC/3Y6HeRpi9oTeUHbE github.com/ipfs/go-ipfs-chunker v0.0.1/go.mod h1:tWewYK0we3+rMbOh7pPFGDyypCtvGcBFymgY4rSDLAw= github.com/ipfs/go-ipfs-cmds v0.0.8 h1:ZMo0ZeQOr10ZKY4yxYA3lRHUbnF/ZYcV9cpU0IrlGFI= github.com/ipfs/go-ipfs-cmds v0.0.8/go.mod h1:TiK4e7/V31tuEb8YWDF8lN3qrnDH+BS7ZqWIeYJlAs8= -github.com/ipfs/go-ipfs-config v0.0.1/go.mod h1:KDbHjNyg4e6LLQSQpkgQMBz6Jf4LXiWAcmnkcwmH0DU= -github.com/ipfs/go-ipfs-config v0.0.4 h1:zOWk1gGvIOptjHvvu0qSC8psB2IBKO/FbQArFnmm0LM= -github.com/ipfs/go-ipfs-config v0.0.4/go.mod h1:KDbHjNyg4e6LLQSQpkgQMBz6Jf4LXiWAcmnkcwmH0DU= +github.com/ipfs/go-ipfs-config v0.0.5 h1:D9ek19anOzm8iYPvezeeamSg5mzwqKPb2jyAyJZT/4A= +github.com/ipfs/go-ipfs-config v0.0.5/go.mod h1:IGkVTacurWv9WFKc7IBPjHGM/7hi6+PEClqUb/l2BIM= github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= github.com/ipfs/go-ipfs-delay v0.0.1 h1:r/UXYyRcddO6thwOnhiznIAiSvxMECGgtv35Xs1IeRQ= github.com/ipfs/go-ipfs-delay v0.0.1/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= @@ -307,8 +302,8 @@ github.com/ipfs/interface-go-ipfs-core v0.1.0 h1:4LD2TJThswXVMJgAji9k9PyPsOGNtmd github.com/ipfs/interface-go-ipfs-core v0.1.0/go.mod h1:h1zJvvfh9dcNU0bK+Jag516LputHLKQkHsDP+z0dz4A= github.com/ipfs/iptb v1.4.0 h1:YFYTrCkLMRwk/35IMyC6+yjoQSHTEcNcefBStLJzgvo= github.com/ipfs/iptb v1.4.0/go.mod h1:1rzHpCYtNp87/+hTxG5TfCVn/yMY3dKnLn8tBiMfdmg= -github.com/ipfs/iptb-plugins v0.0.2 h1:JZp4h/+7f00dY4Epr8gzF+VqKITXmVGsZabvmZp7E9I= -github.com/ipfs/iptb-plugins v0.0.2/go.mod h1:Vud+X6lHv5QlgVbqCPBHt91I0gPIRgmkD6/tMUsI07U= +github.com/ipfs/iptb-plugins v0.1.0 h1:9/PTKJX+rB2qqXkaX/3IDxLSHTBwMMvFrYEf7g2mFo8= +github.com/ipfs/iptb-plugins v0.1.0/go.mod h1:gE+R5nCAM9+Cajd1UhIBk8k7CZus7IG8FFXE0lHvJx0= github.com/jackpal/gateway v1.0.4/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= github.com/jackpal/gateway v1.0.5 h1:qzXWUJfuMdlLMtt0a3Dgt+xkWQiA5itDEITVJtuSwMc= github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= @@ -317,7 +312,6 @@ github.com/jackpal/go-nat-pmp v1.0.1/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+ github.com/jbenet/go-cienv v0.0.0-20150120210510-1bb1476777ec/go.mod h1:rGaEvXB4uRSZMmzKNLoXvTu1sfx+1kv/DojUlPrSZGs= github.com/jbenet/go-cienv v0.1.0 h1:Vc/s0QbQtoxX8MwwSLWWh+xNNZvM3Lw7NsTcHrvvhMc= github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jbenet/go-is-domain v1.0.2 h1:11r5MSptcNFZyBoqubBQnVMUKRWLuRjL1banaIk+iYo= github.com/jbenet/go-is-domain v1.0.2/go.mod h1:xbRLRb0S7FgzDBTJlguhDVwLYM/5yNtvktxj2Ttfy7Q= github.com/jbenet/go-random v0.0.0-20190219211222-123a90aedc0c h1:uUx61FiAa1GI6ZmVd2wf2vULeQZIKG66eybjNXKYCz4= @@ -371,7 +365,6 @@ github.com/libp2p/go-libp2p-autonat v0.0.2/go.mod h1:fs71q5Xk+pdnKU014o2iq1RhMs9 github.com/libp2p/go-libp2p-autonat v0.0.6/go.mod h1:uZneLdOkZHro35xIhpbtTzLlgYturpu4J5+0cZK3MqE= github.com/libp2p/go-libp2p-autonat v0.1.0 h1:aCWAu43Ri4nU0ZPO7NyLzUvvfqd0nE3dX0R/ZGYVgOU= github.com/libp2p/go-libp2p-autonat v0.1.0/go.mod h1:1tLf2yXxiE/oKGtDwPYWTSYG3PtvYlJmg7NeVtPRqH8= -github.com/libp2p/go-libp2p-autonat-svc v0.0.2/go.mod h1:j4iMiw0d3diRm5iB0noXumtb0mPvWrM1qAyh640cp8w= github.com/libp2p/go-libp2p-autonat-svc v0.1.0 h1:28IM7iWMDclZeVkpiFQaWVANwXwE7zLlpbnS7yXxrfs= github.com/libp2p/go-libp2p-autonat-svc v0.1.0/go.mod h1:fqi8Obl/z3R4PFVLm8xFtZ6PBL9MlV/xumymRFkKq5A= github.com/libp2p/go-libp2p-blankhost v0.0.1/go.mod h1:Ibpbw/7cPPYwFb7PACIWdvxxv0t0XCCI10t7czjAjTc= @@ -381,33 +374,30 @@ github.com/libp2p/go-libp2p-circuit v0.0.1/go.mod h1:Dqm0s/BiV63j8EEAs8hr1H5Hudq 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 h1:eniLL3Y9aq/sryfyV1IAHj5rlvuyj3b7iz8tSiZpdhY= github.com/libp2p/go-libp2p-circuit v0.1.0/go.mod h1:Ahq4cY3V9VJcHcn1SBXjr78AbFkZeIRmfunbA7pmFh8= -github.com/libp2p/go-libp2p-connmgr v0.0.1/go.mod h1:eUBBlbuwBBTd/eim7KV5x0fOD2UHDjSwhzmBL6miIx8= github.com/libp2p/go-libp2p-connmgr v0.1.0 h1:vp0t0F0EuT3rrlTtnMnIyyzCnly7nIlRoEbhJpgp0qU= github.com/libp2p/go-libp2p-connmgr v0.1.0/go.mod h1:wZxh8veAmU5qdrfJ0ZBLcU8oJe9L82ciVP/fl1VHjXk= github.com/libp2p/go-libp2p-core v0.0.1/go.mod h1:g/VxnTZ/1ygHxH3dKok7Vno1VfpvGcGip57wjTU4fco= github.com/libp2p/go-libp2p-core v0.0.2 h1:86uOwW+O6Uc7NbaK4diuLZo2/Ikvqw2rgyV03VcSbLE= github.com/libp2p/go-libp2p-core v0.0.2/go.mod h1:9dAcntw/n46XycV4RnlBq3BpgrmyUi9LuoTNdPrbUco= +github.com/libp2p/go-libp2p-core v0.0.3 h1:+IonUYY0nJZLb5Fdv6a6DOjtGP1L8Bb3faamiI2q5FY= +github.com/libp2p/go-libp2p-core v0.0.3/go.mod h1:j+YQMNz9WNSkNezXOsahp9kwZBKBvxLpKD316QWSJXE= 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 h1:k9MFy+o2zGDNGsaoZl0MA3iZ75qXxr9OOoAZF+sD5OQ= github.com/libp2p/go-libp2p-crypto v0.1.0/go.mod h1:sPUokVISZiy+nNuTTH/TY+leRSxnFj/2GLjtOTW90hI= -github.com/libp2p/go-libp2p-daemon v0.0.6/go.mod h1:nkhjsjSzkF+tg6iScsTTgq9m+VfyMtXNpycYG4CFvC8= +github.com/libp2p/go-libp2p-daemon v0.2.0/go.mod h1:1hlzu8xFRi+fkC1N+zvhSgznGZGo9HxpJtSrj3X5HQw= 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 h1:j+R6cokKcGbnZLf4kcNwpx6mDEUPF3N6SrqMymQhmvs= github.com/libp2p/go-libp2p-discovery v0.1.0/go.mod h1:4F/x+aldVHjHDHuX85x1zWoFTGElt8HnoDzwkFZm29g= github.com/libp2p/go-libp2p-host v0.0.1/go.mod h1:qWd+H1yuU0m5CwzAkvbSjqKairayEHdR5MMl7Cwa7Go= -github.com/libp2p/go-libp2p-host v0.0.3 h1:BB/1Z+4X0rjKP5lbQTmjEjLbDVbrcmLOlA6QDsN5/j4= github.com/libp2p/go-libp2p-host v0.0.3/go.mod h1:Y/qPyA6C8j2coYyos1dfRm0I8+nvd4TGrDGt4tA7JR8= github.com/libp2p/go-libp2p-interface-connmgr v0.0.1/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 h1:KG/KNYL2tYzXAfMvQN5K1aAGTYSYUMJ1prgYa2/JI1E= github.com/libp2p/go-libp2p-interface-connmgr v0.0.5/go.mod h1:GarlRLH0LdeWcLnYM/SaBykKFl9U5JFnbBGruAk/D5k= github.com/libp2p/go-libp2p-interface-pnet v0.0.1/go.mod h1:el9jHpQAXK5dnTpKA4yfCNBZXvrzdOU75zz+C6ryp3k= -github.com/libp2p/go-libp2p-kad-dht v0.0.4/go.mod h1:oaBflOQcuC8H+SVV0YN26H6AS+wcUEJyjUGV66vXuSY= github.com/libp2p/go-libp2p-kad-dht v0.1.0 h1:cupGornmncdQCnjArAv9Txkqy43wgQCxoe/5pfIDF/4= github.com/libp2p/go-libp2p-kad-dht v0.1.0/go.mod h1:EiH74cOsCxcu2Yh1XxQMpf1uHcLNm/hYEJBOIRlzHNE= -github.com/libp2p/go-libp2p-kbucket v0.0.1/go.mod h1:Y0iQDHRTk/ZgM8PC4jExoF+E4j+yXWwRkdldkMa5Xm4= github.com/libp2p/go-libp2p-kbucket v0.2.0 h1:FB2a0VkOTNGTP5gu/I444u4WabNM9V1zCkQcWb7zajI= github.com/libp2p/go-libp2p-kbucket v0.2.0/go.mod h1:JNymBToym3QXKBMKGy3m29+xprg0EVr/GJFHxFEdgh8= github.com/libp2p/go-libp2p-loggables v0.0.1/go.mod h1:lDipDlBNYbpyqyPX/KcoO+eq0sJYEVR2JgOexcivchg= @@ -421,9 +411,7 @@ github.com/libp2p/go-libp2p-mplex v0.2.1/go.mod h1:SC99Rxs8Vuzrf/6WhmH41kNn13TiY github.com/libp2p/go-libp2p-nat v0.0.2/go.mod h1:QrjXQSD5Dj4IJOdEcjHRkWTSomyxRo6HnUkf/TfQpLQ= github.com/libp2p/go-libp2p-nat v0.0.4 h1:+KXK324yaY701On8a0aGjTnw8467kW3ExKcqW2wwmyw= github.com/libp2p/go-libp2p-nat v0.0.4/go.mod h1:N9Js/zVtAXqaeT99cXgTV9e75KpnWCvVOiGzlcHmBbY= -github.com/libp2p/go-libp2p-net v0.0.0-20190226201932-e71fff5ba6e9/go.mod h1:8W6Wx3AZbTRTe8zSMLoAmT3mGyau+w6kGIRk+Z+MZ7Q= github.com/libp2p/go-libp2p-net v0.0.1/go.mod h1:Yt3zgmlsHOgUWSXmt5V/Jpz9upuJBE8EgNU9DrCcR8c= -github.com/libp2p/go-libp2p-net v0.0.2 h1:qP06u4TYXfl7uW/hzqPhlVVTSA2nw1B/bHBJaUnbh6M= github.com/libp2p/go-libp2p-net v0.0.2/go.mod h1:Yt3zgmlsHOgUWSXmt5V/Jpz9upuJBE8EgNU9DrCcR8c= github.com/libp2p/go-libp2p-netutil v0.0.1/go.mod h1:GdusFvujWZI9Vt0X5BKqwWWmZFxecf9Gt03cKxm2f/Q= github.com/libp2p/go-libp2p-netutil v0.1.0 h1:zscYDNVEcGxyUpMd0JReUZTrpMfia8PmLKcKF72EAMQ= @@ -432,23 +420,22 @@ github.com/libp2p/go-libp2p-peer v0.0.1/go.mod h1:nXQvOBbwVqoP+T5Y5nCjeH4sP9IX/J github.com/libp2p/go-libp2p-peer v0.1.1/go.mod h1:jkF12jGB4Gk/IOo+yomm+7oLWxF278F7UnrYUQ1Q8es= github.com/libp2p/go-libp2p-peer v0.2.0 h1:EQ8kMjaCUwt/Y5uLgjT8iY2qg0mGUT0N1zUjer50DsY= github.com/libp2p/go-libp2p-peer v0.2.0/go.mod h1:RCffaCvUyW2CJmG2gAWVqwePwW7JMgxjsHm7+J5kjWY= -github.com/libp2p/go-libp2p-peerstore v0.0.0-20190226201924-e2df3e49eabf/go.mod h1:lLfgn0N3z2t+ER57a88K7NTZjMO27ez5TyWSURd428E= github.com/libp2p/go-libp2p-peerstore v0.0.1/go.mod h1:RabLyPVJLuNQ+GFyoEkfi8H4Ti6k/HtZJ7YKgtSq+20= github.com/libp2p/go-libp2p-peerstore v0.0.6/go.mod h1:RabLyPVJLuNQ+GFyoEkfi8H4Ti6k/HtZJ7YKgtSq+20= github.com/libp2p/go-libp2p-peerstore v0.1.0 h1:MKh7pRNPHSh1fLPj8u/M/s/napdmeNpoi9BRy9lPN0E= github.com/libp2p/go-libp2p-peerstore v0.1.0/go.mod h1:2CeHkQsr8svp4fZ+Oi9ykN1HBb6u0MOvdJ7YIsmcwtY= github.com/libp2p/go-libp2p-pnet v0.1.0 h1:kRUES28dktfnHNIRW4Ro78F7rKBHBiw5MJpl0ikrLIA= github.com/libp2p/go-libp2p-pnet v0.1.0/go.mod h1:ZkyZw3d0ZFOex71halXRihWf9WH/j3OevcJdTmD0lyE= -github.com/libp2p/go-libp2p-protocol v0.0.0-20171212212132-b29f3d97e3a2/go.mod h1:Af9n4PiruirSDjHycM1QuiMi/1VZNHYcK8cLgFJLZ4s= github.com/libp2p/go-libp2p-protocol v0.0.1/go.mod h1:Af9n4PiruirSDjHycM1QuiMi/1VZNHYcK8cLgFJLZ4s= -github.com/libp2p/go-libp2p-protocol v0.1.0 h1:HdqhEyhg0ToCaxgMhnOmUO8snQtt/kQlcjVk3UoJU3c= github.com/libp2p/go-libp2p-protocol v0.1.0/go.mod h1:KQPHpAabB57XQxGrXCNvbL6UEXfQqUgC/1adR2Xtflk= -github.com/libp2p/go-libp2p-pubsub v0.0.1/go.mod h1:fYKlZBOF2yrJzYlgeEVFSbYWfbS+E8Zix6gMZ0A6WgE= github.com/libp2p/go-libp2p-pubsub v0.1.0 h1:SmQeMa7IUv5vadh0fYgYsafWCBA1sCy5d/68kIYqGcU= github.com/libp2p/go-libp2p-pubsub v0.1.0/go.mod h1:ZwlKzRSe1eGvSIdU5bD7+8RZN/Uzw0t1Bp9R1znpR/Q= github.com/libp2p/go-libp2p-pubsub-router v0.1.0 h1:xA5B8Sdx64tNlSRIcay2QUngtlu8LpUJClaUk/dYYrg= github.com/libp2p/go-libp2p-pubsub-router v0.1.0/go.mod h1:PnHOshBr/2I2ZxVfEsqfgCQPsVg09zo+DhSlWkOhPFM= -github.com/libp2p/go-libp2p-quic-transport v0.0.0-20190301030811-862195d91de1/go.mod h1:bw/6H57fSVn44ldP1Js6hnzpoiUm9YgBDKSv+ch+hWc= +github.com/libp2p/go-libp2p-quic-transport v0.1.0 h1:YXKs6LA4aCl0OfhUq50xvdXDHaUlAsjmDFDcBcJPDGI= +github.com/libp2p/go-libp2p-quic-transport v0.1.0 h1:YXKs6LA4aCl0OfhUq50xvdXDHaUlAsjmDFDcBcJPDGI= +github.com/libp2p/go-libp2p-quic-transport v0.1.0/go.mod h1:1oh6y4f8/lDX42jIGlhXO95ox3Y1XMLdffb7zde29Y8= +github.com/libp2p/go-libp2p-quic-transport v0.1.0/go.mod h1:1oh6y4f8/lDX42jIGlhXO95ox3Y1XMLdffb7zde29Y8= github.com/libp2p/go-libp2p-quic-transport v0.1.1 h1:MFMJzvsxIEDEVKzO89BnB/FgvMj9WI4GDGUW2ArDPUA= github.com/libp2p/go-libp2p-quic-transport v0.1.1/go.mod h1:wqG/jzhF3Pu2NrhJEvE+IE0NTHNXslOPn9JQzyCAxzU= github.com/libp2p/go-libp2p-record v0.0.1/go.mod h1:grzqg263Rug/sRex85QrDOLntdFAymLDLm7lxMgU79Q= @@ -473,7 +460,6 @@ github.com/libp2p/go-libp2p-testing v0.0.3 h1:bdij4bKaaND7tCsaXVjRfYkMpvoOeKj9AV github.com/libp2p/go-libp2p-testing v0.0.3/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= github.com/libp2p/go-libp2p-tls v0.1.0 h1:o4bjjAdnUjNgJoPoDd0wUaZH7K+EenlNWJpgyXB3ulA= github.com/libp2p/go-libp2p-tls v0.1.0/go.mod h1:VZdoSWQDeNpIIAFJFv+6uqTqpnIIDHcqZQSTC/A1TT0= -github.com/libp2p/go-libp2p-transport v0.0.0-20190226201958-e8580c8a519d/go.mod h1:lcwgOszllbhvQXul37Kv5YbSYXPoUhRB2Z+Nr3jaBmo= 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= @@ -503,9 +489,7 @@ github.com/libp2p/go-reuseport v0.0.1/go.mod h1:jn6RmB1ufnQwl0Q1f+YxAj8isJgDCQza github.com/libp2p/go-reuseport-transport v0.0.1/go.mod h1:YkbSDrvjUVDL6b8XqriyA20obEtsW9BLkuOUyQAOCbs= github.com/libp2p/go-reuseport-transport v0.0.2 h1:WglMwyXyBu61CMkjCCtnmqNqnjib0GIEjMiHTwR/KN4= github.com/libp2p/go-reuseport-transport v0.0.2/go.mod h1:YkbSDrvjUVDL6b8XqriyA20obEtsW9BLkuOUyQAOCbs= -github.com/libp2p/go-stream-muxer v0.0.0-20190218175335-a3f82916c8ad/go.mod h1:bAo8x7YkSpadMTbtTaxGVHWUQsR/l5MEaHbKaliuT14= github.com/libp2p/go-stream-muxer v0.0.1/go.mod h1:bAo8x7YkSpadMTbtTaxGVHWUQsR/l5MEaHbKaliuT14= -github.com/libp2p/go-stream-muxer v0.1.0 h1:3ToDXUzx8pDC6RfuOzGsUYP5roMDthbUKRdMRRhqAqY= github.com/libp2p/go-stream-muxer v0.1.0/go.mod h1:8JAVsjeRBCWwPoZeH0W1imLOcriqXJyFvB0mR4A04sQ= github.com/libp2p/go-stream-muxer-multistream v0.1.1/go.mod h1:zmGdfkQ1AzOECIAcccoL8L//laqawOsO03zX8Sa+eGw= github.com/libp2p/go-stream-muxer-multistream v0.2.0 h1:714bRJ4Zy9mdhyTLJ+ZKiROmAFwUHpeRidG+q7LTQOg= @@ -514,7 +498,6 @@ github.com/libp2p/go-tcp-transport v0.0.1/go.mod h1:mnjg0o0O5TmXUaUIanYPUqkW4+u6 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 h1:IGhowvEqyMFknOar4FWCKSWE0zL36UFKQtiRQD60/8o= github.com/libp2p/go-tcp-transport v0.1.0/go.mod h1:oJ8I5VXryj493DEJ7OsBieu8fcg2nHGctwtInJVpipc= -github.com/libp2p/go-testutil v0.0.1 h1:Xg+O0G2HIMfHqBOBDcMS1iSZJ3GEcId4qOxCQvsGZHk= github.com/libp2p/go-testutil v0.0.1/go.mod h1:iAcJc/DKJQanJ5ws2V+u5ywdL2n12X1WbbEG+Jjy69I= github.com/libp2p/go-testutil v0.1.0 h1:4QhjaWGO89udplblLVpgGDOQjzFlRavZOjuEnz2rLMc= github.com/libp2p/go-testutil v0.1.0/go.mod h1:81b2n5HypcVyrCg/MJx4Wgfp/VHojytjVe/gLzZ2Ehc= @@ -527,11 +510,12 @@ github.com/libp2p/go-yamux v1.2.2/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZ github.com/libp2p/go-yamux v1.2.3 h1:xX8A36vpXb59frIzWFdEgptLMsOANMFq2K7fPRlunYI= github.com/libp2p/go-yamux v1.2.3/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= -github.com/lucas-clemente/aes12 v0.0.0-20171027163421-cd47fb39b79f/go.mod h1:JpH9J1c9oX6otFSgdUHwUBUizmKlrMjxWnIAjff4m04= -github.com/lucas-clemente/quic-go v0.10.0/go.mod h1:wuD+2XqEx8G9jtwx5ou2BEYBsE+whgQmlj0Vz/77PrY= +github.com/lucas-clemente/quic-go v0.11.1 h1:zasajC848Dqq/+WqfqBCkmPw+YHNe1MBts/z7y7nXf4= +github.com/lucas-clemente/quic-go v0.11.1 h1:zasajC848Dqq/+WqfqBCkmPw+YHNe1MBts/z7y7nXf4= +github.com/lucas-clemente/quic-go v0.11.1/go.mod h1:PpMmPfPKO9nKJ/psF49ESTAGQSdfXxlg1otPbEB2nOw= +github.com/lucas-clemente/quic-go v0.11.1/go.mod h1:PpMmPfPKO9nKJ/psF49ESTAGQSdfXxlg1otPbEB2nOw= github.com/lucas-clemente/quic-go v0.11.2 h1:Mop0ac3zALaBR3wGs6j8OYe/tcFvFsxTUFMkE/7yUOI= github.com/lucas-clemente/quic-go v0.11.2/go.mod h1:PpMmPfPKO9nKJ/psF49ESTAGQSdfXxlg1otPbEB2nOw= -github.com/lucas-clemente/quic-go-certificates v0.0.0-20160823095156-d2f86524cced/go.mod h1:NCcRLrOTZbzhZvixZLlERbJtDtYsmMw8Jc4vS8Z0g58= github.com/magiconair/properties v1.7.6 h1:U+1DqNen04MdEPgFiIwdOUiqZ8qPa37xgogX/sd3+54= github.com/magiconair/properties v1.7.6/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/marten-seemann/qtls v0.2.3 h1:0yWJ43C62LsZt08vuQJDK1uC1czUc3FJeCLPoNAI4vA= @@ -743,6 +727,8 @@ golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f h1:R423Cnkcp5JABoeemiGEPlt9tHXFfw5kvc0yqlxRPWo= golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5 h1:8dUaAV7K4uHsF56JQWkprecIQKdPHtR9jCHF5nB8uzc= +golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -801,7 +787,6 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190420000508-685fecacd0a0 h1:pa1CyBALPFjblgkNQp7T7gEcFcG/GOG5Ck8IcnSVWGs= golang.org/x/tools v0.0.0-20190420000508-685fecacd0a0/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/xerrors v0.0.0-20190212162355-a5947ffaace3/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522 h1:bhOzK9QyoD0ogCnFro1m2mz41+Ib0oOhfJnBp5MR4K4= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= From f938b3d5e3fc5c7f2dd38567a59f0c661e962cac Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Fri, 31 May 2019 17:47:24 -0700 Subject: [PATCH 023/671] ci: rev cache version Something is broken with the cache. --- .circleci/config.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index b0ea0f0b1a1..7c90fd9b561 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -6,13 +6,13 @@ aliases: restore_gomod: &restore_gomod restore_cache: keys: - - v3-dep-{{ .Branch }}-{{ checksum "~/ipfs/go-ipfs/go.sum" }}-{{ .Environment.CIRCLE_JOB }} - - v3-dep-{{ .Branch }}-{{ checksum "~/ipfs/go-ipfs/go.sum" }}- - - v3-dep-{{ .Branch }}- - - v3-dep-master- + - v4-dep-{{ .Branch }}-{{ checksum "~/ipfs/go-ipfs/go.sum" }}-{{ .Environment.CIRCLE_JOB }} + - v4-dep-{{ .Branch }}-{{ checksum "~/ipfs/go-ipfs/go.sum" }}- + - v4-dep-{{ .Branch }}- + - v4-dep-master- store_gomod: &store_gomod save_cache: - key: v3-dep-{{ .Branch }}-{{ checksum "~/ipfs/go-ipfs/go.sum" }}-{{ .Environment.CIRCLE_JOB }} + key: v4-dep-{{ .Branch }}-{{ checksum "~/ipfs/go-ipfs/go.sum" }}-{{ .Environment.CIRCLE_JOB }} paths: - ~/go/pkg/mod - ~/.cache/go-build/ From 0f668692337fdd0b78bdef0ec9a801db84beb3a8 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Sat, 1 Jun 2019 16:05:19 -0700 Subject: [PATCH 024/671] fix: fixed go-ipfs-config --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 374f157a96f..e10bb5c0dfb 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( github.com/ipfs/go-ipfs-blocksutil v0.0.1 github.com/ipfs/go-ipfs-chunker v0.0.1 github.com/ipfs/go-ipfs-cmds v0.0.8 - github.com/ipfs/go-ipfs-config v0.0.5 + github.com/ipfs/go-ipfs-config v0.0.6 github.com/ipfs/go-ipfs-ds-help v0.0.1 github.com/ipfs/go-ipfs-exchange-interface v0.0.1 github.com/ipfs/go-ipfs-exchange-offline v0.0.1 diff --git a/go.sum b/go.sum index 319330449b0..c404db021e0 100644 --- a/go.sum +++ b/go.sum @@ -238,6 +238,8 @@ github.com/ipfs/go-ipfs-cmds v0.0.8 h1:ZMo0ZeQOr10ZKY4yxYA3lRHUbnF/ZYcV9cpU0IrlG github.com/ipfs/go-ipfs-cmds v0.0.8/go.mod h1:TiK4e7/V31tuEb8YWDF8lN3qrnDH+BS7ZqWIeYJlAs8= github.com/ipfs/go-ipfs-config v0.0.5 h1:D9ek19anOzm8iYPvezeeamSg5mzwqKPb2jyAyJZT/4A= github.com/ipfs/go-ipfs-config v0.0.5/go.mod h1:IGkVTacurWv9WFKc7IBPjHGM/7hi6+PEClqUb/l2BIM= +github.com/ipfs/go-ipfs-config v0.0.6 h1:jzK9Tl8S0oWBir3F5ObtGgnHRPdqQ0MYiCmwXtV3Ps4= +github.com/ipfs/go-ipfs-config v0.0.6/go.mod h1:IGkVTacurWv9WFKc7IBPjHGM/7hi6+PEClqUb/l2BIM= github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= github.com/ipfs/go-ipfs-delay v0.0.1 h1:r/UXYyRcddO6thwOnhiznIAiSvxMECGgtv35Xs1IeRQ= github.com/ipfs/go-ipfs-delay v0.0.1/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= From ce5084b5a52f5f26fbd6ceb9a53b2967f17c6df3 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Sat, 1 Jun 2019 17:14:16 -0700 Subject: [PATCH 025/671] fix: go-libp2p-pnet now enforces the correct key size --- test/sharness/t0181-private-network.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/sharness/t0181-private-network.sh b/test/sharness/t0181-private-network.sh index 6a0efd4c2ba..d2230aa1b8c 100755 --- a/test/sharness/t0181-private-network.sh +++ b/test/sharness/t0181-private-network.sh @@ -26,7 +26,7 @@ test_expect_success "daemon output incudes info about the reason" ' pnet_key() { echo '/key/swarm/psk/1.0.0/' echo '/bin/' - random 16 + random 32 } pnet_key > "${IPFS_PATH}/swarm.key" From 4ca2763ee5285a4a7041129bd27139437a199540 Mon Sep 17 00:00:00 2001 From: Hlib Date: Mon, 3 Jun 2019 18:25:49 +0300 Subject: [PATCH 026/671] Remove Repo from routing provider parameter --- core/node/libp2p/routing.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/node/libp2p/routing.go b/core/node/libp2p/routing.go index 6a27373db7e..e5ba1de30bb 100644 --- a/core/node/libp2p/routing.go +++ b/core/node/libp2p/routing.go @@ -14,7 +14,6 @@ import ( "go.uber.org/fx" "github.com/ipfs/go-ipfs/core/node/helpers" - "github.com/ipfs/go-ipfs/repo" ) type BaseIpfsRouting routing.Routing @@ -79,7 +78,6 @@ type p2pPSRoutingIn struct { fx.In BaseIpfsRouting BaseIpfsRouting - Repo repo.Repo Validator record.Validator Host host.Host PubSub *pubsub.PubSub `optional:"true"` From 803dd8b88902b6a298c6d91a620d39ef9441f87f Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 3 Jun 2019 16:27:33 -0700 Subject: [PATCH 027/671] CHANGELOG: add some missed changes * Decreased connection initiation latency. * Better help text. --- CHANGELOG.md | 149 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 148 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b249800cd4..c6f2f085668 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -162,6 +162,16 @@ it uses a _lot_ of file descriptors. Luckily, most modern kernels can handle thousands of file descriptors without any difficulty. +#### Decreased Connection Handshake Latency + +Libp2p now shaves off a couple of round trips when initiating connections by +beginning the protocol negotiation before the remote peer responds to the +initial handshake message. + +In the optimal case (when the target peer speaks our preferred protocol), this +reduces the number of handshake round-trips from 6 to 4 (including the TCP +handshake). + ### Commands This release brings no new commands but does introduce a few changes, bugfixes, @@ -217,6 +227,129 @@ The ping command has received some small improvements and fixes: 3. It now prints out the average latency when canceled with `^C` (like the unix `ping` command). +#### Improved Help Text + +Go-ipfs now intelligently wraps help text for easier reading. On an 80 character +wide terminal, + +**Before** + +``` +USAGE + ipfs add ... - Add a file or directory to ipfs. + +SYNOPSIS + ipfs add [--recursive | -r] [--dereference-args] [--stdin-name=] [ +--hidden | -H] [--quiet | -q] [--quieter | -Q] [--silent] [--progress | -p] [--t +rickle | -t] [--only-hash | -n] [--wrap-with-directory | -w] [--chunker= | -s] [--pin=false] [--raw-leaves] [--nocopy] [--fscache] [--cid-version=] [--hash=] [--inline] [--inline-limit=] [--] +... + +ARGUMENTS + + ... - The path to a file to be added to ipfs. + +OPTIONS + + -r, --recursive bool - Add directory paths recursive +ly. + --dereference-args bool - Symlinks supplied in argument +s are dereferenced. + --stdin-name string - Assign a name if the file sou +rce is stdin. + -H, --hidden bool - Include files that are hidden +. Only takes effect on recursive add. + -q, --quiet bool - Write minimal output. + -Q, --quieter bool - Write only final hash. + --silent bool - Write no output. + -p, --progress bool - Stream progress data. + -t, --trickle bool - Use trickle-dag format for da +g generation. + -n, --only-hash bool - Only chunk and hash - do not +write to disk. + -w, --wrap-with-directory bool - Wrap files with a directory o +bject. + -s, --chunker string - Chunking algorithm, size-[byt +es] or rabin-[min]-[avg]-[max]. Default: size-262144. + --pin bool - Pin this object when adding. +Default: true. + --raw-leaves bool - Use raw blocks for leaf nodes +. (experimental). + --nocopy bool - Add the file using filestore. + Implies raw-leaves. (experimental). + --fscache bool - Check the filestore for pre-e +xisting blocks. (experimental). + --cid-version int - CID version. Defaults to 0 un +less an option that depends on CIDv1 is passed. (experimental). + --hash string - Hash function to use. Implies + CIDv1 if not sha2-256. (experimental). Default: sha2-256. + --inline bool - Inline small blocks into CIDs +. (experimental). + --inline-limit int - Maximum block size to inline. + (experimental). Default: 32. + +``` + + +**After** + +``` +USAGE + ipfs add ... - Add a file or directory to ipfs. + +SYNOPSIS + ipfs add [--recursive | -r] [--dereference-args] [--stdin-name=] + [--hidden | -H] [--quiet | -q] [--quieter | -Q] [--silent] + [--progress | -p] [--trickle | -t] [--only-hash | -n] + [--wrap-with-directory | -w] [--chunker= | -s] [--pin=false] + [--raw-leaves] [--nocopy] [--fscache] [--cid-version=] + [--hash=] [--inline] [--inline-limit=] [--] + ... + +ARGUMENTS + + ... - The path to a file to be added to ipfs. + +OPTIONS + + -r, --recursive bool - Add directory paths recursively. + --dereference-args bool - Symlinks supplied in arguments are + dereferenced. + --stdin-name string - Assign a name if the file source is stdin. + -H, --hidden bool - Include files that are hidden. Only takes + effect on recursive add. + -q, --quiet bool - Write minimal output. + -Q, --quieter bool - Write only final hash. + --silent bool - Write no output. + -p, --progress bool - Stream progress data. + -t, --trickle bool - Use trickle-dag format for dag generation. + -n, --only-hash bool - Only chunk and hash - do not write to + disk. + -w, --wrap-with-directory bool - Wrap files with a directory object. + -s, --chunker string - Chunking algorithm, size-[bytes] or + rabin-[min]-[avg]-[max]. Default: + size-262144. + --pin bool - Pin this object when adding. Default: + true. + --raw-leaves bool - Use raw blocks for leaf nodes. + (experimental). + --nocopy bool - Add the file using filestore. Implies + raw-leaves. (experimental). + --fscache bool - Check the filestore for pre-existing + blocks. (experimental). + --cid-version int - CID version. Defaults to 0 unless an + option that depends on CIDv1 is passed. + (experimental). + --hash string - Hash function to use. Implies CIDv1 if + not sha2-256. (experimental). Default: + sha2-256. + --inline bool - Inline small blocks into CIDs. + (experimental). + --inline-limit int - Maximum block size to inline. + (experimental). Default: 32. +``` + ### Features This release is primarily a bug fix release but it still includes two nice @@ -272,6 +405,7 @@ go versions during builds. ### Changelog - github.com/ipfs/go-ipfs: + - fix: use http.Error for sending errors ([ipfs/go-ipfs#6379](https://github.com/ipfs/go-ipfs/pull/6379)) - core: call app.Stop once ([ipfs/go-ipfs#6380](https://github.com/ipfs/go-ipfs/pull/6380)) - explain what dhtclient does ([ipfs/go-ipfs#6375](https://github.com/ipfs/go-ipfs/pull/6375)) - ci: actually enable golangci-lint ([ipfs/go-ipfs#6362](https://github.com/ipfs/go-ipfs/pull/6362)) @@ -348,7 +482,11 @@ go versions during builds. - sync: apply entire query while locked ([ipfs/go-datastore#129](https://github.com/ipfs/go-datastore/pull/129)) - filter: values are now always bytes ([ipfs/go-datastore#126](https://github.com/ipfs/go-datastore/pull/126)) - autobatch: batch deletes ([ipfs/go-datastore#128](https://github.com/ipfs/go-datastore/pull/128)) -- github.com/ipfs/go-ipfs-cmds (v0.0.5 -> v0.0.7): +- github.com/ipfs/go-ipfs-cmds (v0.0.5 -> v0.0.8): + - fix: use golang's http.Error to send errors ([ipfs/go-ipfs-cmds#167](https://github.com/ipfs/go-ipfs-cmds/pull/167)) + - improve help text on narrow terminals ([ipfs/go-ipfs-cmds#140](https://github.com/ipfs/go-ipfs-cmds/pull/140)) + - chore: remove an old hack ([ipfs/go-ipfs-cmds#165](https://github.com/ipfs/go-ipfs-cmds/pull/165)) + - http: use the request context ([ipfs/go-ipfs-cmds#163](https://github.com/ipfs/go-ipfs-cmds/pull/163)) - merge in go-ipfs-cmdkit ([ipfs/go-ipfs-cmds#164](https://github.com/ipfs/go-ipfs-cmds/pull/164)) - fix: return the correct error ([ipfs/go-ipfs-cmds#162](https://github.com/ipfs/go-ipfs-cmds/pull/162)) - github.com/ipfs/go-ipfs-config (v0.0.1 -> v0.0.3): @@ -439,10 +577,16 @@ go versions during builds. - add an example (mainly for development) ([libp2p/go-libp2p-tls#14](https://github.com/libp2p/go-libp2p-tls/pull/14)) - github.com/libp2p/go-libp2p-transport-upgrader (v0.0.1 -> v0.0.4): - improve correctness of closing connections on failure ([libp2p/go-libp2p-transport-upgrader#19](https://github.com/libp2p/go-libp2p-transport-upgrader/pull/19)) +- github.com/libp2p/go-maddr-filter (v0.0.1 -> v0.0.4): + - fix filter listing ([libp2p/go-maddr-filter#13](https://github.com/libp2p/go-maddr-filter/pull/13)) + - Reinstate deprecated Remove() method to reverse breakage ([libp2p/go-maddr-filter#12](https://github.com/libp2p/go-maddr-filter/pull/12)) + - Implement support for whitelists, default-deny/allow ([libp2p/go-maddr-filter#8](https://github.com/libp2p/go-maddr-filter/pull/8)) - github.com/libp2p/go-mplex (v0.0.1 -> v0.0.4): + - disable write coalescing ([libp2p/go-mplex#61](https://github.com/libp2p/go-mplex/pull/61)) - fix SetDeadline error conditions ([libp2p/go-mplex#59](https://github.com/libp2p/go-mplex/pull/59)) - don't use contexts for deadlines ([libp2p/go-mplex#58](https://github.com/libp2p/go-mplex/pull/58)) - don't reset on pathologies, just ignore the data ([libp2p/go-mplex#57](https://github.com/libp2p/go-mplex/pull/57)) + - coalesce writes ([libp2p/go-mplex#54](https://github.com/libp2p/go-mplex/pull/54)) - read as much as we can in one go ([libp2p/go-mplex#53](https://github.com/libp2p/go-mplex/pull/53)) - use timeouts when sending messages for stream open, close, and reset. ([libp2p/go-mplex#52](https://github.com/libp2p/go-mplex/pull/52)) - fix: reset a stream even if closed remotely ([libp2p/go-mplex#50](https://github.com/libp2p/go-mplex/pull/50)) @@ -450,6 +594,9 @@ go versions during builds. - Fix race condition by adding a mutex for deadline access ([libp2p/go-mplex#41](https://github.com/libp2p/go-mplex/pull/41)) - github.com/libp2p/go-msgio (v0.0.1 -> v0.0.2): - fix: never claim to read more than read ([libp2p/go-msgio#12](https://github.com/libp2p/go-msgio/pull/12)) +- github.com/libp2p/go-ws-transport (v0.0.2 -> v0.0.4): + - dep: import go-smux-* into the libp2p org ([libp2p/go-ws-transport#43](https://github.com/libp2p/go-ws-transport/pull/43)) + - replace gx instructions with note about gomod ([libp2p/go-ws-transport#42](https://github.com/libp2p/go-ws-transport/pull/42)) ## 0.4.20 2019-04-16 From 7be8475c9b4045c5ad9ac54308ed679344507b64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 14 May 2019 23:28:50 +0200 Subject: [PATCH 028/671] block cmd: allow adding multiple blocks at once MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit License: MIT Signed-off-by: Łukasz Magiera --- core/commands/block.go | 42 ++++++++++++++++++++++-------------- test/sharness/t0050-block.sh | 13 +++++++++++ 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/core/commands/block.go b/core/commands/block.go index 69b2c77d38f..30887f13998 100644 --- a/core/commands/block.go +++ b/core/commands/block.go @@ -6,6 +6,8 @@ import ( "io" "os" + files "github.com/ipfs/go-ipfs-files" + util "github.com/ipfs/go-ipfs/blocks/blockstoreutil" cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv" @@ -129,7 +131,7 @@ than 'sha2-256' or format to anything other than 'v0' will result in CIDv1. }, Arguments: []cmds.Argument{ - cmds.FileArg("data", true, false, "The data to be stored as an IPFS block.").EnableStdin(), + cmds.FileArg("data", true, true, "The data to be stored as an IPFS block.").EnableStdin(), }, Options: []cmds.Option{ cmds.StringOption(blockFormatOptionName, "f", "cid format for blocks to be created with."), @@ -143,11 +145,6 @@ than 'sha2-256' or format to anything other than 'v0' will result in CIDv1. return err } - file, err := cmdenv.GetFileArg(req.Files.Entries()) - if err != nil { - return err - } - mhtype, _ := req.Options[mhtypeOptionName].(string) mhtval, ok := mh.Names[mhtype] if !ok { @@ -170,18 +167,31 @@ than 'sha2-256' or format to anything other than 'v0' will result in CIDv1. pin, _ := req.Options[pinOptionName].(bool) - p, err := api.Block().Put(req.Context, file, - options.Block.Hash(mhtval, mhlen), - options.Block.Format(format), - options.Block.Pin(pin)) - if err != nil { - return err + it := req.Files.Entries() + for it.Next() { + file := files.FileFromEntry(it) + if file == nil { + return errors.New("expected a file") + } + + p, err := api.Block().Put(req.Context, file, + options.Block.Hash(mhtval, mhlen), + options.Block.Format(format), + options.Block.Pin(pin)) + if err != nil { + return err + } + + err = res.Emit(&BlockStat{ + Key: p.Path().Cid().String(), + Size: p.Size(), + }) + if err != nil { + return err + } } - return cmds.EmitOnce(res, &BlockStat{ - Key: p.Path().Cid().String(), - Size: p.Size(), - }) + return it.Err() }, Encoders: cmds.EncoderMap{ cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, bs *BlockStat) error { diff --git a/test/sharness/t0050-block.sh b/test/sharness/t0050-block.sh index 7092d4cb87e..abc50c109b6 100755 --- a/test/sharness/t0050-block.sh +++ b/test/sharness/t0050-block.sh @@ -11,6 +11,7 @@ test_description="Test block command" test_init_ipfs HASH="QmRKqGMAM6EZngbpjSqrvYzq5Qd8b1bSWymjSUY9zQSNDk" +HASHB="QmdnpnsaEj69isdw5sNzp3h3HkaDz7xKq7BmvFFBzNr5e7" # # "block put tests" @@ -26,6 +27,18 @@ test_expect_success "'ipfs block put' output looks good" ' test_cmp expected_out actual_out ' +test_expect_success "'ipfs block put' with 2 files succeeds" ' + echo "Hello Mars!" > a && + echo "Hello Venus!" > b && + ipfs block put a b >actual_out +' + +test_expect_success "'ipfs block put' output looks good" ' + echo "$HASH" >expected_out && + echo "$HASHB" >>expected_out && + test_cmp expected_out actual_out +' + # # "block get" tests # From 1f1c68f16eaa57d6a66fd9a7f1de5a2159c6dc7f Mon Sep 17 00:00:00 2001 From: Hlib Date: Tue, 4 Jun 2019 16:11:27 +0300 Subject: [PATCH 029/671] Usage of context helper in Blockstore provider --- core/node/storage.go | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/core/node/storage.go b/core/node/storage.go index 01cc6e0629d..008b1970a07 100644 --- a/core/node/storage.go +++ b/core/node/storage.go @@ -1,7 +1,6 @@ package node import ( - "context" "os" "syscall" "time" @@ -55,15 +54,7 @@ func BaseBlockstoreCtor(cacheOpts blockstore.CacheOpts, nilRepo bool, hashOnRead bs = &verifbs.VerifBS{Blockstore: bs} if !nilRepo { - ctx, cancel := context.WithCancel(mctx) - - lc.Append(fx.Hook{ - OnStop: func(context context.Context) error { - cancel() - return nil - }, - }) - bs, err = blockstore.CachedBlockstore(ctx, bs, cacheOpts) + bs, err = blockstore.CachedBlockstore(helpers.LifecycleCtx(mctx, lc), bs, cacheOpts) if err != nil { return nil, err } From c30aaa921ac57ab134cafbc370289ce1b8d85d62 Mon Sep 17 00:00:00 2001 From: Oli Evans Date: Tue, 4 Jun 2019 16:17:32 +0100 Subject: [PATCH 030/671] docs: default value for HashOnRead is false This is currently the case. It should be filpped to true, but in the meantime let's document the current situation See: https://github.com/ipfs/go-ipfs/issues/1152 --- docs/config.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/config.md b/docs/config.md index a5e6f6af887..862713f6513 100644 --- a/docs/config.md +++ b/docs/config.md @@ -153,6 +153,8 @@ Default: `1h` A boolean value. If set to true, all block reads from disk will be hashed and verified. This will cause increased CPU utilization. +Default: `false` + - `BloomFilterSize` A number representing the size in bytes of the blockstore's [bloom filter](https://en.wikipedia.org/wiki/Bloom_filter). A value of zero represents the feature being disabled. From 846b6b5d9523ba2a859370b48fa8bb20d918d08b Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Tue, 4 Jun 2019 16:48:25 -0700 Subject: [PATCH 031/671] add unixfs get metric License: MIT Signed-off-by: whyrusleeping --- core/corehttp/gateway_handler.go | 2 ++ core/corehttp/metrics.go | 3 +++ 2 files changed, 5 insertions(+) diff --git a/core/corehttp/gateway_handler.go b/core/corehttp/gateway_handler.go index 3f212d9180b..91bfb19787c 100644 --- a/core/corehttp/gateway_handler.go +++ b/core/corehttp/gateway_handler.go @@ -123,6 +123,7 @@ func (i *gatewayHandler) optionsHandler(w http.ResponseWriter, r *http.Request) } func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request) { + begin := time.Now() urlPath := r.URL.Path escapedURLPath := r.URL.EscapedPath() @@ -172,6 +173,7 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request webError(w, "ipfs cat "+escapedURLPath, err, http.StatusNotFound) return } + unixfsGetMetric.Observe(time.Since(begin).Seconds()) defer dr.Close() diff --git a/core/corehttp/metrics.go b/core/corehttp/metrics.go index 3f8c68ccd84..92b5a3a82b3 100644 --- a/core/corehttp/metrics.go +++ b/core/corehttp/metrics.go @@ -97,6 +97,9 @@ var ( peersTotalMetric = prometheus.NewDesc( prometheus.BuildFQName("ipfs", "p2p", "peers_total"), "Number of connected peers", []string{"transport"}, nil) + unixfsGetMetric = prometheus.NewSummary(prometheus.SummaryOpts{ + Name: "unixfsGet", + }) ) type IpfsNodeCollector struct { From ebd89b4011c300601f7b1cfcda01ee51221b748b Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Tue, 4 Jun 2019 17:19:48 -0700 Subject: [PATCH 032/671] gateway: expand get metric metadata --- core/corehttp/metrics.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/core/corehttp/metrics.go b/core/corehttp/metrics.go index 92b5a3a82b3..7a7f30dd995 100644 --- a/core/corehttp/metrics.go +++ b/core/corehttp/metrics.go @@ -97,8 +97,12 @@ var ( peersTotalMetric = prometheus.NewDesc( prometheus.BuildFQName("ipfs", "p2p", "peers_total"), "Number of connected peers", []string{"transport"}, nil) + unixfsGetMetric = prometheus.NewSummary(prometheus.SummaryOpts{ - Name: "unixfsGet", + Namespace: "ipfs", + Subsystem: "http", + Name: "unixfs_get_latency_seconds", + Help: "The time till the first block is received when 'getting' a file from the gateway.", }) ) From d460150f4382b6439bd13c886d725b382ef6542f Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Tue, 4 Jun 2019 17:34:53 -0700 Subject: [PATCH 033/671] gateway: label get requests latency with the path namespace --- core/corehttp/gateway_handler.go | 3 ++- core/corehttp/metrics.go | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/core/corehttp/gateway_handler.go b/core/corehttp/gateway_handler.go index 91bfb19787c..1aa343a5502 100644 --- a/core/corehttp/gateway_handler.go +++ b/core/corehttp/gateway_handler.go @@ -173,7 +173,8 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request webError(w, "ipfs cat "+escapedURLPath, err, http.StatusNotFound) return } - unixfsGetMetric.Observe(time.Since(begin).Seconds()) + + unixfsGetMetric.WithLabelValues(parsedPath.Namespace()).Observe(time.Since(begin).Seconds()) defer dr.Close() diff --git a/core/corehttp/metrics.go b/core/corehttp/metrics.go index 7a7f30dd995..b0aebd3979b 100644 --- a/core/corehttp/metrics.go +++ b/core/corehttp/metrics.go @@ -98,12 +98,12 @@ var ( prometheus.BuildFQName("ipfs", "p2p", "peers_total"), "Number of connected peers", []string{"transport"}, nil) - unixfsGetMetric = prometheus.NewSummary(prometheus.SummaryOpts{ + unixfsGetMetric = prometheus.NewSummaryVec(prometheus.SummaryOpts{ Namespace: "ipfs", Subsystem: "http", Name: "unixfs_get_latency_seconds", Help: "The time till the first block is received when 'getting' a file from the gateway.", - }) + }, []string{"namespace"}) ) type IpfsNodeCollector struct { From 9fe4787dce8b3579188322ddfe2f128c7958ef89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 5 Jun 2019 12:47:38 +0200 Subject: [PATCH 034/671] Run JS interop in CircleCI --- .circleci/config.yml | 53 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 7c90fd9b561..fd606d8ca42 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -2,7 +2,7 @@ version: 2.0 aliases: make_out_dirs: &make_out_dirs - run: mkdir -p $CIRCLE_ARTIFACTS $CIRCLE_TEST_REPORTS/{unit,sharness} + run: mkdir -p $CIRCLE_ARTIFACTS $CIRCLE_WORKSPACE $CIRCLE_TEST_REPORTS/{unit,sharness} restore_gomod: &restore_gomod restore_cache: keys: @@ -29,14 +29,14 @@ defaults: &defaults CIRCLE: 1 SERVICE: circle-ci CIRCLE_ARTIFACTS: /tmp/circleci-artifacts + CIRCLE_WORKSPACE: /tmp/circleci-workspace TEST_VERBOSE: 1 TRAVIS: 1 - docker: - - image: circleci/golang:1.12 - jobs: gobuild: + docker: + - image: circleci/golang:1.12 <<: *defaults steps: - checkout @@ -53,6 +53,8 @@ jobs: - *store_gomod golint: <<: *defaults + docker: + - image: circleci/golang:1.12 steps: - checkout - *make_out_dirs @@ -61,6 +63,8 @@ jobs: make -O test_go_lint - *store_gomod gotest: + docker: + - image: circleci/golang:1.12 <<: *defaults steps: - checkout @@ -88,6 +92,8 @@ jobs: - store_artifacts: path: /tmp/circleci-test-results sharness: + docker: + - image: circleci/golang:1.12 <<: *defaults steps: - run: sudo apt install socat @@ -114,6 +120,41 @@ jobs: path: /tmp/circleci-artifacts - store_artifacts: path: /tmp/circleci-test-results + build-interop: + docker: + - image: circleci/golang:1.12 + <<: *defaults + steps: + - checkout + - *make_out_dirs + - *restore_gomod + - run: make build + - run: cp cmd/ipfs/ipfs /tmp/circleci-workspace + - persist_to_workspace: + root: /tmp/circleci-workspace + paths: + - ipfs + - *store_gomod + interop: + docker: + - image: circleci/node:10 + <<: *defaults + steps: + - *make_out_dirs + - attach_workspace: + at: /tmp/circleci-workspace + - run: git clone https://github.com/ipfs/interop.git + - run: + command: npm install + working_directory: ~/ipfs/go-ipfs/interop + environment: + IPFS_GO_EXEC: /tmp/circleci-workspace/ipfs + - run: + command: npm test + working_directory: ~/ipfs/go-ipfs/interop + environment: + IPFS_GO_EXEC: /tmp/circleci-workspace/ipfs + workflows: version: 2 @@ -123,3 +164,7 @@ workflows: - golint - gotest - sharness + - build-interop + - interop: + requires: + - build-interop From 6b0f9f71e05d9b93f1690a267a4c6d4808ff76b9 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 5 Jun 2019 10:57:43 -0700 Subject: [PATCH 035/671] build: use protoc-gen-* from gomod Also, * Make it possible to override the PROTOC binary. * Remove gx targets. --- .gitignore | 1 + Makefile | 2 -- Rules.mk | 5 +++-- bin/Rules.mk | 7 +++++-- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 9ead6675ade..f96cb84bb88 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ gx-workspace-update.json .ipfs bin/gx +bin/protoc-* bin/gx* bin/tmp bin/gocovmerge diff --git a/Makefile b/Makefile index 4bd63ac03a1..4c175dbc51f 100644 --- a/Makefile +++ b/Makefile @@ -2,8 +2,6 @@ SHELL=PATH='$(PATH)' /bin/sh -PROTOC = protoc --gogofaster_out=. --proto_path=.:$(GOPATH)/src:$(dir $@) $< - # enable second expansion .SECONDEXPANSION: diff --git a/Rules.mk b/Rules.mk index 122aad0d8e5..d4bdf361ac7 100644 --- a/Rules.mk +++ b/Rules.mk @@ -5,6 +5,7 @@ DISTCLEAN := TEST := TEST_SHORT := GOCC ?= go +PROTOC ?= protoc all: help # all has to be first defined target .PHONY: all @@ -58,8 +59,8 @@ include $(dir)/Rules.mk # universal rules # # -------------------- # -%.pb.go: %.proto - $(PROTOC) +%.pb.go: %.proto bin/protoc-gen-gogofaster + $(PROTOC) --gogofaster_out=. --proto_path=.:$(GOPATH)/src:$(dir $@) $< # -------------------- # # core targets # diff --git a/bin/Rules.mk b/bin/Rules.mk index ecb759f3842..f1ee769e005 100644 --- a/bin/Rules.mk +++ b/bin/Rules.mk @@ -2,8 +2,8 @@ include mk/header.mk dist_root_$(d)="/ipfs/QmPrXH9jRVwvd7r5MC5e6nV4uauQGzLk1i2647Ye9Vbbwe" -TGTS_$(d) := $(d)/gx $(d)/gx-go -DISTCLEAN += $(wildcard $(d)/gx-v*) $(wildcard $(d)/gx-go-v*) $(d)/tmp +TGTS_$(d) := $(d)/protoc +DISTCLEAN += $(d)/protoc $(d)/tmp PATH := $(realpath $(d)):$(PATH) @@ -15,5 +15,8 @@ else ln -s $(notdir $^) $@ endif +bin/protoc-gen-gogofaster: + $(call go-build,github.com/gogo/protobuf/protoc-gen-gogofaster) + CLEAN += $(TGTS_$(d)) include mk/footer.mk From 545eb3a4626e1f5ae9f3919f3a8a232f2646f340 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 5 Jun 2019 13:22:55 -0700 Subject: [PATCH 036/671] build: strip GOPATH from build paths This should help fix some of our problems using plugins with go-ipfs. --- mk/golang.mk | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mk/golang.mk b/mk/golang.mk index d8aefa0dff8..e5a58a45d5b 100644 --- a/mk/golang.mk +++ b/mk/golang.mk @@ -10,6 +10,9 @@ unexport GOFLAGS GOFLAGS ?= GOTFLAGS ?= +# Try to make building as reproducible as possible by stripping the go path. +GOFLAGS += -asmflags=all=-trimpath="$(GOPATH)" -gcflags=all=-trimpath="$(GOPATH)" + ifeq ($(tarball-is),1) GOFLAGS += -mod=vendor endif From eb4828d28d5966238ed6d4eeab63e36027fa6565 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 5 Jun 2019 16:07:13 -0700 Subject: [PATCH 037/671] doc: tell windows users to use the pre-built version if possible. --- docs/windows.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/windows.md b/docs/windows.md index 2687805e202..abe151c4769 100644 --- a/docs/windows.md +++ b/docs/windows.md @@ -1,6 +1,8 @@ # Building on Windows ![](https://ipfs.io/ipfs/QmccXW7JSZMVXidSc7tHsU6aktuaiV923q4yBGHUsdymYo/build.gif) +If you just want to install go-ipfs, please download it from https://dist.ipfs.io/#go-ipfs. This document explains how to build it from source. + ## Install Go `go-ipfs` is built on Golang and thus depends on it for all building methods. https://golang.org/doc/install From dd9cae7f04b9bab9fb7fd47e27e31dd9ab826767 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 5 Jun 2019 16:11:01 -0700 Subject: [PATCH 038/671] doc: remove mentions of gx --- docs/windows.md | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/docs/windows.md b/docs/windows.md index abe151c4769..4487e64ffe9 100644 --- a/docs/windows.md +++ b/docs/windows.md @@ -105,27 +105,20 @@ SETX PATH %PATH% ``` ## Minimal -While it's possible to build `go-ipfs` with `go` alone, we'll be using `git` and `gx` for practical source management. -You can use whichever version of `git` you wish but we recommend the Windows builds at . `git` must be in your [`PATH`](https://ss64.com/nt/path.html) for `go get` to recognize and use it. -### `gx` -You may install prebuilt binaries for [`gx`](https://dist.ipfs.io/#gx) & [`gx-go`](https://dist.ipfs.io/#gx-go) if they're available for your platform. -Alternatively, you can build them from source and install them to `%GOPATH%\bin` by running the following: +While it's possible to build `go-ipfs` with `go` alone, we'll be using `git` to fetch the source. -``` -go get -u github.com/whyrusleeping/gx -go get -u github.com/whyrusleeping/gx-go -``` +You can use whichever version of `git` you wish but we recommend the Windows builds at . `git` must be in your [`PATH`](https://ss64.com/nt/path.html) for `go get` to recognize and use it. + +### go-ipfs -### `go-ipfs` +Clone and change directory to the source code, if you haven't already: ``` -SET PATH=%PATH%;%GOPATH%\bin -go get -u -d github.com/ipfs/go-ipfs -cd %GOPATH%/src/github.com/ipfs/go-ipfs -gx --verbose install --global -cd cmd\ipfs +git clone https://github.com/ipfs/go-ipfs %GOPATH%/src/github.com/ipfs/go-ipfs +cd %GOPATH%/src/github.com/ipfs/go-ipfs/cmd/ipfs ``` + We need the `git` commit hash to be included in our build so that in the extremely rare event a bug is found, we have a reference point later for tracking it. We'll ask `git` for it and store it in a variable. The syntax for the next command is different depending on whether you're using the interactive command line or writing a batch file. Use the one that applies to you. - interactive: `FOR /F %V IN ('git rev-parse --short HEAD') do set SHA=%V` - interpreter: `FOR /F %%V IN ('git rev-parse --short HEAD') do set SHA=%%V` From f6ea84952909d1a78cf9bf40d687a6496a989810 Mon Sep 17 00:00:00 2001 From: Dominic Della Valle Date: Wed, 5 Jun 2019 19:57:39 -0400 Subject: [PATCH 039/671] doc: add Windows packages to README --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index 11e63a11485..a4af02c0787 100644 --- a/README.md +++ b/README.md @@ -114,6 +114,18 @@ With snap, in any of the [supported Linux distributions](https://snapcraft.io/do $ sudo snap install ipfs ``` +### From Windows package managers + +- [Chocolatey](#chocolatey) + +#### Chocolatey + +The package [ipfs](https://chocolatey.org/packages/ipfs) currently points to go-ipfs and is being maintained. + +```Powershell +PS> choco install ipfs +``` + ### Build from Source #### Install Go From f2635d1f5ecc30b587f922e7208c6bdf606d5185 Mon Sep 17 00:00:00 2001 From: Sander Pick Date: Wed, 5 Jun 2019 20:32:51 -0700 Subject: [PATCH 040/671] libp2p: moves discovery after host listen Prevents the MDNS server from starting when the host has zero addresses. Re: https://github.com/libp2p/go-libp2p/issues/652 Signed-off-by: Sander Pick --- core/node/groups.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/node/groups.go b/core/node/groups.go index 5e84b9a5838..1e5207b898c 100644 --- a/core/node/groups.go +++ b/core/node/groups.go @@ -94,11 +94,11 @@ func LibP2P(bcfg *BuildCfg, cfg *config.Config) fx.Option { BaseLibP2P, fx.Provide(libp2p.AddrFilters(cfg.Swarm.AddrFilters)), - fx.Invoke(libp2p.SetupDiscovery(cfg.Discovery.MDNS.Enabled, cfg.Discovery.MDNS.Interval)), fx.Provide(libp2p.AddrsFactory(cfg.Addresses.Announce, cfg.Addresses.NoAnnounce)), fx.Provide(libp2p.SmuxTransport(bcfg.getOpt("mplex"))), fx.Provide(libp2p.Relay(cfg.Swarm.DisableRelay, cfg.Swarm.EnableRelayHop)), fx.Invoke(libp2p.StartListening(cfg.Addresses.Swarm)), + fx.Invoke(libp2p.SetupDiscovery(cfg.Discovery.MDNS.Enabled, cfg.Discovery.MDNS.Interval)), fx.Provide(libp2p.Security(!bcfg.DisableEncryptedConnections, cfg.Experimental.PreferTLS)), From 486f01353905629a1d03b4231e7062e13d80804d Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Thu, 6 Jun 2019 15:42:03 -0700 Subject: [PATCH 041/671] pin: fix concurrent map access race Not sure why this didn't show up sooner. fixes #6418 --- pin/pin.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pin/pin.go b/pin/pin.go index 8df21ee1ce3..48a16f84e5e 100644 --- a/pin/pin.go +++ b/pin/pin.go @@ -498,11 +498,17 @@ func LoadPinner(d ds.Datastore, dserv, internal ipld.DAGService) (Pinner, error) // DirectKeys returns a slice containing the directly pinned keys func (p *pinner) DirectKeys() []cid.Cid { + p.lock.RLock() + defer p.lock.RUnlock() + return p.directPin.Keys() } // RecursiveKeys returns a slice containing the recursively pinned keys func (p *pinner) RecursiveKeys() []cid.Cid { + p.lock.RLock() + defer p.lock.RUnlock() + return p.recursePin.Keys() } From 98a508fdd177866a03bca494524b3a3772a27755 Mon Sep 17 00:00:00 2001 From: Hector Sanjuan Date: Sat, 8 Jun 2019 00:51:18 +0200 Subject: [PATCH 042/671] Deps: update go-libp2p-http to its new libp2p location License: MIT Signed-off-by: Hector Sanjuan --- core/corehttp/proxy.go | 2 +- go.mod | 2 +- go.sum | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/corehttp/proxy.go b/core/corehttp/proxy.go index 64d796cba5c..17cb0052824 100644 --- a/core/corehttp/proxy.go +++ b/core/corehttp/proxy.go @@ -10,8 +10,8 @@ import ( core "github.com/ipfs/go-ipfs/core" - p2phttp "github.com/hsanjuan/go-libp2p-http" protocol "github.com/libp2p/go-libp2p-core/protocol" + p2phttp "github.com/libp2p/go-libp2p-http" ) // ProxyOption is an endpoint for proxying a HTTP request to another ipfs peer diff --git a/go.mod b/go.mod index e10bb5c0dfb..9ed7365d57e 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,6 @@ require ( github.com/golangci/golangci-lint v1.16.1-0.20190425135923-692dacb773b7 github.com/hashicorp/go-multierror v1.0.0 github.com/hashicorp/golang-lru v0.5.1 - github.com/hsanjuan/go-libp2p-http v0.1.0 github.com/ipfs/dir-index-html v1.0.3 github.com/ipfs/go-bitswap v0.1.1 github.com/ipfs/go-block-format v0.0.2 @@ -68,6 +67,7 @@ require ( github.com/libp2p/go-libp2p-circuit v0.1.0 github.com/libp2p/go-libp2p-connmgr v0.1.0 github.com/libp2p/go-libp2p-core v0.0.3 + github.com/libp2p/go-libp2p-http v0.1.2 github.com/libp2p/go-libp2p-kad-dht v0.1.0 github.com/libp2p/go-libp2p-kbucket v0.2.0 github.com/libp2p/go-libp2p-loggables v0.1.0 diff --git a/go.sum b/go.sum index c404db021e0..7238391ffdc 100644 --- a/go.sum +++ b/go.sum @@ -177,10 +177,6 @@ github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce h1:xdsDDbiBDQTKASoGE github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/hsanjuan/go-libp2p-gostream v0.1.0 h1:Fk2j4UbUFsCvX9y66iL/8AqU4Il+QGnq73595eMoUX4= -github.com/hsanjuan/go-libp2p-gostream v0.1.0/go.mod h1:+mgB1KPi3ACeWxwwBKaJKxnCh4RTWDfIRqKqWwatvLI= -github.com/hsanjuan/go-libp2p-http v0.1.0 h1:O3t+2R/kqD4pTQUJJQdZlc/sMqub2ZMe+37SpQMGAn8= -github.com/hsanjuan/go-libp2p-http v0.1.0/go.mod h1:cI7XxaacYXbUv6WXkScPgo5EOc1eU1ktw6bVkygjsnk= 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= @@ -392,8 +388,12 @@ github.com/libp2p/go-libp2p-discovery v0.0.1/go.mod h1:ZkkF9xIFRLA1xCc7bstYFkd80 github.com/libp2p/go-libp2p-discovery v0.0.5/go.mod h1:YtF20GUxjgoKZ4zmXj8j3Nb2TUSBHFlOCetzYdbZL5I= github.com/libp2p/go-libp2p-discovery v0.1.0 h1:j+R6cokKcGbnZLf4kcNwpx6mDEUPF3N6SrqMymQhmvs= github.com/libp2p/go-libp2p-discovery v0.1.0/go.mod h1:4F/x+aldVHjHDHuX85x1zWoFTGElt8HnoDzwkFZm29g= +github.com/libp2p/go-libp2p-gostream v0.1.1 h1:9D88ud79U9Nl6iTPiTM1F/9LGC7SQPXdrRD3GWuIC0k= +github.com/libp2p/go-libp2p-gostream v0.1.1/go.mod h1:w0cUXl1GHEMuqFMOomaCnq9g88YK60cxtOENCLku/pE= 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.2 h1:eMkfqm293MIkGZ+FlX8FcTfS7VPE+DMdhEjDfY0+STQ= +github.com/libp2p/go-libp2p-http v0.1.2/go.mod h1:qomMgtxIHzkqu5L3mvg48s/6hEu7IuVNVo4ktL60ogE= 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= From e1bfc9f08ab9688d61681852165686998333e84b Mon Sep 17 00:00:00 2001 From: Rod Vagg Date: Sat, 8 Jun 2019 11:50:31 +1000 Subject: [PATCH 043/671] docs: fix install guide link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a4af02c0787..6ffcd66b7df 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ If the issue is a protocol weakness that cannot be immediately exploited or some ## Install -The canonical download instructions for IPFS are over at: https://docs.ipfs.io/introduction/install/. It is **highly suggested** you follow those instructions if you are not interested in working on IPFS development. +The canonical download instructions for IPFS are over at: https://docs.ipfs.io/guides/guides/install/. It is **highly suggested** you follow those instructions if you are not interested in working on IPFS development. ### System Requirements From 2865ae79a145cfcbe8a8a9cf0fabd3f762639370 Mon Sep 17 00:00:00 2001 From: Kirill Goncharov Date: Sat, 8 Jun 2019 19:13:19 +0300 Subject: [PATCH 044/671] install.sh: Fix wrong destination path for ipfs binary License: MIT Signed-off-by: Kirill Goncharov --- cmd/ipfs/dist/install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/ipfs/dist/install.sh b/cmd/ipfs/dist/install.sh index 08f68752342..34c5d59e9c8 100755 --- a/cmd/ipfs/dist/install.sh +++ b/cmd/ipfs/dist/install.sh @@ -13,7 +13,7 @@ binpaths="/usr/local/bin /usr/bin" is_write_perm_missing="" for binpath in $binpaths; do - if mv "$bin" "$binpath/$bin" ; then + if mv "$bin" "$binpath/ipfs" ; then echo "Moved $bin to $binpath" exit 0 else From 3883dfe45000f611cbc6b295fe6ca88eecbb47cf Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 5 Jun 2019 19:19:44 -0700 Subject: [PATCH 045/671] assets: move away from gx 1. Use a submodule for dir-index-html. This isn't a go dependency and treating it like one is more trouble than it's worth. We don't actually need to checkout the submodule unless we need to regenerate the assets. 2. Avoid a runtime dependency on dir-index-html (may shave a few bytes off the final binary?). 3. Remove unused code. 4. Avoid bundling unused files. 5. Switch to a maintained version of go-bindata. 6. Use go mod to manage go-bindata. --- .gitmodules | 3 + assets/README.md | 3 +- assets/assets.go | 18 +---- assets/assets_test.go | 8 -- assets/bindata.go | 170 ++++++++---------------------------------- assets/bindata_dep.go | 9 +++ assets/dir-index-html | 1 + go.mod | 2 +- go.sum | 4 +- 9 files changed, 51 insertions(+), 167 deletions(-) create mode 100644 .gitmodules create mode 100644 assets/bindata_dep.go create mode 160000 assets/dir-index-html diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000000..f0f10eeb51d --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "assets/dir-index-html"] + path = assets/dir-index-html + url = git@github.com:ipfs/dir-index-html diff --git a/assets/README.md b/assets/README.md index caffb3abb0b..8f0632caf50 100644 --- a/assets/README.md +++ b/assets/README.md @@ -8,6 +8,5 @@ Instead, edit the source files and use `go generate` from within the assets directory: ``` -go get -u github.com/jteeuwen/go-bindata/... -go generate +go generate . ``` diff --git a/assets/assets.go b/assets/assets.go index 56437dfa156..f3f5de06948 100644 --- a/assets/assets.go +++ b/assets/assets.go @@ -1,11 +1,10 @@ -//go:generate go-bindata -pkg=assets -prefix=$GOPATH/src/gx/ipfs/QmT1jwrqzSMjSjLG5oBd9w4P9vXPKQksWuf5ghsE3Q88ZV init-doc $GOPATH/src/gx/ipfs/QmT1jwrqzSMjSjLG5oBd9w4P9vXPKQksWuf5ghsE3Q88ZV/dir-index-html +//go:generate git submodule update --init ./dir-index-html +//go:generate go run github.com/go-bindata/go-bindata/go-bindata -pkg=assets init-doc dir-index-html/dir-index.html dir-index-html/knownIcons.txt //go:generate gofmt -w bindata.go - package assets import ( "fmt" - "os" "path/filepath" "github.com/ipfs/go-ipfs/core" @@ -15,9 +14,6 @@ import ( files "github.com/ipfs/go-ipfs-files" options "github.com/ipfs/interface-go-ipfs-core/options" "github.com/ipfs/interface-go-ipfs-core/path" - - // this import keeps gx from thinking the dep isn't used - _ "github.com/ipfs/dir-index-html" ) // initDocPaths lists the paths for the docs we want to seed during --init @@ -36,16 +32,6 @@ func SeedInitDocs(nd *core.IpfsNode) (cid.Cid, error) { return addAssetList(nd, initDocPaths) } -var initDirPath = filepath.Join(os.Getenv("GOPATH"), "gx", "ipfs", "QmT1jwrqzSMjSjLG5oBd9w4P9vXPKQksWuf5ghsE3Q88ZV", "dir-index-html") -var initDirIndex = []string{ - filepath.Join(initDirPath, "knownIcons.txt"), - filepath.Join(initDirPath, "dir-index.html"), -} - -func SeedInitDirIndex(nd *core.IpfsNode) (cid.Cid, error) { - return addAssetList(nd, initDirIndex) -} - func addAssetList(nd *core.IpfsNode, l []string) (cid.Cid, error) { api, err := coreapi.NewCoreAPI(nd) if err != nil { diff --git a/assets/assets_test.go b/assets/assets_test.go index 4b0ac8294dc..2122afc0068 100644 --- a/assets/assets_test.go +++ b/assets/assets_test.go @@ -12,14 +12,6 @@ func TestEmbeddedDocs(t *testing.T) { testNFiles(initDocPaths, 5, t, "documents") } -func TestDirIndex(t *testing.T) { - t.Skip("skipping for now, code being tested is currently unused") - // TODO: import assets during init. - // this will require figuring out how to set the right paths up for - // referencing the code from its gx path - testNFiles(initDirIndex, 2, t, "assets") -} - func testNFiles(fs []string, wantCnt int, t *testing.T, ftype string) { if len(fs) < wantCnt { t.Fatalf("expected %d %s. got %d", wantCnt, ftype, len(fs)) diff --git a/assets/bindata.go b/assets/bindata.go index 4dd55e4f118..ad00a51de6a 100644 --- a/assets/bindata.go +++ b/assets/bindata.go @@ -1,4 +1,4 @@ -// Code generated by go-bindata. +// Package assets Code generated by go-bindata. (@generated) DO NOT EDIT. // sources: // init-doc/about // init-doc/contact @@ -7,15 +7,8 @@ // init-doc/quick-start // init-doc/readme // init-doc/security-notes -// ../../../../gx/ipfs/QmT1jwrqzSMjSjLG5oBd9w4P9vXPKQksWuf5ghsE3Q88ZV/dir-index-html/LICENSE -// ../../../../gx/ipfs/QmT1jwrqzSMjSjLG5oBd9w4P9vXPKQksWuf5ghsE3Q88ZV/dir-index-html/README.md -// ../../../../gx/ipfs/QmT1jwrqzSMjSjLG5oBd9w4P9vXPKQksWuf5ghsE3Q88ZV/dir-index-html/dir-index-uncat.html -// ../../../../gx/ipfs/QmT1jwrqzSMjSjLG5oBd9w4P9vXPKQksWuf5ghsE3Q88ZV/dir-index-html/dir-index.html -// ../../../../gx/ipfs/QmT1jwrqzSMjSjLG5oBd9w4P9vXPKQksWuf5ghsE3Q88ZV/dir-index-html/index.go -// ../../../../gx/ipfs/QmT1jwrqzSMjSjLG5oBd9w4P9vXPKQksWuf5ghsE3Q88ZV/dir-index-html/knownIcons.txt -// ../../../../gx/ipfs/QmT1jwrqzSMjSjLG5oBd9w4P9vXPKQksWuf5ghsE3Q88ZV/dir-index-html/package.json -// DO NOT EDIT! - +// dir-index-html/dir-index.html +// dir-index-html/knownIcons.txt package assets import ( @@ -62,21 +55,32 @@ type bindataFileInfo struct { modTime time.Time } +// Name return file name func (fi bindataFileInfo) Name() string { return fi.name } + +// Size return file size func (fi bindataFileInfo) Size() int64 { return fi.size } + +// Mode return file mode func (fi bindataFileInfo) Mode() os.FileMode { return fi.mode } + +// Mode return file modify time func (fi bindataFileInfo) ModTime() time.Time { return fi.modTime } + +// IsDir return file whether a directory func (fi bindataFileInfo) IsDir() bool { - return false + return fi.mode&os.ModeDir != 0 } + +// Sys return file is sys mode func (fi bindataFileInfo) Sys() interface{} { return nil } @@ -156,7 +160,7 @@ func initDocPing() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init-doc/ping", size: 4, mode: os.FileMode(384), modTime: time.Unix(1544511852, 0)} + info := bindataFileInfo{name: "init-doc/ping", size: 4, mode: os.FileMode(384), modTime: time.Unix(1555022883, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -176,7 +180,7 @@ func initDocQuickStart() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init-doc/quick-start", size: 1681, mode: os.FileMode(384), modTime: time.Unix(1544568089, 0)} + info := bindataFileInfo{name: "init-doc/quick-start", size: 1681, mode: os.FileMode(384), modTime: time.Unix(1555022883, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -196,7 +200,7 @@ func initDocReadme() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init-doc/readme", size: 1091, mode: os.FileMode(384), modTime: time.Unix(1539187719, 0)} + info := bindataFileInfo{name: "init-doc/readme", size: 1091, mode: os.FileMode(384), modTime: time.Unix(1555022883, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -216,67 +220,7 @@ func initDocSecurityNotes() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "init-doc/security-notes", size: 1162, mode: os.FileMode(384), modTime: time.Unix(1544511852, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _dirIndexHtmlLicense = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x5c\x51\xcd\x8e\xab\x36\x14\xde\xfb\x29\x3e\xcd\x6a\x46\x42\xd3\x9f\x45\x17\xdd\x79\xc0\x09\x56\xc1\x46\xc6\xb9\x69\x96\x04\x9c\xc1\x15\xc1\x11\x76\x3a\xca\xdb\x57\x87\x64\xee\xed\xdc\x15\xc2\xe7\x7c\xbf\xc7\x8e\x0e\xb5\xb4\xa8\x7c\xef\xe6\xe8\xf0\x5c\x4b\xfb\xc2\x58\x1e\x2e\xb7\xc5\xbf\x8f\x09\xcf\xfd\x0b\x7e\xff\xf5\xb7\x3f\x20\x9b\x4d\xcb\x58\xe3\x96\xb3\x8f\xd1\x87\x19\x3e\x62\x74\x8b\x3b\xde\xf0\xbe\x74\x73\x72\x43\x86\xd3\xe2\x1c\xc2\x09\xfd\xd8\x2d\xef\x2e\x43\x0a\xe8\xe6\x1b\x2e\x6e\x89\x61\x46\x38\xa6\xce\xcf\x7e\x7e\x47\x87\x3e\x5c\x6e\x2c\x9c\x90\x46\x1f\x11\xc3\x29\x7d\x74\x8b\x43\x37\x0f\xe8\x62\x0c\xbd\xef\x92\x1b\x30\x84\xfe\x7a\x76\x73\xea\x12\xe9\x9d\xfc\xe4\x22\x9e\xd3\xe8\xf0\xd4\x3e\x10\x4f\x2f\xab\xc8\xe0\xba\x89\xf9\x19\x34\xfb\x1c\xe1\xc3\xa7\x31\x5c\x13\x16\x17\xd3\xe2\x7b\xe2\xc8\xe0\xe7\x7e\xba\x0e\xe4\xe1\x73\x3c\xf9\xb3\x7f\x28\x10\x7c\x4d\x1d\x59\x0a\xb8\x46\x97\xad\x3e\x33\x9c\xc3\xe0\x4f\xf4\x75\x6b\xac\xcb\xf5\x38\xf9\x38\x66\x18\x3c\x51\x1f\xaf\xc9\x65\x88\xf4\xb8\x96\x98\x51\x8e\x5f\xc2\x82\xe8\xa6\x89\xf5\xe1\xe2\x5d\xc4\x9a\xf5\x87\xbb\x75\x87\xac\x5f\xa8\xd0\xf4\xa8\x28\xd2\xcb\xc7\x18\xce\x5f\x93\xf8\xc8\x4e\xd7\x65\xf6\x71\x74\x2b\x66\x08\x88\x61\x55\xfc\xc7\xf5\x89\x5e\x68\xfd\x14\xa6\x29\x7c\x50\xb4\x3e\xcc\x83\xa7\x44\xf1\x4f\xc6\xe8\xc2\xdd\x31\xfc\xeb\xd6\x2c\xf7\xa3\xce\x21\xf9\xfe\x5e\xf7\x7a\x80\xcb\x8f\xab\x3e\x46\x71\xec\xa6\x09\x47\xf7\x28\xcc\x0d\xf0\x33\xba\xff\xc5\x59\x48\x3e\xa6\x6e\x4e\xbe\x9b\x70\x09\xcb\xaa\xf7\x73\xcc\x57\xc6\x6c\x29\xd0\xea\x8d\xdd\x73\x23\x20\x5b\x34\x46\x7f\x93\x85\x28\xf0\xc4\x5b\xc8\xf6\x29\xc3\x5e\xda\x52\xef\x2c\xf6\xdc\x18\xae\xec\x01\x7a\x03\xae\x0e\xf8\x4b\xaa\x22\x83\xf8\xbb\x31\xa2\x6d\xa1\x0d\x93\x75\x53\x49\x51\x64\x90\x2a\xaf\x76\x85\x54\x5b\xbc\xed\x2c\x94\xb6\xa8\x64\x2d\xad\x28\x60\x35\x48\xf0\x41\x25\x45\x4b\x64\xb5\x30\x79\xc9\x95\xe5\x6f\xb2\x92\xf6\x90\xb1\x8d\xb4\x8a\x38\x37\xda\x80\xa3\xe1\xc6\xca\x7c\x57\x71\x83\x66\x67\x1a\xdd\x0a\x70\x55\x40\x69\x25\xd5\xc6\x48\xb5\x15\xb5\x50\xf6\x15\x52\x41\x69\x88\x6f\x42\x59\xb4\x25\xaf\x2a\x92\x62\x7c\x67\x4b\x6d\xc8\x1f\x72\xdd\x1c\x8c\xdc\x96\x16\xa5\xae\x0a\x61\x5a\xbc\x09\x54\x92\xbf\x55\xe2\x2e\xa5\x0e\xc8\x2b\x2e\xeb\x0c\x05\xaf\xf9\x56\xac\x28\x6d\x4b\x61\x18\xad\xdd\xdd\x61\x5f\x0a\x7a\x22\x3d\xae\xc0\x73\x2b\xb5\xa2\x18\xb9\x56\xd6\xf0\xdc\x66\xb0\xda\xd8\xef\xd0\xbd\x6c\x45\x06\x6e\x64\x4b\x85\x6c\x8c\xae\x33\x46\x75\xea\x0d\xad\x48\x45\x38\x25\xee\x2c\x54\x35\xbe\x5c\x44\x9b\xf5\x7f\xd7\x8a\xef\x84\x28\x04\xaf\xa4\xda\xb6\x04\xa6\x88\x9f\xcb\xaf\xec\xbf\x00\x00\x00\xff\xff\x5d\x08\xc6\x03\x2f\x04\x00\x00") - -func dirIndexHtmlLicenseBytes() ([]byte, error) { - return bindataRead( - _dirIndexHtmlLicense, - "dir-index-html/LICENSE", - ) -} - -func dirIndexHtmlLicense() (*asset, error) { - bytes, err := dirIndexHtmlLicenseBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "dir-index-html/LICENSE", size: 1071, mode: os.FileMode(384), modTime: time.Unix(1545346300, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _dirIndexHtmlReadmeMd = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x8c\x54\x6d\x4f\x1b\x39\x10\xfe\xbe\xbf\x62\x4e\x11\xba\x8b\x74\xeb\x45\x41\xe8\x5e\x24\x0e\xa1\x20\x04\xba\xd0\xa6\x25\x15\x6a\xa3\x7e\xf0\xda\xb3\x5e\x07\xdb\xb3\xb5\x67\x1b\xf2\xef\x2b\x6f\x08\x02\x44\x69\x3e\x45\x8a\xe7\x79\x99\x79\x66\x76\x04\xda\xc6\xd2\x06\x8d\xf7\x65\xcb\xde\x15\xc5\xf2\xb7\xe5\xd7\x3f\x5a\xe6\x2e\xfd\x5b\x55\xd6\x1b\x91\x5a\x8b\x4e\x27\x61\xa9\xaa\xa5\x36\x58\x79\xa9\xf1\x60\x72\x58\x6f\xca\x79\x24\x26\x45\xee\x60\x72\x38\x93\x75\x2a\x6b\xd7\xa3\x48\xdf\xcd\x69\xe2\x8d\xc3\x93\xc6\x49\x2e\xd3\xb7\x5e\x46\x1c\x6f\x39\x33\x65\x17\x84\xa5\xf1\x1e\x3a\x5d\xa4\x15\x2a\x2e\xaf\xe6\x17\x37\x7b\x52\x37\x03\x7c\x1f\xf2\x26\x22\x06\xd2\x58\x1e\x4c\x8e\x32\x6e\x2f\x81\x35\xd6\xaa\x95\x2c\x76\x60\x11\x90\xab\x53\xd5\xca\x10\xd0\xa5\x93\x07\xaa\x41\x3e\xb1\x0c\x5a\x46\x5d\x46\x94\xda\x23\x28\xf2\x9d\xb3\x32\xf0\x2f\x7c\x3d\xe2\x1e\x80\xe5\xfb\xff\x4b\x93\xe5\xde\xf4\x96\xe9\x8c\xe5\xb6\xaf\x85\x22\x5f\x7d\xb4\xaa\x95\x51\xcf\x2c\x73\xf5\xc2\xc8\xb8\x28\xfe\x83\x73\x1b\x51\x31\xc5\x0d\x38\x9b\xd8\x06\x03\x97\x8b\xeb\x19\x34\x14\xc1\x50\x99\x7b\x00\x23\x19\xd7\x72\x93\x8a\x62\xd1\xda\x04\x11\x3b\x02\x9b\x20\x10\x43\x8d\xd0\x27\xd4\xb0\x65\x76\x14\x50\xc0\x15\xff\x9e\xb6\xff\xd6\x1b\xe0\x16\x77\x78\x50\xa4\x11\x6c\xd8\xf1\x0e\x95\xce\x65\x0e\x8f\xd1\xa0\x06\x1b\x98\x9e\x21\x3a\xa9\xee\xa4\xc1\x3f\x81\x82\xc2\x67\x2f\xad\x4c\x50\x23\x06\xc0\x7b\x8e\x52\x31\x6a\x68\x22\xf9\x47\xee\xa2\xd8\xc5\x9e\xc7\xb1\x05\x89\xdd\x52\xe4\xdf\xea\x83\x6f\xfe\x9e\xac\x3e\x4d\xff\xf9\xd2\xd3\xcd\x62\xfa\xee\xf3\xf1\x71\xbb\xb9\x3f\xba\xf4\xf6\x1c\xf5\xd1\x6d\x68\x2f\xce\x8f\xe7\xd3\xbf\xa6\x8b\x9b\xb9\x9f\x4e\x2a\x25\x3b\xd1\x05\x33\x2e\x8a\xd1\x08\xa6\x14\x38\xda\xba\x67\x2c\x8a\x0b\x44\x07\x79\x0b\x80\x09\x56\x64\x03\xd8\x20\xe0\xcc\x39\x58\xa3\x53\xe4\x51\xc0\x19\x18\x22\x0d\x9d\x93\x6a\xa8\x4a\x2c\x23\xe7\x11\x2e\x73\x4b\x36\xa5\x1e\xd3\xab\xe1\x0d\x46\x9f\x5f\x65\xb5\x2d\x1f\x8b\x27\x69\x24\x3b\x04\xd8\x48\xe7\x12\xf4\x41\x63\x1c\x66\x95\x8f\x05\x96\xd3\x3c\x75\x6a\xb2\x67\xdd\x2b\xfe\xb9\x8e\x22\xef\xfb\x60\x79\x53\xd5\x8e\xea\xca\xcb\xc4\x18\xab\x1c\x5a\x49\x4d\xa9\xb6\x70\xe1\x75\x96\x1e\x8d\x46\x70\x2b\x03\xe7\x6e\x5a\xa9\xee\x80\xc2\x20\x77\xfa\xe2\xa3\xa1\x74\x10\x51\xae\x8d\xe5\x41\x67\x55\x63\x3e\x13\xf5\x38\xbe\x21\xac\xd2\xd8\x66\x27\x67\xbd\x79\xf2\x2c\x8c\x6d\x5e\x5f\xeb\x37\x1d\x3f\xc0\x6d\x30\xd9\xee\x90\xd8\xcc\x2a\x0c\x09\x8b\xe2\xfa\x6a\xf1\x23\x00\x00\xff\xff\x27\xdb\x5d\x6a\xe9\x04\x00\x00") - -func dirIndexHtmlReadmeMdBytes() ([]byte, error) { - return bindataRead( - _dirIndexHtmlReadmeMd, - "dir-index-html/README.md", - ) -} - -func dirIndexHtmlReadmeMd() (*asset, error) { - bytes, err := dirIndexHtmlReadmeMdBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "dir-index-html/README.md", size: 1257, mode: os.FileMode(384), modTime: time.Unix(1545346300, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _dirIndexHtmlDirIndexUncatHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb4\x55\x4d\x6f\xe3\x36\x10\xbd\xfb\x57\xcc\x2a\x40\x6f\x12\x9d\x2c\xba\x6d\x1c\xd9\x05\xf2\xd1\x6e\x0b\x77\x93\x36\x01\xba\xe9\xa5\xa0\xc4\xb1\xc8\x9a\x22\x05\x72\x1c\x3b\x15\xfc\xdf\x0b\x52\xf2\xd7\xc6\xc1\xe6\xb2\x17\x89\x1e\xbe\x99\x79\xef\x69\x06\xce\xdf\x5d\xdf\x5e\x3d\x3c\xde\xdd\x80\xa4\x5a\x4f\x06\xf9\xe6\x85\x5c\x4c\x06\x00\x79\x8d\xc4\xa1\x94\xdc\x79\xa4\x71\xb2\xa0\x59\xfa\x63\x02\x2c\x5e\xbd\x4b\x53\x78\xb8\xbd\xbe\x1d\x81\x47\x14\x40\x12\x3d\x42\x0a\x35\x7f\x2e\x10\xb4\x9a\x63\x08\x81\x27\xee\x08\x1d\xe0\x0a\xac\x8b\x91\x25\x16\x0b\xf5\x13\xa4\x69\xac\xa2\x95\x99\x83\x43\x3d\x4e\x3c\x3d\x6b\xf4\x12\x91\x12\x90\x0e\x67\xe3\x84\xa9\x66\xe6\xd9\x1f\xf5\xe7\xcb\x1f\xee\xa6\x7f\xfe\xf5\xf1\x43\x71\xa5\x96\xee\x17\x79\xf6\xbb\xbb\xbc\xfc\xf7\xd3\x7c\xfa\xf4\xbe\x7e\x7c\xff\x9b\x78\xfc\x7c\xa5\xe6\x8f\x7f\xdf\x2f\xa7\x37\xd7\xac\xb0\x96\x3c\x39\xde\x64\xb5\x32\x59\xe9\x7d\xb2\xa3\x2b\x51\x37\xe8\x80\x2c\x94\xd6\x78\x72\x8b\x92\x80\xa4\xf2\xa0\x3c\x48\x74\x38\x02\x49\xd4\xf8\x11\x63\x95\x22\xb9\x28\xb2\xd2\xd6\xac\x74\xcf\x0d\xa9\x15\xc3\x55\xc3\x0a\x6d\x0b\x56\x73\x4f\xe8\x98\xaa\x2b\xf4\x0f\xf6\xea\xfe\xfe\x9a\x13\x67\xa5\x35\x4f\xe8\x28\xab\xec\x37\x93\xa6\x02\xeb\x28\x29\xd6\x8f\x55\xc3\x29\x33\xdc\x39\xbb\x84\x76\xa9\x04\xc9\x11\x0c\x9b\xd5\xc5\x3a\xc4\x1b\x2e\x84\x32\x15\xb4\x50\x73\x57\x29\x33\x82\xd3\xe1\xe6\xf2\x24\x7c\x63\x74\xd0\x0e\x00\x00\x0a\x5e\xce\x2b\x67\x17\x46\x8c\xe0\x64\x38\x1c\x5e\x0c\x00\x22\x4a\xdb\xca\xf6\x18\x89\xaa\x92\x34\x82\xb3\xef\x9b\xd5\x45\x8c\xec\xaa\x76\x91\xd8\x34\x28\x4b\x03\xd5\x3e\xad\x23\x75\xfa\xe1\x4b\x88\xe4\x5e\xf6\x90\xd2\x6a\xeb\x46\x70\x72\x7e\x7e\xbe\xc1\xe4\x6c\x2b\x2f\x27\x45\x1a\x27\x6d\x0b\xd9\x1d\x27\x09\xeb\x75\xce\xba\xd0\x20\x67\xdd\xa4\xe6\x85\x15\xcf\x11\x2b\xd4\x13\x28\x31\x4e\x3a\x75\x09\x94\x9a\x7b\x3f\x4e\x9c\x5d\x46\xd3\x7a\x44\x1f\x2d\xad\x4e\x57\x3e\x3d\xeb\xaf\xf6\xd2\x83\xec\x6d\x72\xa4\x1b\x23\x93\xef\x4c\xe1\x9b\x8b\x9c\x09\xf5\xd4\x97\xdb\x1c\x77\x87\xc2\xb1\x2d\x95\xc3\x46\xa7\x67\x47\x48\x34\xdc\xa0\x86\xf8\x4c\x05\xce\xf8\x42\xd3\x21\x9f\x7d\x5c\x1a\x74\x29\x53\x6d\x11\x71\x0e\x9c\x35\xd5\xe4\x57\x23\xc2\x92\xcd\xe0\xc0\xa8\xfe\x72\x8b\x6e\x5b\x50\x33\xc8\x3e\x06\xf3\xd7\xeb\x5d\x91\xbd\x46\xdb\xaf\xb3\xd7\x24\x26\xbe\xcc\xda\xf9\xd0\x43\xd0\x88\x1d\xe0\xe0\x3a\x27\x5e\x68\xdc\xf4\xe8\x7e\xc4\x67\xea\xc9\xa9\x06\xc5\xbe\x24\x72\xfb\xad\x73\x12\x9b\xbc\x6e\xd2\x0f\x88\x1d\x21\x1f\xa7\x2f\x9e\xfe\x29\x34\x37\xf3\x23\xdf\x6d\xc3\x90\xc4\x2b\x9d\xfa\xdd\xf9\xb2\x15\xef\x17\xb8\x6d\xb3\x4b\x5e\xce\xa7\xca\xcc\xd7\xeb\x64\x92\x65\x39\xe3\x5f\xa9\x3c\x39\x8c\xe5\x6c\x5f\x65\xdb\x82\xe3\xa6\x42\xc8\xa6\xca\x53\x58\xda\x7d\x9f\x5f\xf8\xf1\x16\x03\xda\x36\xbc\x7e\x76\xb6\xbe\x59\x11\x64\x9f\x78\x8d\x81\xea\xdb\xad\x78\x55\xfa\x76\xbe\x92\xb8\x95\xa1\x72\x1c\xb6\xaf\x3a\x10\xd0\xf7\xea\xbf\x0e\xfd\x9a\x19\x2f\xc7\x28\xce\xc9\xf1\x7d\xcb\x59\xb7\xfa\x39\xeb\xfe\xba\xfe\x0f\x00\x00\xff\xff\xdb\x20\xe5\x87\xd2\x06\x00\x00") - -func dirIndexHtmlDirIndexUncatHtmlBytes() ([]byte, error) { - return bindataRead( - _dirIndexHtmlDirIndexUncatHtml, - "dir-index-html/dir-index-uncat.html", - ) -} - -func dirIndexHtmlDirIndexUncatHtml() (*asset, error) { - bytes, err := dirIndexHtmlDirIndexUncatHtmlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "dir-index-html/dir-index-uncat.html", size: 1746, mode: os.FileMode(384), modTime: time.Unix(1545346300, 0)} + info := bindataFileInfo{name: "init-doc/security-notes", size: 1162, mode: os.FileMode(384), modTime: time.Unix(1555022883, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -296,27 +240,7 @@ func dirIndexHtmlDirIndexHtml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "dir-index-html/dir-index.html", size: 106086, mode: os.FileMode(384), modTime: time.Unix(1545346300, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _dirIndexHtmlIndexGo = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x2a\x48\x4c\xce\x4e\x4c\x4f\x55\x48\xc9\x2c\xca\xcc\x4b\x49\xad\xc8\x28\xc9\xcd\xe1\x02\x04\x00\x00\xff\xff\x70\x1d\x35\x57\x15\x00\x00\x00") - -func dirIndexHtmlIndexGoBytes() ([]byte, error) { - return bindataRead( - _dirIndexHtmlIndexGo, - "dir-index-html/index.go", - ) -} - -func dirIndexHtmlIndexGo() (*asset, error) { - bytes, err := dirIndexHtmlIndexGoBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "dir-index-html/index.go", size: 21, mode: os.FileMode(384), modTime: time.Unix(1545346300, 0)} + info := bindataFileInfo{name: "dir-index-html/dir-index.html", size: 106086, mode: os.FileMode(384), modTime: time.Unix(1559787449, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -336,27 +260,7 @@ func dirIndexHtmlKnowniconsTxt() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "dir-index-html/knownIcons.txt", size: 311, mode: os.FileMode(384), modTime: time.Unix(1545346300, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _dirIndexHtmlPackageJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x84\x8f\x4d\x4b\xf3\x40\x14\x85\xf7\xf9\x15\x97\xcb\xbb\x6c\x26\xed\x4b\xdd\x64\xab\x2e\xba\x50\x41\xa5\x1b\xeb\x62\x92\x5c\x67\x2e\xcc\x47\x98\x8f\x12\x90\xfe\x77\x99\x24\x50\x05\xc1\xed\xc3\x3d\xcf\x3d\xe7\xb3\x02\x40\x99\x93\xf6\x01\x5b\x40\xa3\x98\x42\xd2\xb8\x29\xb8\xcb\x2a\x62\x0b\xe5\x04\x00\x73\x30\xe5\x42\xa7\x34\xc6\xb6\x69\x14\x27\x9d\x3b\xd1\x7b\xdb\xf0\xf8\x11\x9b\x81\x43\xcd\x6e\xa0\xa9\xd6\xc9\x1a\xac\x00\x2e\xb3\x44\x4d\x57\xc5\x70\xee\x23\xdb\xd1\x87\x54\x4c\x7f\x18\x36\x4b\x46\xf9\x33\x85\xc8\xde\x95\xc8\x4e\xdc\x88\xff\xdf\xdd\x77\x34\x92\x1b\xc8\xf5\x4c\xa5\xea\xdb\xfb\xca\x8f\xd7\xcc\x56\xec\xf6\x62\xbb\x2c\x32\xd2\xa9\x2c\x15\xcd\xef\xfd\xca\xb8\x27\x17\x67\xf4\x70\x78\x5d\x98\x93\x76\x06\xbf\x54\xc2\x40\x86\x64\xa4\x5b\x3b\xac\x23\xa0\xf7\xd6\x72\x82\x5a\x42\x6d\xe1\x84\x6a\x82\x31\x77\x86\xa3\x86\x7f\xc7\xfb\xe7\x97\xc3\xd3\xe3\x09\x97\xec\x8f\x29\x5b\xb1\xc7\xea\x52\x55\x5f\x01\x00\x00\xff\xff\x95\xbf\xad\xd5\x83\x01\x00\x00") - -func dirIndexHtmlPackageJsonBytes() ([]byte, error) { - return bindataRead( - _dirIndexHtmlPackageJson, - "dir-index-html/package.json", - ) -} - -func dirIndexHtmlPackageJson() (*asset, error) { - bytes, err := dirIndexHtmlPackageJsonBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "dir-index-html/package.json", size: 387, mode: os.FileMode(384), modTime: time.Unix(1545346300, 0)} + info := bindataFileInfo{name: "dir-index-html/knownIcons.txt", size: 311, mode: os.FileMode(384), modTime: time.Unix(1559787449, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -413,20 +317,15 @@ func AssetNames() []string { // _bindata is a table, holding each asset generator, mapped to its name. var _bindata = map[string]func() (*asset, error){ - "init-doc/about": initDocAbout, - "init-doc/contact": initDocContact, - "init-doc/help": initDocHelp, - "init-doc/ping": initDocPing, - "init-doc/quick-start": initDocQuickStart, - "init-doc/readme": initDocReadme, - "init-doc/security-notes": initDocSecurityNotes, - "dir-index-html/LICENSE": dirIndexHtmlLicense, - "dir-index-html/README.md": dirIndexHtmlReadmeMd, - "dir-index-html/dir-index-uncat.html": dirIndexHtmlDirIndexUncatHtml, - "dir-index-html/dir-index.html": dirIndexHtmlDirIndexHtml, - "dir-index-html/index.go": dirIndexHtmlIndexGo, - "dir-index-html/knownIcons.txt": dirIndexHtmlKnowniconsTxt, - "dir-index-html/package.json": dirIndexHtmlPackageJson, + "init-doc/about": initDocAbout, + "init-doc/contact": initDocContact, + "init-doc/help": initDocHelp, + "init-doc/ping": initDocPing, + "init-doc/quick-start": initDocQuickStart, + "init-doc/readme": initDocReadme, + "init-doc/security-notes": initDocSecurityNotes, + "dir-index-html/dir-index.html": dirIndexHtmlDirIndexHtml, + "dir-index-html/knownIcons.txt": dirIndexHtmlKnowniconsTxt, } // AssetDir returns the file names below a certain @@ -471,13 +370,8 @@ type bintree struct { var _bintree = &bintree{nil, map[string]*bintree{ "dir-index-html": &bintree{nil, map[string]*bintree{ - "LICENSE": &bintree{dirIndexHtmlLicense, map[string]*bintree{}}, - "README.md": &bintree{dirIndexHtmlReadmeMd, map[string]*bintree{}}, - "dir-index-uncat.html": &bintree{dirIndexHtmlDirIndexUncatHtml, map[string]*bintree{}}, - "dir-index.html": &bintree{dirIndexHtmlDirIndexHtml, map[string]*bintree{}}, - "index.go": &bintree{dirIndexHtmlIndexGo, map[string]*bintree{}}, - "knownIcons.txt": &bintree{dirIndexHtmlKnowniconsTxt, map[string]*bintree{}}, - "package.json": &bintree{dirIndexHtmlPackageJson, map[string]*bintree{}}, + "dir-index.html": &bintree{dirIndexHtmlDirIndexHtml, map[string]*bintree{}}, + "knownIcons.txt": &bintree{dirIndexHtmlKnowniconsTxt, map[string]*bintree{}}, }}, "init-doc": &bintree{nil, map[string]*bintree{ "about": &bintree{initDocAbout, map[string]*bintree{}}, diff --git a/assets/bindata_dep.go b/assets/bindata_dep.go new file mode 100644 index 00000000000..496f6ad0699 --- /dev/null +++ b/assets/bindata_dep.go @@ -0,0 +1,9 @@ +//+build never,!never + +package assets + +import ( + // Make sure go mod tracks these deps but avoid including them in the + // actual build. + _ "github.com/go-bindata/go-bindata" +) diff --git a/assets/dir-index-html b/assets/dir-index-html new file mode 160000 index 00000000000..a2330df8401 --- /dev/null +++ b/assets/dir-index-html @@ -0,0 +1 @@ +Subproject commit a2330df84015a301d77df89af4cb49f2817f2063 diff --git a/go.mod b/go.mod index 9ed7365d57e..c4ad8439e5a 100644 --- a/go.mod +++ b/go.mod @@ -11,12 +11,12 @@ require ( github.com/elgris/jsondiff v0.0.0-20160530203242-765b5c24c302 github.com/fatih/color v1.7.0 // indirect github.com/fsnotify/fsnotify v1.4.7 + github.com/go-bindata/go-bindata v3.1.1+incompatible github.com/go-critic/go-critic v0.0.0-20181204210945-ee9bf5809ead // indirect github.com/gogo/protobuf v1.2.1 github.com/golangci/golangci-lint v1.16.1-0.20190425135923-692dacb773b7 github.com/hashicorp/go-multierror v1.0.0 github.com/hashicorp/golang-lru v0.5.1 - github.com/ipfs/dir-index-html v1.0.3 github.com/ipfs/go-bitswap v0.1.1 github.com/ipfs/go-block-format v0.0.2 github.com/ipfs/go-blockservice v0.1.0 diff --git a/go.sum b/go.sum index 7238391ffdc..f65fd6f37ae 100644 --- a/go.sum +++ b/go.sum @@ -74,6 +74,8 @@ github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv github.com/fd/go-nat v1.0.0/go.mod h1:BTBu/CKvMmOMUPkKVef1pngt2WFH/lg7E6yQnulfp6E= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/go-bindata/go-bindata v3.1.1+incompatible h1:tR4f0e4VTO7LK6B2YWyAoVEzG9ByG1wrXB4TL9+jiYg= +github.com/go-bindata/go-bindata v3.1.1+incompatible/go.mod h1:xK8Dsgwmeed+BBsSy2XTopBn/8uK2HWuGSnA11C3Joo= github.com/go-check/check v0.0.0-20180628173108-788fd7840127 h1:0gkP6mzaMqkmpcJYCFOLkIBwI7xFExG03bbkOkCvUPI= github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= github.com/go-critic/go-critic v0.0.0-20181204210945-c3db6069acc5/go.mod h1:Jc75BZJv2dNy7opKH6bF29VveDQHfGZ6Asn/3phBesg= @@ -185,8 +187,6 @@ github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NH github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/ipfs/bbloom v0.0.1 h1:s7KkiBPfxCeDVo47KySjK0ACPc5GJRUxFpdyWEuDjhw= github.com/ipfs/bbloom v0.0.1/go.mod h1:oqo8CVWsJFMOZqTglBG4wydCE4IQA/G2/SEofB0rjUI= -github.com/ipfs/dir-index-html v1.0.3 h1:cKdOjJBKJgewgcv97zOlqsNOle52N91d3nAkbQadnuY= -github.com/ipfs/dir-index-html v1.0.3/go.mod h1:TG9zbaH/+4MnkGel0xF4SLNhk+YZvBNo6jjBkO/LaWc= github.com/ipfs/go-bitswap v0.0.3/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 h1:28YsHYw9ut6wootnImPXH0WpnU5Dbo3qm6cvQ6e6wYY= From f9e9f2854b98eb8397360372b997690a79e5b60d Mon Sep 17 00:00:00 2001 From: Devin Date: Wed, 5 Jun 2019 22:14:34 +0800 Subject: [PATCH 046/671] Fix a typo --- go.mod | 2 +- go.sum | 4 ++-- test/sharness/t0062-daemon-api.sh | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 9ed7365d57e..f46115d3ec4 100644 --- a/go.mod +++ b/go.mod @@ -32,7 +32,7 @@ require ( github.com/ipfs/go-ipfs-blockstore v0.0.1 github.com/ipfs/go-ipfs-blocksutil v0.0.1 github.com/ipfs/go-ipfs-chunker v0.0.1 - github.com/ipfs/go-ipfs-cmds v0.0.8 + github.com/ipfs/go-ipfs-cmds v0.0.10 github.com/ipfs/go-ipfs-config v0.0.6 github.com/ipfs/go-ipfs-ds-help v0.0.1 github.com/ipfs/go-ipfs-exchange-interface v0.0.1 diff --git a/go.sum b/go.sum index 7238391ffdc..d6886fd946f 100644 --- a/go.sum +++ b/go.sum @@ -230,8 +230,8 @@ github.com/ipfs/go-ipfs-blocksutil v0.0.1 h1:Eh/H4pc1hsvhzsQoMEP3Bke/aW5P5rVM1IW github.com/ipfs/go-ipfs-blocksutil v0.0.1/go.mod h1:Yq4M86uIOmxmGPUHv/uI7uKqZNtLb449gwKqXjIsnRk= github.com/ipfs/go-ipfs-chunker v0.0.1 h1:cHUUxKFQ99pozdahi+uSC/3Y6HeRpi9oTeUHbE27SEw= github.com/ipfs/go-ipfs-chunker v0.0.1/go.mod h1:tWewYK0we3+rMbOh7pPFGDyypCtvGcBFymgY4rSDLAw= -github.com/ipfs/go-ipfs-cmds v0.0.8 h1:ZMo0ZeQOr10ZKY4yxYA3lRHUbnF/ZYcV9cpU0IrlGFI= -github.com/ipfs/go-ipfs-cmds v0.0.8/go.mod h1:TiK4e7/V31tuEb8YWDF8lN3qrnDH+BS7ZqWIeYJlAs8= +github.com/ipfs/go-ipfs-cmds v0.0.10 h1:4kA3E94HbDrLb4RZTkX3yXyUjKv50RfPz0Pv9xkP2cA= +github.com/ipfs/go-ipfs-cmds v0.0.10/go.mod h1:TiK4e7/V31tuEb8YWDF8lN3qrnDH+BS7ZqWIeYJlAs8= github.com/ipfs/go-ipfs-config v0.0.5 h1:D9ek19anOzm8iYPvezeeamSg5mzwqKPb2jyAyJZT/4A= github.com/ipfs/go-ipfs-config v0.0.5/go.mod h1:IGkVTacurWv9WFKc7IBPjHGM/7hi6+PEClqUb/l2BIM= github.com/ipfs/go-ipfs-config v0.0.6 h1:jzK9Tl8S0oWBir3F5ObtGgnHRPdqQ0MYiCmwXtV3Ps4= diff --git a/test/sharness/t0062-daemon-api.sh b/test/sharness/t0062-daemon-api.sh index b4c7eccdb51..3efff74a1d6 100755 --- a/test/sharness/t0062-daemon-api.sh +++ b/test/sharness/t0062-daemon-api.sh @@ -32,7 +32,7 @@ test_client_must_fail() { opts="$@" echo "OPTS = " $opts test_expect_success "client should fail $state" ' - echo "Error: cannot connect to the api. Is the deamon running? To run as a standalone CLI command remove the api file in \`\$IPFS_PATH/api\`" >expected_err && + echo "Error: cannot connect to the api. Is the daemon running? To run as a standalone CLI command remove the api file in \`\$IPFS_PATH/api\`" >expected_err && test_must_fail ipfs id -f="" $opts >actual 2>actual_err && test_cmp expected_err actual_err ' From c444b1b94545888361998e39277d49228ce0c55d Mon Sep 17 00:00:00 2001 From: Simon Menke Date: Wed, 12 Jun 2019 11:55:03 +0200 Subject: [PATCH 047/671] Close started plugins when one of them fails to start. --- plugin/loader/loader.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/loader/loader.go b/plugin/loader/loader.go index b5a2d08edf9..f2a9ab60c4e 100644 --- a/plugin/loader/loader.go +++ b/plugin/loader/loader.go @@ -115,7 +115,7 @@ func (loader *PluginLoader) Start(iface coreiface.CoreAPI) error { if pl, ok := pl.(plugin.PluginDaemon); ok { err := pl.Start(iface) if err != nil { - _ = closePlugins(loader.plugins[i:]) + _ = closePlugins(loader.plugins[:i]) return err } } From 42dc64d0bfc2af7a85d2d2dee44ee61ae82c8ee6 Mon Sep 17 00:00:00 2001 From: Simon Menke Date: Wed, 12 Jun 2019 12:05:31 +0200 Subject: [PATCH 048/671] Load plugins on darwin/macOS --- plugin/loader/{load_linux.go => load_unix.go} | 1 + 1 file changed, 1 insertion(+) rename plugin/loader/{load_linux.go => load_unix.go} (97%) diff --git a/plugin/loader/load_linux.go b/plugin/loader/load_unix.go similarity index 97% rename from plugin/loader/load_linux.go rename to plugin/loader/load_unix.go index 19c1e994bbd..182b8174609 100644 --- a/plugin/loader/load_linux.go +++ b/plugin/loader/load_unix.go @@ -1,4 +1,5 @@ // +build !noplugin +// +build linux,cgo darwin,cgo package loader From 0f4a75f0eda4d412cbd251674c1796d19698716c Mon Sep 17 00:00:00 2001 From: Dominic Della Valle Date: Wed, 12 Jun 2019 10:17:53 -0400 Subject: [PATCH 049/671] doc: add another Windows package to README Add scoop package for scoop users --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index 6ffcd66b7df..65ed3c78382 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,7 @@ $ sudo snap install ipfs ### From Windows package managers - [Chocolatey](#chocolatey) +- [Scoop](#scoop) #### Chocolatey @@ -126,6 +127,14 @@ The package [ipfs](https://chocolatey.org/packages/ipfs) currently points to go- PS> choco install ipfs ``` +#### Scoop + +Scoop provides `go-ipfs` in its 'extras' bucket. +```Powershell +PS> scoop add bucket extras +PS> scoop install go-ipfs +``` + ### Build from Source #### Install Go From bc02a61e7c015e41d15a1533b37090de466274d1 Mon Sep 17 00:00:00 2001 From: Dirk McCormick Date: Wed, 12 Jun 2019 10:23:54 -0400 Subject: [PATCH 050/671] fix: flush pin on block put --- core/commands/block.go | 6 +++--- core/coreapi/block.go | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/core/commands/block.go b/core/commands/block.go index 30887f13998..3709269b787 100644 --- a/core/commands/block.go +++ b/core/commands/block.go @@ -123,10 +123,10 @@ var blockPutCmd = &cmds.Command{ Tagline: "Store input as an IPFS block.", ShortDescription: ` 'ipfs block put' is a plumbing command for storing raw IPFS blocks. -It reads from stdin, and is a base58 encoded multihash. +It reads from stdin, and outputs a multihash to stdout. -By default CIDv0 is going to be generated. Setting 'mhtype' to anything other -than 'sha2-256' or format to anything other than 'v0' will result in CIDv1. +By default the multihash is output in CIDv0 format. Setting 'mhtype' to anything +other than 'sha2-256' or format to anything other than 'v0' will result in CIDv1. `, }, diff --git a/core/coreapi/block.go b/core/coreapi/block.go index 79b89ed02fb..2a371b904f0 100644 --- a/core/coreapi/block.go +++ b/core/coreapi/block.go @@ -56,6 +56,9 @@ func (api *BlockAPI) Put(ctx context.Context, src io.Reader, opts ...caopts.Bloc if settings.Pin { api.pinning.PinWithMode(b.Cid(), pin.Recursive) + if err := api.pinning.Flush(); err != nil { + return nil, err + } } return &BlockStat{path: path.IpldPath(b.Cid()), size: len(data)}, nil From 4b6175f75cb3910716697dc7b473c3b786b16754 Mon Sep 17 00:00:00 2001 From: Dirk McCormick Date: Wed, 12 Jun 2019 12:44:01 -0400 Subject: [PATCH 051/671] fix: block put helptext --- core/commands/block.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/commands/block.go b/core/commands/block.go index 3709269b787..a06bfe0683e 100644 --- a/core/commands/block.go +++ b/core/commands/block.go @@ -123,9 +123,9 @@ var blockPutCmd = &cmds.Command{ Tagline: "Store input as an IPFS block.", ShortDescription: ` 'ipfs block put' is a plumbing command for storing raw IPFS blocks. -It reads from stdin, and outputs a multihash to stdout. +It reads from stdin, and outputs the block's CID to stdout. -By default the multihash is output in CIDv0 format. Setting 'mhtype' to anything +Unless specified, this command returns dag-pb CIDv0 CIDs. Setting 'mhtype' to anything other than 'sha2-256' or format to anything other than 'v0' will result in CIDv1. `, }, From 4ead108a8045010adee4d982cbcb0641b99ef563 Mon Sep 17 00:00:00 2001 From: Dirk McCormick Date: Wed, 12 Jun 2019 14:59:06 -0400 Subject: [PATCH 052/671] fix: ensure pin rm takes a lock --- core/coreapi/pin.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/coreapi/pin.go b/core/coreapi/pin.go index bd2663f0304..b8c84da5292 100644 --- a/core/coreapi/pin.go +++ b/core/coreapi/pin.go @@ -67,6 +67,10 @@ func (api *PinAPI) Rm(ctx context.Context, p path.Path, opts ...caopts.PinRmOpti return err } + // Note: after unpin the pin sets are flushed to the blockstore, so we need + // to take a lock to prevent a concurrent garbage collection + defer api.blockstore.PinLock().Unlock() + if err = api.pinning.Unpin(ctx, rp.Cid(), settings.Recursive); err != nil { return err } From 0cd712a85fe82ee74aa84b0c06b570e2014039c9 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 12 Jun 2019 16:36:38 -0700 Subject: [PATCH 053/671] dep: update go-bitswap fixes #6442 --- go.mod | 10 +++++----- go.sum | 22 ++++++++++++++++++++-- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index 21527a3af00..58f71da8150 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/golangci/golangci-lint v1.16.1-0.20190425135923-692dacb773b7 github.com/hashicorp/go-multierror v1.0.0 github.com/hashicorp/golang-lru v0.5.1 - github.com/ipfs/go-bitswap v0.1.1 + github.com/ipfs/go-bitswap v0.1.3 github.com/ipfs/go-block-format v0.0.2 github.com/ipfs/go-blockservice v0.1.0 github.com/ipfs/go-cid v0.0.2 @@ -62,7 +62,7 @@ require ( github.com/jbenet/go-random-files v0.0.0-20190219210431-31b3f20ebded github.com/jbenet/go-temp-err-catcher v0.0.0-20150120210811-aac704a3f4f2 github.com/jbenet/goprocess v0.1.3 - github.com/libp2p/go-libp2p v0.1.0 + github.com/libp2p/go-libp2p v0.1.1 github.com/libp2p/go-libp2p-autonat-svc v0.1.0 github.com/libp2p/go-libp2p-circuit v0.1.0 github.com/libp2p/go-libp2p-connmgr v0.1.0 @@ -81,9 +81,9 @@ require ( github.com/libp2p/go-libp2p-routing-helpers v0.1.0 github.com/libp2p/go-libp2p-secio v0.1.0 github.com/libp2p/go-libp2p-swarm v0.1.0 - github.com/libp2p/go-libp2p-testing v0.0.3 + github.com/libp2p/go-libp2p-testing v0.0.4 github.com/libp2p/go-libp2p-tls v0.1.0 - github.com/libp2p/go-libp2p-yamux v0.2.0 + github.com/libp2p/go-libp2p-yamux v0.2.1 github.com/libp2p/go-maddr-filter v0.0.4 github.com/mattn/go-runewidth v0.0.4 // indirect github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect @@ -109,7 +109,7 @@ require ( go.uber.org/goleak v0.10.0 // indirect go.uber.org/multierr v1.1.0 // indirect go4.org v0.0.0-20190313082347-94abd6928b1d // indirect - golang.org/x/sys v0.0.0-20190526052359-791d8a0f4d09 + golang.org/x/sys v0.0.0-20190610200419-93c9922d18ae gopkg.in/cheggaaa/pb.v1 v1.0.28 gotest.tools/gotestsum v0.3.4 ) diff --git a/go.sum b/go.sum index 4b977a561c3..202cae75128 100644 --- a/go.sum +++ b/go.sum @@ -30,6 +30,8 @@ github.com/bren2010/proquint v0.0.0-20160323162903-38337c27106d/go.mod h1:Jbj8eK github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c h1:aEbSeNALREWXk0G7UdNhR3ayBV7tZ4M2PNmnrCAph6Q= github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= +github.com/btcsuite/btcd v0.0.0-20190605094302-a0d1e3e36d50 h1:4i3KsuVA0o0KoBxAC5x+MY7RbteiMK1V7gf/G08NGIQ= +github.com/btcsuite/btcd v0.0.0-20190605094302-a0d1e3e36d50/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= @@ -191,8 +193,8 @@ github.com/ipfs/go-bitswap v0.0.3/go.mod h1:jadAZYsP/tcRMl47ZhFxhaNuDQoXawT8iHMg github.com/ipfs/go-bitswap v0.0.9/go.mod h1:kAPf5qgn2W2DrgAcscZ3HrM9qh4pH+X8Fkk3UPrwvis= github.com/ipfs/go-bitswap v0.1.0 h1:28YsHYw9ut6wootnImPXH0WpnU5Dbo3qm6cvQ6e6wYY= github.com/ipfs/go-bitswap v0.1.0/go.mod h1:FFJEf18E9izuCqUtHxbWEvq+reg7o4CW5wSAE1wsxj0= -github.com/ipfs/go-bitswap v0.1.1 h1:5cNAqH8I7pRmgCIrEaPErWewxbUnLru2BCliegnN/5w= -github.com/ipfs/go-bitswap v0.1.1/go.mod h1:Eb5r34ftg4R38fGnQDlojCLZwZyr+WDsvBH5uLUQsjg= +github.com/ipfs/go-bitswap v0.1.3 h1:jAl9Z/TYObpGeGATUemnOZ7RYb0F/kzNVlhcYZesz+0= +github.com/ipfs/go-bitswap v0.1.3/go.mod h1:YEQlFy0kkxops5Vy+OxWdRSEZIoS7I7KDIwoa5Chkps= github.com/ipfs/go-block-format v0.0.1/go.mod h1:DK/YYcsSUIVAFNwo/KZCdIIbpN0ROH/baNLgayt4pFc= github.com/ipfs/go-block-format v0.0.2 h1:qPDvcP19izTjU8rgo6p7gTXZlkMkF5bz5G3fqIsSCPE= github.com/ipfs/go-block-format v0.0.2/go.mod h1:AWR46JfpcObNfg3ok2JHDUfdiHRgWhJgCQF+KIgOPJY= @@ -287,6 +289,8 @@ github.com/ipfs/go-path v0.0.7/go.mod h1:6KTKmeRnBXgqrTvzFrPV3CamxcgvXX/4z79tfAd github.com/ipfs/go-peertaskqueue v0.0.4/go.mod h1:03H8fhyeMfKNFWqzYEVyMbcPUeYrqP1MX6Kd+aN+rMQ= github.com/ipfs/go-peertaskqueue v0.1.0 h1:bpRbgv76eT4avutNPDFZuCPOQus6qTgurEYxfulgZW4= github.com/ipfs/go-peertaskqueue v0.1.0/go.mod h1:Jmk3IyCcfl1W3jTW3YpghSwSEC6IJ3Vzz/jUmWw8Z0U= +github.com/ipfs/go-peertaskqueue v0.1.1 h1:+gPjbI+V3NktXZOqJA1kzbms2pYmhjgQQal0MzZrOAY= +github.com/ipfs/go-peertaskqueue v0.1.1/go.mod h1:Jmk3IyCcfl1W3jTW3YpghSwSEC6IJ3Vzz/jUmWw8Z0U= github.com/ipfs/go-todocounter v0.0.1 h1:kITWA5ZcQZfrUnDNkRn04Xzh0YFaDFXsoO2A81Eb6Lw= github.com/ipfs/go-todocounter v0.0.1/go.mod h1:l5aErvQc8qKE2r7NDMjmq5UNAvuZy0rC8BHOplkWvZ4= github.com/ipfs/go-unixfs v0.0.4/go.mod h1:eIo/p9ADu/MFOuyxzwU+Th8D6xoxU//r590vUpWyfz8= @@ -359,6 +363,8 @@ github.com/libp2p/go-libp2p v0.0.2/go.mod h1:Qu8bWqFXiocPloabFGUcVG4kk94fLvfC8mW github.com/libp2p/go-libp2p v0.0.30/go.mod h1:XWT8FGHlhptAv1+3V/+J5mEpzyui/5bvFsNuWYs611A= github.com/libp2p/go-libp2p v0.1.0 h1:8VXadcPNni74ODoZ+7326LMAppFYmz1fRQOUuT5iZvQ= github.com/libp2p/go-libp2p v0.1.0/go.mod h1:6D/2OBauqLUoqcADOJpn9WbKqvaM07tDw68qHM0BxUM= +github.com/libp2p/go-libp2p v0.1.1 h1:52sB0TJuDk2nYMcMfHOKaPoaayDZjaYVCq6Vk1ejUTk= +github.com/libp2p/go-libp2p v0.1.1/go.mod h1:I00BRo1UuUSdpuc8Q2mN7yDF/oTUTRAX6JWpTiK9Rp8= 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 h1:aCWAu43Ri4nU0ZPO7NyLzUvvfqd0nE3dX0R/ZGYVgOU= @@ -460,6 +466,8 @@ github.com/libp2p/go-libp2p-testing v0.0.1/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MB github.com/libp2p/go-libp2p-testing v0.0.2/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= github.com/libp2p/go-libp2p-testing v0.0.3 h1:bdij4bKaaND7tCsaXVjRfYkMpvoOeKj9AVQGJllA6jM= github.com/libp2p/go-libp2p-testing v0.0.3/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= +github.com/libp2p/go-libp2p-testing v0.0.4 h1:Qev57UR47GcLPXWjrunv5aLIQGO4n9mhI/8/EIrEEFc= +github.com/libp2p/go-libp2p-testing v0.0.4/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= github.com/libp2p/go-libp2p-tls v0.1.0 h1:o4bjjAdnUjNgJoPoDd0wUaZH7K+EenlNWJpgyXB3ulA= github.com/libp2p/go-libp2p-tls v0.1.0/go.mod h1:VZdoSWQDeNpIIAFJFv+6uqTqpnIIDHcqZQSTC/A1TT0= github.com/libp2p/go-libp2p-transport v0.0.1/go.mod h1:UzbUs9X+PHOSw7S3ZmeOxfnwaQY5vGDzZmKPod3N3tk= @@ -473,6 +481,8 @@ github.com/libp2p/go-libp2p-yamux v0.1.2/go.mod h1:xUoV/RmYkg6BW/qGxA9XJyg+HzXFY github.com/libp2p/go-libp2p-yamux v0.1.3/go.mod h1:VGSQVrqkh6y4nm0189qqxMtvyBft44MOYYPpYKXiVt4= github.com/libp2p/go-libp2p-yamux v0.2.0 h1:TSPZ5cMMz/wdoYsye/wU1TE4G3LDGMoeEN0xgnCKU/I= github.com/libp2p/go-libp2p-yamux v0.2.0/go.mod h1:Db2gU+XfLpm6E4rG5uGCFX6uXA8MEXOxFcRoXUODaK8= +github.com/libp2p/go-libp2p-yamux v0.2.1 h1:Q3XYNiKCC2vIxrvUJL+Jg1kiyeEaIDNKLjgEjo3VQdI= +github.com/libp2p/go-libp2p-yamux v0.2.1/go.mod h1:1FBXiHDk1VyRM1C0aez2bCfHQ4vMZKkAQzZbkSQt5fI= github.com/libp2p/go-maddr-filter v0.0.1/go.mod h1:6eT12kSQMA9x2pvFQa+xesMKUBlj9VImZbj3B9FBH/Q= github.com/libp2p/go-maddr-filter v0.0.4 h1:hx8HIuuwk34KePddrp2mM5ivgPkZ09JH4AvsALRbFUs= github.com/libp2p/go-maddr-filter v0.0.4/go.mod h1:6eT12kSQMA9x2pvFQa+xesMKUBlj9VImZbj3B9FBH/Q= @@ -484,6 +494,8 @@ github.com/libp2p/go-mplex v0.1.0/go.mod h1:SXgmdki2kwCUlCCbfGLEgHjC4pFqhTp0ZoV6 github.com/libp2p/go-msgio v0.0.1/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= github.com/libp2p/go-msgio v0.0.2 h1:ivPvEKHxmVkTClHzg6RXTYHqaJQ0V9cDbq+6lKb3UV0= github.com/libp2p/go-msgio v0.0.2/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= +github.com/libp2p/go-msgio v0.0.3 h1:VsOlWispTivSsOMg70e0W77y6oiSBSRCyP6URrWvE04= +github.com/libp2p/go-msgio v0.0.3/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= github.com/libp2p/go-nat v0.0.3 h1:l6fKV+p0Xa354EqQOQP+d8CivdLM4kl5GxC1hSc/UeI= github.com/libp2p/go-nat v0.0.3/go.mod h1:88nUEt0k0JD45Bk93NIwDqjlhiOwOoV36GchpcVc1yI= github.com/libp2p/go-reuseport v0.0.1 h1:7PhkfH73VXfPJYKQ6JwS5I/eVcoyYi9IMNGc6FWpFLw= @@ -731,6 +743,8 @@ golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f h1:R423Cnkcp5JABoeemiGEPl golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5 h1:8dUaAV7K4uHsF56JQWkprecIQKdPHtR9jCHF5nB8uzc= golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 h1:1wopBVtVdWnn03fZelqdXTqk7U7zPQCb+T4rbU9ZEoU= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -750,6 +764,8 @@ golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190522155817-f3200d17e092 h1:4QSRKanuywn15aTZvI/mIDEgPQpswuFndXpOj3rKEco= golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190611141213-3f473d35a33a h1:+KkCgOMgnKSgenxTBoiwkMqTiouMIy/3o8RLdmSbGoY= +golang.org/x/net v0.0.0-20190611141213-3f473d35a33a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -773,6 +789,8 @@ golang.org/x/sys v0.0.0-20190524122548-abf6ff778158/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190524152521-dbbf3f1254d4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190526052359-791d8a0f4d09 h1:IlD35wZE03o2qJy2o37WIskL33b7PT6cHdGnE8bieZs= golang.org/x/sys v0.0.0-20190526052359-791d8a0f4d09/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190610200419-93c9922d18ae h1:xiXzMMEQdQcric9hXtr1QU98MHunKK7OTtsoU6bYWs4= +golang.org/x/sys v0.0.0-20190610200419-93c9922d18ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.0.0-20170915090833-1cbadb444a80/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= From 1a9ff602464b04cef2a483672138786058d593a2 Mon Sep 17 00:00:00 2001 From: Jim McDonald Date: Thu, 13 Jun 2019 15:08:36 +0100 Subject: [PATCH 054/671] Allow resolution of .eth names via .eth.link --- namesys/namesys.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/namesys/namesys.go b/namesys/namesys.go index 6d59c62e334..cf944001d97 100644 --- a/namesys/namesys.go +++ b/namesys/namesys.go @@ -80,6 +80,9 @@ func (ns *mpns) ResolveAsync(ctx context.Context, name string, options ...opts.R return resolveAsync(ctx, ns, name, opts.ProcessOpts(options)) } +const ethTLD = ".eth" +const linkTLD = ".link" + // resolveOnce implements resolver. func (ns *mpns) resolveOnceAsync(ctx context.Context, name string, options opts.ResolveOpts) <-chan onceResult { out := make(chan onceResult, 1) @@ -87,6 +90,11 @@ func (ns *mpns) resolveOnceAsync(ctx context.Context, name string, options opts. if !strings.HasPrefix(name, ipnsPrefix) { name = ipnsPrefix + name } + if strings.HasSuffix(name, 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. + name = name + linkTLD + } segments := strings.SplitN(name, "/", 4) if len(segments) < 3 || segments[0] != "" { log.Debugf("invalid name syntax for %s", name) From d3a3530566b641633f7ddced6e55497126dbe045 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Thu, 13 Jun 2019 12:12:30 -0700 Subject: [PATCH 055/671] gitmodules: use https so we don't need an ssh key --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index f0f10eeb51d..d3c1139287c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "assets/dir-index-html"] path = assets/dir-index-html - url = git@github.com:ipfs/dir-index-html + url = https://github.com/ipfs/dir-index-html.git From aa06693e12c2759910a2acef14d8c474d2fe700c Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Fri, 14 Jun 2019 10:21:32 -0700 Subject: [PATCH 056/671] dep: update bitswap fixes a critical panic --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 58f71da8150..93c03daeffb 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/golangci/golangci-lint v1.16.1-0.20190425135923-692dacb773b7 github.com/hashicorp/go-multierror v1.0.0 github.com/hashicorp/golang-lru v0.5.1 - github.com/ipfs/go-bitswap v0.1.3 + github.com/ipfs/go-bitswap v0.1.4 github.com/ipfs/go-block-format v0.0.2 github.com/ipfs/go-blockservice v0.1.0 github.com/ipfs/go-cid v0.0.2 diff --git a/go.sum b/go.sum index 202cae75128..643b28d548e 100644 --- a/go.sum +++ b/go.sum @@ -193,8 +193,8 @@ github.com/ipfs/go-bitswap v0.0.3/go.mod h1:jadAZYsP/tcRMl47ZhFxhaNuDQoXawT8iHMg github.com/ipfs/go-bitswap v0.0.9/go.mod h1:kAPf5qgn2W2DrgAcscZ3HrM9qh4pH+X8Fkk3UPrwvis= github.com/ipfs/go-bitswap v0.1.0 h1:28YsHYw9ut6wootnImPXH0WpnU5Dbo3qm6cvQ6e6wYY= github.com/ipfs/go-bitswap v0.1.0/go.mod h1:FFJEf18E9izuCqUtHxbWEvq+reg7o4CW5wSAE1wsxj0= -github.com/ipfs/go-bitswap v0.1.3 h1:jAl9Z/TYObpGeGATUemnOZ7RYb0F/kzNVlhcYZesz+0= -github.com/ipfs/go-bitswap v0.1.3/go.mod h1:YEQlFy0kkxops5Vy+OxWdRSEZIoS7I7KDIwoa5Chkps= +github.com/ipfs/go-bitswap v0.1.4 h1:5MF09tIdEXL2omt+ySVhG8KOcFb7yyAMQUQqLUj2xs0= +github.com/ipfs/go-bitswap v0.1.4/go.mod h1:YEQlFy0kkxops5Vy+OxWdRSEZIoS7I7KDIwoa5Chkps= github.com/ipfs/go-block-format v0.0.1/go.mod h1:DK/YYcsSUIVAFNwo/KZCdIIbpN0ROH/baNLgayt4pFc= github.com/ipfs/go-block-format v0.0.2 h1:qPDvcP19izTjU8rgo6p7gTXZlkMkF5bz5G3fqIsSCPE= github.com/ipfs/go-block-format v0.0.2/go.mod h1:AWR46JfpcObNfg3ok2JHDUfdiHRgWhJgCQF+KIgOPJY= From 131a5eea6f091812392f27ee82d3665aeac3cd92 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 19 Jun 2019 11:42:46 +0200 Subject: [PATCH 057/671] dep: update go-bitswap and go-libp2p-kad-dht Reduces long-term allocations. --- go.mod | 4 ++-- go.sum | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 93c03daeffb..23d3c14870c 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/golangci/golangci-lint v1.16.1-0.20190425135923-692dacb773b7 github.com/hashicorp/go-multierror v1.0.0 github.com/hashicorp/golang-lru v0.5.1 - github.com/ipfs/go-bitswap v0.1.4 + github.com/ipfs/go-bitswap v0.1.5 github.com/ipfs/go-block-format v0.0.2 github.com/ipfs/go-blockservice v0.1.0 github.com/ipfs/go-cid v0.0.2 @@ -68,7 +68,7 @@ require ( github.com/libp2p/go-libp2p-connmgr v0.1.0 github.com/libp2p/go-libp2p-core v0.0.3 github.com/libp2p/go-libp2p-http v0.1.2 - github.com/libp2p/go-libp2p-kad-dht v0.1.0 + github.com/libp2p/go-libp2p-kad-dht v0.1.1 github.com/libp2p/go-libp2p-kbucket v0.2.0 github.com/libp2p/go-libp2p-loggables v0.1.0 github.com/libp2p/go-libp2p-mplex v0.2.1 diff --git a/go.sum b/go.sum index 643b28d548e..66b23172566 100644 --- a/go.sum +++ b/go.sum @@ -193,8 +193,8 @@ github.com/ipfs/go-bitswap v0.0.3/go.mod h1:jadAZYsP/tcRMl47ZhFxhaNuDQoXawT8iHMg github.com/ipfs/go-bitswap v0.0.9/go.mod h1:kAPf5qgn2W2DrgAcscZ3HrM9qh4pH+X8Fkk3UPrwvis= github.com/ipfs/go-bitswap v0.1.0 h1:28YsHYw9ut6wootnImPXH0WpnU5Dbo3qm6cvQ6e6wYY= github.com/ipfs/go-bitswap v0.1.0/go.mod h1:FFJEf18E9izuCqUtHxbWEvq+reg7o4CW5wSAE1wsxj0= -github.com/ipfs/go-bitswap v0.1.4 h1:5MF09tIdEXL2omt+ySVhG8KOcFb7yyAMQUQqLUj2xs0= -github.com/ipfs/go-bitswap v0.1.4/go.mod h1:YEQlFy0kkxops5Vy+OxWdRSEZIoS7I7KDIwoa5Chkps= +github.com/ipfs/go-bitswap v0.1.5 h1:pgajlrTCFbbPgYJ234M1pssneLuIsVuxtfpx1I4cz3Y= +github.com/ipfs/go-bitswap v0.1.5/go.mod h1:TOWoxllhccevbWFUR2N7B1MTSVVge1s6XSMiCSA4MzM= github.com/ipfs/go-block-format v0.0.1/go.mod h1:DK/YYcsSUIVAFNwo/KZCdIIbpN0ROH/baNLgayt4pFc= github.com/ipfs/go-block-format v0.0.2 h1:qPDvcP19izTjU8rgo6p7gTXZlkMkF5bz5G3fqIsSCPE= github.com/ipfs/go-block-format v0.0.2/go.mod h1:AWR46JfpcObNfg3ok2JHDUfdiHRgWhJgCQF+KIgOPJY= @@ -406,6 +406,8 @@ github.com/libp2p/go-libp2p-interface-connmgr v0.0.5/go.mod h1:GarlRLH0LdeWcLnYM github.com/libp2p/go-libp2p-interface-pnet v0.0.1/go.mod h1:el9jHpQAXK5dnTpKA4yfCNBZXvrzdOU75zz+C6ryp3k= github.com/libp2p/go-libp2p-kad-dht v0.1.0 h1:cupGornmncdQCnjArAv9Txkqy43wgQCxoe/5pfIDF/4= github.com/libp2p/go-libp2p-kad-dht v0.1.0/go.mod h1:EiH74cOsCxcu2Yh1XxQMpf1uHcLNm/hYEJBOIRlzHNE= +github.com/libp2p/go-libp2p-kad-dht v0.1.1 h1:IH6NQuoUv5w5e1O8Jc3KyVDtr0rNd0G9aaADpLI1xVo= +github.com/libp2p/go-libp2p-kad-dht v0.1.1/go.mod h1:1kj2Rk5pX3/0RwqMm9AMNCT7DzcMHYhgDN5VTi+cY0M= github.com/libp2p/go-libp2p-kbucket v0.2.0 h1:FB2a0VkOTNGTP5gu/I444u4WabNM9V1zCkQcWb7zajI= github.com/libp2p/go-libp2p-kbucket v0.2.0/go.mod h1:JNymBToym3QXKBMKGy3m29+xprg0EVr/GJFHxFEdgh8= github.com/libp2p/go-libp2p-loggables v0.0.1/go.mod h1:lDipDlBNYbpyqyPX/KcoO+eq0sJYEVR2JgOexcivchg= @@ -494,8 +496,8 @@ github.com/libp2p/go-mplex v0.1.0/go.mod h1:SXgmdki2kwCUlCCbfGLEgHjC4pFqhTp0ZoV6 github.com/libp2p/go-msgio v0.0.1/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= github.com/libp2p/go-msgio v0.0.2 h1:ivPvEKHxmVkTClHzg6RXTYHqaJQ0V9cDbq+6lKb3UV0= github.com/libp2p/go-msgio v0.0.2/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= -github.com/libp2p/go-msgio v0.0.3 h1:VsOlWispTivSsOMg70e0W77y6oiSBSRCyP6URrWvE04= -github.com/libp2p/go-msgio v0.0.3/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= +github.com/libp2p/go-msgio v0.0.4 h1:agEFehY3zWJFUHK6SEMR7UYmk2z6kC3oeCM7ybLhguA= +github.com/libp2p/go-msgio v0.0.4/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= github.com/libp2p/go-nat v0.0.3 h1:l6fKV+p0Xa354EqQOQP+d8CivdLM4kl5GxC1hSc/UeI= github.com/libp2p/go-nat v0.0.3/go.mod h1:88nUEt0k0JD45Bk93NIwDqjlhiOwOoV36GchpcVc1yI= github.com/libp2p/go-reuseport v0.0.1 h1:7PhkfH73VXfPJYKQ6JwS5I/eVcoyYi9IMNGc6FWpFLw= From a7f8d69008347e55abd08666b00a234e83fc0ff4 Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Fri, 21 Jun 2019 15:07:47 +0200 Subject: [PATCH 058/671] Update go-ds-badger Use replace to require go-libp2p-core@0.0.3 License: MIT Signed-off-by: Jakub Sztandera --- go.mod | 8 +++++--- go.sum | 23 +++++++++++++++-------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/go.mod b/go.mod index 23d3c14870c..57df7d774f7 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( github.com/ipfs/go-cidutil v0.0.2 github.com/ipfs/go-datastore v0.0.5 github.com/ipfs/go-detect-race v0.0.1 - github.com/ipfs/go-ds-badger v0.0.3 + github.com/ipfs/go-ds-badger v0.0.4 github.com/ipfs/go-ds-flatfs v0.0.2 github.com/ipfs/go-ds-leveldb v0.0.2 github.com/ipfs/go-ds-measure v0.0.1 @@ -66,13 +66,13 @@ require ( github.com/libp2p/go-libp2p-autonat-svc v0.1.0 github.com/libp2p/go-libp2p-circuit v0.1.0 github.com/libp2p/go-libp2p-connmgr v0.1.0 - github.com/libp2p/go-libp2p-core v0.0.3 + github.com/libp2p/go-libp2p-core v0.0.4 github.com/libp2p/go-libp2p-http v0.1.2 github.com/libp2p/go-libp2p-kad-dht v0.1.1 github.com/libp2p/go-libp2p-kbucket v0.2.0 github.com/libp2p/go-libp2p-loggables v0.1.0 github.com/libp2p/go-libp2p-mplex v0.2.1 - github.com/libp2p/go-libp2p-peerstore v0.1.0 + github.com/libp2p/go-libp2p-peerstore v0.1.2-0.20190621130618-cfa9bb890c1a github.com/libp2p/go-libp2p-pnet v0.1.0 github.com/libp2p/go-libp2p-pubsub v0.1.0 github.com/libp2p/go-libp2p-pubsub-router v0.1.0 @@ -114,4 +114,6 @@ require ( gotest.tools/gotestsum v0.3.4 ) +replace github.com/libp2p/go-libp2p-core => github.com/libp2p/go-libp2p-core v0.0.3 + go 1.12 diff --git a/go.sum b/go.sum index 66b23172566..c1e2956b3a8 100644 --- a/go.sum +++ b/go.sum @@ -59,8 +59,9 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018 h1:6xT9KW8zLC5IlbaIF5Q7JNieBoACT7iW0YTxQHR0in0= github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018/go.mod h1:rQYf4tfk5sSwFsnDg3qYaBxSjsD9S8+59vW0dKUgme4= github.com/dgraph-io/badger v1.5.5-0.20190226225317-8115aed38f8f/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ= -github.com/dgraph-io/badger v2.0.0-rc.2+incompatible h1:7KPp6xv5+wymkVUbkAnZZXvmDrJlf09m/7u1HG5lAYA= -github.com/dgraph-io/badger v2.0.0-rc.2+incompatible/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ= +github.com/dgraph-io/badger/v2 v2.0.0-20190620211019-41d170b5158f h1:vxg+rV4/+3GqzeZZdZUSjMlnbdUx0Vr65okIulvJNHk= +github.com/dgraph-io/badger/v2 v2.0.0-20190620211019-41d170b5158f/go.mod h1:jUaIjOV835xZ/mCLG/8P/38ZxiT4bG/K1khDNZJxuwU= +github.com/dgryski/go-farm v0.0.0-20180109070241-2de33835d102/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20190104051053-3adb47b1fb0f h1:dDxpBYafY/GYpcl+LS4Bn3ziLPuEdGRkRjYAbSlWxSA= github.com/dgryski/go-farm v0.0.0-20190104051053-3adb47b1fb0f/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= @@ -215,8 +216,8 @@ github.com/ipfs/go-datastore v0.0.5/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAK github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk= github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= github.com/ipfs/go-ds-badger v0.0.2/go.mod h1:Y3QpeSFWQf6MopLTiZD+VT6IC1yZqaGmjvRcKeSGij8= -github.com/ipfs/go-ds-badger v0.0.3 h1:sVYE2YlCzltznTZeAP1S+bp3qipz7VzogfZDtf6tGq0= -github.com/ipfs/go-ds-badger v0.0.3/go.mod h1:7AzMKCsGav0u46HpdLiAEAOqizR1H6AZsjpHpQSPYCQ= +github.com/ipfs/go-ds-badger v0.0.4 h1:zpAfddnYEZBX980c2a7PJHAlwlnSE4LVCjmUJYevgFc= +github.com/ipfs/go-ds-badger v0.0.4/go.mod h1:UIu++7eal30eVc+njb9LyGgBoJ3F+Y5cBpvD/dwn5VQ= github.com/ipfs/go-ds-flatfs v0.0.2 h1:1zujtU5bPBH6B8roE+TknKIbBCrpau865xUk0dH3x2A= github.com/ipfs/go-ds-flatfs v0.0.2/go.mod h1:YsMGWjUieue+smePAWeH/YhHtlmEMnEGhiwIn6K6rEM= github.com/ipfs/go-ds-leveldb v0.0.1/go.mod h1:feO8V3kubwsEF22n0YRQCffeb79OOYIykR4L04tMOYc= @@ -380,9 +381,6 @@ github.com/libp2p/go-libp2p-circuit v0.1.0 h1:eniLL3Y9aq/sryfyV1IAHj5rlvuyj3b7iz github.com/libp2p/go-libp2p-circuit v0.1.0/go.mod h1:Ahq4cY3V9VJcHcn1SBXjr78AbFkZeIRmfunbA7pmFh8= github.com/libp2p/go-libp2p-connmgr v0.1.0 h1:vp0t0F0EuT3rrlTtnMnIyyzCnly7nIlRoEbhJpgp0qU= github.com/libp2p/go-libp2p-connmgr v0.1.0/go.mod h1:wZxh8veAmU5qdrfJ0ZBLcU8oJe9L82ciVP/fl1VHjXk= -github.com/libp2p/go-libp2p-core v0.0.1/go.mod h1:g/VxnTZ/1ygHxH3dKok7Vno1VfpvGcGip57wjTU4fco= -github.com/libp2p/go-libp2p-core v0.0.2 h1:86uOwW+O6Uc7NbaK4diuLZo2/Ikvqw2rgyV03VcSbLE= -github.com/libp2p/go-libp2p-core v0.0.2/go.mod h1:9dAcntw/n46XycV4RnlBq3BpgrmyUi9LuoTNdPrbUco= github.com/libp2p/go-libp2p-core v0.0.3 h1:+IonUYY0nJZLb5Fdv6a6DOjtGP1L8Bb3faamiI2q5FY= github.com/libp2p/go-libp2p-core v0.0.3/go.mod h1:j+YQMNz9WNSkNezXOsahp9kwZBKBvxLpKD316QWSJXE= github.com/libp2p/go-libp2p-crypto v0.0.1/go.mod h1:yJkNyDmO341d5wwXxDUGO0LykUVT72ImHNUqh5D/dBE= @@ -434,6 +432,8 @@ github.com/libp2p/go-libp2p-peerstore v0.0.1/go.mod h1:RabLyPVJLuNQ+GFyoEkfi8H4T github.com/libp2p/go-libp2p-peerstore v0.0.6/go.mod h1:RabLyPVJLuNQ+GFyoEkfi8H4Ti6k/HtZJ7YKgtSq+20= github.com/libp2p/go-libp2p-peerstore v0.1.0 h1:MKh7pRNPHSh1fLPj8u/M/s/napdmeNpoi9BRy9lPN0E= github.com/libp2p/go-libp2p-peerstore v0.1.0/go.mod h1:2CeHkQsr8svp4fZ+Oi9ykN1HBb6u0MOvdJ7YIsmcwtY= +github.com/libp2p/go-libp2p-peerstore v0.1.2-0.20190621130618-cfa9bb890c1a h1:xW2Q7yiWAQnBpxe6m5Y094bYxxBCaoNruxc1sDlVxs0= +github.com/libp2p/go-libp2p-peerstore v0.1.2-0.20190621130618-cfa9bb890c1a/go.mod h1:DAchSrPUuksotuxrqPcvk5jvifXlxC3oH/65iHFmBns= github.com/libp2p/go-libp2p-pnet v0.1.0 h1:kRUES28dktfnHNIRW4Ro78F7rKBHBiw5MJpl0ikrLIA= github.com/libp2p/go-libp2p-pnet v0.1.0/go.mod h1:ZkyZw3d0ZFOex71halXRihWf9WH/j3OevcJdTmD0lyE= github.com/libp2p/go-libp2p-protocol v0.0.1/go.mod h1:Af9n4PiruirSDjHycM1QuiMi/1VZNHYcK8cLgFJLZ4s= @@ -568,7 +568,6 @@ github.com/mitchellh/mapstructure v0.0.0-20180220230111-00c29f56e238 h1:+MZW2uvH github.com/mitchellh/mapstructure v0.0.0-20180220230111-00c29f56e238/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mozilla/tls-observatory v0.0.0-20180409132520-8791a200eb40/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk= github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= -github.com/mr-tron/base58 v1.1.1/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= github.com/mr-tron/base58 v1.1.2 h1:ZEw4I2EgPKDJ2iEw0cNmLB3ROrEmkOtXIkaG7wZg+78= github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/multiformats/go-base32 v0.0.3 h1:tw5+NhuwaOjJCC5Pp82QuXbrmLzWg7uxlMFp8Nq/kkI= @@ -670,10 +669,14 @@ github.com/spf13/cast v1.2.0 h1:HHl1DSRbEQN2i8tJmtS6ViPyHx35+p51amrdsiTCrkg= github.com/spf13/cast v1.2.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg= github.com/spf13/cobra v0.0.2 h1:NfkwRbgViGoyjBKsLI0QMDcuMnhM+SBg3T0cGfpvKDE= github.com/spf13/cobra v0.0.2/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/jwalterweatherman v0.0.0-20180109140146-7c0cea34c8ec h1:2ZXvIUGghLpdTVHR1UfvfrzoVlZaE/yOWC5LueIHZig= github.com/spf13/jwalterweatherman v0.0.0-20180109140146-7c0cea34c8ec/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v1.0.1 h1:aCvUg6QPl3ibpQUxyLkrEkCHtPqYJL4x9AuhqVqFis4= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/viper v1.0.2 h1:Ncr3ZIuJn322w2k1qmzXDnkLAdQMlJqBa9kfAH+irso= github.com/spf13/viper v1.0.2/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -759,6 +762,7 @@ golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20181102091132-c10e9556a7bc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181217023233-e147a9138326/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -774,12 +778,15 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20171026204733-164713f0dfce/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181218192612-074acd46bca6/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= From fd84cb3957b75c77e53ff55cd5f728437f915736 Mon Sep 17 00:00:00 2001 From: Leo Arias Date: Fri, 21 Jun 2019 10:54:05 -0600 Subject: [PATCH 059/671] Update the required go version in the README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 65ed3c78382..314ade8455c 100644 --- a/README.md +++ b/README.md @@ -139,7 +139,7 @@ PS> scoop install go-ipfs #### Install Go -The build process for ipfs requires Go 1.11 or higher. If you don't have it: [Download Go 1.11+](https://golang.org/dl/). +The build process for ipfs requires Go 1.12 or higher. If you don't have it: [Download Go 1.12+](https://golang.org/dl/). You'll need to add Go's bin directories to your `$PATH` environment variable e.g., by adding these lines to your `/etc/profile` (for a system-wide installation) or `$HOME/.profile`: From 4db0ce7385c17b984c69c9a8b35a08b71804d9db Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Mon, 24 Jun 2019 16:29:59 +0200 Subject: [PATCH 060/671] dep: update go-libp2p@0.2.0 to fix go-libp2p-core breakage License: MIT Signed-off-by: Jakub Sztandera --- go.mod | 6 ++---- go.sum | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 57df7d774f7..755f97d26fb 100644 --- a/go.mod +++ b/go.mod @@ -62,11 +62,11 @@ require ( github.com/jbenet/go-random-files v0.0.0-20190219210431-31b3f20ebded github.com/jbenet/go-temp-err-catcher v0.0.0-20150120210811-aac704a3f4f2 github.com/jbenet/goprocess v0.1.3 - github.com/libp2p/go-libp2p v0.1.1 + github.com/libp2p/go-libp2p v0.2.0 github.com/libp2p/go-libp2p-autonat-svc v0.1.0 github.com/libp2p/go-libp2p-circuit v0.1.0 github.com/libp2p/go-libp2p-connmgr v0.1.0 - github.com/libp2p/go-libp2p-core v0.0.4 + github.com/libp2p/go-libp2p-core v0.0.6 github.com/libp2p/go-libp2p-http v0.1.2 github.com/libp2p/go-libp2p-kad-dht v0.1.1 github.com/libp2p/go-libp2p-kbucket v0.2.0 @@ -114,6 +114,4 @@ require ( gotest.tools/gotestsum v0.3.4 ) -replace github.com/libp2p/go-libp2p-core => github.com/libp2p/go-libp2p-core v0.0.3 - go 1.12 diff --git a/go.sum b/go.sum index c1e2956b3a8..1576f86ed1d 100644 --- a/go.sum +++ b/go.sum @@ -358,6 +358,8 @@ github.com/libp2p/go-conn-security-multistream v0.0.1/go.mod h1:nc9vud7inQ+d6SO0 github.com/libp2p/go-conn-security-multistream v0.0.2/go.mod h1:nc9vud7inQ+d6SO0I/6dSWrdMnHnzZNHeyUQqrAJulE= github.com/libp2p/go-conn-security-multistream v0.1.0 h1:aqGmto+ttL/uJgX0JtQI0tD21CIEy5eYd1Hlp0juHY0= github.com/libp2p/go-conn-security-multistream v0.1.0/go.mod h1:aw6eD7LOsHEX7+2hJkDxw1MteijaVcI+/eP2/x3J1xc= +github.com/libp2p/go-eventbus v0.0.2 h1:L9eslON8FjFBJlyUs9fyEZKnxSqZd2AMDUNldPrqmZI= +github.com/libp2p/go-eventbus v0.0.2/go.mod h1:Hr/yGlwxA/stuLnpMiu82lpNKpvRy3EaJxPu40XYOwk= github.com/libp2p/go-flow-metrics v0.0.1 h1:0gxuFd2GuK7IIP5pKljLwps6TvcuYgvG7Atqi3INF5s= github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8= github.com/libp2p/go-libp2p v0.0.2/go.mod h1:Qu8bWqFXiocPloabFGUcVG4kk94fLvfC8mWTDdFC9wE= @@ -366,6 +368,8 @@ github.com/libp2p/go-libp2p v0.1.0 h1:8VXadcPNni74ODoZ+7326LMAppFYmz1fRQOUuT5iZv github.com/libp2p/go-libp2p v0.1.0/go.mod h1:6D/2OBauqLUoqcADOJpn9WbKqvaM07tDw68qHM0BxUM= github.com/libp2p/go-libp2p v0.1.1 h1:52sB0TJuDk2nYMcMfHOKaPoaayDZjaYVCq6Vk1ejUTk= github.com/libp2p/go-libp2p v0.1.1/go.mod h1:I00BRo1UuUSdpuc8Q2mN7yDF/oTUTRAX6JWpTiK9Rp8= +github.com/libp2p/go-libp2p v0.2.0 h1:hYJgMZYdcwHzDHKb/nLePrtuSP3LqkGIFOQ2aIbKOCM= +github.com/libp2p/go-libp2p v0.2.0/go.mod h1:5nXHmf4Hs+NmkaMsmWcFJgUHTbYNpCfxr20lwus0p1c= 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 h1:aCWAu43Ri4nU0ZPO7NyLzUvvfqd0nE3dX0R/ZGYVgOU= @@ -375,14 +379,21 @@ github.com/libp2p/go-libp2p-autonat-svc v0.1.0/go.mod h1:fqi8Obl/z3R4PFVLm8xFtZ6 github.com/libp2p/go-libp2p-blankhost v0.0.1/go.mod h1:Ibpbw/7cPPYwFb7PACIWdvxxv0t0XCCI10t7czjAjTc= github.com/libp2p/go-libp2p-blankhost v0.1.1 h1:X919sCh+KLqJcNRApj43xCSiQRYqOSI88Fdf55ngf78= github.com/libp2p/go-libp2p-blankhost v0.1.1/go.mod h1:pf2fvdLJPsC1FsVrNP3DUUvMzUts2dsLLBEpo1vW1ro= +github.com/libp2p/go-libp2p-blankhost v0.1.3 h1:0KycuXvPDhmehw0ASsg+s1o3IfXgCUDqfzAl94KEBOg= +github.com/libp2p/go-libp2p-blankhost v0.1.3/go.mod h1:KML1//wiKR8vuuJO0y3LUd1uLv+tlkGTAr3jC0S5cLg= github.com/libp2p/go-libp2p-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 h1:eniLL3Y9aq/sryfyV1IAHj5rlvuyj3b7iz8tSiZpdhY= github.com/libp2p/go-libp2p-circuit v0.1.0/go.mod h1:Ahq4cY3V9VJcHcn1SBXjr78AbFkZeIRmfunbA7pmFh8= github.com/libp2p/go-libp2p-connmgr v0.1.0 h1:vp0t0F0EuT3rrlTtnMnIyyzCnly7nIlRoEbhJpgp0qU= github.com/libp2p/go-libp2p-connmgr v0.1.0/go.mod h1:wZxh8veAmU5qdrfJ0ZBLcU8oJe9L82ciVP/fl1VHjXk= +github.com/libp2p/go-libp2p-core v0.0.1/go.mod h1:g/VxnTZ/1ygHxH3dKok7Vno1VfpvGcGip57wjTU4fco= +github.com/libp2p/go-libp2p-core v0.0.2/go.mod h1:9dAcntw/n46XycV4RnlBq3BpgrmyUi9LuoTNdPrbUco= github.com/libp2p/go-libp2p-core v0.0.3 h1:+IonUYY0nJZLb5Fdv6a6DOjtGP1L8Bb3faamiI2q5FY= github.com/libp2p/go-libp2p-core v0.0.3/go.mod h1:j+YQMNz9WNSkNezXOsahp9kwZBKBvxLpKD316QWSJXE= +github.com/libp2p/go-libp2p-core v0.0.4/go.mod h1:jyuCQP356gzfCFtRKyvAbNkyeuxb7OlyhWZ3nls5d2I= +github.com/libp2p/go-libp2p-core v0.0.6 h1:SsYhfWJ47vLP1Rd9/0hqEm/W/PlFbC/3YLZyLCcvo1w= +github.com/libp2p/go-libp2p-core v0.0.6/go.mod h1:0d9xmaYAVY5qmbp/fcgxHT3ZJsLjYeYPMJAUKpaCHrE= 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 h1:k9MFy+o2zGDNGsaoZl0MA3iZ75qXxr9OOoAZF+sD5OQ= @@ -432,6 +443,7 @@ github.com/libp2p/go-libp2p-peerstore v0.0.1/go.mod h1:RabLyPVJLuNQ+GFyoEkfi8H4T github.com/libp2p/go-libp2p-peerstore v0.0.6/go.mod h1:RabLyPVJLuNQ+GFyoEkfi8H4Ti6k/HtZJ7YKgtSq+20= github.com/libp2p/go-libp2p-peerstore v0.1.0 h1:MKh7pRNPHSh1fLPj8u/M/s/napdmeNpoi9BRy9lPN0E= github.com/libp2p/go-libp2p-peerstore v0.1.0/go.mod h1:2CeHkQsr8svp4fZ+Oi9ykN1HBb6u0MOvdJ7YIsmcwtY= +github.com/libp2p/go-libp2p-peerstore v0.1.1/go.mod h1:ojEWnwG7JpJLkJ9REWYXQslyu9ZLrPWPEcCdiZzEbSM= github.com/libp2p/go-libp2p-peerstore v0.1.2-0.20190621130618-cfa9bb890c1a h1:xW2Q7yiWAQnBpxe6m5Y094bYxxBCaoNruxc1sDlVxs0= github.com/libp2p/go-libp2p-peerstore v0.1.2-0.20190621130618-cfa9bb890c1a/go.mod h1:DAchSrPUuksotuxrqPcvk5jvifXlxC3oH/65iHFmBns= github.com/libp2p/go-libp2p-pnet v0.1.0 h1:kRUES28dktfnHNIRW4Ro78F7rKBHBiw5MJpl0ikrLIA= @@ -568,6 +580,7 @@ github.com/mitchellh/mapstructure v0.0.0-20180220230111-00c29f56e238 h1:+MZW2uvH github.com/mitchellh/mapstructure v0.0.0-20180220230111-00c29f56e238/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mozilla/tls-observatory v0.0.0-20180409132520-8791a200eb40/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk= github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= +github.com/mr-tron/base58 v1.1.1/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= github.com/mr-tron/base58 v1.1.2 h1:ZEw4I2EgPKDJ2iEw0cNmLB3ROrEmkOtXIkaG7wZg+78= github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/multiformats/go-base32 v0.0.3 h1:tw5+NhuwaOjJCC5Pp82QuXbrmLzWg7uxlMFp8Nq/kkI= @@ -750,6 +763,8 @@ golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5 h1:8dUaAV7K4uHsF56JQWkpre golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 h1:1wopBVtVdWnn03fZelqdXTqk7U7zPQCb+T4rbU9ZEoU= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443 h1:IcSOAf4PyMp3U3XbIEj1/xJ2BjNN2jWv7JoyOsMxXUU= +golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= From 7889932ae9d7e578beb4b2e73edfc5f51a3f339d Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Thu, 27 Jun 2019 18:14:15 +0200 Subject: [PATCH 061/671] dep: update swarm/maddr-filter Reduces allocations/CPU when handling many inbound connections. --- go.mod | 4 ++-- go.sum | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 755f97d26fb..19056ae7cf7 100644 --- a/go.mod +++ b/go.mod @@ -80,11 +80,11 @@ require ( github.com/libp2p/go-libp2p-record v0.1.0 github.com/libp2p/go-libp2p-routing-helpers v0.1.0 github.com/libp2p/go-libp2p-secio v0.1.0 - github.com/libp2p/go-libp2p-swarm v0.1.0 + github.com/libp2p/go-libp2p-swarm v0.1.1 github.com/libp2p/go-libp2p-testing v0.0.4 github.com/libp2p/go-libp2p-tls v0.1.0 github.com/libp2p/go-libp2p-yamux v0.2.1 - github.com/libp2p/go-maddr-filter v0.0.4 + github.com/libp2p/go-maddr-filter v0.0.5 github.com/mattn/go-runewidth v0.0.4 // indirect github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect github.com/mitchellh/go-homedir v1.1.0 diff --git a/go.sum b/go.sum index 1576f86ed1d..1e8223a8c54 100644 --- a/go.sum +++ b/go.sum @@ -476,6 +476,8 @@ github.com/libp2p/go-libp2p-swarm v0.0.1/go.mod h1:mh+KZxkbd3lQnveQ3j2q60BM1Cw2m github.com/libp2p/go-libp2p-swarm v0.0.6/go.mod h1:s5GZvzg9xXe8sbeESuFpjt8CJPTCa8mhEusweJqyFy8= github.com/libp2p/go-libp2p-swarm v0.1.0 h1:HrFk2p0awrGEgch9JXK/qp/hfjqQfgNxpLWnCiWPg5s= github.com/libp2p/go-libp2p-swarm v0.1.0/go.mod h1:wQVsCdjsuZoc730CgOvh5ox6K8evllckjebkdiY5ta4= +github.com/libp2p/go-libp2p-swarm v0.1.1 h1:QW7pjyTRIxt9yyBid52YmMRGtkFXUE/rbEVWsQ0ae+w= +github.com/libp2p/go-libp2p-swarm v0.1.1/go.mod h1:4NVJaLwq/dr5kEq79Jo6pMin7ZFwLx73ln1FTefR91Q= github.com/libp2p/go-libp2p-testing v0.0.1/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= github.com/libp2p/go-libp2p-testing v0.0.2/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= github.com/libp2p/go-libp2p-testing v0.0.3 h1:bdij4bKaaND7tCsaXVjRfYkMpvoOeKj9AVQGJllA6jM= @@ -500,6 +502,8 @@ github.com/libp2p/go-libp2p-yamux v0.2.1/go.mod h1:1FBXiHDk1VyRM1C0aez2bCfHQ4vMZ github.com/libp2p/go-maddr-filter v0.0.1/go.mod h1:6eT12kSQMA9x2pvFQa+xesMKUBlj9VImZbj3B9FBH/Q= github.com/libp2p/go-maddr-filter v0.0.4 h1:hx8HIuuwk34KePddrp2mM5ivgPkZ09JH4AvsALRbFUs= github.com/libp2p/go-maddr-filter v0.0.4/go.mod h1:6eT12kSQMA9x2pvFQa+xesMKUBlj9VImZbj3B9FBH/Q= +github.com/libp2p/go-maddr-filter v0.0.5 h1:CW3AgbMO6vUvT4kf87y4N+0P8KUl2aqLYhrGyDUbLSg= +github.com/libp2p/go-maddr-filter v0.0.5/go.mod h1:Jk+36PMfIqCJhAnaASRH83bdAvfDRp/w6ENFaC9bG+M= github.com/libp2p/go-mplex v0.0.1/go.mod h1:pK5yMLmOoBR1pNCqDlA2GQrdAVTMkqFalaTWe7l4Yd0= github.com/libp2p/go-mplex v0.0.3/go.mod h1:pK5yMLmOoBR1pNCqDlA2GQrdAVTMkqFalaTWe7l4Yd0= github.com/libp2p/go-mplex v0.0.4/go.mod h1:pK5yMLmOoBR1pNCqDlA2GQrdAVTMkqFalaTWe7l4Yd0= From d3d5db2657928b4c41b8a9fc076d7019bc9134b3 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Fri, 28 Jun 2019 06:25:36 +0200 Subject: [PATCH 062/671] dep: fix badger version revert to v1.6 --- go.mod | 6 ++++-- go.sum | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 19056ae7cf7..0183829aa7c 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( github.com/ipfs/go-cidutil v0.0.2 github.com/ipfs/go-datastore v0.0.5 github.com/ipfs/go-detect-race v0.0.1 - github.com/ipfs/go-ds-badger v0.0.4 + github.com/ipfs/go-ds-badger v0.0.5 github.com/ipfs/go-ds-flatfs v0.0.2 github.com/ipfs/go-ds-leveldb v0.0.2 github.com/ipfs/go-ds-measure v0.0.1 @@ -109,7 +109,9 @@ require ( go.uber.org/goleak v0.10.0 // indirect go.uber.org/multierr v1.1.0 // indirect go4.org v0.0.0-20190313082347-94abd6928b1d // indirect - golang.org/x/sys v0.0.0-20190610200419-93c9922d18ae + golang.org/x/sync v0.0.0-20190423024810-112230192c58 // indirect + golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb + google.golang.org/appengine v1.4.0 // indirect gopkg.in/cheggaaa/pb.v1 v1.0.28 gotest.tools/gotestsum v0.3.4 ) diff --git a/go.sum b/go.sum index 1e8223a8c54..085b81e0023 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,8 @@ bazil.org/fuse v0.0.0-20180421153158-65cc252bf669/go.mod h1:Xbm+BRKSBEpa4q4hTSxo cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7 h1:PqzgE6kAMi81xWQA2QIVxjWkFHptGgC547vchpUbtFo= github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= +github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9 h1:HD8gA2tkByhMAwYaFAX9w2l7vxvBQ5NMoxDrkhqhtn4= +github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Kubuxu/go-os-helper v0.0.1 h1:EJiD2VUQyh5A9hWJLmc6iWg6yIcJ7jpBcwC8GMGXfDk= @@ -20,6 +22,7 @@ github.com/Stebalien/go-bitfield v0.0.1/go.mod h1:GNjFpasyUVkHMsfEOk8EFLJ9syQ6SI github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -46,10 +49,13 @@ github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghf github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.2.1-0.20180108230905-e214231b295a/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cskr/pubsub v1.0.2 h1:vlOzMhl6PFn60gRlTQQsIfVwaPB/B/8MziK8FhEPt/0= github.com/cskr/pubsub v1.0.2/go.mod h1:/8MzYXk/NJAz782G8RPkFzXTZVu63VotefPnR9TIRis= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -59,11 +65,15 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018 h1:6xT9KW8zLC5IlbaIF5Q7JNieBoACT7iW0YTxQHR0in0= github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018/go.mod h1:rQYf4tfk5sSwFsnDg3qYaBxSjsD9S8+59vW0dKUgme4= github.com/dgraph-io/badger v1.5.5-0.20190226225317-8115aed38f8f/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ= +github.com/dgraph-io/badger v1.6.0-rc1 h1:JphPpoBZJ3WHha133BGYlQqltSGIhV+VsEID0++nN9A= +github.com/dgraph-io/badger v1.6.0-rc1/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= github.com/dgraph-io/badger/v2 v2.0.0-20190620211019-41d170b5158f h1:vxg+rV4/+3GqzeZZdZUSjMlnbdUx0Vr65okIulvJNHk= github.com/dgraph-io/badger/v2 v2.0.0-20190620211019-41d170b5158f/go.mod h1:jUaIjOV835xZ/mCLG/8P/38ZxiT4bG/K1khDNZJxuwU= github.com/dgryski/go-farm v0.0.0-20180109070241-2de33835d102/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20190104051053-3adb47b1fb0f h1:dDxpBYafY/GYpcl+LS4Bn3ziLPuEdGRkRjYAbSlWxSA= github.com/dgryski/go-farm v0.0.0-20190104051053-3adb47b1fb0f/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= +github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= @@ -180,6 +190,8 @@ github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce h1:xdsDDbiBDQTKASoGEZ+pEmF1OnWuu8AQ9I8iNbHNeno= github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huin/goupnp v0.0.0-20180415215157-1395d1447324/go.mod h1:MZ2ZmwcBpvOoJ22IJsc7va19ZwoheaBk43rKg12SKag= @@ -218,6 +230,8 @@ github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46U github.com/ipfs/go-ds-badger v0.0.2/go.mod h1:Y3QpeSFWQf6MopLTiZD+VT6IC1yZqaGmjvRcKeSGij8= github.com/ipfs/go-ds-badger v0.0.4 h1:zpAfddnYEZBX980c2a7PJHAlwlnSE4LVCjmUJYevgFc= github.com/ipfs/go-ds-badger v0.0.4/go.mod h1:UIu++7eal30eVc+njb9LyGgBoJ3F+Y5cBpvD/dwn5VQ= +github.com/ipfs/go-ds-badger v0.0.5 h1:dxKuqw5T1Jm8OuV+lchA76H9QZFyPKZeLuT6bN42hJQ= +github.com/ipfs/go-ds-badger v0.0.5/go.mod h1:g5AuuCGmr7efyzQhLL8MzwqcauPojGPUaHzfGTzuE3s= github.com/ipfs/go-ds-flatfs v0.0.2 h1:1zujtU5bPBH6B8roE+TknKIbBCrpau865xUk0dH3x2A= github.com/ipfs/go-ds-flatfs v0.0.2/go.mod h1:YsMGWjUieue+smePAWeH/YhHtlmEMnEGhiwIn6K6rEM= github.com/ipfs/go-ds-leveldb v0.0.1/go.mod h1:feO8V3kubwsEF22n0YRQCffeb79OOYIykR4L04tMOYc= @@ -550,6 +564,8 @@ github.com/lucas-clemente/quic-go v0.11.2 h1:Mop0ac3zALaBR3wGs6j8OYe/tcFvFsxTUFM github.com/lucas-clemente/quic-go v0.11.2/go.mod h1:PpMmPfPKO9nKJ/psF49ESTAGQSdfXxlg1otPbEB2nOw= github.com/magiconair/properties v1.7.6 h1:U+1DqNen04MdEPgFiIwdOUiqZ8qPa37xgogX/sd3+54= github.com/magiconair/properties v1.7.6/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/marten-seemann/qtls v0.2.3 h1:0yWJ43C62LsZt08vuQJDK1uC1czUc3FJeCLPoNAI4vA= github.com/marten-seemann/qtls v0.2.3/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= @@ -582,6 +598,8 @@ github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk github.com/mitchellh/go-ps v0.0.0-20170309133038-4fdf99ab2936/go.mod h1:r1VsdOzOPt1ZSrGZWFoNhsAedKnEd6r9Np1+5blZCWk= github.com/mitchellh/mapstructure v0.0.0-20180220230111-00c29f56e238 h1:+MZW2uvHgN8kYvksEN3f7eFL2wpzk0GxmlFsMybWc7E= github.com/mitchellh/mapstructure v0.0.0-20180220230111-00c29f56e238/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mozilla/tls-observatory v0.0.0-20180409132520-8791a200eb40/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk= github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= github.com/mr-tron/base58 v1.1.1/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= @@ -630,6 +648,8 @@ github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFSt github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.1.0 h1:cmiOvKzEunMsAxyhXSzpL5Q1CRKpVv0KQsnAIcSEVYM= github.com/pelletier/go-toml v1.1.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -657,6 +677,7 @@ github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40T github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rs/cors v1.6.0 h1:G9tHG9lebljV9mfp9SNPDL36nCDxmo3zTlAf1YgvzmI= github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/shirou/gopsutil v0.0.0-20180427012116-c95755e4bcd7/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc= @@ -682,20 +703,30 @@ github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0b github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.0 h1:bopulORc2JeYaxfHLvJa5NzxviA9PoWhpiiJkru7Ji4= github.com/spf13/afero v1.1.0/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/cast v1.2.0 h1:HHl1DSRbEQN2i8tJmtS6ViPyHx35+p51amrdsiTCrkg= github.com/spf13/cast v1.2.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg= +github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.2 h1:NfkwRbgViGoyjBKsLI0QMDcuMnhM+SBg3T0cGfpvKDE= github.com/spf13/cobra v0.0.2/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/jwalterweatherman v0.0.0-20180109140146-7c0cea34c8ec h1:2ZXvIUGghLpdTVHR1UfvfrzoVlZaE/yOWC5LueIHZig= github.com/spf13/jwalterweatherman v0.0.0-20180109140146-7c0cea34c8ec/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v1.0.1 h1:aCvUg6QPl3ibpQUxyLkrEkCHtPqYJL4x9AuhqVqFis4= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/viper v1.0.2 h1:Ncr3ZIuJn322w2k1qmzXDnkLAdQMlJqBa9kfAH+irso= github.com/spf13/viper v1.0.2/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM= +github.com/spf13/viper v1.3.2 h1:VUFqw5KcqRf7i70GOzW7N+Q7+gxVBkSSqiXB12+JQ4M= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -705,6 +736,7 @@ github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFd github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e h1:T5PdfK/M1xyrHwynxMIVMWLS7f/qHwfslZphxtGnw7s= github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e/go.mod h1:XDKHRm5ThF8YJjx001LtgelzsoaEcvnA7lVWz9EeX3g= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/warpfork/go-wish v0.0.0-20180510122957-5ad1f5abf436 h1:qOpVTI+BrstcjTZLm2Yz/3sOnqkzj3FQoh0g+E5s3Gc= @@ -737,6 +769,7 @@ github.com/whyrusleeping/tar-utils v0.0.0-20180509141711-8c6c8ba81d5c/go.mod h1: 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/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= go.opencensus.io v0.21.0 h1:mU6zScU4U1YAFPHEHYk+3JC4SY7JxgkqS10ZOSyksNg= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= @@ -755,6 +788,7 @@ go4.org v0.0.0-20190313082347-94abd6928b1d/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1 golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180426230345-b49d69b5da94/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -791,6 +825,8 @@ golang.org/x/net v0.0.0-20190522155817-f3200d17e092 h1:4QSRKanuywn15aTZvI/mIDEgP golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190611141213-3f473d35a33a h1:+KkCgOMgnKSgenxTBoiwkMqTiouMIy/3o8RLdmSbGoY= golang.org/x/net v0.0.0-20190611141213-3f473d35a33a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -805,6 +841,7 @@ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181218192612-074acd46bca6/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -819,6 +856,8 @@ golang.org/x/sys v0.0.0-20190526052359-791d8a0f4d09 h1:IlD35wZE03o2qJy2o37WIskL3 golang.org/x/sys v0.0.0-20190526052359-791d8a0f4d09/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190610200419-93c9922d18ae h1:xiXzMMEQdQcric9hXtr1QU98MHunKK7OTtsoU6bYWs4= golang.org/x/sys v0.0.0-20190610200419-93c9922d18ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb h1:fgwFCsaw9buMuxNd6+DQfAuSFqbNiQZpcgJQAgJsK6k= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.0.0-20170915090833-1cbadb444a80/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= From 5d29073925b918760c77a5ac57ee0f02d74fe944 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Fri, 28 Jun 2019 06:26:35 +0200 Subject: [PATCH 063/671] dep: pull in latest go event bus There was a panic in the old version. --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 0183829aa7c..845548a46e4 100644 --- a/go.mod +++ b/go.mod @@ -62,6 +62,7 @@ require ( github.com/jbenet/go-random-files v0.0.0-20190219210431-31b3f20ebded github.com/jbenet/go-temp-err-catcher v0.0.0-20150120210811-aac704a3f4f2 github.com/jbenet/goprocess v0.1.3 + github.com/libp2p/go-eventbus v0.0.3 // indirect github.com/libp2p/go-libp2p v0.2.0 github.com/libp2p/go-libp2p-autonat-svc v0.1.0 github.com/libp2p/go-libp2p-circuit v0.1.0 @@ -111,7 +112,6 @@ require ( go4.org v0.0.0-20190313082347-94abd6928b1d // indirect golang.org/x/sync v0.0.0-20190423024810-112230192c58 // indirect golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb - google.golang.org/appengine v1.4.0 // indirect gopkg.in/cheggaaa/pb.v1 v1.0.28 gotest.tools/gotestsum v0.3.4 ) diff --git a/go.sum b/go.sum index 085b81e0023..337302c8ad7 100644 --- a/go.sum +++ b/go.sum @@ -374,6 +374,8 @@ github.com/libp2p/go-conn-security-multistream v0.1.0 h1:aqGmto+ttL/uJgX0JtQI0tD github.com/libp2p/go-conn-security-multistream v0.1.0/go.mod h1:aw6eD7LOsHEX7+2hJkDxw1MteijaVcI+/eP2/x3J1xc= github.com/libp2p/go-eventbus v0.0.2 h1:L9eslON8FjFBJlyUs9fyEZKnxSqZd2AMDUNldPrqmZI= github.com/libp2p/go-eventbus v0.0.2/go.mod h1:Hr/yGlwxA/stuLnpMiu82lpNKpvRy3EaJxPu40XYOwk= +github.com/libp2p/go-eventbus v0.0.3 h1:4sB0NrwnWr6qGeq2RWUp/JG1wNajf6gyILInId72hrw= +github.com/libp2p/go-eventbus v0.0.3/go.mod h1:Hr/yGlwxA/stuLnpMiu82lpNKpvRy3EaJxPu40XYOwk= github.com/libp2p/go-flow-metrics v0.0.1 h1:0gxuFd2GuK7IIP5pKljLwps6TvcuYgvG7Atqi3INF5s= github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8= github.com/libp2p/go-libp2p v0.0.2/go.mod h1:Qu8bWqFXiocPloabFGUcVG4kk94fLvfC8mWTDdFC9wE= From 4badef2a14c6e0c2421fd915540d79060cbf3df3 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Fri, 28 Jun 2019 08:42:29 +0200 Subject: [PATCH 064/671] feat: make it easier to load custom plugins 1. Allow loading from arbitrary and multiple directories. 2. Make it possible to directly load built-in plugins that _aren't_ in the preload list. --- cmd/ipfs/main.go | 16 ++-- plugin/loader/loader.go | 158 +++++++++++++++++++++++++++++-------- repo/fsrepo/config_test.go | 2 +- 3 files changed, 136 insertions(+), 40 deletions(-) diff --git a/cmd/ipfs/main.go b/cmd/ipfs/main.go index 26973553dfa..61ad3d56360 100644 --- a/cmd/ipfs/main.go +++ b/cmd/ipfs/main.go @@ -49,18 +49,20 @@ const ( func loadPlugins(repoPath string) (*loader.PluginLoader, error) { pluginpath := filepath.Join(repoPath, "plugins") + plugins, err := loader.NewPluginLoader() + if err != nil { + return nil, fmt.Errorf("error loading preloaded plugins: %s", err) + } + // check if repo is accessible before loading plugins - var plugins *loader.PluginLoader ok, err := checkPermissions(repoPath) if err != nil { return nil, err } - if !ok { - pluginpath = "" - } - plugins, err = loader.NewPluginLoader(pluginpath) - if err != nil { - return nil, fmt.Errorf("error loading plugins: %s", err) + if ok { + if err := plugins.LoadDirectory(pluginpath); err != nil { + return nil, err + } } if err := plugins.Initialize(); err != nil { diff --git a/plugin/loader/loader.go b/plugin/loader/loader.go index f2a9ab60c4e..5f0e0891a6a 100644 --- a/plugin/loader/loader.go +++ b/plugin/loader/loader.go @@ -21,43 +21,113 @@ var loadPluginsFunc = func(string) ([]plugin.Plugin, error) { return nil, nil } +type loaderState int + +const ( + loaderLoading loaderState = iota + loaderInitializing + loaderInitialized + loaderInjecting + loaderInjected + loaderStarting + loaderStarted + loaderClosing + loaderClosed + loaderFailed +) + +func (ls loaderState) String() string { + switch ls { + case loaderLoading: + return "Loading" + case loaderInitializing: + return "Initializing" + case loaderInitialized: + return "Initialized" + case loaderInjecting: + return "Injecting" + case loaderInjected: + return "Injected" + case loaderStarting: + return "Starting" + case loaderStarted: + return "Started" + case loaderClosing: + return "Closing" + case loaderClosed: + return "Closed" + case loaderFailed: + return "Failed" + default: + return "Unknown" + } +} + // PluginLoader keeps track of loaded plugins type PluginLoader struct { - plugins []plugin.Plugin + state loaderState + plugins map[string]plugin.Plugin + started []plugin.Plugin } // NewPluginLoader creates new plugin loader -func NewPluginLoader(pluginDir string) (*PluginLoader, error) { - plMap := make(map[string]plugin.Plugin) +func NewPluginLoader() (*PluginLoader, error) { + loader := &PluginLoader{plugins: make(map[string]plugin.Plugin, len(preloadPlugins))} for _, v := range preloadPlugins { - plMap[v.Name()] = v - } - - if pluginDir != "" { - newPls, err := loadDynamicPlugins(pluginDir) - if err != nil { + if err := loader.Load(v); err != nil { return nil, err } + } + return loader, nil +} - for _, pl := range newPls { - if ppl, ok := plMap[pl.Name()]; ok { - // plugin is already preloaded - return nil, fmt.Errorf( - "plugin: %s, is duplicated in version: %s, "+ - "while trying to load dynamically: %s", - ppl.Name(), ppl.Version(), pl.Version()) - } - plMap[pl.Name()] = pl - } +func (loader *PluginLoader) assertState(state loaderState) error { + if loader.state != state { + return fmt.Errorf("loader state must be %s, was %s", state, loader.state) } + return nil +} - loader := &PluginLoader{plugins: make([]plugin.Plugin, 0, len(plMap))} +func (loader *PluginLoader) transition(from, to loaderState) error { + if err := loader.assertState(from); err != nil { + return err + } + loader.state = to + return nil +} - for _, v := range plMap { - loader.plugins = append(loader.plugins, v) +func (loader *PluginLoader) Load(pl plugin.Plugin) error { + if err := loader.assertState(loaderLoading); err != nil { + return err } - return loader, nil + name := pl.Name() + if ppl, ok := loader.plugins[name]; ok { + // plugin is already loaded + return fmt.Errorf( + "plugin: %s, is duplicated in version: %s, "+ + "while trying to load dynamically: %s", + name, ppl.Version(), pl.Version()) + } + loader.plugins[name] = pl + return nil +} + +func (loader *PluginLoader) LoadDirectory(pluginDir string) error { + if err := loader.assertState(loaderLoading); err != nil { + return err + } + newPls, err := loadDynamicPlugins(pluginDir) + if err != nil { + return err + } + + for _, pl := range newPls { + if err := loader.Load(pl); err != nil { + return err + } + } + return nil } func loadDynamicPlugins(pluginDir string) ([]plugin.Plugin, error) { @@ -74,63 +144,85 @@ func loadDynamicPlugins(pluginDir string) ([]plugin.Plugin, error) { // Initialize initializes all loaded plugins func (loader *PluginLoader) Initialize() error { + if err := loader.transition(loaderLoading, loaderInitializing); err != nil { + return err + } for _, p := range loader.plugins { err := p.Init() if err != nil { + loader.state = loaderFailed return err } } - return nil + return loader.transition(loaderInitializing, loaderInitialized) } // Inject hooks all the plugins into the appropriate subsystems. func (loader *PluginLoader) Inject() error { + if err := loader.transition(loaderInitialized, loaderInjecting); err != nil { + return err + } + for _, pl := range loader.plugins { if pl, ok := pl.(plugin.PluginIPLD); ok { err := injectIPLDPlugin(pl) if err != nil { + loader.state = loaderFailed return err } } if pl, ok := pl.(plugin.PluginTracer); ok { err := injectTracerPlugin(pl) if err != nil { + loader.state = loaderFailed return err } } if pl, ok := pl.(plugin.PluginDatastore); ok { err := injectDatastorePlugin(pl) if err != nil { + loader.state = loaderFailed return err } } } - return nil + + return loader.transition(loaderInjecting, loaderInjected) } // Start starts all long-running plugins. func (loader *PluginLoader) Start(iface coreiface.CoreAPI) error { - for i, pl := range loader.plugins { + if err := loader.transition(loaderInjected, loaderStarting); err != nil { + return err + } + for _, pl := range loader.plugins { if pl, ok := pl.(plugin.PluginDaemon); ok { err := pl.Start(iface) if err != nil { - _ = closePlugins(loader.plugins[:i]) + _ = loader.Close() return err } + loader.started = append(loader.started, pl) } } - return nil + + return loader.transition(loaderStarting, loaderStarted) } // StopDaemon stops all long-running plugins. func (loader *PluginLoader) Close() error { - return closePlugins(loader.plugins) -} + switch loader.state { + case loaderClosing, loaderFailed, loaderClosed: + // nothing to do. + return nil + } + loader.state = loaderClosing -func closePlugins(plugins []plugin.Plugin) error { var errs []string - for _, pl := range plugins { + started := loader.started + loader.started = nil + for _, pl := range started { if pl, ok := pl.(plugin.PluginDaemon); ok { err := pl.Close() if err != nil { @@ -143,8 +235,10 @@ func closePlugins(plugins []plugin.Plugin) error { } } if errs != nil { + loader.state = loaderFailed return fmt.Errorf(strings.Join(errs, "\n")) } + loader.state = loaderClosed return nil } diff --git a/repo/fsrepo/config_test.go b/repo/fsrepo/config_test.go index f7c19c30765..109860caed2 100644 --- a/repo/fsrepo/config_test.go +++ b/repo/fsrepo/config_test.go @@ -75,7 +75,7 @@ var measureConfig = []byte(`{ }`) func TestDefaultDatastoreConfig(t *testing.T) { - loader, err := loader.NewPluginLoader("") + loader, err := loader.NewPluginLoader() if err != nil { t.Fatal(err) } From a9f749014912ad4e3862bdfc52bfa3e861463278 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Fri, 28 Jun 2019 08:47:38 +0200 Subject: [PATCH 065/671] feat(plugins): add a bit of documentation --- plugin/loader/loader.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/plugin/loader/loader.go b/plugin/loader/loader.go index 5f0e0891a6a..b2276e1d7a1 100644 --- a/plugin/loader/loader.go +++ b/plugin/loader/loader.go @@ -63,7 +63,15 @@ func (ls loaderState) String() string { } } -// PluginLoader keeps track of loaded plugins +// PluginLoader keeps track of loaded plugins. +// +// To use: +// 1. Load any desired plugins with Load and LoadDirectory. Preloaded plugins +// will automatically be loaded. +// 2. Call Initialize to run all initialization logic. +// 3. Call Inject to register the plugins. +// 4. Optionally call Start to start plugins. +// 5. Call Close to close all plugins. type PluginLoader struct { state loaderState plugins map[string]plugin.Plugin @@ -96,6 +104,7 @@ func (loader *PluginLoader) transition(from, to loaderState) error { return nil } +// Load loads a plugin into the plugin loader. func (loader *PluginLoader) Load(pl plugin.Plugin) error { if err := loader.assertState(loaderLoading); err != nil { return err @@ -113,6 +122,7 @@ func (loader *PluginLoader) Load(pl plugin.Plugin) error { return nil } +// LoadDirectory loads a directory of plugins into the plugin loader. func (loader *PluginLoader) LoadDirectory(pluginDir string) error { if err := loader.assertState(loaderLoading); err != nil { return err From 074305690a36482ca6f32a18c29c241f542a2421 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Sat, 29 Jun 2019 10:32:17 +0200 Subject: [PATCH 066/671] fix: ignore stale APIs fixes #5784 --- cmd/ipfs/main.go | 213 ++++++++++++++++++----------------------------- go.mod | 3 +- go.sum | 4 +- 3 files changed, 85 insertions(+), 135 deletions(-) diff --git a/cmd/ipfs/main.go b/cmd/ipfs/main.go index 26973553dfa..7beab2bb1c1 100644 --- a/cmd/ipfs/main.go +++ b/cmd/ipfs/main.go @@ -21,7 +21,6 @@ import ( repo "github.com/ipfs/go-ipfs/repo" fsrepo "github.com/ipfs/go-ipfs/repo/fsrepo" - osh "github.com/Kubuxu/go-os-helper" "github.com/ipfs/go-ipfs-cmds" "github.com/ipfs/go-ipfs-cmds/cli" "github.com/ipfs/go-ipfs-cmds/http" @@ -195,21 +194,90 @@ func checkDebug(req *cmds.Request) { } } +func apiAddrOption(req *cmds.Request) (ma.Multiaddr, error) { + apiAddrStr, apiSpecified := req.Options[corecmds.ApiOption].(string) + if !apiSpecified { + return nil, nil + } + return ma.NewMultiaddr(apiAddrStr) +} + func makeExecutor(req *cmds.Request, env interface{}) (cmds.Executor, error) { + exe := cmds.NewExecutor(req.Root) + cctx := env.(*oldcmds.Context) details := commandDetails(req.Path) - client, err := commandShouldRunOnDaemon(*details, req, env.(*oldcmds.Context)) + + // Check if the command is disabled. + if details.cannotRunOnClient && details.cannotRunOnDaemon { + return nil, fmt.Errorf("command disabled: %v", req.Path) + } + + // Can we just run this locally? + if !details.cannotRunOnClient && details.doesNotUseRepo { + return exe, nil + } + + // Get the API option from the commandline. + apiAddr, err := apiAddrOption(req) if err != nil { return nil, err } - var exctr cmds.Executor - if client != nil && !req.Command.External { - exctr = client.(cmds.Executor) - } else { - exctr = cmds.NewExecutor(req.Root) + // Force the daemon when the API flag is passed (unless we're trying to + // _run_ the daemon). + daemonForced := apiAddr != nil && req.Command != daemonCmd + + // Run this on the client if required. + if details.cannotRunOnDaemon || req.Command.External { + if daemonForced { + // User requested that the command be run on the daemon but we can't. + // NOTE: We drop this check for the `ipfs daemon` command. + return nil, errors.New("api flag specified but command cannot be run on the daemon") + } + return exe, nil + } + + // Finally, look in the repo for an API file. + if apiAddr == nil { + var err error + apiAddr, err = fsrepo.APIAddr(cctx.ConfigRoot) + switch err { + case nil, repo.ErrApiNotRunning: + default: + return nil, err + } } - return exctr, nil + // Still no api specified? Run it on the client or fail. + if apiAddr == nil { + if details.cannotRunOnClient { + return nil, fmt.Errorf("command must be run on the daemon: %v", req.Path) + } + return exe, nil + } + + // Resolve the API addr. + apiAddr, err = resolveAddr(req.Context, apiAddr) + if err != nil { + return nil, err + } + _, host, err := manet.DialArgs(apiAddr) + if err != nil { + return nil, err + } + + // Construct the executor. + opts := []http.ClientOpt{ + http.ClientWithAPIPrefix(corehttp.APIPath), + } + + // Fallback on a local executor if we (a) have a repo and (b) aren't + // forcing a daemon. + if !daemonForced && fsrepo.IsInitialized(cctx.ConfigRoot) { + opts = append(opts, http.ClientWithFallback(exe)) + } + + return http.NewClient(host, opts...), nil } func checkPermissions(path string) (bool, error) { @@ -227,7 +295,11 @@ func checkPermissions(path string) (bool, error) { } // commandDetails returns a command's details for the command given by |path|. -func commandDetails(path []string) *cmdDetails { +func commandDetails(path []string) cmdDetails { + if len(path) == 0 { + // special case root command + return cmdDetails{doesNotUseRepo: true} + } var details cmdDetails // find the last command in path that has a cmdDetailsMap entry for i := range path { @@ -235,67 +307,7 @@ func commandDetails(path []string) *cmdDetails { details = cmdDetails } } - return &details -} - -// commandShouldRunOnDaemon determines, from command details, whether a -// command ought to be executed on an ipfs daemon. -// -// It returns a client if the command should be executed on a daemon and nil if -// it should be executed on a client. It returns an error if the command must -// NOT be executed on either. -func commandShouldRunOnDaemon(details cmdDetails, req *cmds.Request, cctx *oldcmds.Context) (http.Client, error) { - path := req.Path - // root command. - if len(path) < 1 { - return nil, nil - } - - if details.cannotRunOnClient && details.cannotRunOnDaemon { - return nil, fmt.Errorf("command disabled: %s", path[0]) - } - - if details.doesNotUseRepo && details.canRunOnClient() { - return nil, nil - } - - // at this point need to know whether api is running. we defer - // to this point so that we don't check unnecessarily - - // did user specify an api to use for this command? - apiAddrStr, _ := req.Options[corecmds.ApiOption].(string) - - client, err := getAPIClient(req.Context, cctx.ConfigRoot, apiAddrStr) - if err == repo.ErrApiNotRunning { - if apiAddrStr != "" && req.Command != daemonCmd { - // if user SPECIFIED an api, and this cmd is not daemon - // we MUST use it. so error out. - return nil, err - } - - // ok for api not to be running - } else if err != nil { // some other api error - return nil, err - } - - if client != nil { - if details.cannotRunOnDaemon { - // check if daemon locked. legacy error text, for now. - log.Debugf("Command cannot run on daemon. Checking if daemon is locked") - if daemonLocked, _ := fsrepo.LockedByOtherProcess(cctx.ConfigRoot); daemonLocked { - return nil, cmds.ClientError("ipfs daemon is running. please stop it to run this command") - } - return nil, nil - } - - return client, nil - } - - if details.cannotRunOnClient { - return nil, cmds.ClientError("must run on the ipfs daemon") - } - - return nil, nil + return details } func getRepoPath(req *cmds.Request) (string, error) { @@ -366,67 +378,6 @@ func profileIfEnabled() (func(), error) { return func() {}, nil } -var apiFileErrorFmt string = `Failed to parse '%[1]s/api' file. - error: %[2]s -If you're sure go-ipfs isn't running, you can just delete it. -` -var checkIPFSUnixFmt = "Otherwise check:\n\tps aux | grep ipfs" -var checkIPFSWinFmt = "Otherwise check:\n\ttasklist | findstr ipfs" - -// getAPIClient checks the repo, and the given options, checking for -// a running API service. if there is one, it returns a client. -// otherwise, it returns errApiNotRunning, or another error. -func getAPIClient(ctx context.Context, repoPath, apiAddrStr string) (http.Client, error) { - var apiErrorFmt string - switch { - case osh.IsUnix(): - apiErrorFmt = apiFileErrorFmt + checkIPFSUnixFmt - case osh.IsWindows(): - apiErrorFmt = apiFileErrorFmt + checkIPFSWinFmt - default: - apiErrorFmt = apiFileErrorFmt - } - - var addr ma.Multiaddr - var err error - if len(apiAddrStr) != 0 { - addr, err = ma.NewMultiaddr(apiAddrStr) - if err != nil { - return nil, err - } - if len(addr.Protocols()) == 0 { - return nil, fmt.Errorf("multiaddr doesn't provide any protocols") - } - } else { - addr, err = fsrepo.APIAddr(repoPath) - if err == repo.ErrApiNotRunning { - return nil, err - } - - if err != nil { - return nil, fmt.Errorf(apiErrorFmt, repoPath, err.Error()) - } - } - if len(addr.Protocols()) == 0 { - return nil, fmt.Errorf(apiErrorFmt, repoPath, "multiaddr doesn't provide any protocols") - } - return apiClientForAddr(ctx, addr) -} - -func apiClientForAddr(ctx context.Context, addr ma.Multiaddr) (http.Client, error) { - addr, err := resolveAddr(ctx, addr) - if err != nil { - return nil, err - } - - _, host, err := manet.DialArgs(addr) - if err != nil { - return nil, err - } - - return http.NewClient(host, http.ClientWithAPIPrefix(corehttp.APIPath)), nil -} - func resolveAddr(ctx context.Context, addr ma.Multiaddr) (ma.Multiaddr, error) { ctx, cancelFunc := context.WithTimeout(ctx, 10*time.Second) defer cancelFunc() diff --git a/go.mod b/go.mod index 845548a46e4..9403511ce3a 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,6 @@ module github.com/ipfs/go-ipfs require ( bazil.org/fuse v0.0.0-20180421153158-65cc252bf669 - github.com/Kubuxu/go-os-helper v0.0.1 github.com/Kubuxu/gocovmerge v0.0.0-20161216165753-7ecaa51963cd github.com/blang/semver v3.5.1+incompatible github.com/bren2010/proquint v0.0.0-20160323162903-38337c27106d @@ -32,7 +31,7 @@ require ( github.com/ipfs/go-ipfs-blockstore v0.0.1 github.com/ipfs/go-ipfs-blocksutil v0.0.1 github.com/ipfs/go-ipfs-chunker v0.0.1 - github.com/ipfs/go-ipfs-cmds v0.0.10 + github.com/ipfs/go-ipfs-cmds v0.1.0 github.com/ipfs/go-ipfs-config v0.0.6 github.com/ipfs/go-ipfs-ds-help v0.0.1 github.com/ipfs/go-ipfs-exchange-interface v0.0.1 diff --git a/go.sum b/go.sum index 337302c8ad7..c05f54f1923 100644 --- a/go.sum +++ b/go.sum @@ -247,8 +247,8 @@ github.com/ipfs/go-ipfs-blocksutil v0.0.1 h1:Eh/H4pc1hsvhzsQoMEP3Bke/aW5P5rVM1IW github.com/ipfs/go-ipfs-blocksutil v0.0.1/go.mod h1:Yq4M86uIOmxmGPUHv/uI7uKqZNtLb449gwKqXjIsnRk= github.com/ipfs/go-ipfs-chunker v0.0.1 h1:cHUUxKFQ99pozdahi+uSC/3Y6HeRpi9oTeUHbE27SEw= github.com/ipfs/go-ipfs-chunker v0.0.1/go.mod h1:tWewYK0we3+rMbOh7pPFGDyypCtvGcBFymgY4rSDLAw= -github.com/ipfs/go-ipfs-cmds v0.0.10 h1:4kA3E94HbDrLb4RZTkX3yXyUjKv50RfPz0Pv9xkP2cA= -github.com/ipfs/go-ipfs-cmds v0.0.10/go.mod h1:TiK4e7/V31tuEb8YWDF8lN3qrnDH+BS7ZqWIeYJlAs8= +github.com/ipfs/go-ipfs-cmds v0.1.0 h1:0CEde9EcxByej8+L6d1PST57J4ambRPyCTjLG5Ymou8= +github.com/ipfs/go-ipfs-cmds v0.1.0/go.mod h1:TiK4e7/V31tuEb8YWDF8lN3qrnDH+BS7ZqWIeYJlAs8= github.com/ipfs/go-ipfs-config v0.0.5 h1:D9ek19anOzm8iYPvezeeamSg5mzwqKPb2jyAyJZT/4A= github.com/ipfs/go-ipfs-config v0.0.5/go.mod h1:IGkVTacurWv9WFKc7IBPjHGM/7hi6+PEClqUb/l2BIM= github.com/ipfs/go-ipfs-config v0.0.6 h1:jzK9Tl8S0oWBir3F5ObtGgnHRPdqQ0MYiCmwXtV3Ps4= From e96416dea6a3ac23ba95d7fcd33e5325e7e2888e Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Sat, 29 Jun 2019 11:10:31 +0200 Subject: [PATCH 067/671] test: test operations when the API file is stale --- test/sharness/t0064-api-file.sh | 100 ++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100755 test/sharness/t0064-api-file.sh diff --git a/test/sharness/t0064-api-file.sh b/test/sharness/t0064-api-file.sh new file mode 100755 index 00000000000..97c1a7b239c --- /dev/null +++ b/test/sharness/t0064-api-file.sh @@ -0,0 +1,100 @@ +#!/usr/bin/env bash +# +# MIT Licensed; see the LICENSE file in this repository. +# + +test_description="Test api file" + +. lib/test-lib.sh + +test_init_ipfs + + +test_launch_ipfs_daemon +test_kill_ipfs_daemon + +test_expect_success "version always works" ' + ipfs version >/dev/null +' + +test_expect_success "swarm peers fails when offline" ' + test_must_fail ipfs swarm peers >/dev/null +' + +test_expect_success "swarm peers fails when offline and API specified" ' + test_must_fail ipfs swarm peers --api="$API_MADDR" >/dev/null +' + +test_expect_success "pin ls succeeds when offline" ' + ipfs pin ls >/dev/null +' + +test_expect_success "pin ls fails when offline and API specified" ' + test_must_fail ipfs pin ls --api="$API_MADDR" >/dev/null +' + +test_expect_success "id succeeds when offline" ' + ipfs id >/dev/null +' + +test_expect_success "id fails when offline API specified" ' + test_must_fail ipfs id --api="$API_MADDR" >/dev/null +' + +test_expect_success "create API file" ' + echo "$API_MADDR" > "$IPFS_PATH/api" +' + +test_expect_success "version always works" ' + ipfs version >/dev/null +' + +test_expect_success "id succeeds when offline and API file exists" ' + ipfs id >/dev/null +' + +test_expect_success "pin ls succeeds when offline and API file exists" ' + ipfs pin ls >/dev/null +' + +test_launch_ipfs_daemon + +test_expect_success "version always works" ' + ipfs version >/dev/null +' + +test_expect_success "id succeeds when online" ' + ipfs id >/dev/null +' + +test_expect_success "swarm peers succeeds when online" ' + ipfs swarm peers >/dev/null +' + +test_expect_success "pin ls succeeds when online" ' + ipfs pin ls >/dev/null +' + +test_expect_success "remove API file when daemon is running" ' + rm "$IPFS_PATH/api" +' + +test_expect_success "version always works" ' + ipfs version >/dev/null +' + +test_expect_success "swarm peers fails when the API file is missing" ' + test_must_fail ipfs swarm peers >/dev/null +' + +test_expect_success "id fails when daemon is running but API file is missing (locks repo)" ' + test_must_fail ipfs pin ls >/dev/null +' + +test_expect_success "pin ls fails when daemon is running but API file is missing (locks repo)" ' + test_must_fail ipfs pin ls >/dev/null +' + +test_kill_ipfs_daemon + +test_done From b10e3891357956021516eec0b4463d4c351af595 Mon Sep 17 00:00:00 2001 From: Michael Avila Date: Tue, 2 Jul 2019 09:49:55 -0700 Subject: [PATCH 068/671] Change queue to be timestamp based --- provider/queue/queue.go | 122 +++++++++-------------------------- provider/queue/queue_test.go | 44 +++---------- 2 files changed, 37 insertions(+), 129 deletions(-) diff --git a/provider/queue/queue.go b/provider/queue/queue.go index 2afbc81ee9b..dceb67447a7 100644 --- a/provider/queue/queue.go +++ b/provider/queue/queue.go @@ -3,8 +3,7 @@ package queue import ( "context" "fmt" - "strconv" - "strings" + "time" cid "github.com/ipfs/go-cid" datastore "github.com/ipfs/go-datastore" @@ -25,8 +24,6 @@ type Queue struct { // e.g. provider vs reprovider name string ctx context.Context - tail uint64 - head uint64 ds datastore.Datastore // Must be threadsafe dequeue chan cid.Cid enqueue chan cid.Cid @@ -37,16 +34,10 @@ type Queue struct { // NewQueue creates a queue for cids func NewQueue(ctx context.Context, name string, ds datastore.Datastore) (*Queue, error) { namespaced := namespace.Wrap(ds, datastore.NewKey("/"+name+"/queue/")) - head, tail, err := getQueueHeadTail(ctx, namespaced) - if err != nil { - return nil, err - } cancelCtx, cancel := context.WithCancel(ctx) q := &Queue{ name: name, ctx: cancelCtx, - head: head, - tail: tail, ds: namespaced, dequeue: make(chan cid.Cid), enqueue: make(chan cid.Cid), @@ -77,41 +68,6 @@ func (q *Queue) Dequeue() <-chan cid.Cid { return q.dequeue } -// Look for next Cid in the queue and return it. Skip over gaps and mangled data -func (q *Queue) nextEntry() (datastore.Key, cid.Cid) { - for { - if q.head >= q.tail { - return datastore.Key{}, cid.Undef - } - - key := q.queueKey(q.head) - value, err := q.ds.Get(key) - - if err != nil { - if err == datastore.ErrNotFound { - log.Warningf("Error missing entry in queue: %s", key) - } else { - log.Errorf("Error fetching from queue: %s", err) - } - q.head++ // move on - continue - } - - c, err := cid.Parse(value) - if err != nil { - log.Warningf("Error marshalling Cid from queue: ", err) - q.head++ - err = q.ds.Delete(key) - if err != nil { - log.Warningf("Provider queue failed to delete: %s", key) - } - continue - } - - return key, c - } -} - // Run dequeues and enqueues when available. func (q *Queue) work() { go func() { @@ -124,7 +80,26 @@ func (q *Queue) work() { for { if c == cid.Undef { - k, c = q.nextEntry() + head, e := q.getQueueHead() + + if e != nil { + log.Errorf("error querying for head of queue: %s, stopping provider", e) + return + } else if head != nil { + k = datastore.NewKey(head.Key) + c, e = cid.Parse(head.Value) + if e != nil { + log.Warningf("error parsing queue entry cid with key (%s), removing it from queue: %s", head.Key, e) + err := q.ds.Delete(k) + if err != nil { + log.Errorf("error deleting queue entry with key (%s), due to error (%s), stopping provider", head.Key, err) + return + } + continue + } + } else { + c = cid.Undef + } } // If c != cid.Undef set dequeue and attempt write, otherwise wait for enqueue @@ -135,14 +110,12 @@ func (q *Queue) work() { select { case toQueue := <-q.enqueue: - nextKey := q.queueKey(q.tail) + nextKey := datastore.NewKey(fmt.Sprintf("%d", time.Now().UnixNano())) if err := q.ds.Put(nextKey, toQueue.Bytes()); err != nil { log.Errorf("Failed to enqueue cid: %s", err) continue } - - q.tail++ case dequeue <- c: err := q.ds.Delete(k) @@ -151,7 +124,6 @@ func (q *Queue) work() { continue } c = cid.Undef - q.head++ case <-q.ctx.Done(): return } @@ -159,53 +131,17 @@ func (q *Queue) work() { }() } -func (q *Queue) queueKey(id uint64) datastore.Key { - s := fmt.Sprintf("%016X", id) - return datastore.NewKey(s) -} - -func getQueueHeadTail(ctx context.Context, datastore datastore.Datastore) (uint64, uint64, error) { - head, err := getQueueHead(datastore) - if err != nil { - return 0, 0, err - } - tail, err := getQueueTail(datastore) - if err != nil { - return 0, 0, err - } - return head, tail, nil -} - -func getQueueHead(ds datastore.Datastore) (uint64, error) { - return getFirstIDByOrder(ds, query.OrderByKey{}) -} - -func getQueueTail(ds datastore.Datastore) (uint64, error) { - tail, err := getFirstIDByOrder(ds, query.OrderByKeyDescending{}) +func (q *Queue) getQueueHead() (*query.Result, error) { + qry := query.Query{Orders: []query.Order{query.OrderByKey{}}} + results, err := q.ds.Query(qry) if err != nil { - return 0, err - } - if tail > 0 { - tail++ - } - return tail, nil -} - -func getFirstIDByOrder(ds datastore.Datastore, order query.Order) (uint64, error) { - q := query.Query{Orders: []query.Order{order}} - results, err := ds.Query(q) - if err != nil { - return 0, err + return nil, err } defer results.Close() r, ok := results.NextSync() if !ok { - return 0, nil - } - trimmed := strings.TrimPrefix(r.Key, "/") - id, err := strconv.ParseUint(trimmed, 16, 64) - if err != nil { - return 0, err + return nil, nil } - return id, nil + + return &r, nil } diff --git a/provider/queue/queue_test.go b/provider/queue/queue_test.go index c8fb8682e31..819fa90f978 100644 --- a/provider/queue/queue_test.go +++ b/provider/queue/queue_test.go @@ -5,9 +5,9 @@ import ( "testing" "time" - cid "github.com/ipfs/go-cid" - datastore "github.com/ipfs/go-datastore" - sync "github.com/ipfs/go-datastore/sync" + "github.com/ipfs/go-cid" + "github.com/ipfs/go-datastore" + "github.com/ipfs/go-datastore/sync" "github.com/ipfs/go-ipfs-blocksutil" ) @@ -55,36 +55,6 @@ func TestBasicOperation(t *testing.T) { assertOrdered(cids, queue, t) } -func TestSparseDatastore(t *testing.T) { - ctx := context.Background() - defer ctx.Done() - - ds := sync.MutexWrap(datastore.NewMapDatastore()) - queue, err := NewQueue(ctx, "test", ds) - if err != nil { - t.Fatal(err) - } - - cids := makeCids(10) - for _, c := range cids { - queue.Enqueue(c) - } - - // remove entries in the middle - err = queue.ds.Delete(queue.queueKey(5)) - if err != nil { - t.Fatal(err) - } - - err = queue.ds.Delete(queue.queueKey(6)) - if err != nil { - t.Fatal(err) - } - - expected := append(cids[:5], cids[7:]...) - assertOrdered(expected, queue, t) -} - func TestMangledData(t *testing.T) { ctx := context.Background() defer ctx.Done() @@ -100,13 +70,15 @@ func TestMangledData(t *testing.T) { queue.Enqueue(c) } - // remove entries in the middle - err = queue.ds.Put(queue.queueKey(5), []byte("borked")) + // put bad data in the queue + queueKey := datastore.NewKey("/test/0") + err = queue.ds.Put(queueKey, []byte("borked")) if err != nil { t.Fatal(err) } - expected := append(cids[:5], cids[6:]...) + // expect to only see the valid cids we entered + expected := cids assertOrdered(expected, queue, t) } From 2ef67c97319f8669362305349d8c818542de26d3 Mon Sep 17 00:00:00 2001 From: Michael Avila Date: Tue, 2 Jul 2019 09:50:14 -0700 Subject: [PATCH 069/671] Avoid collisions by appending cid --- provider/queue/queue.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/provider/queue/queue.go b/provider/queue/queue.go index dceb67447a7..29355223371 100644 --- a/provider/queue/queue.go +++ b/provider/queue/queue.go @@ -110,7 +110,8 @@ func (q *Queue) work() { select { case toQueue := <-q.enqueue: - nextKey := datastore.NewKey(fmt.Sprintf("%d", time.Now().UnixNano())) + keyPath := fmt.Sprintf("%d/%s", time.Now().UnixNano(), c.String()) + nextKey := datastore.NewKey(keyPath) if err := q.ds.Put(nextKey, toQueue.Bytes()); err != nil { log.Errorf("Failed to enqueue cid: %s", err) From 143e41570bca067d92bec85cfa5e5fe283946f21 Mon Sep 17 00:00:00 2001 From: Michael Avila Date: Tue, 2 Jul 2019 13:15:14 -0700 Subject: [PATCH 070/671] Add limit for getQueueHead call --- provider/queue/queue.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/provider/queue/queue.go b/provider/queue/queue.go index 29355223371..ddaa97582e8 100644 --- a/provider/queue/queue.go +++ b/provider/queue/queue.go @@ -133,7 +133,7 @@ func (q *Queue) work() { } func (q *Queue) getQueueHead() (*query.Result, error) { - qry := query.Query{Orders: []query.Order{query.OrderByKey{}}} + qry := query.Query{Orders: []query.Order{query.OrderByKey{}}, Limit: 1} results, err := q.ds.Query(qry) if err != nil { return nil, err From 6751f714baf4f19e7ebe449402a9b2491eaa6ef1 Mon Sep 17 00:00:00 2001 From: David Dias Date: Wed, 3 Jul 2019 09:23:48 +0200 Subject: [PATCH 071/671] docs: update Release Flow --- docs/releases.md | 182 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 150 insertions(+), 32 deletions(-) diff --git a/docs/releases.md b/docs/releases.md index fb75ed8e766..3e2c0abfb6d 100644 --- a/docs/releases.md +++ b/docs/releases.md @@ -1,39 +1,157 @@ -# go-ipfs releases +# `go-ipfs` Release Flow -## Release Schedule -go-ipfs is on a six week release schedule. Following a release, there will be -five weeks for code of any type (features, bugfixes, etc) to be added. After -the five weeks is up, a release candidate is tagged and only important bugfixes -will be allowed up to release day. +## Table of Contents -## Release Candidate Checklist -- [ ] CHANGELOG.md has been updated - - use `./bin/mkreleaselog` to generate a nice starter list +- [Release Philosophy](#release-philosophy) +- [Release Flow](#release-flow) +- [Performing a Release](#performing-a-release) +- [Release Version Numbers (aka semver)](#release-version-numbers-aka-semver) + +## Release Philosophy + +`go-ipfs` aims to have release every six weeks, two releases per quarter. During these 6 week releases, we go through 4 different stages of Release Candidates (RC) that gives us the opportunity to test the new version against our test envinronments, production envinronments, IPFS apps (e.g. Desktop and WebUI) and with our close partners that have IPFS running in Production, by leveraging their own test infrastructure. + +We might expand the six week release schedule in case of: +- No new updates to be added +- In case of a large community event that takes the core team availability away (e.g. IPFS Conf, Dev Meetings, IPFS Camp, etc) + +## Release Flow + +`go-ipfs` releases come in 4 stages: + +- **Release Stage 1 - Internal testing** - Test the Release against our testing infrastructure, including interoperability, integration, test lab, multiple runtimes and the apps we've built (WebUI, Desktop, NPM on IPFS, HTTP Client Libraries). The intent is to make this stage fully automated (and somewhat is already), until then, we manually check a list and ensure that all tests have been run +- **Release Stage 2 - Invite IPFS partners to test** - Reach out to our partners (i.e. projects that have volunteered to support `go-ipfs` by using their own test infrastructure and tell us the results) +- **Release Stage 3 - Announce to the broader community** - Communicate to the community that a new Release Candidate is ready and that everyone is welcome to test it with us +- **Release Stage 4 - Complete the Release** - Finalize the release, start the next release. + +The Release Stages are not linked to Release Candidate numbers, in fact, there can be multiple release candidate per stages as we catch bugs and improve the release itself. + +

+ + + +

+ +## Performing a Release + +The first step is for the `Lead Maintainer` for `go-ipfs` to open an issue with Title `go-ipfs Release` and a c&p of the following template: + +``` +> + +# 🗺 What's left for release + + + +# 🔦 Highlights + + + +# 🏗 API Changes + + + +# ✅ Release Checklist + +For each RC published in each stage: - [ ] version string in `version.go` has been updated - [ ] tag commit with vX.Y.Z-rcN -## Pre-Release Checklist -- [ ] before release, tag 'release candidate' for users to test against - - if bugs are found/fixed, do another release candidate -- [ ] all tests pass (no exceptions) -- [ ] run interop tests https://github.com/ipfs/interop#test-with-a-non-yet-released-version-of-go-ipfs -- [ ] webui works (for most definitions of 'works') - Test the multiple pages and verify that no visible errors are shown. +### Release Stage 1 - Internal testing + +When Release Stage 1, there is a features freeze for the release branch. + - [ ] CHANGELOG.md has been updated - use `./bin/mkreleaselog` to generate a nice starter list -- [ ] version string in `repo/version.go` has been updated -- [ ] tag commit with vX.Y.Z -- [ ] update release branch to point to release commit (`git merge vX.Y.Z`). -- [ ] publish dist.ipfs.io -- [ ] publish next version to https://github.com/ipfs/npm-go-ipfs - -## Post-Release -- [ ] Bump version string in `repo/version.go` to `vX.Y.Z-dev` -- [ ] Upload the final release to the github releases page: https://github.com/ipfs/go-ipfs/releases -- Communication - - [ ] Create the release issue - - [ ] Announcements (both pre-release and post-release) - - [ ] Twitter - - [ ] IRC - - [ ] Reddit - - [ ] Blog post (at minimum, paste the changelog. optionally add context and thank contributors.) -- [ ] Update HTTP-API Documentation on the Website using https://github.com/ipfs/http-api-docs +- [ ] Automated Testing - Ensure that all tests are passing, this includes: + - [ ] unit + - [ ] sharness + - [ ] [interop](https://github.com/ipfs/interop#test-with-a-non-yet-released-version-of-go-ipfs) +- [ ] Network Testing: + - [ ] test lab things +- [ ] Infrastructure Testing: + - [ ] Deploy new version to a subset of Bootstrappers + - [ ] Deploy new version to a subset of Gateways + - [ ] Deploy new version to a subset of Preload nodes + - [ ] Collect metrics every day. Work with the Infrastructure team to learn of any hiccup +- [ ] IPFS HTTP Client Libraries Testing: + - [ ] [JS](http://github.com/ipfs/js-ipfs-http-client) + - [ ] [Go](https://github.com/ipfs/go-ipfs-api) +- [ ] IPFS Application Testing - Run the tests of the following applications: + - [ ] WebUI + - [ ] IPFS Desktop + - [ ] IPFS Companion + - [ ] NPM on IPFS + +### Release Stage 2 - Invite IPFS partners to test + +- [ ] Reach out to the following IPFS partners for testing this release (check when no more problems have been reported): + - [ ] Infura + - [ ] Textila + - [ ] Open Bazaar + - [ ] QRI +- [ ] Run tests available in the following repos with the latest RC (check when all tests pass): + - [ ] [orbit-db](https://github.com/orbitdb/orbit-db) + +PSA: If you are a heavy user of `go-ipfs`, have developed a solid test infrastructure for your application and would love to help us would like to help us test `go-ipfs` release candidates, reach out to go-ipfs-wg@ipfs.io. + +### Release Stage 3 - Announce to the broader community + +- [ ] Documentation + - [ ] Ensure that CHANGELOG.md is up to date + - [ ] Ensure that README.md is up to date + - [ ] Ensure that all the examples we have produced for go-ipfs run without problems + - [ ] Update HTTP-API Documentation on the Website using https://github.com/ipfs/http-api-docs +- [ ] Invite the community through (link to the release issue): + - [ ] [discuss.ipfs.io](https://discuss.ipfs.io/c/announcements) + - [ ] Twitter + +### Release Stage 4 - Complete the Release + +- Take a snapshot between of everyone that has contributed to this release (including its subdeps in IPFS, libp2p, IPLD and multiformats) using [`name-your-contributors`](https://www.npmjs.com/package/name-your-contributors). Generate a nice markdown list with [this script](https://gist.github.com/alanshaw/5a2d9465c5a05b201d949551bdb1fcc3). Add it to this issue. + +- [ ] Final preparation + - [ ] Verify that version string in `repo/version.go` has been updated + - [ ] tag commit with vX.Y.Z + - [ ] update release branch to point to release commit (`git merge vX.Y.Z`). + - [ ] publish dist.ipfs.io + - [ ] publish next version to https://github.com/ipfs/npm-go-ipfs +- [ ] Publish a Release Blog post (at minimum, a c&p of this release issue with all the highlights, API changes, link to changelog and thank yous) +- [ ] Broadcasting (link to blog post) + - [ ] Twitter + - [ ] IRC + - [ ] Reddit + - [ ] [discuss.ipfs.io](https://discuss.ipfs.io/c/announcements) + - [ ] Announce it on the [IPFS Users mlist](https://groups.google.com/forum/#!forum/ipfs-users) + +# ❤️ Huge thank you to everyone that made this release possible + +In alphabetical order, here are all the humans that contributed to the release: + +- + +# 🙌🏽 Want to contribute? + +Would you like to contribute to the IPFS project and don't know how? Well, there are a few places you can get started: + +- Check the issues with the `help wanted` label in the [go-ipfs repo](https://github.com/ipfs/go-ipfs/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22) +- Join an IPFS All Hands, introduce yourself and let us know where you would like to contribute - https://github.com/ipfs/team-mgmt/#weekly-ipfs-all-hands +- Hack with IPFS and show us what you made! The All Hands call is also the perfect venue for demos, join in and show us what you built +- Join the discussion at http://discuss.ipfs.io/ and help users finding their answers. +- Join the [Go Core Dev Team Weekly Sync](https://github.com/ipfs/team-mgmt/issues/650) and be part of the Sprint action! + +# ⁉️ Do you have questions? + +The best place to ask your questions about IPFS, how it works and what you can do with it is at [discuss.ipfs.io](http://discuss.ipfs.io). We are also available at the `#ipfs` channel on Freenode. +``` + +## Release Version Numbers (aka semver) + +Until `go-ipfs` 0.4.X, `go-ipfs` was not using semver to communicate the type of relase + +Post `go-ipfs` 0.5.X, `go-ipfs` will use semver. This means that patch releases will not contain any breaking changes nor new features. Minor releases might contain breaking changes and always contain some new feature + +Post `go-ipfs` 1.X.X (future), `go-ipfs` will use semver. This means that only major releases will contain breaking changes, minors will be reserved for new features and patches for bug fixes. + +We do not yet retroactively apply fixes to older releases (no Long Term Support releases for now), which means that we always recommend users to update to the latest, whenever possible. +TBW From a066a707efd5d5a71b7aae7c580c2b67cb1e2c2d Mon Sep 17 00:00:00 2001 From: David Dias Date: Wed, 3 Jul 2019 11:52:16 +0200 Subject: [PATCH 072/671] Update docs/releases.md Co-Authored-By: Michael Burns <5170+mburns@users.noreply.github.com> --- docs/releases.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/releases.md b/docs/releases.md index 3e2c0abfb6d..7171cbb0603 100644 --- a/docs/releases.md +++ b/docs/releases.md @@ -147,7 +147,7 @@ The best place to ask your questions about IPFS, how it works and what you can d ## Release Version Numbers (aka semver) -Until `go-ipfs` 0.4.X, `go-ipfs` was not using semver to communicate the type of relase +Until `go-ipfs` 0.4.X, `go-ipfs` was not using semver to communicate the type of release Post `go-ipfs` 0.5.X, `go-ipfs` will use semver. This means that patch releases will not contain any breaking changes nor new features. Minor releases might contain breaking changes and always contain some new feature From 288a83ce7dcbf4a2498e06e4a95245bbb5e30f45 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Sat, 29 Jun 2019 11:15:30 +0200 Subject: [PATCH 073/671] feat: deprecate ipfs repo fsck command This command is no longer necessary and is quite dangerous: 1. All lockfiles are now released by the OS when the daemon stops. 2. The API file is ignored when (a) the repo is initialized and (b) daemon is off. fixes #6435 --- core/commands/repo.go | 39 +------ test/sharness/t0083-repo-fsck.sh | 190 ------------------------------- 2 files changed, 2 insertions(+), 227 deletions(-) delete mode 100755 test/sharness/t0083-repo-fsck.sh diff --git a/core/commands/repo.go b/core/commands/repo.go index 7d6b8a499a1..cef056c1961 100644 --- a/core/commands/repo.go +++ b/core/commands/repo.go @@ -6,7 +6,6 @@ import ( "fmt" "io" "os" - "path/filepath" "runtime" "strings" "sync" @@ -20,7 +19,6 @@ import ( cid "github.com/ipfs/go-cid" bstore "github.com/ipfs/go-ipfs-blockstore" cmds "github.com/ipfs/go-ipfs-cmds" - config "github.com/ipfs/go-ipfs-config" ) type RepoVersion struct { @@ -216,44 +214,11 @@ var repoFsckCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Remove repo lockfiles.", ShortDescription: ` -'ipfs repo fsck' is a plumbing command that will remove repo and level db -lockfiles, as well as the api file. This command can only run when no ipfs -daemons are running. +'ipfs repo fsck' is now a no-op. `, }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { - configRoot, err := cmdenv.GetConfigRoot(env) - if err != nil { - return err - } - - dsPath, err := config.DataStorePath(configRoot) - if err != nil { - return err - } - - dsLockFile := filepath.Join(dsPath, "LOCK") // TODO: get this lockfile programmatically - repoLockFile := filepath.Join(configRoot, fsrepo.LockFile) - apiFile := filepath.Join(configRoot, "api") // TODO: get this programmatically - - log.Infof("Removing repo lockfile: %s", repoLockFile) - log.Infof("Removing datastore lockfile: %s", dsLockFile) - log.Infof("Removing api file: %s", apiFile) - - err = os.Remove(repoLockFile) - if err != nil && !os.IsNotExist(err) { - return err - } - err = os.Remove(dsLockFile) - if err != nil && !os.IsNotExist(err) { - return err - } - err = os.Remove(apiFile) - if err != nil && !os.IsNotExist(err) { - return err - } - - return cmds.EmitOnce(res, &MessageOutput{"Lockfiles have been removed.\n"}) + return cmds.EmitOnce(res, &MessageOutput{"`ipfs repo fsck` is deprecated and does nothing.\n"}) }, Type: MessageOutput{}, Encoders: cmds.EncoderMap{ diff --git a/test/sharness/t0083-repo-fsck.sh b/test/sharness/t0083-repo-fsck.sh deleted file mode 100755 index fe567840cd5..00000000000 --- a/test/sharness/t0083-repo-fsck.sh +++ /dev/null @@ -1,190 +0,0 @@ -#!/usr/bin/env bash -# -# Copyright (c) 2016 Mike Pfister -# MIT Licensed; see the LICENSE file in this repository. -# - -test_description="Test ipfs repo fsck operations" - -. lib/test-lib.sh - -test_init_ipfs - -############################# -# Test without daemon running -############################# -# NOTE: if api file isn't present we can assume the daemon isn't running - -# Try with all lock files present: repo.lock, api, and datastore/LOCK with -# repo.lock and datastore/LOCK being empty -test_expect_success "'ipfs repo fsck' succeeds with no daemon running empty -repo.lock" ' - mkdir -p $IPFS_PATH && - mkdir -p $IPFS_PATH/datastore && - touch $IPFS_PATH/datastore/LOCK && - touch $IPFS_PATH/repo.lock && - printf "/ip4/127.0.0.1/tcp/5001" > "$IPFS_PATH/api" && - ipfs repo fsck > fsck_out_actual1 -' -test_expect_success "'ipfs repo fsck' output looks good with no daemon" ' - grep "Lockfiles have been removed." fsck_out_actual1 -' - -# Make sure the files are actually removed -test_expect_success "'ipfs repo fsck' confirm file deletion" ' - test ! -e "$IPFS_PATH/repo.lock" && - test ! -e "$IPFS_PATH/datastore/LOCK" && - test ! -e "$IPFS_PATH/api" -' - -# Try with all lock files present: repo.lock, api, and datastore/LOCK with -# repo.lock is non-zero TODO: this test is broken until we find consensus on the -# non-zero repo.lock issue -test_expect_success "'ipfs repo fsck' succeeds with no daemon running non-zero -repo.lock" ' - mkdir -p "$IPFS_PATH" && - printf ":D" > "$IPFS_PATH/repo.lock" && - touch "$IPFS_PATH/datastore/LOCK" && - ipfs repo fsck > fsck_out_actual1b -' -test_expect_success "'ipfs repo fsck' output looks good with no daemon" ' - grep "Lockfiles have been removed." fsck_out_actual1b -' - -# Make sure the files are actually removed -test_expect_success "'ipfs repo fsck' confirm file deletion" ' - test ! -e "$IPFS_PATH/repo.lock" && - test ! -e "$IPFS_PATH/datastore/LOCK" && - test ! -e "$IPFS_PATH/api" -' - -######################## -# Test for partial locks -######################## - -# Try with locks api and datastore/LOCK -test_expect_success "'ipfs repo fsck' succeeds partial lock" ' - printf "/ip4/127.0.0.1/tcp/5001" > "$IPFS_PATH/api" && - touch $IPFS_PATH/datastore/LOCK && - ipfs repo fsck > fsck_out_actual2 -' - -test_expect_success "'ipfs repo fsck' output looks good with no daemon" ' - grep "Lockfiles have been removed." fsck_out_actual2 -' - -# Make sure the files are actually removed -test_expect_success "'ipfs repo fsck' confirm file deletion" ' - test ! -e "$IPFS_PATH/repo.lock" && - test ! -e "$IPFS_PATH/datastore/LOCK" && - test ! -e "$IPFS_PATH/api" -' - -# Try with locks api and repo.lock -test_expect_success "'ipfs repo fsck' succeeds partial lock" ' - printf "/ip4/127.0.0.1/tcp/5001" > "$IPFS_PATH/api" && - touch $IPFS_PATH/repo.lock && - ipfs repo fsck > fsck_out_actual3 -' - -test_expect_success "'ipfs repo fsck' output looks good with no daemon" ' - grep "Lockfiles have been removed." fsck_out_actual3 -' - -# Make sure the files are actually removed -test_expect_success "'ipfs repo fsck' confirm file deletion" ' - test ! -e "$IPFS_PATH/repo.lock" && - test ! -e "$IPFS_PATH/datastore/LOCK" && - test ! -e "$IPFS_PATH/api" -' - -# Try with locks repo.lock and datastore -test_expect_success "'ipfs repo fsck' succeeds partial lock" ' - touch $IPFS_PATH/repo.lock && - touch $IPFS_PATH/datastore/LOCK && - ipfs repo fsck > fsck_out_actual4 -' - -test_expect_success "'ipfs repo fsck' output looks good with no daemon" ' - grep "Lockfiles have been removed." fsck_out_actual4 -' - -# Make sure the files are actually removed -test_expect_success "'ipfs repo fsck' confirm file deletion" ' - test ! -e "$IPFS_PATH/repo.lock" && - test ! -e "$IPFS_PATH/datastore/LOCK" && - test ! -e "$IPFS_PATH/api" -' - -####################### -# Test for single locks -####################### - -# Try with single locks repo.lock -test_expect_success "'ipfs repo fsck' succeeds partial lock" ' - touch $IPFS_PATH/repo.lock && - ipfs repo fsck > fsck_out_actual5 -' -test_expect_success "'ipfs repo fsck' output looks good with no daemon" ' - grep "Lockfiles have been removed." fsck_out_actual5 -' - -# Make sure the files are actually removed -test_expect_success "'ipfs repo fsck' confirm file deletion" ' - test ! -e "$IPFS_PATH/repo.lock" && - test ! -e "$IPFS_PATH/datastore/LOCK" && - test ! -e "$IPFS_PATH/api" -' - -# Try with single locks datastore/LOCK -test_expect_success "'ipfs repo fsck' succeeds partial lock" ' - touch $IPFS_PATH/datastore/LOCK && - ipfs repo fsck > fsck_out_actual6 -' -test_expect_success "'ipfs repo fsck' output looks good with no daemon" ' - grep "Lockfiles have been removed." fsck_out_actual6 -' - -# Make sure the files are actually removed -test_expect_success "'ipfs repo fsck' confirm file deletion" ' - test ! -e "$IPFS_PATH/repo.lock" && - test ! -e "$IPFS_PATH/datastore/LOCK" && - test ! -e "$IPFS_PATH/api" -' - -# Try with single lock api -test_expect_success "'ipfs repo fsck' succeeds partial lock" ' - printf "/ip4/127.0.0.1/tcp/5001" > "$IPFS_PATH/api" && - ipfs repo fsck > fsck_out_actual7 -' - -test_expect_success "'ipfs repo fsck' output looks good with no daemon" ' - grep "Lockfiles have been removed." fsck_out_actual7 -' - -# Make sure the files are actually removed -test_expect_success "'ipfs repo fsck' confirm file deletion" ' - test ! -e "$IPFS_PATH/repo.lock" && - test ! -e "$IPFS_PATH/datastore/LOCK" && - test ! -e "$IPFS_PATH/api" -' - -########################## -# Test with daemon running -########################## - -test_launch_ipfs_daemon - -# Daemon is running -> command doesn't run -test_expect_success "'ipfs repo fsck' fails with daemon running" ' - ! (ipfs repo fsck 2>fsck_out_actual8 ) - -' - -test_expect_success "'ipfs repo fsck' output looks good with daemon" ' - grep "Error: ipfs daemon is running" fsck_out_actual8 -' - -test_kill_ipfs_daemon - -test_done From 2b61dbb6128040c4e0fbe8329daf51aad064dcf9 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 3 Jul 2019 14:10:56 -0700 Subject: [PATCH 074/671] main: clarify api-flag behavior --- cmd/ipfs/main.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cmd/ipfs/main.go b/cmd/ipfs/main.go index 7beab2bb1c1..acd3d5c4a9f 100644 --- a/cmd/ipfs/main.go +++ b/cmd/ipfs/main.go @@ -223,13 +223,13 @@ func makeExecutor(req *cmds.Request, env interface{}) (cmds.Executor, error) { return nil, err } - // Force the daemon when the API flag is passed (unless we're trying to - // _run_ the daemon). - daemonForced := apiAddr != nil && req.Command != daemonCmd + // Require that the command be run on the daemon when the API flag is + // passed (unless we're trying to _run_ the daemon). + daemonRequested := apiAddr != nil && req.Command != daemonCmd // Run this on the client if required. if details.cannotRunOnDaemon || req.Command.External { - if daemonForced { + if daemonRequested { // User requested that the command be run on the daemon but we can't. // NOTE: We drop this check for the `ipfs daemon` command. return nil, errors.New("api flag specified but command cannot be run on the daemon") @@ -273,7 +273,7 @@ func makeExecutor(req *cmds.Request, env interface{}) (cmds.Executor, error) { // Fallback on a local executor if we (a) have a repo and (b) aren't // forcing a daemon. - if !daemonForced && fsrepo.IsInitialized(cctx.ConfigRoot) { + if !daemonRequested && fsrepo.IsInitialized(cctx.ConfigRoot) { opts = append(opts, http.ClientWithFallback(exe)) } From 20c8c85e2dcec3e9b43438666831cfca0c7b45a5 Mon Sep 17 00:00:00 2001 From: Michael Avila Date: Wed, 3 Jul 2019 14:21:24 -0700 Subject: [PATCH 075/671] Add go-ipfs-provider as dependency --- go.mod | 2 ++ go.sum | 2 ++ 2 files changed, 4 insertions(+) diff --git a/go.mod b/go.mod index 845548a46e4..40d4fd39f24 100644 --- a/go.mod +++ b/go.mod @@ -39,6 +39,7 @@ require ( github.com/ipfs/go-ipfs-exchange-offline v0.0.1 github.com/ipfs/go-ipfs-files v0.0.3 github.com/ipfs/go-ipfs-posinfo v0.0.1 + github.com/ipfs/go-ipfs-provider v0.1.0 github.com/ipfs/go-ipfs-routing v0.1.0 github.com/ipfs/go-ipfs-util v0.0.1 github.com/ipfs/go-ipld-cbor v0.0.2 @@ -112,6 +113,7 @@ require ( go4.org v0.0.0-20190313082347-94abd6928b1d // indirect golang.org/x/sync v0.0.0-20190423024810-112230192c58 // indirect golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb + google.golang.org/appengine v1.4.0 // indirect gopkg.in/cheggaaa/pb.v1 v1.0.28 gotest.tools/gotestsum v0.3.4 ) diff --git a/go.sum b/go.sum index 337302c8ad7..25cdc7113db 100644 --- a/go.sum +++ b/go.sum @@ -270,6 +270,8 @@ github.com/ipfs/go-ipfs-posinfo v0.0.1 h1:Esoxj+1JgSjX0+ylc0hUmJCOv6V2vFoZiETLR6 github.com/ipfs/go-ipfs-posinfo v0.0.1/go.mod h1:SwyeVP+jCwiDu0C313l/8jg6ZxM0qqtlt2a0vILTc1A= github.com/ipfs/go-ipfs-pq v0.0.1 h1:zgUotX8dcAB/w/HidJh1zzc1yFq6Vm8J7T2F4itj/RU= github.com/ipfs/go-ipfs-pq v0.0.1/go.mod h1:LWIqQpqfRG3fNc5XsnIhz/wQ2XXGyugQwls7BgUmUfY= +github.com/ipfs/go-ipfs-provider v0.1.0 h1:lYSVVxWpL0KJw1PLj3+DAn0zuVfc+z93wzUXS09ZjZk= +github.com/ipfs/go-ipfs-provider v0.1.0/go.mod h1:gzVZZXC4zhr2r+MkNR21/+FS54oc7VfTKtDT2mdDxD8= github.com/ipfs/go-ipfs-routing v0.0.1/go.mod h1:k76lf20iKFxQTjcJokbPM9iBXVXVZhcOwc360N4nuKs= github.com/ipfs/go-ipfs-routing v0.1.0 h1:gAJTT1cEeeLj6/DlLX6t+NxD9fQe2ymTO6qWRDI/HQQ= github.com/ipfs/go-ipfs-routing v0.1.0/go.mod h1:hYoUkJLyAUKhF58tysKpids8RNDPO42BVMgK5dNsoqY= From 40af13e8b9ec84b129191fcdfba9fdcda6a51c69 Mon Sep 17 00:00:00 2001 From: Michael Avila Date: Wed, 3 Jul 2019 14:22:03 -0700 Subject: [PATCH 076/671] Remove existing provider system (will fail) --- provider/offline.go | 28 ---- provider/provider.go | 26 ---- provider/queue/queue.go | 148 -------------------- provider/queue/queue_test.go | 133 ------------------ provider/simple/provider.go | 72 ---------- provider/simple/provider_test.go | 83 ----------- provider/simple/reprovide.go | 225 ------------------------------ provider/simple/reprovide_test.go | 61 -------- provider/system.go | 59 -------- 9 files changed, 835 deletions(-) delete mode 100644 provider/offline.go delete mode 100644 provider/provider.go delete mode 100644 provider/queue/queue.go delete mode 100644 provider/queue/queue_test.go delete mode 100644 provider/simple/provider.go delete mode 100644 provider/simple/provider_test.go delete mode 100644 provider/simple/reprovide.go delete mode 100644 provider/simple/reprovide_test.go delete mode 100644 provider/system.go diff --git a/provider/offline.go b/provider/offline.go deleted file mode 100644 index 5511364ed74..00000000000 --- a/provider/offline.go +++ /dev/null @@ -1,28 +0,0 @@ -package provider - -import ( - "context" - "github.com/ipfs/go-cid" -) - -type offlineProvider struct{} - -// NewOfflineProvider creates a ProviderSystem that does nothing -func NewOfflineProvider() System { - return &offlineProvider{} -} - -func (op *offlineProvider) Run() { -} - -func (op *offlineProvider) Close() error { - return nil -} - -func (op *offlineProvider) Provide(cid.Cid) error { - return nil -} - -func (op *offlineProvider) Reprovide(context.Context) error { - return nil -} diff --git a/provider/provider.go b/provider/provider.go deleted file mode 100644 index 7dec4c172e6..00000000000 --- a/provider/provider.go +++ /dev/null @@ -1,26 +0,0 @@ -package provider - -import ( - "context" - "github.com/ipfs/go-cid" -) - -// Provider announces blocks to the network -type Provider interface { - // Run is used to begin processing the provider work - Run() - // Provide takes a cid and makes an attempt to announce it to the network - Provide(cid.Cid) error - // Close stops the provider - Close() error -} - -// Reprovider reannounces blocks to the network -type Reprovider interface { - // Run is used to begin processing the reprovider work and waiting for reprovide triggers - Run() - // Trigger a reprovide - Trigger(context.Context) error - // Close stops the reprovider - Close() error -} diff --git a/provider/queue/queue.go b/provider/queue/queue.go deleted file mode 100644 index ddaa97582e8..00000000000 --- a/provider/queue/queue.go +++ /dev/null @@ -1,148 +0,0 @@ -package queue - -import ( - "context" - "fmt" - "time" - - cid "github.com/ipfs/go-cid" - datastore "github.com/ipfs/go-datastore" - namespace "github.com/ipfs/go-datastore/namespace" - query "github.com/ipfs/go-datastore/query" - logging "github.com/ipfs/go-log" -) - -var log = logging.Logger("provider.queue") - -// Queue provides a durable, FIFO interface to the datastore for storing cids -// -// Durability just means that cids in the process of being provided when a -// crash or shutdown occurs will still be in the queue when the node is -// brought back online. -type Queue struct { - // used to differentiate queues in datastore - // e.g. provider vs reprovider - name string - ctx context.Context - ds datastore.Datastore // Must be threadsafe - dequeue chan cid.Cid - enqueue chan cid.Cid - close context.CancelFunc - closed chan struct{} -} - -// NewQueue creates a queue for cids -func NewQueue(ctx context.Context, name string, ds datastore.Datastore) (*Queue, error) { - namespaced := namespace.Wrap(ds, datastore.NewKey("/"+name+"/queue/")) - cancelCtx, cancel := context.WithCancel(ctx) - q := &Queue{ - name: name, - ctx: cancelCtx, - ds: namespaced, - dequeue: make(chan cid.Cid), - enqueue: make(chan cid.Cid), - close: cancel, - closed: make(chan struct{}, 1), - } - q.work() - return q, nil -} - -// Close stops the queue -func (q *Queue) Close() error { - q.close() - <-q.closed - return nil -} - -// Enqueue puts a cid in the queue -func (q *Queue) Enqueue(cid cid.Cid) { - select { - case q.enqueue <- cid: - case <-q.ctx.Done(): - } -} - -// Dequeue returns a channel that if listened to will remove entries from the queue -func (q *Queue) Dequeue() <-chan cid.Cid { - return q.dequeue -} - -// Run dequeues and enqueues when available. -func (q *Queue) work() { - go func() { - var k datastore.Key = datastore.Key{} - var c cid.Cid = cid.Undef - - defer func() { - close(q.closed) - }() - - for { - if c == cid.Undef { - head, e := q.getQueueHead() - - if e != nil { - log.Errorf("error querying for head of queue: %s, stopping provider", e) - return - } else if head != nil { - k = datastore.NewKey(head.Key) - c, e = cid.Parse(head.Value) - if e != nil { - log.Warningf("error parsing queue entry cid with key (%s), removing it from queue: %s", head.Key, e) - err := q.ds.Delete(k) - if err != nil { - log.Errorf("error deleting queue entry with key (%s), due to error (%s), stopping provider", head.Key, err) - return - } - continue - } - } else { - c = cid.Undef - } - } - - // If c != cid.Undef set dequeue and attempt write, otherwise wait for enqueue - var dequeue chan cid.Cid - if c != cid.Undef { - dequeue = q.dequeue - } - - select { - case toQueue := <-q.enqueue: - keyPath := fmt.Sprintf("%d/%s", time.Now().UnixNano(), c.String()) - nextKey := datastore.NewKey(keyPath) - - if err := q.ds.Put(nextKey, toQueue.Bytes()); err != nil { - log.Errorf("Failed to enqueue cid: %s", err) - continue - } - case dequeue <- c: - err := q.ds.Delete(k) - - if err != nil { - log.Errorf("Failed to delete queued cid %s with key %s: %s", c, k, err) - continue - } - c = cid.Undef - case <-q.ctx.Done(): - return - } - } - }() -} - -func (q *Queue) getQueueHead() (*query.Result, error) { - qry := query.Query{Orders: []query.Order{query.OrderByKey{}}, Limit: 1} - results, err := q.ds.Query(qry) - if err != nil { - return nil, err - } - defer results.Close() - r, ok := results.NextSync() - if !ok { - return nil, nil - } - - return &r, nil -} diff --git a/provider/queue/queue_test.go b/provider/queue/queue_test.go deleted file mode 100644 index 819fa90f978..00000000000 --- a/provider/queue/queue_test.go +++ /dev/null @@ -1,133 +0,0 @@ -package queue - -import ( - "context" - "testing" - "time" - - "github.com/ipfs/go-cid" - "github.com/ipfs/go-datastore" - "github.com/ipfs/go-datastore/sync" - "github.com/ipfs/go-ipfs-blocksutil" -) - -var blockGenerator = blocksutil.NewBlockGenerator() - -func makeCids(n int) []cid.Cid { - cids := make([]cid.Cid, 0, n) - for i := 0; i < n; i++ { - c := blockGenerator.Next().Cid() - cids = append(cids, c) - } - return cids -} - -func assertOrdered(cids []cid.Cid, q *Queue, t *testing.T) { - for _, c := range cids { - select { - case dequeued := <-q.dequeue: - if c != dequeued { - t.Fatalf("Error in ordering of CIDs retrieved from queue. Expected: %s, got: %s", c, dequeued) - } - - case <-time.After(time.Second * 1): - t.Fatal("Timeout waiting for cids to be provided.") - } - } -} - -func TestBasicOperation(t *testing.T) { - ctx := context.Background() - defer ctx.Done() - - ds := sync.MutexWrap(datastore.NewMapDatastore()) - queue, err := NewQueue(ctx, "test", ds) - if err != nil { - t.Fatal(err) - } - - cids := makeCids(10) - - for _, c := range cids { - queue.Enqueue(c) - } - - assertOrdered(cids, queue, t) -} - -func TestMangledData(t *testing.T) { - ctx := context.Background() - defer ctx.Done() - - ds := sync.MutexWrap(datastore.NewMapDatastore()) - queue, err := NewQueue(ctx, "test", ds) - if err != nil { - t.Fatal(err) - } - - cids := makeCids(10) - for _, c := range cids { - queue.Enqueue(c) - } - - // put bad data in the queue - queueKey := datastore.NewKey("/test/0") - err = queue.ds.Put(queueKey, []byte("borked")) - if err != nil { - t.Fatal(err) - } - - // expect to only see the valid cids we entered - expected := cids - assertOrdered(expected, queue, t) -} - -func TestInitialization(t *testing.T) { - ctx := context.Background() - defer ctx.Done() - - ds := sync.MutexWrap(datastore.NewMapDatastore()) - queue, err := NewQueue(ctx, "test", ds) - if err != nil { - t.Fatal(err) - } - - cids := makeCids(10) - for _, c := range cids { - queue.Enqueue(c) - } - - assertOrdered(cids[:5], queue, t) - - // make a new queue, same data - queue, err = NewQueue(ctx, "test", ds) - if err != nil { - t.Fatal(err) - } - - assertOrdered(cids[5:], queue, t) -} - -func TestInitializationWithManyCids(t *testing.T) { - ctx := context.Background() - defer ctx.Done() - - ds := sync.MutexWrap(datastore.NewMapDatastore()) - queue, err := NewQueue(ctx, "test", ds) - if err != nil { - t.Fatal(err) - } - - cids := makeCids(25) - for _, c := range cids { - queue.Enqueue(c) - } - - // make a new queue, same data - queue, err = NewQueue(ctx, "test", ds) - if err != nil { - t.Fatal(err) - } - - assertOrdered(cids, queue, t) -} diff --git a/provider/simple/provider.go b/provider/simple/provider.go deleted file mode 100644 index abe13ce5986..00000000000 --- a/provider/simple/provider.go +++ /dev/null @@ -1,72 +0,0 @@ -// Package simple implements structures and methods to provide blocks, -// keep track of which blocks are provided, and to allow those blocks to -// be reprovided. -package simple - -import ( - "context" - - cid "github.com/ipfs/go-cid" - q "github.com/ipfs/go-ipfs/provider/queue" - logging "github.com/ipfs/go-log" - routing "github.com/libp2p/go-libp2p-core/routing" -) - -var logP = logging.Logger("provider.simple") - -const provideOutgoingWorkerLimit = 8 - -// Provider announces blocks to the network -type Provider struct { - ctx context.Context - // the CIDs for which provide announcements should be made - queue *q.Queue - // used to announce providing to the network - contentRouting routing.ContentRouting -} - -// NewProvider creates a provider that announces blocks to the network using a content router -func NewProvider(ctx context.Context, queue *q.Queue, contentRouting routing.ContentRouting) *Provider { - return &Provider{ - ctx: ctx, - queue: queue, - contentRouting: contentRouting, - } -} - -// Close stops the provider -func (p *Provider) Close() error { - p.queue.Close() - return nil -} - -// Run workers to handle provide requests. -func (p *Provider) Run() { - p.handleAnnouncements() -} - -// Provide the given cid using specified strategy. -func (p *Provider) Provide(root cid.Cid) error { - p.queue.Enqueue(root) - return nil -} - -// Handle all outgoing cids by providing (announcing) them -func (p *Provider) handleAnnouncements() { - for workers := 0; workers < provideOutgoingWorkerLimit; workers++ { - go func() { - for p.ctx.Err() == nil { - select { - case <-p.ctx.Done(): - return - case c := <-p.queue.Dequeue(): - logP.Info("announce - start - ", c) - if err := p.contentRouting.Provide(p.ctx, c, true); err != nil { - logP.Warningf("Unable to provide entry: %s, %s", c, err) - } - logP.Info("announce - end - ", c) - } - } - }() - } -} diff --git a/provider/simple/provider_test.go b/provider/simple/provider_test.go deleted file mode 100644 index 4922958c8c9..00000000000 --- a/provider/simple/provider_test.go +++ /dev/null @@ -1,83 +0,0 @@ -package simple_test - -import ( - "context" - "math/rand" - "testing" - "time" - - cid "github.com/ipfs/go-cid" - datastore "github.com/ipfs/go-datastore" - sync "github.com/ipfs/go-datastore/sync" - blocksutil "github.com/ipfs/go-ipfs-blocksutil" - peer "github.com/libp2p/go-libp2p-core/peer" - - q "github.com/ipfs/go-ipfs/provider/queue" - - . "github.com/ipfs/go-ipfs/provider/simple" -) - -var blockGenerator = blocksutil.NewBlockGenerator() - -type mockRouting struct { - provided chan cid.Cid -} - -func (r *mockRouting) Provide(ctx context.Context, cid cid.Cid, recursive bool) error { - r.provided <- cid - return nil -} - -func (r *mockRouting) FindProvidersAsync(ctx context.Context, cid cid.Cid, timeout int) <-chan peer.AddrInfo { - return nil -} - -func mockContentRouting() *mockRouting { - r := mockRouting{} - r.provided = make(chan cid.Cid) - return &r -} - -func TestAnnouncement(t *testing.T) { - ctx := context.Background() - defer ctx.Done() - - ds := sync.MutexWrap(datastore.NewMapDatastore()) - queue, err := q.NewQueue(ctx, "test", ds) - if err != nil { - t.Fatal(err) - } - - r := mockContentRouting() - - prov := NewProvider(ctx, queue, r) - prov.Run() - - cids := cid.NewSet() - - for i := 0; i < 100; i++ { - c := blockGenerator.Next().Cid() - cids.Add(c) - } - - go func() { - for _, c := range cids.Keys() { - err = prov.Provide(c) - // A little goroutine stirring to exercise some different states - r := rand.Intn(10) - time.Sleep(time.Microsecond * time.Duration(r)) - } - }() - - for cids.Len() > 0 { - select { - case cp := <-r.provided: - if !cids.Has(cp) { - t.Fatal("Wrong CID provided") - } - cids.Remove(cp) - case <-time.After(time.Second * 5): - t.Fatal("Timeout waiting for cids to be provided.") - } - } -} diff --git a/provider/simple/reprovide.go b/provider/simple/reprovide.go deleted file mode 100644 index ce5c71812fd..00000000000 --- a/provider/simple/reprovide.go +++ /dev/null @@ -1,225 +0,0 @@ -package simple - -import ( - "context" - "fmt" - "time" - - backoff "github.com/cenkalti/backoff" - cid "github.com/ipfs/go-cid" - cidutil "github.com/ipfs/go-cidutil" - blocks "github.com/ipfs/go-ipfs-blockstore" - pin "github.com/ipfs/go-ipfs/pin" - ipld "github.com/ipfs/go-ipld-format" - logging "github.com/ipfs/go-log" - merkledag "github.com/ipfs/go-merkledag" - verifcid "github.com/ipfs/go-verifcid" - routing "github.com/libp2p/go-libp2p-core/routing" -) - -var logR = logging.Logger("reprovider.simple") - -//KeyChanFunc is function streaming CIDs to pass to content routing -type KeyChanFunc func(context.Context) (<-chan cid.Cid, error) -type doneFunc func(error) - -// Reprovider reannounces blocks to the network -type Reprovider struct { - ctx context.Context - trigger chan doneFunc - - // The routing system to provide values through - rsys routing.ContentRouting - - keyProvider KeyChanFunc - - tick time.Duration -} - -// NewReprovider creates new Reprovider instance. -func NewReprovider(ctx context.Context, reprovideIniterval time.Duration, rsys routing.ContentRouting, keyProvider KeyChanFunc) *Reprovider { - return &Reprovider{ - ctx: ctx, - trigger: make(chan doneFunc), - - rsys: rsys, - keyProvider: keyProvider, - tick: reprovideIniterval, - } -} - -// Close the reprovider -func (rp *Reprovider) Close() error { - return nil -} - -// Run re-provides keys with 'tick' interval or when triggered -func (rp *Reprovider) Run() { - // dont reprovide immediately. - // may have just started the daemon and shutting it down immediately. - // probability( up another minute | uptime ) increases with uptime. - after := time.After(time.Minute) - var done doneFunc - for { - if rp.tick == 0 { - after = make(chan time.Time) - } - - select { - case <-rp.ctx.Done(): - return - case done = <-rp.trigger: - case <-after: - } - - //'mute' the trigger channel so when `ipfs bitswap reprovide` is called - //a 'reprovider is already running' error is returned - unmute := rp.muteTrigger() - - err := rp.Reprovide() - if err != nil { - logR.Debug(err) - } - - if done != nil { - done(err) - } - - unmute() - - after = time.After(rp.tick) - } -} - -// Reprovide registers all keys given by rp.keyProvider to libp2p content routing -func (rp *Reprovider) Reprovide() error { - keychan, err := rp.keyProvider(rp.ctx) - if err != nil { - return fmt.Errorf("failed to get key chan: %s", err) - } - for c := range keychan { - // hash security - if err := verifcid.ValidateCid(c); err != nil { - logR.Errorf("insecure hash in reprovider, %s (%s)", c, err) - continue - } - op := func() error { - err := rp.rsys.Provide(rp.ctx, c, true) - if err != nil { - logR.Debugf("Failed to provide key: %s", err) - } - return err - } - - // TODO: this backoff library does not respect our context, we should - // eventually work contexts into it. low priority. - err := backoff.Retry(op, backoff.NewExponentialBackOff()) - if err != nil { - logR.Debugf("Providing failed after number of retries: %s", err) - return err - } - } - return nil -} - -// Trigger starts reprovision process in rp.Run and waits for it -func (rp *Reprovider) Trigger(ctx context.Context) error { - progressCtx, done := context.WithCancel(ctx) - - var err error - df := func(e error) { - err = e - done() - } - - select { - case <-rp.ctx.Done(): - return context.Canceled - case <-ctx.Done(): - return context.Canceled - case rp.trigger <- df: - <-progressCtx.Done() - return err - } -} - -func (rp *Reprovider) muteTrigger() context.CancelFunc { - ctx, cf := context.WithCancel(rp.ctx) - go func() { - defer cf() - for { - select { - case <-ctx.Done(): - return - case done := <-rp.trigger: - done(fmt.Errorf("reprovider is already running")) - } - } - }() - - return cf -} - -// Strategies - -// NewBlockstoreProvider returns key provider using bstore.AllKeysChan -func NewBlockstoreProvider(bstore blocks.Blockstore) KeyChanFunc { - return func(ctx context.Context) (<-chan cid.Cid, error) { - return bstore.AllKeysChan(ctx) - } -} - -// NewPinnedProvider returns provider supplying pinned keys -func NewPinnedProvider(onlyRoots bool) func(pin.Pinner, ipld.DAGService) KeyChanFunc { - return func(pinning pin.Pinner, dag ipld.DAGService) KeyChanFunc { - return func(ctx context.Context) (<-chan cid.Cid, error) { - set, err := pinSet(ctx, pinning, dag, onlyRoots) - if err != nil { - return nil, err - } - - outCh := make(chan cid.Cid) - go func() { - defer close(outCh) - for c := range set.New { - select { - case <-ctx.Done(): - return - case outCh <- c: - } - } - - }() - - return outCh, nil - } - } -} - -func pinSet(ctx context.Context, pinning pin.Pinner, dag ipld.DAGService, onlyRoots bool) (*cidutil.StreamingSet, error) { - set := cidutil.NewStreamingSet() - - go func() { - ctx, cancel := context.WithCancel(ctx) - defer cancel() - defer close(set.New) - - for _, key := range pinning.DirectKeys() { - set.Visitor(ctx)(key) - } - - for _, key := range pinning.RecursiveKeys() { - set.Visitor(ctx)(key) - - if !onlyRoots { - err := merkledag.EnumerateChildren(ctx, merkledag.GetLinksWithDAG(dag), key, set.Visitor(ctx)) - if err != nil { - logR.Errorf("reprovide indirect pins: %s", err) - return - } - } - } - }() - - return set, nil -} diff --git a/provider/simple/reprovide_test.go b/provider/simple/reprovide_test.go deleted file mode 100644 index e9925e55ec8..00000000000 --- a/provider/simple/reprovide_test.go +++ /dev/null @@ -1,61 +0,0 @@ -package simple_test - -import ( - "context" - "testing" - "time" - - blocks "github.com/ipfs/go-block-format" - ds "github.com/ipfs/go-datastore" - dssync "github.com/ipfs/go-datastore/sync" - "github.com/ipfs/go-ipfs-blockstore" - mock "github.com/ipfs/go-ipfs-routing/mock" - peer "github.com/libp2p/go-libp2p-core/peer" - testutil "github.com/libp2p/go-libp2p-testing/net" - - . "github.com/ipfs/go-ipfs/provider/simple" -) - -func TestReprovide(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - mrserv := mock.NewServer() - - idA := testutil.RandIdentityOrFatal(t) - idB := testutil.RandIdentityOrFatal(t) - - clA := mrserv.Client(idA) - clB := mrserv.Client(idB) - - bstore := blockstore.NewBlockstore(dssync.MutexWrap(ds.NewMapDatastore())) - - blk := blocks.NewBlock([]byte("this is a test")) - err := bstore.Put(blk) - if err != nil { - t.Fatal(err) - } - - keyProvider := NewBlockstoreProvider(bstore) - reprov := NewReprovider(ctx, time.Hour, clA, keyProvider) - err = reprov.Reprovide() - if err != nil { - t.Fatal(err) - } - - var providers []peer.AddrInfo - maxProvs := 100 - - provChan := clB.FindProvidersAsync(ctx, blk.Cid(), maxProvs) - for p := range provChan { - providers = append(providers, p) - } - - if len(providers) == 0 { - t.Fatal("Should have gotten a provider") - } - - if providers[0].ID != idA.ID() { - t.Fatal("Somehow got the wrong peer back as a provider.") - } -} diff --git a/provider/system.go b/provider/system.go deleted file mode 100644 index b3e17ee40c5..00000000000 --- a/provider/system.go +++ /dev/null @@ -1,59 +0,0 @@ -package provider - -import ( - "context" - "github.com/ipfs/go-cid" -) - -// System defines the interface for interacting with the value -// provider system -type System interface { - Run() - Close() error - Provide(cid.Cid) error - Reprovide(context.Context) error -} - -type system struct { - provider Provider - reprovider Reprovider -} - -// NewSystem constructs a new provider system from a provider and reprovider -func NewSystem(provider Provider, reprovider Reprovider) System { - return &system{provider, reprovider} -} - -// Run the provider system by running the provider and reprovider -func (s *system) Run() { - go s.provider.Run() - go s.reprovider.Run() -} - -// Close the provider and reprovider -func (s *system) Close() error { - var errs []error - - if err := s.provider.Close(); err != nil { - errs = append(errs, err) - } - - if err := s.reprovider.Close(); err != nil { - errs = append(errs, err) - } - - if len(errs) > 0 { - return errs[0] - } - return nil -} - -// Provide a value -func (s *system) Provide(cid cid.Cid) error { - return s.provider.Provide(cid) -} - -// Reprovide all the previously provided values -func (s *system) Reprovide(ctx context.Context) error { - return s.reprovider.Trigger(ctx) -} From 10de165644ebd0e37fba4b31c9976268096cb6f3 Mon Sep 17 00:00:00 2001 From: Michael Avila Date: Wed, 3 Jul 2019 14:22:55 -0700 Subject: [PATCH 077/671] Change to construct provider from go-ipfs-provider --- core/core.go | 2 +- core/coreapi/coreapi.go | 2 +- core/node/provider.go | 19 ++++++++++++++----- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/core/core.go b/core/core.go index 24535208dbf..f87fd1da779 100644 --- a/core/core.go +++ b/core/core.go @@ -23,12 +23,12 @@ import ( ipnsrp "github.com/ipfs/go-ipfs/namesys/republisher" "github.com/ipfs/go-ipfs/p2p" "github.com/ipfs/go-ipfs/pin" - "github.com/ipfs/go-ipfs/provider" "github.com/ipfs/go-ipfs/repo" bserv "github.com/ipfs/go-blockservice" bstore "github.com/ipfs/go-ipfs-blockstore" exchange "github.com/ipfs/go-ipfs-exchange-interface" + "github.com/ipfs/go-ipfs-provider" ipld "github.com/ipfs/go-ipld-format" logging "github.com/ipfs/go-log" mfs "github.com/ipfs/go-mfs" diff --git a/core/coreapi/coreapi.go b/core/coreapi/coreapi.go index 85a2b24f602..5f2201df624 100644 --- a/core/coreapi/coreapi.go +++ b/core/coreapi/coreapi.go @@ -22,13 +22,13 @@ import ( "github.com/ipfs/go-ipfs/core/node" "github.com/ipfs/go-ipfs/namesys" "github.com/ipfs/go-ipfs/pin" - "github.com/ipfs/go-ipfs/provider" "github.com/ipfs/go-ipfs/repo" bserv "github.com/ipfs/go-blockservice" "github.com/ipfs/go-ipfs-blockstore" "github.com/ipfs/go-ipfs-exchange-interface" offlinexch "github.com/ipfs/go-ipfs-exchange-offline" + "github.com/ipfs/go-ipfs-provider" offlineroute "github.com/ipfs/go-ipfs-routing/offline" ipld "github.com/ipfs/go-ipld-format" logging "github.com/ipfs/go-log" diff --git a/core/node/provider.go b/core/node/provider.go index c87e2ac58d5..5390c3a9b70 100644 --- a/core/node/provider.go +++ b/core/node/provider.go @@ -6,10 +6,13 @@ import ( "time" "github.com/ipfs/go-ipfs/core/node/helpers" - "github.com/ipfs/go-ipfs/provider" - q "github.com/ipfs/go-ipfs/provider/queue" - "github.com/ipfs/go-ipfs/provider/simple" + "github.com/ipfs/go-ipfs/pin" "github.com/ipfs/go-ipfs/repo" + + "github.com/ipfs/go-ipfs-provider" + q "github.com/ipfs/go-ipfs-provider/queue" + "github.com/ipfs/go-ipfs-provider/simple" + ipld "github.com/ipfs/go-ipld-format" "github.com/libp2p/go-libp2p-core/routing" "go.uber.org/fx" ) @@ -101,9 +104,9 @@ func SimpleProviders(reprovideStrategy string, reprovideInterval string) fx.Opti case "": keyProvider = fx.Provide(simple.NewBlockstoreProvider) case "roots": - keyProvider = fx.Provide(simple.NewPinnedProvider(true)) + keyProvider = fx.Provide(pinnedProviderStrategy(true)) case "pinned": - keyProvider = fx.Provide(simple.NewPinnedProvider(false)) + keyProvider = fx.Provide(pinnedProviderStrategy(false)) default: return fx.Error(fmt.Errorf("unknown reprovider strategy '%s'", reprovideStrategy)) } @@ -115,3 +118,9 @@ func SimpleProviders(reprovideStrategy string, reprovideInterval string) fx.Opti fx.Provide(SimpleReprovider(reproviderInterval)), ) } + +func pinnedProviderStrategy(onlyRoots bool) interface{} { + return func(pinner pin.Pinner, dag ipld.DAGService) simple.KeyChanFunc { + return simple.NewPinnedProvider(onlyRoots, pinner, dag) + } +} From 72fef7f529717867c2af89890d8ef3daf167521e Mon Sep 17 00:00:00 2001 From: Michael Avila Date: Wed, 3 Jul 2019 16:26:11 -0700 Subject: [PATCH 078/671] Update to provider with timestamp based queue --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 40d4fd39f24..b904bbaf4b1 100644 --- a/go.mod +++ b/go.mod @@ -39,7 +39,7 @@ require ( github.com/ipfs/go-ipfs-exchange-offline v0.0.1 github.com/ipfs/go-ipfs-files v0.0.3 github.com/ipfs/go-ipfs-posinfo v0.0.1 - github.com/ipfs/go-ipfs-provider v0.1.0 + github.com/ipfs/go-ipfs-provider v0.1.1 github.com/ipfs/go-ipfs-routing v0.1.0 github.com/ipfs/go-ipfs-util v0.0.1 github.com/ipfs/go-ipld-cbor v0.0.2 diff --git a/go.sum b/go.sum index 25cdc7113db..8b3b986bd22 100644 --- a/go.sum +++ b/go.sum @@ -272,6 +272,8 @@ github.com/ipfs/go-ipfs-pq v0.0.1 h1:zgUotX8dcAB/w/HidJh1zzc1yFq6Vm8J7T2F4itj/RU github.com/ipfs/go-ipfs-pq v0.0.1/go.mod h1:LWIqQpqfRG3fNc5XsnIhz/wQ2XXGyugQwls7BgUmUfY= github.com/ipfs/go-ipfs-provider v0.1.0 h1:lYSVVxWpL0KJw1PLj3+DAn0zuVfc+z93wzUXS09ZjZk= github.com/ipfs/go-ipfs-provider v0.1.0/go.mod h1:gzVZZXC4zhr2r+MkNR21/+FS54oc7VfTKtDT2mdDxD8= +github.com/ipfs/go-ipfs-provider v0.1.1 h1:nsC6oWr6bDJ4H7pZfZJqAk6oXaHsrqnwhpQIqTdSDic= +github.com/ipfs/go-ipfs-provider v0.1.1/go.mod h1:gzVZZXC4zhr2r+MkNR21/+FS54oc7VfTKtDT2mdDxD8= github.com/ipfs/go-ipfs-routing v0.0.1/go.mod h1:k76lf20iKFxQTjcJokbPM9iBXVXVZhcOwc360N4nuKs= github.com/ipfs/go-ipfs-routing v0.1.0 h1:gAJTT1cEeeLj6/DlLX6t+NxD9fQe2ymTO6qWRDI/HQQ= github.com/ipfs/go-ipfs-routing v0.1.0/go.mod h1:hYoUkJLyAUKhF58tysKpids8RNDPO42BVMgK5dNsoqY= From 5a98567e0d7ed898c2038d290c525a9482091e64 Mon Sep 17 00:00:00 2001 From: David Dias Date: Thu, 4 Jul 2019 10:20:25 +0200 Subject: [PATCH 079/671] apply review --- docs/releases.md | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/docs/releases.md b/docs/releases.md index 7171cbb0603..2a4c4372b29 100644 --- a/docs/releases.md +++ b/docs/releases.md @@ -9,7 +9,7 @@ ## Release Philosophy -`go-ipfs` aims to have release every six weeks, two releases per quarter. During these 6 week releases, we go through 4 different stages of Release Candidates (RC) that gives us the opportunity to test the new version against our test envinronments, production envinronments, IPFS apps (e.g. Desktop and WebUI) and with our close partners that have IPFS running in Production, by leveraging their own test infrastructure. +`go-ipfs` aims to have release every six weeks, two releases per quarter. During these 6 week releases, we go through 4 different stages of Release Candidates (RC) that gives us the opportunity to test the new version against our test environments (unit, interop, integration), QA in our current production environmment, IPFS apps (e.g. Desktop and WebUI) and with our _early testers_[1] that have IPFS running in Production, by leveraging their own test infrastructure and QA systems. We might expand the six week release schedule in case of: - No new updates to be added @@ -20,7 +20,7 @@ We might expand the six week release schedule in case of: `go-ipfs` releases come in 4 stages: - **Release Stage 1 - Internal testing** - Test the Release against our testing infrastructure, including interoperability, integration, test lab, multiple runtimes and the apps we've built (WebUI, Desktop, NPM on IPFS, HTTP Client Libraries). The intent is to make this stage fully automated (and somewhat is already), until then, we manually check a list and ensure that all tests have been run -- **Release Stage 2 - Invite IPFS partners to test** - Reach out to our partners (i.e. projects that have volunteered to support `go-ipfs` by using their own test infrastructure and tell us the results) +- **Release Stage 2 - Invite _early testers_ to try it out** - Reach out to our _early testers_ (i.e. projects that have volunteered to support `go-ipfs` by using their own test infrastructure and tell us the results) - **Release Stage 3 - Announce to the broader community** - Communicate to the community that a new Release Candidate is ready and that everyone is welcome to test it with us - **Release Stage 4 - Complete the Release** - Finalize the release, start the next release. @@ -45,7 +45,7 @@ The first step is for the `Lead Maintainer` for `go-ipfs` to open an issue with # 🔦 Highlights - + # 🏗 API Changes @@ -83,12 +83,12 @@ When Release Stage 1, there is a features freeze for the release branch. - [ ] IPFS Companion - [ ] NPM on IPFS -### Release Stage 2 - Invite IPFS partners to test +### Release Stage 2 - Invite _early testers_ to try it out -- [ ] Reach out to the following IPFS partners for testing this release (check when no more problems have been reported): +- [ ] Reach out to the following IPFS _early testers_ for testing this release (check when no more problems have been reported): - [ ] Infura - [ ] Textila - - [ ] Open Bazaar + - [ ] Pinata - [ ] QRI - [ ] Run tests available in the following repos with the latest RC (check when all tests pass): - [ ] [orbit-db](https://github.com/orbitdb/orbit-db) @@ -105,11 +105,10 @@ PSA: If you are a heavy user of `go-ipfs`, have developed a solid test infrastru - [ ] Invite the community through (link to the release issue): - [ ] [discuss.ipfs.io](https://discuss.ipfs.io/c/announcements) - [ ] Twitter + - [ ] IRC ### Release Stage 4 - Complete the Release -- Take a snapshot between of everyone that has contributed to this release (including its subdeps in IPFS, libp2p, IPLD and multiformats) using [`name-your-contributors`](https://www.npmjs.com/package/name-your-contributors). Generate a nice markdown list with [this script](https://gist.github.com/alanshaw/5a2d9465c5a05b201d949551bdb1fcc3). Add it to this issue. - - [ ] Final preparation - [ ] Verify that version string in `repo/version.go` has been updated - [ ] tag commit with vX.Y.Z @@ -142,7 +141,7 @@ Would you like to contribute to the IPFS project and don't know how? Well, there # ⁉️ Do you have questions? -The best place to ask your questions about IPFS, how it works and what you can do with it is at [discuss.ipfs.io](http://discuss.ipfs.io). We are also available at the `#ipfs` channel on Freenode. +The best place to ask your questions about IPFS, how it works and what you can do with it is at [discuss.ipfs.io](http://discuss.ipfs.io). We are also available at the `#ipfs` channel on Freenode, which is also [accessible through our Matrix bridge](https://riot.im/app/#/room/#freenode_#ipfs:matrix.org). ``` ## Release Version Numbers (aka semver) @@ -155,3 +154,7 @@ Post `go-ipfs` 1.X.X (future), `go-ipfs` will use semver. This means that only m We do not yet retroactively apply fixes to older releases (no Long Term Support releases for now), which means that we always recommend users to update to the latest, whenever possible. TBW + +---------------------------- + +- **[1]** - _early testers_ is an IPFS program in which members of the community can self-volunteer to help test `go-ipfs` Release Candidates. You find more info about it at [EARLY_TESTERS.md](./EARLY_TESTERS.md) From 1196554bd59f304c2a776c94942d7aa98f12fbd4 Mon Sep 17 00:00:00 2001 From: David Dias Date: Thu, 4 Jul 2019 10:24:20 +0200 Subject: [PATCH 080/671] create stub for EARLY TESTERS --- docs/EARLY_TESTERS.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 docs/EARLY_TESTERS.md diff --git a/docs/EARLY_TESTERS.md b/docs/EARLY_TESTERS.md new file mode 100644 index 00000000000..105e280cb1c --- /dev/null +++ b/docs/EARLY_TESTERS.md @@ -0,0 +1,14 @@ +# EARLY TESTERS PROGRAMME + +## What is it? + +## What are the expectations? + +## Who has signed up? + +- Infura +- Textile + +## How to sign up? + +Simply submit a PR to this document by adding your project name and contact. From bb096ad13799f0efb559e1e5bf5e153765099050 Mon Sep 17 00:00:00 2001 From: David Dias Date: Thu, 4 Jul 2019 10:24:49 +0200 Subject: [PATCH 081/671] Update releases.md --- docs/releases.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/releases.md b/docs/releases.md index 2a4c4372b29..e00cbdd15a0 100644 --- a/docs/releases.md +++ b/docs/releases.md @@ -157,4 +157,4 @@ TBW ---------------------------- -- **[1]** - _early testers_ is an IPFS program in which members of the community can self-volunteer to help test `go-ipfs` Release Candidates. You find more info about it at [EARLY_TESTERS.md](./EARLY_TESTERS.md) +- **[1]** - _early testers_ is an IPFS programme in which members of the community can self-volunteer to help test `go-ipfs` Release Candidates. You find more info about it at [EARLY_TESTERS.md](./EARLY_TESTERS.md) From a7f322f8747d78a4a29374f4bd8b60311c08e3bf Mon Sep 17 00:00:00 2001 From: Jim McDonald Date: Thu, 4 Jul 2019 18:44:17 +0100 Subject: [PATCH 082/671] Add test for resolution of .eth names --- namesys/namesys_test.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/namesys/namesys_test.go b/namesys/namesys_test.go index 031ae833ac6..d1ecf49e858 100644 --- a/namesys/namesys_test.go +++ b/namesys/namesys_test.go @@ -51,6 +51,7 @@ func mockResolverOne() *mockResolver { "QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy": "/ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj", "QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n": "/ipns/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy", "QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD": "/ipns/ipfs.io", + "QmQ4QZh8nrsczdUEwTyfBope4THUhqxqc1fx6qYhhzZQei": "/ipfs/QmP3ouCnU8NNLsW6261pAx2pNLV2E4dQoisB1sgda12Act", }, } } @@ -58,7 +59,8 @@ func mockResolverOne() *mockResolver { func mockResolverTwo() *mockResolver { return &mockResolver{ entries: map[string]string{ - "ipfs.io": "/ipns/QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n", + "ipfs.io": "/ipns/QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n", + "www.wealdtech.eth.link": "/ipns/QmQ4QZh8nrsczdUEwTyfBope4THUhqxqc1fx6qYhhzZQei", }, } } @@ -80,6 +82,8 @@ func TestNamesysResolution(t *testing.T) { testResolution(t, r, "/ipns/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", 1, "/ipns/ipfs.io", ErrResolveRecursion) testResolution(t, r, "/ipns/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", 2, "/ipns/QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n", ErrResolveRecursion) testResolution(t, r, "/ipns/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", 3, "/ipns/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy", ErrResolveRecursion) + testResolution(t, r, "/ipns/www.wealdtech.eth", 1, "/ipns/QmQ4QZh8nrsczdUEwTyfBope4THUhqxqc1fx6qYhhzZQei", ErrResolveRecursion) + testResolution(t, r, "/ipns/www.wealdtech.eth", 2, "/ipfs/QmP3ouCnU8NNLsW6261pAx2pNLV2E4dQoisB1sgda12Act", nil) } func TestPublishWithCache0(t *testing.T) { From 2198bf377dd91400513d303c9a11f07eefaecfbd Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 8 Jul 2019 05:34:46 -0700 Subject: [PATCH 083/671] debug: copy ipfs binary as well --- bin/collect-profiles.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/bin/collect-profiles.sh b/bin/collect-profiles.sh index e1f80cd32c9..ca336e51b91 100644 --- a/bin/collect-profiles.sh +++ b/bin/collect-profiles.sh @@ -8,6 +8,11 @@ tmpdir=$(mktemp -d) export PPROF_TMPDIR="$tmpdir" pushd "$tmpdir" +IPFS_BIN=$(which ipfs) +if [[ -e "$IPFS_BIN" ]]; then + cp "$IPFS_BIN" ipfs +fi + echo Collecting goroutine stacks curl -o goroutines.stacks "http://$HTTP_API"'/debug/pprof/goroutine?debug=2' From 20f7ce8508274c73f81ead5e15f475675a3137e8 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 8 Jul 2019 05:34:48 -0700 Subject: [PATCH 084/671] debug: document the debug script fixes #6457 --- docs/debug-guide.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/debug-guide.md b/docs/debug-guide.md index 9ef046a47e1..170e58254b5 100644 --- a/docs/debug-guide.md +++ b/docs/debug-guide.md @@ -15,6 +15,11 @@ When you see ipfs doing something (using lots of CPU, memory, or otherwise being weird), the first thing you want to do is gather all the relevant profiling information. +There's a script (`bin/collect-profiles.sh`) that will do this for you and +bundle the results up into a tarball, ready to be attached to a bug report. + +If you feel intrepid, you can dump this information and investigate it yourself: + - goroutine dump - `curl localhost:5001/debug/pprof/goroutine\?debug=2 > ipfs.stacks` - 30 second cpu profile @@ -26,10 +31,6 @@ profiling information. - system information - `ipfs diag sys > ipfs.sysinfo` -Bundle all that up and include a copy of the ipfs binary that you are running -(having the exact same binary is important, it contains debug info). - -You can investigate yourself if you feel intrepid: ### Analyzing the stack dump From c76cc59218de9361afec9e6e9e83c9c16cab1812 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 8 Jul 2019 13:53:53 -0700 Subject: [PATCH 085/671] docs: releases.md spelling Co-Authored-By: Marcin Rataj --- docs/releases.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/releases.md b/docs/releases.md index e00cbdd15a0..e96bf59e395 100644 --- a/docs/releases.md +++ b/docs/releases.md @@ -9,7 +9,7 @@ ## Release Philosophy -`go-ipfs` aims to have release every six weeks, two releases per quarter. During these 6 week releases, we go through 4 different stages of Release Candidates (RC) that gives us the opportunity to test the new version against our test environments (unit, interop, integration), QA in our current production environmment, IPFS apps (e.g. Desktop and WebUI) and with our _early testers_[1] that have IPFS running in Production, by leveraging their own test infrastructure and QA systems. +`go-ipfs` aims to have release every six weeks, two releases per quarter. During these 6 week releases, we go through 4 different stages of Release Candidates (RC) that gives us the opportunity to test the new version against our test environments (unit, interop, integration), QA in our current production environment, IPFS apps (e.g. Desktop and WebUI) and with our _early testers_[1] that have IPFS running in Production, by leveraging their own test infrastructure and QA systems. We might expand the six week release schedule in case of: - No new updates to be added From 23df11821bb195b87b2f859342cc619c19ba0fe1 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 8 Jul 2019 15:05:21 -0700 Subject: [PATCH 086/671] add more testers to EARLY_TESTERS along with contact info --- docs/EARLY_TESTERS.md | 7 +++++-- docs/releases.md | 8 ++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/docs/EARLY_TESTERS.md b/docs/EARLY_TESTERS.md index 105e280cb1c..4d3e8182e77 100644 --- a/docs/EARLY_TESTERS.md +++ b/docs/EARLY_TESTERS.md @@ -6,8 +6,11 @@ ## Who has signed up? -- Infura -- Textile +- [ ] Infura (@MichaelMure) +- [ ] Textile (@sanderpick) +- [ ] Pinata (@obo20) +- [ ] RTrade (@postables) +- [ ] QRI (@b5) ## How to sign up? diff --git a/docs/releases.md b/docs/releases.md index e96bf59e395..c1341edaec3 100644 --- a/docs/releases.md +++ b/docs/releases.md @@ -86,10 +86,10 @@ When Release Stage 1, there is a features freeze for the release branch. ### Release Stage 2 - Invite _early testers_ to try it out - [ ] Reach out to the following IPFS _early testers_ for testing this release (check when no more problems have been reported): - - [ ] Infura - - [ ] Textila - - [ ] Pinata - - [ ] QRI + - [ ] Infura (@MichaelMure) + - [ ] Textile (@sanderpick) + - [ ] Pinata (@obo20) + - [ ] QRI (@b5) - [ ] Run tests available in the following repos with the latest RC (check when all tests pass): - [ ] [orbit-db](https://github.com/orbitdb/orbit-db) From b786abea95958481e05bc757ac35b498145fb17c Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 8 Jul 2019 15:05:42 -0700 Subject: [PATCH 087/671] docs: remove early testers from docs/releases.md so it doesn't get out of date --- docs/releases.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/docs/releases.md b/docs/releases.md index c1341edaec3..56b412f9a56 100644 --- a/docs/releases.md +++ b/docs/releases.md @@ -85,11 +85,8 @@ When Release Stage 1, there is a features freeze for the release branch. ### Release Stage 2 - Invite _early testers_ to try it out -- [ ] Reach out to the following IPFS _early testers_ for testing this release (check when no more problems have been reported): - - [ ] Infura (@MichaelMure) - - [ ] Textile (@sanderpick) - - [ ] Pinata (@obo20) - - [ ] QRI (@b5) +- [ ] Reach out to the IPFS _early testers_ listed below for testing this release (check when no more problems have been reported). + - [ ] **COPY THE LIST FROM `docs/EARLY_TESTERS.md`** - [ ] Run tests available in the following repos with the latest RC (check when all tests pass): - [ ] [orbit-db](https://github.com/orbitdb/orbit-db) From 4f6d6e11fe9efe61483526a2b539e4df3b5d3b8f Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Tue, 9 Jul 2019 15:21:54 -0700 Subject: [PATCH 088/671] dep: update go-multiaddr-dns fixes #6485 --- go.mod | 5 +---- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 08bcb17153e..bdd04154673 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,6 @@ require ( github.com/Kubuxu/gocovmerge v0.0.0-20161216165753-7ecaa51963cd github.com/blang/semver v3.5.1+incompatible github.com/bren2010/proquint v0.0.0-20160323162903-38337c27106d - github.com/cenkalti/backoff v2.1.1+incompatible github.com/dustin/go-humanize v1.0.0 github.com/elgris/jsondiff v0.0.0-20160530203242-765b5c24c302 github.com/fatih/color v1.7.0 // indirect @@ -29,7 +28,6 @@ require ( github.com/ipfs/go-ds-measure v0.0.1 github.com/ipfs/go-fs-lock v0.0.1 github.com/ipfs/go-ipfs-blockstore v0.0.1 - github.com/ipfs/go-ipfs-blocksutil v0.0.1 github.com/ipfs/go-ipfs-chunker v0.0.1 github.com/ipfs/go-ipfs-cmds v0.1.0 github.com/ipfs/go-ipfs-config v0.0.6 @@ -91,7 +89,7 @@ require ( github.com/mitchellh/go-homedir v1.1.0 github.com/mr-tron/base58 v1.1.2 github.com/multiformats/go-multiaddr v0.0.4 - github.com/multiformats/go-multiaddr-dns v0.0.2 + github.com/multiformats/go-multiaddr-dns v0.0.3 github.com/multiformats/go-multiaddr-net v0.0.1 github.com/multiformats/go-multibase v0.0.1 github.com/multiformats/go-multihash v0.0.5 @@ -112,7 +110,6 @@ require ( go4.org v0.0.0-20190313082347-94abd6928b1d // indirect golang.org/x/sync v0.0.0-20190423024810-112230192c58 // indirect golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb - google.golang.org/appengine v1.4.0 // indirect gopkg.in/cheggaaa/pb.v1 v1.0.28 gotest.tools/gotestsum v0.3.4 ) diff --git a/go.sum b/go.sum index 024f6d41a08..d748d6c8b14 100644 --- a/go.sum +++ b/go.sum @@ -270,8 +270,6 @@ github.com/ipfs/go-ipfs-posinfo v0.0.1 h1:Esoxj+1JgSjX0+ylc0hUmJCOv6V2vFoZiETLR6 github.com/ipfs/go-ipfs-posinfo v0.0.1/go.mod h1:SwyeVP+jCwiDu0C313l/8jg6ZxM0qqtlt2a0vILTc1A= github.com/ipfs/go-ipfs-pq v0.0.1 h1:zgUotX8dcAB/w/HidJh1zzc1yFq6Vm8J7T2F4itj/RU= github.com/ipfs/go-ipfs-pq v0.0.1/go.mod h1:LWIqQpqfRG3fNc5XsnIhz/wQ2XXGyugQwls7BgUmUfY= -github.com/ipfs/go-ipfs-provider v0.1.0 h1:lYSVVxWpL0KJw1PLj3+DAn0zuVfc+z93wzUXS09ZjZk= -github.com/ipfs/go-ipfs-provider v0.1.0/go.mod h1:gzVZZXC4zhr2r+MkNR21/+FS54oc7VfTKtDT2mdDxD8= github.com/ipfs/go-ipfs-provider v0.1.1 h1:nsC6oWr6bDJ4H7pZfZJqAk6oXaHsrqnwhpQIqTdSDic= github.com/ipfs/go-ipfs-provider v0.1.1/go.mod h1:gzVZZXC4zhr2r+MkNR21/+FS54oc7VfTKtDT2mdDxD8= github.com/ipfs/go-ipfs-routing v0.0.1/go.mod h1:k76lf20iKFxQTjcJokbPM9iBXVXVZhcOwc360N4nuKs= @@ -620,6 +618,8 @@ github.com/multiformats/go-multiaddr v0.0.4/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lg github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= github.com/multiformats/go-multiaddr-dns v0.0.2 h1:/Bbsgsy3R6e3jf2qBahzNHzww6usYaZ0NhNH3sqdFS8= github.com/multiformats/go-multiaddr-dns v0.0.2/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= +github.com/multiformats/go-multiaddr-dns v0.0.3 h1:P19q/k9jwmtgh+qXFkKfgFM7rCg/9l5AVqh7VNxSXhs= +github.com/multiformats/go-multiaddr-dns v0.0.3/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= github.com/multiformats/go-multiaddr-fmt v0.0.1 h1:5YjeOIzbX8OTKVaN72aOzGIYW7PnrZrnkDyOfAWRSMA= github.com/multiformats/go-multiaddr-fmt v0.0.1/go.mod h1:aBYjqL4T/7j4Qx+R73XSv/8JsgnRFlf0w2KGLCmXl3Q= github.com/multiformats/go-multiaddr-net v0.0.1 h1:76O59E3FavvHqNg7jvzWzsPSW5JSi/ek0E4eiDVbg9g= From 1791f6866b3d8f1e722d6a1b0457856c324af49f Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Tue, 9 Jul 2019 20:15:06 -0700 Subject: [PATCH 089/671] ci: test the http clients --- .circleci/config.yml | 68 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 59 insertions(+), 9 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index fd606d8ca42..fc53ab750f6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -120,7 +120,7 @@ jobs: path: /tmp/circleci-artifacts - store_artifacts: path: /tmp/circleci-test-results - build-interop: + build: docker: - image: circleci/golang:1.12 <<: *defaults @@ -128,12 +128,18 @@ jobs: - checkout - *make_out_dirs - *restore_gomod - - run: make build - - run: cp cmd/ipfs/ipfs /tmp/circleci-workspace + - run: + name: Building + command: make build + - run: + name: Storing + command: | + mkdir -p /tmp/circleci-workspace/bin + cp cmd/ipfs/ipfs /tmp/circleci-workspace/bin - persist_to_workspace: root: /tmp/circleci-workspace paths: - - ipfs + - bin/ipfs - *store_gomod interop: docker: @@ -148,13 +154,51 @@ jobs: command: npm install working_directory: ~/ipfs/go-ipfs/interop environment: - IPFS_GO_EXEC: /tmp/circleci-workspace/ipfs + IPFS_GO_EXEC: /tmp/circleci-workspace/bin/ipfs - run: command: npm test working_directory: ~/ipfs/go-ipfs/interop environment: - IPFS_GO_EXEC: /tmp/circleci-workspace/ipfs - + IPFS_GO_EXEC: /tmp/circleci-workspace/bin/ipfs + go-ipfs-api: + docker: + - image: circleci/golang:1.12 + <<: *defaults + steps: + - *make_out_dirs + - attach_workspace: + at: /tmp/circleci-workspace + - run: git clone https://github.com/ipfs/go-ipfs-api.git + - run: + name: IPFS Daemon + command: /tmp/circleci-workspace/bin/ipfs daemon --init --enable-namesys-pubsub + background: true + - run: + name: Waiting for the daemon + no_output_timeout: 10s + command: | + while ! /tmp/circleci-workspace/bin/ipfs id --api=/ip4/127.0.0.1/tcp/5001 2>/dev/null; do + sleep 1 + done + - run: + command: go test -v ./... + working_directory: ~/ipfs/go-ipfs/go-ipfs-api + go-ipfs-http-client: + docker: + - image: circleci/golang:1.12 + <<: *defaults + steps: + - *make_out_dirs + - attach_workspace: + at: /tmp/circleci-workspace + - run: git clone https://github.com/ipfs/go-ipfs-http-client.git + - run: + command: | + export PATH=/tmp/circleci-workspace/bin:$PATH + go test -v ./... + working_directory: ~/ipfs/go-ipfs/go-ipfs-http-client + - run: + command: /tmp/circleci-workspace/bin/ipfs shutdown workflows: version: 2 @@ -164,7 +208,13 @@ workflows: - golint - gotest - sharness - - build-interop + - build - interop: requires: - - build-interop + - build + - go-ipfs-api: + requires: + - build + - go-ipfs-http-client: + requires: + - build From e32a41392d34821a32ab69c15c1fe1802dc073ae Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Tue, 9 Jul 2019 21:02:39 -0700 Subject: [PATCH 090/671] ci: improve caching --- .circleci/config.yml | 43 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index fc53ab750f6..744e82d674f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -150,11 +150,19 @@ jobs: - attach_workspace: at: /tmp/circleci-workspace - run: git clone https://github.com/ipfs/interop.git + - restore_cache: + keys: + - v1-interop-{{ checksum "~/ipfs/go-ipfs/interop/package-lock.json" }} + - v1-interop- - run: command: npm install working_directory: ~/ipfs/go-ipfs/interop environment: IPFS_GO_EXEC: /tmp/circleci-workspace/bin/ipfs + - save_cache: + key: v1-interop-{{ checksum "~/ipfs/go-ipfs/interop/package-lock.json" }} + paths: + - ~/ipfs/go-ipfs/interop/node_modules - run: command: npm test working_directory: ~/ipfs/go-ipfs/interop @@ -168,9 +176,11 @@ jobs: - *make_out_dirs - attach_workspace: at: /tmp/circleci-workspace - - run: git clone https://github.com/ipfs/go-ipfs-api.git - run: - name: IPFS Daemon + name: Cloning + command: git clone https://github.com/ipfs/go-ipfs-api.git + - run: + name: Starting the daemon command: /tmp/circleci-workspace/bin/ipfs daemon --init --enable-namesys-pubsub background: true - run: @@ -180,9 +190,21 @@ jobs: while ! /tmp/circleci-workspace/bin/ipfs id --api=/ip4/127.0.0.1/tcp/5001 2>/dev/null; do sleep 1 done + - restore_cache: + keys: + - v1-go-api-{{ checksum "~/ipfs/go-ipfs/go-ipfs-api/go.sum" }} + - v1-go-api- - run: command: go test -v ./... working_directory: ~/ipfs/go-ipfs/go-ipfs-api + - save_cache: + key: v1-go-api-{{ checksum "~/ipfs/go-ipfs/go-ipfs-api/go.sum" }} + paths: + - ~/go/pkg/mod + - ~/.cache/go-build/ + - run: + name: Stopping the daemon + command: /tmp/circleci-workspace/bin/ipfs shutdown go-ipfs-http-client: docker: - image: circleci/golang:1.12 @@ -191,15 +213,24 @@ jobs: - *make_out_dirs - attach_workspace: at: /tmp/circleci-workspace - - run: git clone https://github.com/ipfs/go-ipfs-http-client.git - run: + name: Cloning + command: git clone https://github.com/ipfs/go-ipfs-http-client.git + - restore_cache: + keys: + - v1-http-client-{{ checksum "~/ipfs/go-ipfs/go-ipfs-http-client/go.sum" }} + - v1-http-client- + - run: + name: go test -v ./... command: | export PATH=/tmp/circleci-workspace/bin:$PATH go test -v ./... working_directory: ~/ipfs/go-ipfs/go-ipfs-http-client - - run: - command: /tmp/circleci-workspace/bin/ipfs shutdown - + - save_cache: + key: v1-http-client-{{ checksum "~/ipfs/go-ipfs/go-ipfs-http-client/go.sum" }} + paths: + - ~/go/pkg/mod + - ~/.cache/go-build/ workflows: version: 2 test: From bb601845268fa7ffcf90cfe21d5eca9c8b42f590 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Mur=C3=A9?= Date: Wed, 26 Jun 2019 23:07:35 +0200 Subject: [PATCH 091/671] pin cmd: stream recursive pins Add a --stream flag to stream the results instead of accumulating the final result in memory. This is a rework of https://github.com/ipfs/go-ipfs/pull/5005 --- core/commands/pin.go | 151 ++++++++++++++++++++++++++++++------------- 1 file changed, 107 insertions(+), 44 deletions(-) diff --git a/core/commands/pin.go b/core/commands/pin.go index c1548904a83..55f10385e1e 100644 --- a/core/commands/pin.go +++ b/core/commands/pin.go @@ -259,8 +259,9 @@ collected if needed. (By default, recursively. Use -r=false for direct pins.) } const ( - pinTypeOptionName = "type" - pinQuietOptionName = "quiet" + pinTypeOptionName = "type" + pinQuietOptionName = "quiet" + pinStreamOptionName = "stream" ) var listPinCmd = &cmds.Command{ @@ -313,6 +314,7 @@ Example: Options: []cmds.Option{ cmds.StringOption(pinTypeOptionName, "t", "The type of pinned keys to list. Can be \"direct\", \"indirect\", \"recursive\", or \"all\".").WithDefault("all"), cmds.BoolOption(pinQuietOptionName, "q", "Write just hashes of objects."), + cmds.BoolOption(pinStreamOptionName, "s", "Don't buffer pins before sending."), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { n, err := cmdenv.GetNode(env) @@ -326,9 +328,7 @@ Example: } typeStr, _ := req.Options[pinTypeOptionName].(string) - if err != nil { - return err - } + stream, _ := req.Options[pinStreamOptionName].(bool) switch typeStr { case "all", "direct", "indirect", "recursive": @@ -337,34 +337,50 @@ Example: return err } - enc, err := cmdenv.GetCidEncoder(req) - if err != nil { - return err + // For backward compatibility, we accumulate the pins in the same output type as before. + emit := res.Emit + lgcList := map[string]RefObject{} + if !stream { + emit = func(v interface{}) error { + obj := v.(*PinLsOutputWrapper) + lgcList[obj.RefKeyObject.Cid] = RefObject{Type: obj.RefKeyObject.Type} + return nil + } } - var keys map[cid.Cid]RefKeyObject if len(req.Arguments) > 0 { - keys, err = pinLsKeys(req.Context, req.Arguments, typeStr, n, api) + err = pinLsKeys(req.Context, req.Arguments, typeStr, n, api, emit) } else { - keys, err = pinLsAll(req.Context, typeStr, n) + err = pinLsAll(req.Context, typeStr, n, emit) } if err != nil { return err } - refKeys := make(map[string]RefKeyObject, len(keys)) - for k, v := range keys { - refKeys[enc.Encode(k)] = v + if !stream { + return cmds.EmitOnce(res, &PinLsOutputWrapper{ + RefKeyList: RefKeyList{Keys: lgcList}, + }) } - return cmds.EmitOnce(res, &RefKeyList{Keys: refKeys}) + return nil }, - Type: RefKeyList{}, + Type: &PinLsOutputWrapper{}, Encoders: cmds.EncoderMap{ - cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *RefKeyList) error { + cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *PinLsOutputWrapper) error { quiet, _ := req.Options[pinQuietOptionName].(bool) + stream, _ := req.Options[pinStreamOptionName].(bool) + + if stream { + if quiet { + fmt.Fprintf(w, "%s\n", out.RefKeyObject.Cid) + } else { + fmt.Fprintf(w, "%s %s\n", out.RefKeyObject.Cid, out.RefKeyObject.Type) + } + return nil + } - for k, v := range out.Keys { + for k, v := range out.RefKeyList.Keys { if quiet { fmt.Fprintf(w, "%s\n", k) } else { @@ -492,35 +508,44 @@ var verifyPinCmd = &cmds.Command{ } type RefKeyObject struct { + Cid string + Type string +} + +type RefObject struct { Type string } type RefKeyList struct { - Keys map[string]RefKeyObject + Keys map[string]RefObject } -func pinLsKeys(ctx context.Context, args []string, typeStr string, n *core.IpfsNode, api coreiface.CoreAPI) (map[cid.Cid]RefKeyObject, error) { +// Pin ls needs to output two different type depending on if it's streamed or not. +// We use this to bypass the cmds lib refusing to have interface{} +type PinLsOutputWrapper struct { + RefKeyList + RefKeyObject +} +func pinLsKeys(ctx context.Context, args []string, typeStr string, n *core.IpfsNode, api coreiface.CoreAPI, emit func(value interface{}) error) error { mode, ok := pin.StringToMode(typeStr) if !ok { - return nil, fmt.Errorf("invalid pin mode '%s'", typeStr) + return fmt.Errorf("invalid pin mode '%s'", typeStr) } - keys := make(map[cid.Cid]RefKeyObject) - for _, p := range args { c, err := api.ResolvePath(ctx, path.New(p)) if err != nil { - return nil, err + return err } pinType, pinned, err := n.Pinning.IsPinnedWithType(c.Cid(), mode) if err != nil { - return nil, err + return err } if !pinned { - return nil, fmt.Errorf("path '%s' is not pinned", p) + return fmt.Errorf("path '%s' is not pinned", p) } switch pinType { @@ -528,44 +553,82 @@ func pinLsKeys(ctx context.Context, args []string, typeStr string, n *core.IpfsN default: pinType = "indirect through " + pinType } - keys[c.Cid()] = RefKeyObject{ - Type: pinType, + + err = emit(&PinLsOutputWrapper{ + RefKeyObject: RefKeyObject{ + Type: pinType, + Cid: c.Cid().String(), + }, + }) + if err != nil { + return err } } - return keys, nil + return nil } -func pinLsAll(ctx context.Context, typeStr string, n *core.IpfsNode) (map[cid.Cid]RefKeyObject, error) { - - keys := make(map[cid.Cid]RefKeyObject) +func pinLsAll(ctx context.Context, typeStr string, n *core.IpfsNode, emit func(value interface{}) error) error { + keys := cid.NewSet() - AddToResultKeys := func(keyList []cid.Cid, typeStr string) { + AddToResultKeys := func(keyList []cid.Cid, typeStr string) error { for _, c := range keyList { - keys[c] = RefKeyObject{ - Type: typeStr, + if keys.Visit(c) { + err := emit(&PinLsOutputWrapper{ + RefKeyObject: RefKeyObject{ + Type: typeStr, + Cid: c.String(), + }, + }) + if err != nil { + return err + } } } + return nil } if typeStr == "direct" || typeStr == "all" { - AddToResultKeys(n.Pinning.DirectKeys(), "direct") + err := AddToResultKeys(n.Pinning.DirectKeys(), "direct") + if err != nil { + return err + } + } + if typeStr == "recursive" || typeStr == "all" { + err := AddToResultKeys(n.Pinning.RecursiveKeys(), "recursive") + if err != nil { + return err + } } if typeStr == "indirect" || typeStr == "all" { - set := cid.NewSet() for _, k := range n.Pinning.RecursiveKeys() { - err := dag.EnumerateChildren(ctx, dag.GetLinksWithDAG(n.DAG), k, set.Visit) + var visitErr error + err := dag.EnumerateChildren(ctx, dag.GetLinksWithDAG(n.DAG), k, func(c cid.Cid) bool { + r := keys.Visit(c) + if r { + err := emit(&PinLsOutputWrapper{ + RefKeyObject: RefKeyObject{ + Type: "indirect", + Cid: c.String(), + }, + }) + if err != nil { + visitErr = err + } + } + return r + }) + + if visitErr != nil { + return visitErr + } if err != nil { - return nil, err + return err } } - AddToResultKeys(set.Keys(), "indirect") - } - if typeStr == "recursive" || typeStr == "all" { - AddToResultKeys(n.Pinning.RecursiveKeys(), "recursive") } - return keys, nil + return nil } // PinVerifyRes is the result returned for each pin checked in "pin verify" From dd06956d30df86126af314c7b88d846d44f3c583 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Mur=C3=A9?= Date: Thu, 11 Jul 2019 13:51:54 +0200 Subject: [PATCH 092/671] pin cmd: proper CID encoding and backward compat --- core/commands/ls.go | 2 +- core/commands/pin.go | 264 ++++++++++++++++++++++--------------------- 2 files changed, 138 insertions(+), 128 deletions(-) diff --git a/core/commands/ls.go b/core/commands/ls.go index 23c0ebc05ad..4b0114d3341 100644 --- a/core/commands/ls.go +++ b/core/commands/ls.go @@ -65,7 +65,7 @@ The JSON output contains type information. cmds.BoolOption(lsHeadersOptionNameTime, "v", "Print table headers (Hash, Size, Name)."), cmds.BoolOption(lsResolveTypeOptionName, "Resolve linked objects to find out their types.").WithDefault(true), cmds.BoolOption(lsSizeOptionName, "Resolve linked objects to find out their file size.").WithDefault(true), - cmds.BoolOption(lsStreamOptionName, "s", "Enable exprimental streaming of directory entries as they are traversed."), + cmds.BoolOption(lsStreamOptionName, "s", "Enable experimental streaming of directory entries as they are traversed."), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { api, err := cmdenv.GetApi(env, req) diff --git a/core/commands/pin.go b/core/commands/pin.go index 55f10385e1e..b9e92530655 100644 --- a/core/commands/pin.go +++ b/core/commands/pin.go @@ -314,7 +314,7 @@ Example: Options: []cmds.Option{ cmds.StringOption(pinTypeOptionName, "t", "The type of pinned keys to list. Can be \"direct\", \"indirect\", \"recursive\", or \"all\".").WithDefault("all"), cmds.BoolOption(pinQuietOptionName, "q", "Write just hashes of objects."), - cmds.BoolOption(pinStreamOptionName, "s", "Don't buffer pins before sending."), + cmds.BoolOption(pinStreamOptionName, "s", "Enable streaming of pins as they are discovered."), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { n, err := cmdenv.GetNode(env) @@ -349,9 +349,9 @@ Example: } if len(req.Arguments) > 0 { - err = pinLsKeys(req.Context, req.Arguments, typeStr, n, api, emit) + err = pinLsKeys(req, typeStr, n, api, emit) } else { - err = pinLsAll(req.Context, typeStr, n, emit) + err = pinLsAll(req, typeStr, n, emit) } if err != nil { return err @@ -393,6 +393,140 @@ Example: }, } +type RefKeyObject struct { + Cid string `json:",omitempty"` + Type string `json:",omitempty"` +} + +type RefObject struct { + Type string +} + +type RefKeyList struct { + Keys map[string]RefObject `json:",omitempty"` +} + +// Pin ls needs to output two different type depending on if it's streamed or not. +// We use this to bypass the cmds lib refusing to have interface{} +type PinLsOutputWrapper struct { + RefKeyList + RefKeyObject +} + +func pinLsKeys(req *cmds.Request, typeStr string, n *core.IpfsNode, api coreiface.CoreAPI, emit func(value interface{}) error) error { + mode, ok := pin.StringToMode(typeStr) + if !ok { + return fmt.Errorf("invalid pin mode '%s'", typeStr) + } + + enc, err := cmdenv.GetCidEncoder(req) + if err != nil { + return err + } + + for _, p := range req.Arguments { + c, err := api.ResolvePath(req.Context, path.New(p)) + if err != nil { + return err + } + + pinType, pinned, err := n.Pinning.IsPinnedWithType(c.Cid(), mode) + if err != nil { + return err + } + + if !pinned { + return fmt.Errorf("path '%s' is not pinned", p) + } + + switch pinType { + case "direct", "indirect", "recursive", "internal": + default: + pinType = "indirect through " + pinType + } + + err = emit(&PinLsOutputWrapper{ + RefKeyObject: RefKeyObject{ + Type: pinType, + Cid: enc.Encode(c.Cid()), + }, + }) + if err != nil { + return err + } + } + + return nil +} + +func pinLsAll(req *cmds.Request, typeStr string, n *core.IpfsNode, emit func(value interface{}) error) error { + enc, err := cmdenv.GetCidEncoder(req) + if err != nil { + return err + } + + keys := cid.NewSet() + + AddToResultKeys := func(keyList []cid.Cid, typeStr string) error { + for _, c := range keyList { + if keys.Visit(c) { + err := emit(&PinLsOutputWrapper{ + RefKeyObject: RefKeyObject{ + Type: typeStr, + Cid: enc.Encode(c), + }, + }) + if err != nil { + return err + } + } + } + return nil + } + + if typeStr == "direct" || typeStr == "all" { + err := AddToResultKeys(n.Pinning.DirectKeys(), "direct") + if err != nil { + return err + } + } + if typeStr == "indirect" || typeStr == "all" { + for _, k := range n.Pinning.RecursiveKeys() { + var visitErr error + err := dag.EnumerateChildren(req.Context, dag.GetLinksWithDAG(n.DAG), k, func(c cid.Cid) bool { + r := keys.Visit(c) + if r { + err := emit(&PinLsOutputWrapper{ + RefKeyObject: RefKeyObject{ + Type: typeStr, + Cid: enc.Encode(c), + }, + }) + if err != nil { + visitErr = err + } + } + return r + }) + + if visitErr != nil { + return visitErr + } + if err != nil { + return err + } + } + } + if typeStr == "recursive" || typeStr == "all" { + err := AddToResultKeys(n.Pinning.RecursiveKeys(), "recursive") + if err != nil { + return err + } + } + + return nil +} + const ( pinUnpinOptionName = "unpin" ) @@ -507,130 +641,6 @@ var verifyPinCmd = &cmds.Command{ }, } -type RefKeyObject struct { - Cid string - Type string -} - -type RefObject struct { - Type string -} - -type RefKeyList struct { - Keys map[string]RefObject -} - -// Pin ls needs to output two different type depending on if it's streamed or not. -// We use this to bypass the cmds lib refusing to have interface{} -type PinLsOutputWrapper struct { - RefKeyList - RefKeyObject -} - -func pinLsKeys(ctx context.Context, args []string, typeStr string, n *core.IpfsNode, api coreiface.CoreAPI, emit func(value interface{}) error) error { - mode, ok := pin.StringToMode(typeStr) - if !ok { - return fmt.Errorf("invalid pin mode '%s'", typeStr) - } - - for _, p := range args { - c, err := api.ResolvePath(ctx, path.New(p)) - if err != nil { - return err - } - - pinType, pinned, err := n.Pinning.IsPinnedWithType(c.Cid(), mode) - if err != nil { - return err - } - - if !pinned { - return fmt.Errorf("path '%s' is not pinned", p) - } - - switch pinType { - case "direct", "indirect", "recursive", "internal": - default: - pinType = "indirect through " + pinType - } - - err = emit(&PinLsOutputWrapper{ - RefKeyObject: RefKeyObject{ - Type: pinType, - Cid: c.Cid().String(), - }, - }) - if err != nil { - return err - } - } - - return nil -} - -func pinLsAll(ctx context.Context, typeStr string, n *core.IpfsNode, emit func(value interface{}) error) error { - keys := cid.NewSet() - - AddToResultKeys := func(keyList []cid.Cid, typeStr string) error { - for _, c := range keyList { - if keys.Visit(c) { - err := emit(&PinLsOutputWrapper{ - RefKeyObject: RefKeyObject{ - Type: typeStr, - Cid: c.String(), - }, - }) - if err != nil { - return err - } - } - } - return nil - } - - if typeStr == "direct" || typeStr == "all" { - err := AddToResultKeys(n.Pinning.DirectKeys(), "direct") - if err != nil { - return err - } - } - if typeStr == "recursive" || typeStr == "all" { - err := AddToResultKeys(n.Pinning.RecursiveKeys(), "recursive") - if err != nil { - return err - } - } - if typeStr == "indirect" || typeStr == "all" { - for _, k := range n.Pinning.RecursiveKeys() { - var visitErr error - err := dag.EnumerateChildren(ctx, dag.GetLinksWithDAG(n.DAG), k, func(c cid.Cid) bool { - r := keys.Visit(c) - if r { - err := emit(&PinLsOutputWrapper{ - RefKeyObject: RefKeyObject{ - Type: "indirect", - Cid: c.String(), - }, - }) - if err != nil { - visitErr = err - } - } - return r - }) - - if visitErr != nil { - return visitErr - } - if err != nil { - return err - } - } - } - - return nil -} - // PinVerifyRes is the result returned for each pin checked in "pin verify" type PinVerifyRes struct { Cid string From 58ea970135284a4ba3f64c1bf868f2f1dffe488b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Mur=C3=A9?= Date: Thu, 11 Jul 2019 13:59:09 +0200 Subject: [PATCH 093/671] pin cmd: better struct naming --- core/commands/pin.go | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/core/commands/pin.go b/core/commands/pin.go index b9e92530655..10fd4b242ed 100644 --- a/core/commands/pin.go +++ b/core/commands/pin.go @@ -339,11 +339,11 @@ Example: // For backward compatibility, we accumulate the pins in the same output type as before. emit := res.Emit - lgcList := map[string]RefObject{} + lgcList := map[string]PinLsType{} if !stream { emit = func(v interface{}) error { obj := v.(*PinLsOutputWrapper) - lgcList[obj.RefKeyObject.Cid] = RefObject{Type: obj.RefKeyObject.Type} + lgcList[obj.PinLsObject.Cid] = PinLsType{Type: obj.PinLsObject.Type} return nil } } @@ -359,7 +359,7 @@ Example: if !stream { return cmds.EmitOnce(res, &PinLsOutputWrapper{ - RefKeyList: RefKeyList{Keys: lgcList}, + PinLsList: PinLsList{Keys: lgcList}, }) } @@ -373,14 +373,14 @@ Example: if stream { if quiet { - fmt.Fprintf(w, "%s\n", out.RefKeyObject.Cid) + fmt.Fprintf(w, "%s\n", out.PinLsObject.Cid) } else { - fmt.Fprintf(w, "%s %s\n", out.RefKeyObject.Cid, out.RefKeyObject.Type) + fmt.Fprintf(w, "%s %s\n", out.PinLsObject.Cid, out.PinLsObject.Type) } return nil } - for k, v := range out.RefKeyList.Keys { + for k, v := range out.PinLsList.Keys { if quiet { fmt.Fprintf(w, "%s\n", k) } else { @@ -393,24 +393,24 @@ Example: }, } -type RefKeyObject struct { +type PinLsObject struct { Cid string `json:",omitempty"` Type string `json:",omitempty"` } -type RefObject struct { +type PinLsType struct { Type string } -type RefKeyList struct { - Keys map[string]RefObject `json:",omitempty"` +type PinLsList struct { + Keys map[string]PinLsType `json:",omitempty"` } // Pin ls needs to output two different type depending on if it's streamed or not. // We use this to bypass the cmds lib refusing to have interface{} type PinLsOutputWrapper struct { - RefKeyList - RefKeyObject + PinLsList + PinLsObject } func pinLsKeys(req *cmds.Request, typeStr string, n *core.IpfsNode, api coreiface.CoreAPI, emit func(value interface{}) error) error { @@ -446,7 +446,7 @@ func pinLsKeys(req *cmds.Request, typeStr string, n *core.IpfsNode, api coreifac } err = emit(&PinLsOutputWrapper{ - RefKeyObject: RefKeyObject{ + PinLsObject: PinLsObject{ Type: pinType, Cid: enc.Encode(c.Cid()), }, @@ -471,7 +471,7 @@ func pinLsAll(req *cmds.Request, typeStr string, n *core.IpfsNode, emit func(val for _, c := range keyList { if keys.Visit(c) { err := emit(&PinLsOutputWrapper{ - RefKeyObject: RefKeyObject{ + PinLsObject: PinLsObject{ Type: typeStr, Cid: enc.Encode(c), }, @@ -497,7 +497,7 @@ func pinLsAll(req *cmds.Request, typeStr string, n *core.IpfsNode, emit func(val r := keys.Visit(c) if r { err := emit(&PinLsOutputWrapper{ - RefKeyObject: RefKeyObject{ + PinLsObject: PinLsObject{ Type: typeStr, Cid: enc.Encode(c), }, From 4ec37b6f7ba672b3f68c4a4c75ce55c10fcfc7f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Mur=C3=A9?= Date: Thu, 11 Jul 2019 14:05:05 +0200 Subject: [PATCH 094/671] pin cmd: document pin ls output types --- core/commands/pin.go | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/core/commands/pin.go b/core/commands/pin.go index 10fd4b242ed..c5a77470204 100644 --- a/core/commands/pin.go +++ b/core/commands/pin.go @@ -393,24 +393,28 @@ Example: }, } -type PinLsObject struct { - Cid string `json:",omitempty"` - Type string `json:",omitempty"` -} - -type PinLsType struct { - Type string +// PinLsOutputWrapper is the output type of the pin ls command. +// Pin ls needs to output two different type depending on if it's streamed or not. +// We use this to bypass the cmds lib refusing to have interface{} +type PinLsOutputWrapper struct { + PinLsList + PinLsObject } +// PinLsList is a set of pins with their type type PinLsList struct { Keys map[string]PinLsType `json:",omitempty"` } -// Pin ls needs to output two different type depending on if it's streamed or not. -// We use this to bypass the cmds lib refusing to have interface{} -type PinLsOutputWrapper struct { - PinLsList - PinLsObject +// PinLsType contains the type of a pin +type PinLsType struct { + Type string +} + +// PinLsObject contains the description of a pin +type PinLsObject struct { + Cid string `json:",omitempty"` + Type string `json:",omitempty"` } func pinLsKeys(req *cmds.Request, typeStr string, n *core.IpfsNode, api coreiface.CoreAPI, emit func(value interface{}) error) error { From 9b21269e037cf92396c752610d17b684a3152df6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Mur=C3=A9?= Date: Thu, 11 Jul 2019 14:33:34 +0200 Subject: [PATCH 095/671] pin cmd: output the recursive pins first for performance --- core/commands/pin.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/commands/pin.go b/core/commands/pin.go index c5a77470204..27092d698f4 100644 --- a/core/commands/pin.go +++ b/core/commands/pin.go @@ -494,6 +494,12 @@ func pinLsAll(req *cmds.Request, typeStr string, n *core.IpfsNode, emit func(val return err } } + if typeStr == "recursive" || typeStr == "all" { + err := AddToResultKeys(n.Pinning.RecursiveKeys(), "recursive") + if err != nil { + return err + } + } if typeStr == "indirect" || typeStr == "all" { for _, k := range n.Pinning.RecursiveKeys() { var visitErr error @@ -521,12 +527,6 @@ func pinLsAll(req *cmds.Request, typeStr string, n *core.IpfsNode, emit func(val } } } - if typeStr == "recursive" || typeStr == "all" { - err := AddToResultKeys(n.Pinning.RecursiveKeys(), "recursive") - if err != nil { - return err - } - } return nil } From 16b4d74d3b372f9a404ab4c92fa4c81dd8449d39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Mur=C3=A9?= Date: Thu, 11 Jul 2019 14:34:23 +0200 Subject: [PATCH 096/671] pin cmd: fix incorect pin type for indirect pins --- core/commands/pin.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/commands/pin.go b/core/commands/pin.go index 27092d698f4..1f77a90d7b9 100644 --- a/core/commands/pin.go +++ b/core/commands/pin.go @@ -508,7 +508,7 @@ func pinLsAll(req *cmds.Request, typeStr string, n *core.IpfsNode, emit func(val if r { err := emit(&PinLsOutputWrapper{ PinLsObject: PinLsObject{ - Type: typeStr, + Type: "indirect", Cid: enc.Encode(c), }, }) From 010336c89f980687004dde96c6a037f0b3da3f1b Mon Sep 17 00:00:00 2001 From: Hector Sanjuan Date: Fri, 21 Jun 2019 11:20:18 +0100 Subject: [PATCH 097/671] Document the AddrFilters option Shouldn't have to scan through an old issue to figure out what is happening and why this is super important. --- docs/config.md | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/docs/config.md b/docs/config.md index 862713f6513..7d855d9ed0f 100644 --- a/docs/config.md +++ b/docs/config.md @@ -342,10 +342,18 @@ Tells reprovider what should be announced. Valid strategies are: Options for configuring the swarm. -- `AddrFilters` -An array of address filters (multiaddr netmasks) to filter dials to. -See [this issue](https://github.com/ipfs/go-ipfs/issues/1226#issuecomment-120494604) for more -information. +- `AddrFilters` An array of address filters (multiaddr netmasks) to filter +automatic dials to. The ipfs daemon will otherwise attempt to randomly dial +the default listen port on every IP of the the local network IP range. This +improves autodiscovery of other daemons in the same network, but may also +trigger netscan alerts on some hosting providers or cause strain in some +setups. + +The `server` configuration profile fills up this list with sensible defaults, +preventing scans to most common local network (`10.0.0.0/8` or +`192.168.0.0/16`), but you should always check settings against your own +network and/or hosting provider. + - `DisableBandwidthMetrics` A boolean value that when set to true, will cause ipfs to not keep track of From 72122a5dbfdce14533b1e04675e9ac516301b406 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Thu, 11 Jul 2019 19:03:21 -0700 Subject: [PATCH 098/671] doc: correct the address filter documentation --- docs/config.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/docs/config.md b/docs/config.md index 7d855d9ed0f..e0630b40f2b 100644 --- a/docs/config.md +++ b/docs/config.md @@ -342,17 +342,18 @@ Tells reprovider what should be announced. Valid strategies are: Options for configuring the swarm. -- `AddrFilters` An array of address filters (multiaddr netmasks) to filter -automatic dials to. The ipfs daemon will otherwise attempt to randomly dial -the default listen port on every IP of the the local network IP range. This -improves autodiscovery of other daemons in the same network, but may also -trigger netscan alerts on some hosting providers or cause strain in some -setups. +- `AddrFilters` +An array of addresses (multiaddr netmasks) to not dial. By default, IPFS nodes advertise +_all_ addresses, even internal ones. This makes it easier for nodes on the same +network to reach each other. Unfortunately, this means that an IPFS node will +try to connect to one or more private IP addresses whenever dialing another +node, even if this other node is on a different network. This may may trigger +netscan alerts on some hosting providers or cause strain in some setups. The `server` configuration profile fills up this list with sensible defaults, -preventing scans to most common local network (`10.0.0.0/8` or -`192.168.0.0/16`), but you should always check settings against your own -network and/or hosting provider. +preventing dials to all non-routable IP addresses (e.g., `192.168.0.0/16`) but +you should always check settings against your own network and/or hosting +provider. - `DisableBandwidthMetrics` From 9bb15f232f14220c587f33d71e7a6a159d4149ba Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Thu, 11 Jul 2019 00:21:48 -0700 Subject: [PATCH 099/671] releases: switch to a soft release model And other nits. --- docs/RELEASE_TEMPLATE.md | 27 ++++++ docs/releases.md | 187 +++++++++++++++++++-------------------- 2 files changed, 117 insertions(+), 97 deletions(-) create mode 100644 docs/RELEASE_TEMPLATE.md diff --git a/docs/RELEASE_TEMPLATE.md b/docs/RELEASE_TEMPLATE.md new file mode 100644 index 00000000000..ec50089694f --- /dev/null +++ b/docs/RELEASE_TEMPLATE.md @@ -0,0 +1,27 @@ +# Go-IPFS Changelog Template + +## X.Y.Z YYYY-MM-DD + +We're happy to announce go-ipfs X.Y.Z, bla bla... + +< release notes > + +### Contributors + +< list generated by bin/mkreleaselog > + +Would you like to contribute to the IPFS project and don't know how? Well, there are a few places you can get started: + +- Check the issues with the `help wanted` label in the [go-ipfs repo](https://github.com/ipfs/go-ipfs/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22) +- Join an IPFS All Hands, introduce yourself and let us know where you would like to contribute - https://github.com/ipfs/team-mgmt/#weekly-ipfs-all-hands +- Hack with IPFS and show us what you made! The All Hands call is also the perfect venue for demos, join in and show us what you built +- Join the discussion at http://discuss.ipfs.io/ and help users finding their answers. +- Join the [Go Core Dev Team Weekly Sync](https://github.com/ipfs/team-mgmt/issues/650) and be part of the Sprint action! + +### ⁉️ Do you have questions? + +The best place to ask your questions about IPFS, how it works and what you can do with it is at [discuss.ipfs.io](http://discuss.ipfs.io). We are also available at the `#ipfs` channel on Freenode, which is also [accessible through our Matrix bridge](https://riot.im/app/#/room/#freenode_#ipfs:matrix.org). + +### Changelog + +< changelog generated by bin/mkreleaselog > diff --git a/docs/releases.md b/docs/releases.md index 56b412f9a56..9284db2bf98 100644 --- a/docs/releases.md +++ b/docs/releases.md @@ -9,7 +9,7 @@ ## Release Philosophy -`go-ipfs` aims to have release every six weeks, two releases per quarter. During these 6 week releases, we go through 4 different stages of Release Candidates (RC) that gives us the opportunity to test the new version against our test environments (unit, interop, integration), QA in our current production environment, IPFS apps (e.g. Desktop and WebUI) and with our _early testers_[1] that have IPFS running in Production, by leveraging their own test infrastructure and QA systems. +`go-ipfs` aims to have release every six weeks, two releases per quarter. During these 6 week releases, we go through 4 different stages that gives us the opportunity to test the new version against our test environments (unit, interop, integration), QA in our current production environment, IPFS apps (e.g. Desktop and WebUI) and with our community and _early testers_[1] that have IPFS running in Production. We might expand the six week release schedule in case of: - No new updates to be added @@ -17,20 +17,41 @@ We might expand the six week release schedule in case of: ## Release Flow -`go-ipfs` releases come in 4 stages: +`go-ipfs` releases come in 4 stages designed to gradually roll out changes and reduce the impact of any regressions that may have been introduced. If we need to merge non-trivial features/fixes during the process, we start over at stage 1. -- **Release Stage 1 - Internal testing** - Test the Release against our testing infrastructure, including interoperability, integration, test lab, multiple runtimes and the apps we've built (WebUI, Desktop, NPM on IPFS, HTTP Client Libraries). The intent is to make this stage fully automated (and somewhat is already), until then, we manually check a list and ensure that all tests have been run -- **Release Stage 2 - Invite _early testers_ to try it out** - Reach out to our _early testers_ (i.e. projects that have volunteered to support `go-ipfs` by using their own test infrastructure and tell us the results) -- **Release Stage 3 - Announce to the broader community** - Communicate to the community that a new Release Candidate is ready and that everyone is welcome to test it with us -- **Release Stage 4 - Complete the Release** - Finalize the release, start the next release. +### Stage 1 - Internal Testing -The Release Stages are not linked to Release Candidate numbers, in fact, there can be multiple release candidate per stages as we catch bugs and improve the release itself. +Before this stage, we expect _all_ tests (interop, testlab, performance, etc.) to pass. -

- - - -

+At this stage, we'll: + +1. Start a partial-rollout to our own infrastructure. +2. Test against ipfs and ipfs-shipyard applications. + +**Goal(s):** + +1. Make sure we haven't introduced any obvious regressions. +2. Test the release in an environment we can monitor and easily roll back (i.e., our own infra). + +### Stage 2 - Public Beta + +At this stage, we'll announce the impending release to the community and ask for beta testers. + +**Goal:** Test the release in as many non-production environments as possible. This is relatively low-risk but gives us a _breadth_ of testing internal testing can't. + +### Stage 3 - Soft Release + +At this stage, we consider the release to be "production ready" and ask will ask the community and our early testers to (partially) deploy the release to their production infrastructure. + +**Goal(s):** + +1. Test the release in some production environments with heavy workloads. +2. Partially roll-out an upgrade to see how it affects the network. +3. Retain the ability to ship last-minute fixes before the final release. + +### Stage 4 - Release + +At this stage, the release is "battle hardened" and ready for wide deployment. ## Performing a Release @@ -54,91 +75,63 @@ The first step is for the `Lead Maintainer` for `go-ipfs` to open an issue with # ✅ Release Checklist For each RC published in each stage: -- [ ] version string in `version.go` has been updated -- [ ] tag commit with vX.Y.Z-rcN - -### Release Stage 1 - Internal testing - -When Release Stage 1, there is a features freeze for the release branch. - -- [ ] CHANGELOG.md has been updated - - use `./bin/mkreleaselog` to generate a nice starter list -- [ ] Automated Testing - Ensure that all tests are passing, this includes: - - [ ] unit - - [ ] sharness - - [ ] [interop](https://github.com/ipfs/interop#test-with-a-non-yet-released-version-of-go-ipfs) -- [ ] Network Testing: - - [ ] test lab things -- [ ] Infrastructure Testing: - - [ ] Deploy new version to a subset of Bootstrappers - - [ ] Deploy new version to a subset of Gateways - - [ ] Deploy new version to a subset of Preload nodes - - [ ] Collect metrics every day. Work with the Infrastructure team to learn of any hiccup -- [ ] IPFS HTTP Client Libraries Testing: - - [ ] [JS](http://github.com/ipfs/js-ipfs-http-client) - - [ ] [Go](https://github.com/ipfs/go-ipfs-api) -- [ ] IPFS Application Testing - Run the tests of the following applications: - - [ ] WebUI - - [ ] IPFS Desktop - - [ ] IPFS Companion - - [ ] NPM on IPFS - -### Release Stage 2 - Invite _early testers_ to try it out - -- [ ] Reach out to the IPFS _early testers_ listed below for testing this release (check when no more problems have been reported). - - [ ] **COPY THE LIST FROM `docs/EARLY_TESTERS.md`** -- [ ] Run tests available in the following repos with the latest RC (check when all tests pass): - - [ ] [orbit-db](https://github.com/orbitdb/orbit-db) - -PSA: If you are a heavy user of `go-ipfs`, have developed a solid test infrastructure for your application and would love to help us would like to help us test `go-ipfs` release candidates, reach out to go-ipfs-wg@ipfs.io. - -### Release Stage 3 - Announce to the broader community - -- [ ] Documentation - - [ ] Ensure that CHANGELOG.md is up to date - - [ ] Ensure that README.md is up to date - - [ ] Ensure that all the examples we have produced for go-ipfs run without problems - - [ ] Update HTTP-API Documentation on the Website using https://github.com/ipfs/http-api-docs -- [ ] Invite the community through (link to the release issue): - - [ ] [discuss.ipfs.io](https://discuss.ipfs.io/c/announcements) - - [ ] Twitter - - [ ] IRC - -### Release Stage 4 - Complete the Release - -- [ ] Final preparation - - [ ] Verify that version string in `repo/version.go` has been updated - - [ ] tag commit with vX.Y.Z - - [ ] update release branch to point to release commit (`git merge vX.Y.Z`). - - [ ] publish dist.ipfs.io - - [ ] publish next version to https://github.com/ipfs/npm-go-ipfs -- [ ] Publish a Release Blog post (at minimum, a c&p of this release issue with all the highlights, API changes, link to changelog and thank yous) -- [ ] Broadcasting (link to blog post) - - [ ] Twitter - - [ ] IRC - - [ ] Reddit - - [ ] [discuss.ipfs.io](https://discuss.ipfs.io/c/announcements) - - [ ] Announce it on the [IPFS Users mlist](https://groups.google.com/forum/#!forum/ipfs-users) - -# ❤️ Huge thank you to everyone that made this release possible - -In alphabetical order, here are all the humans that contributed to the release: - -- - -# 🙌🏽 Want to contribute? - -Would you like to contribute to the IPFS project and don't know how? Well, there are a few places you can get started: - -- Check the issues with the `help wanted` label in the [go-ipfs repo](https://github.com/ipfs/go-ipfs/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22) -- Join an IPFS All Hands, introduce yourself and let us know where you would like to contribute - https://github.com/ipfs/team-mgmt/#weekly-ipfs-all-hands -- Hack with IPFS and show us what you made! The All Hands call is also the perfect venue for demos, join in and show us what you built -- Join the discussion at http://discuss.ipfs.io/ and help users finding their answers. -- Join the [Go Core Dev Team Weekly Sync](https://github.com/ipfs/team-mgmt/issues/650) and be part of the Sprint action! - -# ⁉️ Do you have questions? - -The best place to ask your questions about IPFS, how it works and what you can do with it is at [discuss.ipfs.io](http://discuss.ipfs.io). We are also available at the `#ipfs` channel on Freenode, which is also [accessible through our Matrix bridge](https://riot.im/app/#/room/#freenode_#ipfs:matrix.org). + +- version string in `version.go` has been updated +- tag commit with vX.Y.Z-rcN + +- [ ] Stage 1 - Internal Testing + - [ ] Feature freeze. If any non-trivial features get added to the release, uncheck all the checkboxes and return to this stage. + - [ ] CHANGELOG.md has been updated + - use `./bin/mkreleaselog` to generate a nice starter list + - use `./doc/RELEASE_TEMPLATE.md` as a template + - [ ] Automated Testing (already tested in CI) - Ensure that all tests are passing, this includes: + - [ ] unit + - [ ] sharness + - [ ] [interop](https://github.com/ipfs/interop#test-with-a-non-yet-released-version-of-go-ipfs) + - [ ] go-ipfs-api + - [ ] go-ipfs-http-client + - [ ] Network Testing: + - [ ] test lab things + - [ ] Infrastructure Testing: + - [ ] Deploy new version to a subset of Bootstrappers + - [ ] Deploy new version to a subset of Gateways + - [ ] Deploy new version to a subset of Preload nodes + - [ ] Collect metrics every day. Work with the Infrastructure team to learn of any hiccup + - [ ] IPFS Application Testing - Run the tests of the following applications: + - [ ] WebUI + - [ ] IPFS Desktop + - [ ] IPFS Companion + - [ ] NPM on IPFS +- [ ] Stage 2 - Public Beta + - [ ] Reach out to the IPFS _early testers_ listed in `docs/EARLY_TESTERS.md` for testing this release (check when no more problems have been reported). If you'd like to be added to this list, please file a PR. + - [ ] Reach out to on IRC for beta testers. + - [ ] Run tests available in the following repos with the latest beta (check when all tests pass): + - [ ] [orbit-db](https://github.com/orbitdb/orbit-db) +- [ ] Stage 3 - Soft Release + - [ ] Documentation + - [ ] Ensure that CHANGELOG.md is up to date + - [ ] Ensure that README.md is up to date + - [ ] Ensure that all the examples we have produced for go-ipfs run without problems + - [ ] Update HTTP-API Documentation on the Website using https://github.com/ipfs/http-api-docs + - [ ] Invite the IPFS _early testers_ to deploy the release to part of their production infrastructure. + - [ ] Invite the wider community through (link to the release issue): + - [ ] [discuss.ipfs.io](https://discuss.ipfs.io/c/announcements) + - [ ] Twitter + - [ ] IRC +- [ ] Stage 4 - Release + - [ ] Final preparation + - [ ] Verify that version string in `repo/version.go` has been updated + - [ ] tag commit with vX.Y.Z + - [ ] update release branch to point to release commit (`git merge vX.Y.Z`). + - [ ] publish dist.ipfs.io + - [ ] publish next version to https://github.com/ipfs/npm-go-ipfs + - [ ] Publish a Release Blog post (at minimum, a c&p of this release issue with all the highlights, API changes, link to changelog and thank yous) + - [ ] Broadcasting (link to blog post) + - [ ] Twitter + - [ ] IRC + - [ ] Reddit + - [ ] [discuss.ipfs.io](https://discuss.ipfs.io/c/announcements) + - [ ] Announce it on the [IPFS Users mlist](https://groups.google.com/forum/#!forum/ipfs-users) ``` ## Release Version Numbers (aka semver) From 146d9d2ac515ef140e9bab65cb0d72f135dcc456 Mon Sep 17 00:00:00 2001 From: Hector Sanjuan Date: Fri, 12 Jul 2019 13:03:27 +0200 Subject: [PATCH 100/671] Improve pin/update description I was unable to actually understand what pin update does from the existing description. License: MIT Signed-off-by: Hector Sanjuan --- core/commands/pin.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/core/commands/pin.go b/core/commands/pin.go index c1548904a83..fbd4948970e 100644 --- a/core/commands/pin.go +++ b/core/commands/pin.go @@ -385,15 +385,20 @@ var updatePinCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Update a recursive pin", ShortDescription: ` -Updates one pin to another, making sure that all objects in the new pin are -local. Then removes the old pin. This is an optimized version of adding the -new pin and removing the old one. +Efficiently pins a new object based on differences from an existing one and, +by default, removes the old pin. + +This commands is useful when the new pin contains many similarities or is a +derivate of an existing one, particuarly for large objects. This allows a more +efficient DAG-traversal which fully skips already-pinned branches from the old +object. As a requirement, the old object needs to be an existing recursive +pin. `, }, Arguments: []cmds.Argument{ cmds.StringArg("from-path", true, false, "Path to old object."), - cmds.StringArg("to-path", true, false, "Path to new object to be pinned."), + cmds.StringArg("to-path", true, false, "Path to a new object to be pinned."), }, Options: []cmds.Option{ cmds.BoolOption(pinUnpinOptionName, "Remove the old pin.").WithDefault(true), From 9b5fe58291d480120846d9f95c1561a5e8d9781f Mon Sep 17 00:00:00 2001 From: Andrew Nesbitt Date: Fri, 12 Jul 2019 15:22:22 +0100 Subject: [PATCH 101/671] Fix automatic labels in issue templates Label list should be a comma seperated string instead of a yaml array --- .github/ISSUE_TEMPLATE/bug-report.md | 3 +-- .github/ISSUE_TEMPLATE/doc.md | 3 +-- .github/ISSUE_TEMPLATE/enhancement.md | 3 +-- .github/ISSUE_TEMPLATE/feature.md | 3 +-- .github/ISSUE_TEMPLATE/question.md | 4 +--- 5 files changed, 5 insertions(+), 11 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md index 1b0fed9acdd..8e24a4e128c 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.md +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -1,8 +1,7 @@ --- name: 'Bug Report' about: 'Report a bug in go-ipfs.' -labels: - - bug +labels: bug --- #### Version information: diff --git a/.github/ISSUE_TEMPLATE/doc.md b/.github/ISSUE_TEMPLATE/doc.md index 4662fb7bb06..5a0d1982180 100644 --- a/.github/ISSUE_TEMPLATE/doc.md +++ b/.github/ISSUE_TEMPLATE/doc.md @@ -1,8 +1,7 @@ --- name: 'Documentation Issue' about: 'Report missing/erroneous documentation, propose new documentation, report broken links, etc.' -labels: - - documentation +labels: documentation --- #### Location diff --git a/.github/ISSUE_TEMPLATE/enhancement.md b/.github/ISSUE_TEMPLATE/enhancement.md index 6615bf70e8c..4d2233d35f2 100644 --- a/.github/ISSUE_TEMPLATE/enhancement.md +++ b/.github/ISSUE_TEMPLATE/enhancement.md @@ -1,8 +1,7 @@ --- name: 'Enhancement' about: 'Suggest an improvement to an existing go-ipfs feature.' -labels: - - enhancement +labels: enhancement --- + +Default: `false` + + +#### `Gateway.PublicGateways: NoDNSLink` + +A boolean to configure whether DNSLink for hostname present in `Host` +HTTP header should be resolved. Overrides global setting. +If `Paths` are defined, they take priority over DNSLink. + +Default: `false` (DNSLink lookup enabled by default for every defined hostname) + +#### Implicit defaults of `Gateway.PublicGateways` + +Default entries for `localhost` hostname and loopback IPs are always present. +If additional config is provided for those hostnames, it will be merged on top of implicit values: +```json +{ + "Gateway": { + "PublicGateways": { + "localhost": { + "Paths": ["/ipfs", "/ipns"], + "UseSubdomains": true + } + } + } +} +``` + +It is also possible to remove a default by setting it to `null`. +For example, to disable subdomain gateway on `localhost` +and make that hostname act the same as `127.0.0.1`: + +```console +$ ipfs config --json Gateway.PublicGateways '{"localhost": null }' +``` + +### `Gateway` recipes + +Below is a list of the most common public gateway setups. + +* Public [subdomain gateway](https://docs-beta.ipfs.io/how-to/address-ipfs-on-web/#subdomain-gateway) at `http://{cid}.ipfs.dweb.link` (each content root gets its own Origin) + ```console + $ ipfs config --json Gateway.PublicGateways '{ + "dweb.link": { + "UseSubdomains": true, + "Paths": ["/ipfs", "/ipns"] + } + }' + ``` + **Note:** this enables automatic redirects from content paths to subdomains + `http://dweb.link/ipfs/{cid}` → `http://{cid}.ipfs.dweb.link` + +* Public [path gateway](https://docs-beta.ipfs.io/how-to/address-ipfs-on-web/#path-gateway) at `http://ipfs.io/ipfs/{cid}` (no Origin separation) + ```console + $ ipfs config --json Gateway.PublicGateways '{ + "ipfs.io": { + "UseSubdomains": false, + "Paths": ["/ipfs", "/ipns", "/api"] + } + }' + ``` + +* Public [DNSLink](https://dnslink.io/) gateway resolving every hostname passed in `Host` header. + ```console + $ ipfs config --json Gateway.NoDNSLink true + ``` + * Note that `NoDNSLink: false` is the default (it works out of the box unless set to `true` manually) + +* Hardened, site-specific [DNSLink gateway](https://docs-beta.ipfs.io/how-to/address-ipfs-on-web/#dnslink-gateway). + Disable fetching of remote data (`NoFetch: true`) + and resolving DNSLink at unknown hostnames (`NoDNSLink: true`). + Then, enable DNSLink gateway only for the specific hostname (for which data + is already present on the node), without exposing any content-addressing `Paths`: + "NoFetch": true, + "NoDNSLink": true, + ```console + $ ipfs config --json Gateway.NoFetch true + $ ipfs config --json Gateway.NoDNSLink true + $ ipfs config --json Gateway.PublicGateways '{ + "en.wikipedia-on-ipfs.org": { + "NoDNSLink": false, + "Paths": [] + } + }' + ``` + ## `Identity` ### `Identity.PeerID` diff --git a/docs/environment-variables.md b/docs/environment-variables.md index fdc92f461c3..b64a4e2481d 100644 --- a/docs/environment-variables.md +++ b/docs/environment-variables.md @@ -84,7 +84,7 @@ Default: https://ipfs.io/ipfs/$something (depends on the IPFS version) ## `IPFS_NS_MAP` -Prewarms namesys cache with static records for deteministic tests and debugging. +Adds static namesys records for deteministic tests and debugging. Useful for testing things like DNSLink without real DNS lookup. Example: diff --git a/go.mod b/go.mod index 53ccb013976..c1823843bd9 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,7 @@ require ( github.com/ipfs/go-ipfs-blockstore v0.1.4 github.com/ipfs/go-ipfs-chunker v0.0.4 github.com/ipfs/go-ipfs-cmds v0.1.2 - github.com/ipfs/go-ipfs-config v0.2.1 + github.com/ipfs/go-ipfs-config v0.3.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 diff --git a/go.sum b/go.sum index 88d51c67606..9a8b551dc0b 100644 --- a/go.sum +++ b/go.sum @@ -268,14 +268,10 @@ github.com/ipfs/go-ipfs-chunker v0.0.1 h1:cHUUxKFQ99pozdahi+uSC/3Y6HeRpi9oTeUHbE github.com/ipfs/go-ipfs-chunker v0.0.1/go.mod h1:tWewYK0we3+rMbOh7pPFGDyypCtvGcBFymgY4rSDLAw= github.com/ipfs/go-ipfs-chunker v0.0.4 h1:nb2ZIgtOk0TxJ5KDBEk+sv6iqJTF/PHg6owN2xCrUjE= github.com/ipfs/go-ipfs-chunker v0.0.4/go.mod h1:jhgdF8vxRHycr00k13FM8Y0E+6BoalYeobXmUyTreP8= -github.com/ipfs/go-ipfs-cmds v0.1.1 h1:H9/BLf5rcsULHMj/x8gC0e5o+raYhqk1OQsfzbGMNM4= -github.com/ipfs/go-ipfs-cmds v0.1.1/go.mod h1:k1zMXcOLtljA9iAnZHddbH69yVm5+weRL0snmMD/rK0= -github.com/ipfs/go-ipfs-cmds v0.1.2-0.20200316211807-0c2a21b0dacc h1:HIG2l6XUnov+M6UwcUKKrwGc8Q+n9AYGbiGM4pK21SM= -github.com/ipfs/go-ipfs-cmds v0.1.2-0.20200316211807-0c2a21b0dacc/go.mod h1:a9LyFOtQCnVc3BvbAgW+GrMXEuN29aLCNi3Wk0IM8wo= github.com/ipfs/go-ipfs-cmds v0.1.2 h1:02FLzTA9jYRle/xdMWYwGwxu3gzC3GhPUaz35dH+FrY= github.com/ipfs/go-ipfs-cmds v0.1.2/go.mod h1:a9LyFOtQCnVc3BvbAgW+GrMXEuN29aLCNi3Wk0IM8wo= -github.com/ipfs/go-ipfs-config v0.2.1 h1:Mpyvdf9Zc8k3jg+sRe8e9iylYXHYXqFMuePUjAZQvsE= -github.com/ipfs/go-ipfs-config v0.2.1/go.mod h1:zCKH1uf1XIvf67589BnQ5IAv/Pld2J3gQoQYvG8TK8w= +github.com/ipfs/go-ipfs-config v0.3.0 h1:fGs3JBqB9ia/Joi8up47uiKn150EOEqqVFwv8HZqXao= +github.com/ipfs/go-ipfs-config v0.3.0/go.mod h1:nSLCFtlaL+2rbl3F+9D4gQZQbT1LjRKx7TJg/IHz6oM= github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= github.com/ipfs/go-ipfs-delay v0.0.1 h1:r/UXYyRcddO6thwOnhiznIAiSvxMECGgtv35Xs1IeRQ= github.com/ipfs/go-ipfs-delay v0.0.1/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= diff --git a/namesys/namesys.go b/namesys/namesys.go index 11f4646f174..a486b83b8a3 100644 --- a/namesys/namesys.go +++ b/namesys/namesys.go @@ -2,11 +2,13 @@ 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" @@ -14,7 +16,6 @@ import ( ci "github.com/libp2p/go-libp2p-core/crypto" peer "github.com/libp2p/go-libp2p-core/peer" routing "github.com/libp2p/go-libp2p-core/routing" - mh "github.com/multiformats/go-multihash" ) // mpns (a multi-protocol NameSystem) implements generic IPFS naming. @@ -133,12 +134,28 @@ func (ns *mpns) resolveOnceAsync(ctx context.Context, name string, options opts. } // Resolver selection: - // 1. if it is a multihash resolve through "ipns". + // 1. if it is a PeerID/CID/multihash resolve through "ipns". // 2. if it is a domain name, resolve through "dns" // 3. otherwise resolve through the "proquint" resolver var res resolver - if _, err := mh.FromB58String(key); err == nil { + _, err := peer.Decode(key) + + // CIDs in IPNS are expected to have libp2p-key multicodec + // We ease the transition by returning a more meaningful error with a valid CID + if err != nil && err.Error() == "can't convert CID of type protobuf to a peer ID" { + ipnsCid, cidErr := cid.Decode(key) + if cidErr == nil && ipnsCid.Version() == 1 && ipnsCid.Type() != cid.Libp2pKey { + fixedCid := cid.NewCidV1(cid.Libp2pKey, ipnsCid.Hash()).String() + codecErr := fmt.Errorf("peer ID represented as CIDv1 require libp2p-key multicodec: retry with /ipns/%s", fixedCid) + log.Debugf("RoutingResolver: could not convert public key hash %s to peer ID: %s\n", key, codecErr) + out <- onceResult{err: codecErr} + close(out) + return out + } + } + + if err == nil { res = ns.ipnsResolver } else if isd.IsDomain(key) { res = ns.dnsResolver diff --git a/namesys/namesys_test.go b/namesys/namesys_test.go index a0ffbc50d80..b3e963c9e9e 100644 --- a/namesys/namesys_test.go +++ b/namesys/namesys_test.go @@ -11,7 +11,7 @@ import ( offroute "github.com/ipfs/go-ipfs-routing/offline" ipns "github.com/ipfs/go-ipns" path "github.com/ipfs/go-path" - "github.com/ipfs/go-unixfs" + unixfs "github.com/ipfs/go-unixfs" opts "github.com/ipfs/interface-go-ipfs-core/options/namesys" ci "github.com/libp2p/go-libp2p-core/crypto" peer "github.com/libp2p/go-libp2p-core/peer" @@ -49,10 +49,12 @@ func (r *mockResolver) resolveOnceAsync(ctx context.Context, name string, option func mockResolverOne() *mockResolver { return &mockResolver{ entries: map[string]string{ - "QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy": "/ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj", - "QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n": "/ipns/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy", - "QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD": "/ipns/ipfs.io", - "QmQ4QZh8nrsczdUEwTyfBope4THUhqxqc1fx6qYhhzZQei": "/ipfs/QmP3ouCnU8NNLsW6261pAx2pNLV2E4dQoisB1sgda12Act", + "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 }, } } @@ -82,6 +84,8 @@ func TestNamesysResolution(t *testing.T) { testResolution(t, r, "/ipns/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", 1, "/ipns/ipfs.io", ErrResolveRecursion) testResolution(t, r, "/ipns/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", 2, "/ipns/QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n", ErrResolveRecursion) testResolution(t, r, "/ipns/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", 3, "/ipns/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy", ErrResolveRecursion) + testResolution(t, r, "/ipns/12D3KooWFB51PRY9BxcXSH6khFXw1BZeszeLDy7C8GciskqCTZn5", 1, "/ipns/QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n", ErrResolveRecursion) + testResolution(t, r, "/ipns/bafzbeickencdqw37dpz3ha36ewrh4undfjt2do52chtcky4rxkj447qhdm", 1, "/ipns/QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n", ErrResolveRecursion) } func TestPublishWithCache0(t *testing.T) { diff --git a/namesys/routing.go b/namesys/routing.go index c2d0d0252d4..60928fbca69 100644 --- a/namesys/routing.go +++ b/namesys/routing.go @@ -59,6 +59,7 @@ func (r *IpnsResolver) resolveOnceAsync(ctx context.Context, name string, option } 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) diff --git a/test/sharness/t0111-gateway-writeable.sh b/test/sharness/t0111-gateway-writeable.sh index f63b49bcf4b..6708b91a6db 100755 --- a/test/sharness/t0111-gateway-writeable.sh +++ b/test/sharness/t0111-gateway-writeable.sh @@ -41,7 +41,7 @@ test_expect_success "HTTP gateway gives access to sample file" ' test_expect_success "HTTP POST file gives Hash" ' echo "$RANDOM" >infile && - URL="http://localhost:$port/ipfs/" && + URL="http://127.0.0.1:$port/ipfs/" && curl -svX POST --data-binary @infile "$URL" 2>curl_post.out && grep "HTTP/1.1 201 Created" curl_post.out && LOCATION=$(grep Location curl_post.out) && @@ -49,7 +49,7 @@ test_expect_success "HTTP POST file gives Hash" ' ' test_expect_success "We can HTTP GET file just created" ' - URL="http://localhost:${port}${HASH}" && + URL="http://127.0.0.1:${port}${HASH}" && curl -so outfile "$URL" && test_cmp infile outfile ' @@ -60,7 +60,7 @@ test_expect_success "We got the correct hash" ' ' test_expect_success "HTTP GET empty directory" ' - URL="http://localhost:$port/ipfs/$HASH_EMPTY_DIR/" && + URL="http://127.0.0.1:$port/ipfs/$HASH_EMPTY_DIR/" && echo "GET $URL" && curl -so outfile "$URL" 2>curl_getEmpty.out && grep "Index of /ipfs/$HASH_EMPTY_DIR/" outfile @@ -68,7 +68,7 @@ test_expect_success "HTTP GET empty directory" ' test_expect_success "HTTP PUT file to construct a hierarchy" ' echo "$RANDOM" >infile && - URL="http://localhost:$port/ipfs/$HASH_EMPTY_DIR/test.txt" && + URL="http://127.0.0.1:$port/ipfs/$HASH_EMPTY_DIR/test.txt" && echo "PUT $URL" && curl -svX PUT --data-binary @infile "$URL" 2>curl_put.out && grep "HTTP/1.1 201 Created" curl_put.out && @@ -77,7 +77,7 @@ test_expect_success "HTTP PUT file to construct a hierarchy" ' ' test_expect_success "We can HTTP GET file just created" ' - URL="http://localhost:$port/ipfs/$HASH/test.txt" && + URL="http://127.0.0.1:$port/ipfs/$HASH/test.txt" && echo "GET $URL" && curl -so outfile "$URL" && test_cmp infile outfile @@ -85,7 +85,7 @@ test_expect_success "We can HTTP GET file just created" ' test_expect_success "HTTP PUT file to append to existing hierarchy" ' echo "$RANDOM" >infile2 && - URL="http://localhost:$port/ipfs/$HASH/test/test.txt" && + URL="http://127.0.0.1:$port/ipfs/$HASH/test/test.txt" && echo "PUT $URL" && curl -svX PUT --data-binary @infile2 "$URL" 2>curl_putAgain.out && grep "HTTP/1.1 201 Created" curl_putAgain.out && @@ -95,7 +95,7 @@ test_expect_success "HTTP PUT file to append to existing hierarchy" ' test_expect_success "We can HTTP GET file just updated" ' - URL="http://localhost:$port/ipfs/$HASH/test/test.txt" && + URL="http://127.0.0.1:$port/ipfs/$HASH/test/test.txt" && echo "GET $URL" && curl -svo outfile2 "$URL" 2>curl_getAgain.out && test_cmp infile2 outfile2 @@ -103,7 +103,7 @@ test_expect_success "We can HTTP GET file just updated" ' test_expect_success "HTTP PUT to replace a directory" ' echo "$RANDOM" >infile3 && - URL="http://localhost:$port/ipfs/$HASH/test" && + URL="http://127.0.0.1:$port/ipfs/$HASH/test" && echo "PUT $URL" && curl -svX PUT --data-binary @infile3 "$URL" 2>curl_putOverDirectory.out && grep "HTTP/1.1 201 Created" curl_putOverDirectory.out && @@ -112,7 +112,7 @@ test_expect_success "HTTP PUT to replace a directory" ' ' test_expect_success "We can HTTP GET file just put over a directory" ' - URL="http://localhost:$port/ipfs/$HASH/test" && + URL="http://127.0.0.1:$port/ipfs/$HASH/test" && echo "GET $URL" && curl -svo outfile3 "$URL" 2>curl_getOverDirectory.out && test_cmp infile3 outfile3 @@ -120,7 +120,7 @@ test_expect_success "We can HTTP GET file just put over a directory" ' test_expect_success "HTTP PUT to /ipns fails" ' PEERID=`ipfs id --format=""` && - URL="http://localhost:$port/ipns/$PEERID/test.txt" && + URL="http://127.0.0.1:$port/ipns/$PEERID/test.txt" && echo "PUT $URL" && curl -svX PUT --data-binary @infile1 "$URL" 2>curl_putIpns.out && grep "HTTP/1.1 400 Bad Request" curl_putIpns.out diff --git a/test/sharness/t0114-gateway-subdomains.sh b/test/sharness/t0114-gateway-subdomains.sh new file mode 100755 index 00000000000..38aa4cc9710 --- /dev/null +++ b/test/sharness/t0114-gateway-subdomains.sh @@ -0,0 +1,641 @@ +#!/usr/bin/env bash +# +# Copyright (c) Protocol Labs + +test_description="Test subdomain support on the HTTP gateway" + + +. lib/test-lib.sh + +## ============================================================================ +## Helpers specific to subdomain tests +## ============================================================================ + +# Helper that tests gateway response over direct HTTP +# and in all supported HTTP proxy modes +test_localhost_gateway_response_should_contain() { + local label="$1" + local expected="$3" + + # explicit "Host: $hostname" header to match browser behavior + # and also make tests independent from DNS + local host=$(echo $2 | cut -d'/' -f3 | cut -d':' -f1) + local hostname=$(echo $2 | cut -d'/' -f3 | cut -d':' -f1,2) + + # Proxy is the same as HTTP Gateway, we use raw IP and port to be sure + local proxy="http://127.0.0.1:$GWAY_PORT" + + # Create a raw URL version with IP to ensure hostname from Host header is used + # (removes false-positives, Host header is used for passing hostname already) + local url="$2" + local rawurl=$(echo "$url" | sed "s/$hostname/127.0.0.1:$GWAY_PORT/") + + #echo "hostname: $hostname" + #echo "url before: $url" + #echo "url after: $rawurl" + + # regular HTTP request + # (hostname in Host header, raw IP in URL) + test_expect_success "$label (direct HTTP)" " + curl -H \"Host: $hostname\" -sD - \"$rawurl\" > response && + test_should_contain \"$expected\" response + " + + # HTTP proxy + # (hostname is passed via URL) + # Note: proxy client should not care, but curl does DNS lookup + # for some reason anyway, so we pass static DNS mapping + test_expect_success "$label (HTTP proxy)" " + curl -x $proxy --resolve $hostname:127.0.0.1 -sD - \"$url\" > response && + test_should_contain \"$expected\" response + " + + # HTTP proxy 1.0 + # (repeating proxy test with older spec, just to be sure) + test_expect_success "$label (HTTP proxy 1.0)" " + curl --proxy1.0 $proxy --resolve $hostname:127.0.0.1 -sD - \"$url\" > response && + test_should_contain \"$expected\" response + " + + # HTTP proxy tunneling (CONNECT) + # https://tools.ietf.org/html/rfc7231#section-4.3.6 + # In HTTP/1.x, the pseudo-method CONNECT + # can be used to convert an HTTP connection into a tunnel to a remote host + test_expect_success "$label (HTTP proxy tunneling)" " + curl --proxytunnel -x $proxy -H \"Host: $hostname\" -sD - \"$rawurl\" > response && + test_should_contain \"$expected\" response + " +} + +# Helper that checks gateway resonse for specific hostname in Host header +test_hostname_gateway_response_should_contain() { + local label="$1" + local hostname="$2" + local url="$3" + local rawurl=$(echo "$url" | sed "s/$hostname/127.0.0.1:$GWAY_PORT/") + local expected="$4" + test_expect_success "$label" " + curl -H \"Host: $hostname\" -sD - \"$rawurl\" > response && + test_should_contain \"$expected\" response + " +} + +## ============================================================================ +## Start IPFS Node and prepare test CIDs +## ============================================================================ + +test_init_ipfs +test_launch_ipfs_daemon --offline + +# CIDv0to1 is necessary because raw-leaves are enabled by default during +# "ipfs add" with CIDv1 and disabled with CIDv0 +test_expect_success "Add test text file" ' + CID_VAL="hello" + CIDv1=$(echo $CID_VAL | ipfs add --cid-version 1 -Q) + CIDv0=$(echo $CID_VAL | ipfs add --cid-version 0 -Q) + CIDv0to1=$(echo "$CIDv0" | ipfs cid base32) +' + +test_expect_success "Add the test directory" ' + mkdir -p testdirlisting/subdir1/subdir2 && + echo "hello" > testdirlisting/hello && + echo "subdir2-bar" > testdirlisting/subdir1/subdir2/bar && + mkdir -p testdirlisting/api && + mkdir -p testdirlisting/ipfs && + echo "I am a txt file" > testdirlisting/api/file.txt && + echo "I am a txt file" > testdirlisting/ipfs/file.txt && + DIR_CID=$(ipfs add -Qr --cid-version 1 testdirlisting) +' + +test_expect_success "Publish test text file to IPNS" ' + PEERID=$(ipfs id --format="") + IPNS_IDv0=$(echo "$PEERID" | ipfs cid format -v 0) + IPNS_IDv1=$(echo "$PEERID" | ipfs cid format -v 1 --codec libp2p-key -b base32) + IPNS_IDv1_DAGPB=$(echo "$IPNS_IDv0" | ipfs cid format -v 1 -b base32) + test_check_peerid "${PEERID}" && + ipfs name publish --allow-offline -Q "/ipfs/$CIDv1" > name_publish_out && + ipfs name resolve "$PEERID" > output && + printf "/ipfs/%s\n" "$CIDv1" > expected2 && + test_cmp expected2 output +' + + +# ensure we start with empty Gateway.PublicGateways +test_expect_success 'start daemon with empty config for Gateway.PublicGateways' ' + test_kill_ipfs_daemon && + ipfs config --json Gateway.PublicGateways "{}" && + test_launch_ipfs_daemon --offline +' + +## ============================================================================ +## Test path-based requests to a local gateway with default config +## (forced redirects to http://*.localhost) +## ============================================================================ + +# /ipfs/ + +# IP remains old school path-based gateway + +test_localhost_gateway_response_should_contain \ + "request for 127.0.0.1/ipfs/{CID} stays on path" \ + "http://127.0.0.1:$GWAY_PORT/ipfs/$CIDv1" \ + "$CID_VAL" + +# 'localhost' hostname is used for subdomains, and should not return +# payload directly, but redirect to URL with proper origin isolation + +test_localhost_gateway_response_should_contain \ + "request for localhost/ipfs/{CIDv1} redirects to subdomain" \ + "http://localhost:$GWAY_PORT/ipfs/$CIDv1" \ + "Location: http://$CIDv1.ipfs.localhost:$GWAY_PORT/" + +test_localhost_gateway_response_should_contain \ + "request for localhost/ipfs/{CIDv0} redirects to CIDv1 representation in subdomain" \ + "http://localhost:$GWAY_PORT/ipfs/$CIDv0" \ + "Location: http://${CIDv0to1}.ipfs.localhost:$GWAY_PORT/" + +# /ipns/ + +test_localhost_gateway_response_should_contain \ + "request for localhost/ipns/{CIDv0} redirects to CIDv1 with libp2p-key multicodec in subdomain" \ + "http://localhost:$GWAY_PORT/ipns/$IPNS_IDv0" \ + "Location: http://${IPNS_IDv1}.ipns.localhost:$GWAY_PORT/" + +# /ipns/ + +test_localhost_gateway_response_should_contain \ + "request for localhost/ipns/{fqdn} redirects to DNSLink in subdomain" \ + "http://localhost:$GWAY_PORT/ipns/en.wikipedia-on-ipfs.org/wiki" \ + "Location: http://en.wikipedia-on-ipfs.org.ipns.localhost:$GWAY_PORT/wiki" + +# API on localhost subdomain gateway + +# /api/v0 present on the root hostname +test_localhost_gateway_response_should_contain \ + "request for localhost/api" \ + "http://localhost:$GWAY_PORT/api/v0/refs?arg=${DIR_CID}&r=true" \ + "Ref" + +# /api/v0 not mounted on content root subdomains +test_localhost_gateway_response_should_contain \ + "request for {cid}.ipfs.localhost/api returns data if present on the content root" \ + "http://${DIR_CID}.ipfs.localhost:$GWAY_PORT/api/file.txt" \ + "I am a txt file" + +test_localhost_gateway_response_should_contain \ + "request for {cid}.ipfs.localhost/api/v0/refs returns 404" \ + "http://${DIR_CID}.ipfs.localhost:$GWAY_PORT/api/v0/refs?arg=${DIR_CID}&r=true" \ + "404 Not Found" + +## ============================================================================ +## Test subdomain-based requests to a local gateway with default config +## (origin per content root at http://*.localhost) +## ============================================================================ + +# {CID}.ipfs.localhost + +test_localhost_gateway_response_should_contain \ + "request for {CID}.ipfs.localhost should return expected payload" \ + "http://${CIDv1}.ipfs.localhost:$GWAY_PORT" \ + "$CID_VAL" + +# ensure /ipfs/ namespace is not mounted on subdomain +test_localhost_gateway_response_should_contain \ + "request for {CID}.ipfs.localhost/ipfs/{CID} should return HTTP 404" \ + "http://${CIDv1}.ipfs.localhost:$GWAY_PORT/ipfs/$CIDv1" \ + "404 Not Found" + +# ensure requests to /ipfs/* are not blocked, if content root has such subdirectory +test_localhost_gateway_response_should_contain \ + "request for {CID}.ipfs.localhost/ipfs/file.txt should return data from a file in CID content root" \ + "http://${DIR_CID}.ipfs.localhost:$GWAY_PORT/ipfs/file.txt" \ + "I am a txt file" + +# {CID}.ipfs.localhost/sub/dir (Directory Listing) +DIR_HOSTNAME="${DIR_CID}.ipfs.localhost:$GWAY_PORT" + +test_expect_success "valid file and subdirectory paths in directory listing at {cid}.ipfs.localhost" ' + curl -s --resolve $DIR_HOSTNAME:127.0.0.1 "http://$DIR_HOSTNAME" > list_response && + test_should_contain "hello" list_response && + test_should_contain "subdir1" list_response +' + +test_expect_success "valid parent directory path in directory listing at {cid}.ipfs.localhost/sub/dir" ' + curl -s --resolve $DIR_HOSTNAME:127.0.0.1 "http://$DIR_HOSTNAME/subdir1/subdir2/" > list_response && + test_should_contain ".." list_response && + test_should_contain "bar" list_response +' + +test_expect_success "request for deep path resource at {cid}.ipfs.localhost/sub/dir/file" ' + curl -s --resolve $DIR_HOSTNAME:127.0.0.1 "http://$DIR_HOSTNAME/subdir1/subdir2/bar" > list_response && + test_should_contain "subdir2-bar" list_response +' + +# *.ipns.localhost + +# .ipns.localhost + +test_localhost_gateway_response_should_contain \ + "request for {CIDv1-libp2p-key}.ipns.localhost returns expected payload" \ + "http://${IPNS_IDv1}.ipns.localhost:$GWAY_PORT" \ + "$CID_VAL" + +test_localhost_gateway_response_should_contain \ + "request for {CIDv1-dag-pb}.ipns.localhost redirects to CID with libp2p-key multicodec" \ + "http://${IPNS_IDv1_DAGPB}.ipns.localhost:$GWAY_PORT" \ + "Location: http://${IPNS_IDv1}.ipns.localhost:$GWAY_PORT/" + +# .ipns.localhost + +# DNSLink test requires a daemon in online mode with precached /ipns/ mapping +test_kill_ipfs_daemon +DNSLINK_FQDN="dnslink-test.example.com" +export IPFS_NS_MAP="$DNSLINK_FQDN:/ipfs/$CIDv1" +test_launch_ipfs_daemon + +test_localhost_gateway_response_should_contain \ + "request for {dnslink}.ipns.localhost returns expected payload" \ + "http://$DNSLINK_FQDN.ipns.localhost:$GWAY_PORT" \ + "$CID_VAL" + +# api.localhost/api + +# Note: we use DIR_CID so refs -r returns some CIDs for child nodes +test_localhost_gateway_response_should_contain \ + "request for api.localhost returns API response" \ + "http://api.localhost:$GWAY_PORT/api/v0/refs?arg=$DIR_CID&r=true" \ + "Ref" + +## ============================================================================ +## Test subdomain-based requests with a custom hostname config +## (origin per content root at http://*.example.com) +## ============================================================================ + +# set explicit subdomain gateway config for the hostname +ipfs config --json Gateway.PublicGateways '{ + "example.com": { + "UseSubdomains": true, + "Paths": ["/ipfs", "/ipns", "/api"] + } +}' || exit 1 +# restart daemon to apply config changes +test_kill_ipfs_daemon +test_launch_ipfs_daemon --offline + + +# example.com/ip(f|n)s/* +# ============================================================================= + +# path requests to the root hostname should redirect +# to a subdomain URL with proper origin isolation + +test_hostname_gateway_response_should_contain \ + "request for example.com/ipfs/{CIDv1} produces redirect to {CIDv1}.ipfs.example.com" \ + "example.com" \ + "http://127.0.0.1:$GWAY_PORT/ipfs/$CIDv1" \ + "Location: http://$CIDv1.ipfs.example.com/" + +# error message should include original CID +# (and it should be case-sensitive, as we can't assume everyone uses base32) +test_hostname_gateway_response_should_contain \ + "request for example.com/ipfs/{InvalidCID} produces useful error before redirect" \ + "example.com" \ + "http://127.0.0.1:$GWAY_PORT/ipfs/QmInvalidCID" \ + 'invalid path \"/ipfs/QmInvalidCID\"' + +test_hostname_gateway_response_should_contain \ + "request for example.com/ipfs/{CIDv0} produces redirect to {CIDv1}.ipfs.example.com" \ + "example.com" \ + "http://127.0.0.1:$GWAY_PORT/ipfs/$CIDv0" \ + "Location: http://${CIDv0to1}.ipfs.example.com/" + +# Support X-Forwarded-Proto +test_expect_success "request for http://example.com/ipfs/{CID} with X-Forwarded-Proto: https produces redirect to HTTPS URL" " + curl -H \"X-Forwarded-Proto: https\" -H \"Host: example.com\" -sD - \"http://127.0.0.1:$GWAY_PORT/ipfs/$CIDv1\" > response && + test_should_contain \"Location: https://$CIDv1.ipfs.example.com/\" response +" + + + +# example.com/ipns/ + +test_hostname_gateway_response_should_contain \ + "request for example.com/ipns/{CIDv0} redirects to CIDv1 with libp2p-key multicodec in subdomain" \ + "example.com" \ + "http://127.0.0.1:$GWAY_PORT/ipns/$IPNS_IDv0" \ + "Location: http://${IPNS_IDv1}.ipns.example.com/" + +# example.com/ipns/ + +test_hostname_gateway_response_should_contain \ + "request for example.com/ipns/{fqdn} redirects to DNSLink in subdomain" \ + "example.com" \ + "http://127.0.0.1:$GWAY_PORT/ipns/en.wikipedia-on-ipfs.org/wiki" \ + "Location: http://en.wikipedia-on-ipfs.org.ipns.example.com/wiki" + +# *.ipfs.example.com: subdomain requests made with custom FQDN in Host header + +test_hostname_gateway_response_should_contain \ + "request for {CID}.ipfs.example.com should return expected payload" \ + "${CIDv1}.ipfs.example.com" \ + "http://127.0.0.1:$GWAY_PORT/" \ + "$CID_VAL" + +test_hostname_gateway_response_should_contain \ + "request for {CID}.ipfs.example.com/ipfs/{CID} should return HTTP 404" \ + "${CIDv1}.ipfs.example.com" \ + "http://127.0.0.1:$GWAY_PORT/ipfs/$CIDv1" \ + "404 Not Found" + +# {CID}.ipfs.example.com/sub/dir (Directory Listing) +DIR_FQDN="${DIR_CID}.ipfs.example.com" + +test_expect_success "valid file and directory paths in directory listing at {cid}.ipfs.example.com" ' + curl -s -H "Host: $DIR_FQDN" http://127.0.0.1:$GWAY_PORT > list_response && + test_should_contain "hello" list_response && + test_should_contain "subdir1" list_response +' + +test_expect_success "valid parent directory path in directory listing at {cid}.ipfs.example.com/sub/dir" ' + curl -s -H "Host: $DIR_FQDN" http://127.0.0.1:$GWAY_PORT/subdir1/subdir2/ > list_response && + test_should_contain ".." list_response && + test_should_contain "bar" list_response +' + +test_expect_success "request for deep path resource {cid}.ipfs.example.com/sub/dir/file" ' + curl -s -H "Host: $DIR_FQDN" http://127.0.0.1:$GWAY_PORT/subdir1/subdir2/bar > list_response && + test_should_contain "subdir2-bar" list_response +' + +# *.ipns.example.com +# ============================================================================ + +# .ipns.example.com + +test_hostname_gateway_response_should_contain \ + "request for {CIDv1-libp2p-key}.ipns.example.com returns expected payload" \ + "${IPNS_IDv1}.ipns.example.com" \ + "http://127.0.0.1:$GWAY_PORT" \ + "$CID_VAL" + +test_hostname_gateway_response_should_contain \ + "request for {CIDv1-dag-pb}.ipns.localhost redirects to CID with libp2p-key multicodec" \ + "${IPNS_IDv1_DAGPB}.ipns.example.com" \ + "http://127.0.0.1:$GWAY_PORT" \ + "Location: http://${IPNS_IDv1}.ipns.example.com/" + +# API on subdomain gateway example.com +# ============================================================================ + +# present at the root domain +test_hostname_gateway_response_should_contain \ + "request for example.com/api/v0/refs returns expected payload when /api is on Paths whitelist" \ + "example.com" \ + "http://127.0.0.1:$GWAY_PORT/api/v0/refs?arg=${DIR_CID}&r=true" \ + "Ref" + +# not mounted on content root subdomains +test_hostname_gateway_response_should_contain \ + "request for {cid}.ipfs.example.com/api returns data if present on the content root" \ + "$DIR_CID.ipfs.example.com" \ + "http://127.0.0.1:$GWAY_PORT/api/file.txt" \ + "I am a txt file" + +test_hostname_gateway_response_should_contain \ + "request for {cid}.ipfs.example.com/api/v0/refs returns 404" \ + "$CIDv1.ipfs.example.com" \ + "http://127.0.0.1:$GWAY_PORT/api/v0/refs?arg=${DIR_CID}&r=true" \ + "404 Not Found" + +# disable /api on example.com +ipfs config --json Gateway.PublicGateways '{ + "example.com": { + "UseSubdomains": true, + "Paths": ["/ipfs", "/ipns"] + } +}' || exit 1 +# restart daemon to apply config changes +test_kill_ipfs_daemon +test_launch_ipfs_daemon --offline + +# not mounted at the root domain +test_hostname_gateway_response_should_contain \ + "request for example.com/api/v0/refs returns 404 if /api not on Paths whitelist" \ + "example.com" \ + "http://127.0.0.1:$GWAY_PORT/api/v0/refs?arg=${DIR_CID}&r=true" \ + "404 Not Found" + +# not mounted on content root subdomains +test_hostname_gateway_response_should_contain \ + "request for {cid}.ipfs.example.com/api returns data if present on the content root" \ + "$DIR_CID.ipfs.example.com" \ + "http://127.0.0.1:$GWAY_PORT/api/file.txt" \ + "I am a txt file" + +# DNSLink: .ipns.example.com +# (not really useful outside of localhost, as setting TLS for more than one +# level of wildcard is a pain, but we support it if someone really wants it) +# ============================================================================ + +# DNSLink test requires a daemon in online mode with precached /ipns/ mapping +test_kill_ipfs_daemon +DNSLINK_FQDN="dnslink-subdomain-gw-test.example.org" +export IPFS_NS_MAP="$DNSLINK_FQDN:/ipfs/$CIDv1" +test_launch_ipfs_daemon + +test_hostname_gateway_response_should_contain \ + "request for {dnslink}.ipns.example.com returns expected payload" \ + "$DNSLINK_FQDN.ipns.example.com" \ + "http://127.0.0.1:$GWAY_PORT" \ + "$CID_VAL" + +# Disable selected Paths for the subdomain gateway hostname +# ============================================================================= + +# disable /ipns for the hostname by not whitelisting it +ipfs config --json Gateway.PublicGateways '{ + "example.com": { + "UseSubdomains": true, + "Paths": ["/ipfs"] + } +}' || exit 1 +# restart daemon to apply config changes +test_kill_ipfs_daemon +test_launch_ipfs_daemon --offline + +# refuse requests to Paths that were not explicitly whitelisted for the hostname +test_hostname_gateway_response_should_contain \ + "request for *.ipns.example.com returns HTTP 404 Not Found when /ipns is not on Paths whitelist" \ + "${IPNS_IDv1}.ipns.example.com" \ + "http://127.0.0.1:$GWAY_PORT" \ + "404 Not Found" + + +## ============================================================================ +## Test path-based requests with a custom hostname config +## ============================================================================ + +# set explicit subdomain gateway config for the hostname +ipfs config --json Gateway.PublicGateways '{ + "example.com": { + "UseSubdomains": false, + "Paths": ["/ipfs"] + } +}' || exit 1 + +# restart daemon to apply config changes +test_kill_ipfs_daemon +test_launch_ipfs_daemon --offline + +# example.com/ip(f|n)s/* smoke-tests +# ============================================================================= + +# confirm path gateway works for /ipfs +test_hostname_gateway_response_should_contain \ + "request for example.com/ipfs/{CIDv1} returns expected payload" \ + "example.com" \ + "http://127.0.0.1:$GWAY_PORT/ipfs/$CIDv1" \ + "$CID_VAL" + +# refuse subdomain requests on path gateway +# (we don't want false sense of security) +test_hostname_gateway_response_should_contain \ + "request for {CID}.ipfs.example.com/ipfs/{CID} should return HTTP 404 Not Found" \ + "${CIDv1}.ipfs.example.com" \ + "http://127.0.0.1:$GWAY_PORT/ipfs/$CIDv1" \ + "404 Not Found" + +# refuse requests to Paths that were not explicitly whitelisted for the hostname +test_hostname_gateway_response_should_contain \ + "request for example.com/ipns/ returns HTTP 404 Not Found when /ipns is not on Paths whitelist" \ + "example.com" \ + "http://127.0.0.1:$GWAY_PORT/ipns/$IPNS_IDv1" \ + "404 Not Found" + +## ============================================================================ +## Test DNSLink requests with a custom PublicGateway (hostname config) +## (DNSLink site at http://dnslink-test.example.com) +## ============================================================================ + +test_kill_ipfs_daemon + +# disable wildcard DNSLink gateway +# and enable it on specific NSLink hostname +ipfs config --json Gateway.NoDNSLink true && \ +ipfs config --json Gateway.PublicGateways '{ + "dnslink-enabled-on-fqdn.example.org": { + "NoDNSLink": false, + "UseSubdomains": false, + "Paths": ["/ipfs"] + }, + "only-dnslink-enabled-on-fqdn.example.org": { + "NoDNSLink": false, + "UseSubdomains": false, + "Paths": [] + }, + "dnslink-disabled-on-fqdn.example.com": { + "NoDNSLink": true, + "UseSubdomains": false, + "Paths": [] + } +}' || exit 1 + +# DNSLink test requires a daemon in online mode with precached /ipns/ mapping +DNSLINK_FQDN="dnslink-enabled-on-fqdn.example.org" +ONLY_DNSLINK_FQDN="only-dnslink-enabled-on-fqdn.example.org" +NO_DNSLINK_FQDN="dnslink-disabled-on-fqdn.example.com" +export IPFS_NS_MAP="$DNSLINK_FQDN:/ipfs/$CIDv1,$ONLY_DNSLINK_FQDN:/ipfs/$DIR_CID" + +# restart daemon to apply config changes +test_launch_ipfs_daemon + +# make sure test setup is valid (fail if CoreAPI is unable to resolve) +test_expect_success "spoofed DNSLink record resolves in cli" " + ipfs resolve /ipns/$DNSLINK_FQDN > result && + test_should_contain \"$CIDv1\" result && + ipfs cat /ipns/$DNSLINK_FQDN > result && + test_should_contain \"$CID_VAL\" result +" + +# DNSLink enabled + +test_hostname_gateway_response_should_contain \ + "request for http://{dnslink-fqdn}/ PublicGateway returns expected payload" \ + "$DNSLINK_FQDN" \ + "http://127.0.0.1:$GWAY_PORT/" \ + "$CID_VAL" + +test_hostname_gateway_response_should_contain \ + "request for {dnslink-fqdn}/ipfs/{cid} returns expected payload when /ipfs is on Paths whitelist" \ + "$DNSLINK_FQDN" \ + "http://127.0.0.1:$GWAY_PORT/ipfs/$CIDv1" \ + "$CID_VAL" + +# Test for a fun edge case: DNSLink-only gateway without /ipfs/ namespace +# mounted, and with subdirectory named "ipfs" ¯\_(ツ)_/¯ +test_hostname_gateway_response_should_contain \ + "request for {dnslink-fqdn}/ipfs/file.txt returns data from content root when /ipfs in not on Paths whitelist" \ + "$ONLY_DNSLINK_FQDN" \ + "http://127.0.0.1:$GWAY_PORT/ipfs/file.txt" \ + "I am a txt file" + +test_hostname_gateway_response_should_contain \ + "request for {dnslink-fqdn}/ipns/{peerid} returns 404 when path is not whitelisted" \ + "$DNSLINK_FQDN" \ + "http://127.0.0.1:$GWAY_PORT/ipns/$IPNS_IDv0" \ + "404 Not Found" + +# DNSLink disabled + +test_hostname_gateway_response_should_contain \ + "request for http://{dnslink-fqdn}/ returns 404 when NoDNSLink=true" \ + "$NO_DNSLINK_FQDN" \ + "http://127.0.0.1:$GWAY_PORT/" \ + "404 Not Found" + +test_hostname_gateway_response_should_contain \ + "request for {dnslink-fqdn}/ipfs/{cid} returns 404 when path is not whitelisted" \ + "$NO_DNSLINK_FQDN" \ + "http://127.0.0.1:$GWAY_PORT/ipfs/$CIDv0" \ + "404 Not Found" + + +## ============================================================================ +## Test wildcard DNSLink (any hostname, with default config) +## ============================================================================ + +test_kill_ipfs_daemon + +# enable wildcard DNSLink gateway (any value in Host header) +# and remove custom PublicGateways +ipfs config --json Gateway.NoDNSLink false && \ +ipfs config --json Gateway.PublicGateways '{}' || exit 1 + +# DNSLink test requires a daemon in online mode with precached /ipns/ mapping +DNSLINK_FQDN="wildcard-dnslink-not-in-config.example.com" +export IPFS_NS_MAP="$DNSLINK_FQDN:/ipfs/$CIDv1" + +# restart daemon to apply config changes +test_launch_ipfs_daemon + +# make sure test setup is valid (fail if CoreAPI is unable to resolve) +test_expect_success "spoofed DNSLink record resolves in cli" " + ipfs resolve /ipns/$DNSLINK_FQDN > result && + test_should_contain \"$CIDv1\" result && + ipfs cat /ipns/$DNSLINK_FQDN > result && + test_should_contain \"$CID_VAL\" result +" + +# gateway test +test_hostname_gateway_response_should_contain \ + "request for http://{dnslink-fqdn}/ (wildcard) returns expected payload" \ + "$DNSLINK_FQDN" \ + "http://127.0.0.1:$GWAY_PORT/" \ + "$CID_VAL" + +# ============================================================================= +# ensure we end with empty Gateway.PublicGateways +ipfs config --json Gateway.PublicGateways '{}' +test_kill_ipfs_daemon + +test_done diff --git a/test/sharness/t0160-resolve.sh b/test/sharness/t0160-resolve.sh index 87740685644..62a6f5b3bfa 100755 --- a/test/sharness/t0160-resolve.sh +++ b/test/sharness/t0160-resolve.sh @@ -116,6 +116,15 @@ test_resolve_cmd_b32() { test_resolve_setup_name "self" "/ipfs/$c_hash_b32" test_resolve "/ipns/$self_hash" "/ipfs/$c_hash_b32" --cid-base=base32 + + # peer ID represented as CIDv1 require libp2p-key multicodec + # https://github.com/libp2p/specs/blob/master/RFC/0001-text-peerid-cid.md + local self_hash_b32protobuf=$(echo $self_hash | ipfs cid format -v 1 -b b --codec protobuf) + local self_hash_b32libp2pkey=$(echo $self_hash | ipfs cid format -v 1 -b b --codec libp2p-key) + test_expect_success "resolve of /ipns/{cidv1} with multicodec other than libp2p-key returns a meaningful error" ' + test_expect_code 1 ipfs resolve /ipns/$self_hash_b32protobuf 2>cidcodec_error && + grep "Error: peer ID represented as CIDv1 require libp2p-key multicodec: retry with /ipns/$self_hash_b32libp2pkey" cidcodec_error + ' } diff --git a/test/sharness/t0184-http-proxy-over-p2p.sh b/test/sharness/t0184-http-proxy-over-p2p.sh index 578a3f424df..06a3b9ccb18 100755 --- a/test/sharness/t0184-http-proxy-over-p2p.sh +++ b/test/sharness/t0184-http-proxy-over-p2p.sh @@ -144,10 +144,19 @@ test_expect_success 'configure nodes' ' iptb testbed create -type localipfs -count 2 -force -init && ipfsi 0 config --json Experimental.Libp2pStreamMounting true && ipfsi 1 config --json Experimental.Libp2pStreamMounting true && - ipfsi 0 config --json Experimental.P2pHttpProxy true + ipfsi 0 config --json Experimental.P2pHttpProxy true && ipfsi 0 config --json Addresses.Gateway "[\"/ip4/127.0.0.1/tcp/$IPFS_GATEWAY_PORT\"]" ' +test_expect_success 'configure a subdomain gateway with /p2p/ path whitelisted' " + ipfsi 0 config --json Gateway.PublicGateways '{ + \"example.com\": { + \"UseSubdomains\": true, + \"Paths\": [\"/p2p/\"] + } + }' +" + test_expect_success 'start and connect nodes' ' iptb start -wait && iptb connect 0 1 ' @@ -206,6 +215,30 @@ test_expect_success 'handle multipart/form-data http request' ' curl_send_multipart_form_request 200 ' +# subdomain gateway at *.p2p.example.com requires PeerdID in base32 +RECEIVER_ID_CIDv1=$( ipfs cid format -v 1 -b b --codec libp2p-key -- $RECEIVER_ID) + +# OK: $peerid.p2p.example.com/http/index.txt +test_expect_success "handle http request to a subdomain gateway" ' + serve_content "SUBDOMAIN PROVIDES ORIGIN ISOLATION PER RECEIVER_ID" && + curl -H "Host: $RECEIVER_ID_CIDv1.p2p.example.com" -sD - $SENDER_GATEWAY/http/index.txt > p2p_response && + test_should_contain "SUBDOMAIN PROVIDES ORIGIN ISOLATION PER RECEIVER_ID" p2p_response +' + +# FAIL: $peerid.p2p.example.com/p2p/$peerid/http/index.txt +test_expect_success "handle invalid http request to a subdomain gateway" ' + serve_content "SUBDOMAIN DOES NOT SUPPORT FULL /p2p/ PATH" && + curl -H "Host: $RECEIVER_ID_CIDv1.p2p.example.com" -sD - $SENDER_GATEWAY/p2p/$RECEIVER_ID/http/index.txt > p2p_response && + test_should_contain "400 Bad Request" p2p_response +' + +# REDIRECT: example.com/p2p/$peerid/http/index.txt → $peerid.p2p.example.com/http/index.txt +test_expect_success "redirect http path request to subdomain gateway" ' + serve_content "SUBDOMAIN ROOT REDIRECTS /p2p/ PATH TO SUBDOMAIN" && + curl -H "Host: example.com" -sD - $SENDER_GATEWAY/p2p/$RECEIVER_ID/http/index.txt > p2p_response && + test_should_contain "Location: http://$RECEIVER_ID_CIDv1.p2p.example.com/http/index.txt" p2p_response +' + test_expect_success 'stop http server' ' teardown_remote_server ' From f9567a0a0fb12b2d27735708e85b9e16a84f528c Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Wed, 11 Mar 2020 18:07:28 +0100 Subject: [PATCH 499/671] fix(gateway): curl without redirect on localhost When request is sent to http://localhost:8080/ipfs/$cid response has HTTP 301 status code and "Location" header with redirect destination at $cid.ipfs.localhost:8080 Redirect is followed by browsersi, but not by commandline tools. Status 301 is ignored by curl in default mode: it will print response and won't follow redirect, user needs to add -L for that. To fix curl, we return correct payload in body of HTTP 301 response, but set Clear-Site-Data header to ensure Origin sandbox can't be abused. This requires a surgical workaround: If Location header is present in ResponseWriter's Header map, we ensure http.ServeContent() returns HTTP 301 Context: https://github.com/ipfs/go-ipfs/pull/6982 License: MIT Signed-off-by: Marcin Rataj --- core/corehttp/gateway_handler.go | 20 ++++++++++++++++++++ core/corehttp/hostname.go | 20 ++++++++++++++++++-- test/sharness/t0114-gateway-subdomains.sh | 23 ++++++++++++++++++++++- 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/core/corehttp/gateway_handler.go b/core/corehttp/gateway_handler.go index cf74202434a..d3c4d26392d 100644 --- a/core/corehttp/gateway_handler.go +++ b/core/corehttp/gateway_handler.go @@ -38,6 +38,25 @@ type gatewayHandler struct { api coreiface.CoreAPI } +// StatusResponseWriter enables us to override HTTP Status Code passed to +// WriteHeader function inside of http.ServeContent. Decision is based on +// presence of HTTP Headers such as Location. +type statusResponseWriter struct { + http.ResponseWriter +} + +func (sw *statusResponseWriter) WriteHeader(code int) { + // Check if we need to adjust Status Code to account for scheduled redirect + // This enables us to return payload along with HTTP 301 + // for subdomain redirect in web browsers while also returning body for cli + // tools which do not follow redirects by default (curl, wget). + redirect := sw.ResponseWriter.Header().Get("Location") + if redirect != "" && code == http.StatusOK { + code = http.StatusMovedPermanently + } + sw.ResponseWriter.WriteHeader(code) +} + func newGatewayHandler(c GatewayConfig, api coreiface.CoreAPI) *gatewayHandler { i := &gatewayHandler{ config: c, @@ -366,6 +385,7 @@ func (i *gatewayHandler) serveFile(w http.ResponseWriter, req *http.Request, nam } w.Header().Set("Content-Type", ctype) + w = &statusResponseWriter{w} http.ServeContent(w, req, name, modtime, content) } diff --git a/core/corehttp/hostname.go b/core/corehttp/hostname.go index 910ba5bc87d..143435106e5 100644 --- a/core/corehttp/hostname.go +++ b/core/corehttp/hostname.go @@ -95,8 +95,24 @@ func HostnameOption() ServeOption { // Yes, redirect if applicable // Example: dweb.link/ipfs/{cid} → {cid}.ipfs.dweb.link if newURL, ok := toSubdomainURL(r.Host, r.URL.Path, r); ok { - http.Redirect(w, r, newURL, http.StatusMovedPermanently) - return + // Just to be sure single Origin can't be abused in + // web browsers that ignored the redirect for some + // reason, Clear-Site-Data header clears browsing + // data (cookies, storage etc) associated with + // hostname's root Origin + // Note: we can't use "*" due to bug in Chromium: + // https://bugs.chromium.org/p/chromium/issues/detail?id=898503 + w.Header().Set("Clear-Site-Data", "\"cookies\", \"storage\"") + + // Set "Location" header with redirect destination. + // It is ignored by curl in default mode, but will + // be respected by user agents that follow + // redirects by default, namely web browsers + w.Header().Set("Location", newURL) + + // Note: we continue regular gateway processing: + // HTTP Status Code http.StatusMovedPermanently + // will be set later, in statusResponseWriter } } diff --git a/test/sharness/t0114-gateway-subdomains.sh b/test/sharness/t0114-gateway-subdomains.sh index 38aa4cc9710..d079f56e6c7 100755 --- a/test/sharness/t0114-gateway-subdomains.sh +++ b/test/sharness/t0114-gateway-subdomains.sh @@ -145,10 +145,31 @@ test_localhost_gateway_response_should_contain \ # payload directly, but redirect to URL with proper origin isolation test_localhost_gateway_response_should_contain \ - "request for localhost/ipfs/{CIDv1} redirects to subdomain" \ + "request for localhost/ipfs/{CIDv1} returns status code HTTP 301" \ + "http://localhost:$GWAY_PORT/ipfs/$CIDv1" \ + "301 Moved Permanently" + +test_localhost_gateway_response_should_contain \ + "request for localhost/ipfs/{CIDv1} returns Location HTTP header for subdomain redirect in browsers" \ "http://localhost:$GWAY_PORT/ipfs/$CIDv1" \ "Location: http://$CIDv1.ipfs.localhost:$GWAY_PORT/" +# Responses to the root domain of subdomain gateway hostname should Clear-Site-Data +# https://github.com/ipfs/go-ipfs/issues/6975#issuecomment-597472477 +test_localhost_gateway_response_should_contain \ + "request for localhost/ipfs/{CIDv1} returns Clear-Site-Data header to purge Origin cookies and storage" \ + "http://localhost:$GWAY_PORT/ipfs/$CIDv1" \ + 'Clear-Site-Data: \"cookies\", \"storage\"' + +# We return body with HTTP 301 so existing cli scripts that use path-based +# gateway do not break (curl doesn't auto-redirect without passing -L; wget +# does not span across hostnames by default) +# Context: https://github.com/ipfs/go-ipfs/issues/6975 +test_localhost_gateway_response_should_contain \ + "request for localhost/ipfs/{CIDv1} includes valid payload in body for CLI tools like curl" \ + "http://localhost:$GWAY_PORT/ipfs/$CIDv1" \ + "$CID_VAL" + test_localhost_gateway_response_should_contain \ "request for localhost/ipfs/{CIDv0} redirects to CIDv1 representation in subdomain" \ "http://localhost:$GWAY_PORT/ipfs/$CIDv0" \ From 05fe3086a5823a642622d24d0621f8a46527ce68 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Tue, 17 Mar 2020 20:10:52 -0700 Subject: [PATCH 500/671] fix(sharness): fix sharness tests to take removed bootstrap peers into account --- test/sharness/t0120-bootstrap.sh | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/test/sharness/t0120-bootstrap.sh b/test/sharness/t0120-bootstrap.sh index 883e29a8be6..538c5bde0ef 100755 --- a/test/sharness/t0120-bootstrap.sh +++ b/test/sharness/t0120-bootstrap.sh @@ -10,14 +10,6 @@ BP2="/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19 BP3="/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb" BP4="/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt" BP5="/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ" -BP6="/ip4/104.236.179.241/tcp/4001/p2p/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM" -BP7="/ip4/104.236.76.40/tcp/4001/p2p/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64" -BP8="/ip4/128.199.219.111/tcp/4001/p2p/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu" -BP9="/ip4/178.62.158.247/tcp/4001/p2p/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd" -BP10="/ip6/2400:6180:0:d0::151:6001/tcp/4001/p2p/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu" -BP11="/ip6/2604:a880:1:20::203:d001/tcp/4001/p2p/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM" -BP12="/ip6/2604:a880:800:10::4a:5001/tcp/4001/p2p/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64" -BP13="/ip6/2a03:b0c0:0:1010::23:1001/tcp/4001/p2p/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd" test_description="Test ipfs repo operations" @@ -99,18 +91,10 @@ test_bootstrap_cmd() { echo "added $BP3" >>add2_expected && echo "added $BP4" >>add2_expected && echo "added $BP5" >>add2_expected && - echo "added $BP6" >>add2_expected && - echo "added $BP7" >>add2_expected && - echo "added $BP8" >>add2_expected && - echo "added $BP9" >>add2_expected && - echo "added $BP10" >>add2_expected && - echo "added $BP11" >>add2_expected && - echo "added $BP12" >>add2_expected && - echo "added $BP13" >>add2_expected && test_cmp add2_expected add2_actual ' - test_bootstrap_list_cmd $BP1 $BP2 $BP3 $BP4 $BP5 $BP6 $BP7 $BP8 $BP9 $BP10 $BP11 $BP12 $BP13 $BP14 $BP15 $BP16 $BP17 + test_bootstrap_list_cmd $BP1 $BP2 $BP3 $BP4 $BP5 test_expect_success "'ipfs bootstrap rm --all' succeeds" ' ipfs bootstrap rm --all >rm2_actual @@ -122,14 +106,6 @@ test_bootstrap_cmd() { echo "removed $BP3" >>rm2_expected && echo "removed $BP4" >>rm2_expected && echo "removed $BP5" >>rm2_expected && - echo "removed $BP6" >>rm2_expected && - echo "removed $BP7" >>rm2_expected && - echo "removed $BP8" >>rm2_expected && - echo "removed $BP9" >>rm2_expected && - echo "removed $BP10" >>rm2_expected && - echo "removed $BP11" >>rm2_expected && - echo "removed $BP12" >>rm2_expected && - echo "removed $BP13" >>rm2_expected && test_cmp rm2_expected rm2_actual ' From 5b308bb30cf6d57f9c4a0dd1731a043c8af084bc Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 18 Mar 2020 09:17:21 -0700 Subject: [PATCH 501/671] chore: update dependencies --- go.mod | 4 ++-- go.sum | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index c1823843bd9..cb74f0d5dbb 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/gogo/protobuf v1.3.1 github.com/hashicorp/go-multierror v1.0.0 github.com/hashicorp/golang-lru v0.5.4 - github.com/ipfs/go-bitswap v0.2.3 + github.com/ipfs/go-bitswap v0.2.4 github.com/ipfs/go-block-format v0.0.2 github.com/ipfs/go-blockservice v0.1.2 github.com/ipfs/go-cid v0.0.5 @@ -80,7 +80,7 @@ require ( github.com/libp2p/go-libp2p-swarm v0.2.2 github.com/libp2p/go-libp2p-testing v0.1.1 github.com/libp2p/go-libp2p-tls v0.1.3 - github.com/libp2p/go-libp2p-yamux v0.2.4 + github.com/libp2p/go-libp2p-yamux v0.2.5 github.com/libp2p/go-maddr-filter v0.0.5 github.com/libp2p/go-socket-activation v0.0.2 github.com/mattn/go-runewidth v0.0.8 // indirect diff --git a/go.sum b/go.sum index 9a8b551dc0b..bf3d1616bab 100644 --- a/go.sum +++ b/go.sum @@ -195,8 +195,8 @@ github.com/ipfs/go-bitswap v0.0.9/go.mod h1:kAPf5qgn2W2DrgAcscZ3HrM9qh4pH+X8Fkk3 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.2.3 h1:pIqG9XEj3uL36drRUSiJJqR3IPhI9DYt4Qq4mO7QKmk= -github.com/ipfs/go-bitswap v0.2.3/go.mod h1:vHqjV7wGhpoEIT83n+NAD66YpqpZlKVKfLhAYlbbBDY= +github.com/ipfs/go-bitswap v0.2.4 h1:dGP81oDfiJxDDlSpWRnGjQWyPfsobHcilYsBuzllTTw= +github.com/ipfs/go-bitswap v0.2.4/go.mod h1:vHqjV7wGhpoEIT83n+NAD66YpqpZlKVKfLhAYlbbBDY= github.com/ipfs/go-block-format v0.0.1/go.mod h1:DK/YYcsSUIVAFNwo/KZCdIIbpN0ROH/baNLgayt4pFc= github.com/ipfs/go-block-format v0.0.2 h1:qPDvcP19izTjU8rgo6p7gTXZlkMkF5bz5G3fqIsSCPE= github.com/ipfs/go-block-format v0.0.2/go.mod h1:AWR46JfpcObNfg3ok2JHDUfdiHRgWhJgCQF+KIgOPJY= @@ -602,8 +602,8 @@ github.com/libp2p/go-libp2p-yamux v0.2.1 h1:Q3XYNiKCC2vIxrvUJL+Jg1kiyeEaIDNKLjgE github.com/libp2p/go-libp2p-yamux v0.2.1/go.mod h1:1FBXiHDk1VyRM1C0aez2bCfHQ4vMZKkAQzZbkSQt5fI= github.com/libp2p/go-libp2p-yamux v0.2.2 h1:eGvbqWqWY9S5lrpe2gA0UCOLCdzCgYSAR3vo/xCsNQg= github.com/libp2p/go-libp2p-yamux v0.2.2/go.mod h1:lIohaR0pT6mOt0AZ0L2dFze9hds9Req3OfS+B+dv4qw= -github.com/libp2p/go-libp2p-yamux v0.2.4 h1:SoIR1z7kjjncCPliuchPptd4n/xTxePzWtmR2vIQLwM= -github.com/libp2p/go-libp2p-yamux v0.2.4/go.mod h1:Qq6yW6EfI9vNeL4J8H1l8yCcBoZnJiljJGsbZgfC/08= +github.com/libp2p/go-libp2p-yamux v0.2.5 h1:MuyItOqz03oi8npvjgMJxgnhllJLZnO/dKVOpTZ9+XI= +github.com/libp2p/go-libp2p-yamux v0.2.5/go.mod h1:Zpgj6arbyQrmZ3wxSZxfBmbdnWtbZ48OpsfmQVTErwA= github.com/libp2p/go-maddr-filter v0.0.1/go.mod h1:6eT12kSQMA9x2pvFQa+xesMKUBlj9VImZbj3B9FBH/Q= github.com/libp2p/go-maddr-filter v0.0.4/go.mod h1:6eT12kSQMA9x2pvFQa+xesMKUBlj9VImZbj3B9FBH/Q= github.com/libp2p/go-maddr-filter v0.0.5 h1:CW3AgbMO6vUvT4kf87y4N+0P8KUl2aqLYhrGyDUbLSg= @@ -660,8 +660,8 @@ github.com/libp2p/go-yamux v1.2.3 h1:xX8A36vpXb59frIzWFdEgptLMsOANMFq2K7fPRlunYI github.com/libp2p/go-yamux v1.2.3/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= github.com/libp2p/go-yamux v1.3.0 h1:FsYzT16Wq2XqUGJsBbOxoz9g+dFklvNi7jN6YFPfl7U= github.com/libp2p/go-yamux v1.3.0/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= -github.com/libp2p/go-yamux v1.3.2 h1:9ABGfqAAQB5hlBHWk0bAbGnS4dDaAJLSF0C7TPYia+0= -github.com/libp2p/go-yamux v1.3.2/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= +github.com/libp2p/go-yamux v1.3.3 h1:mWuzZRCAeTBFdynLlsYgA/EIeMOLr8XY04wa52NRhsE= +github.com/libp2p/go-yamux v1.3.3/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= github.com/lucas-clemente/quic-go v0.15.2 h1:RgxRJ7rPde0Q/uXDeb3/UdblVvxrYGDAG9G9GO78LmI= github.com/lucas-clemente/quic-go v0.15.2/go.mod h1:qxmO5Y4ZMhdNkunGfxuZnZXnJwYpW9vjQkyrZ7BsgUI= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= From b8261d6417a91449301a0306bec1dc46a428f898 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 19 Mar 2020 11:30:39 +0000 Subject: [PATCH 502/671] chore(deps): bump github.com/libp2p/go-libp2p from 0.6.0 to 0.6.1 Bumps [github.com/libp2p/go-libp2p](https://github.com/libp2p/go-libp2p) from 0.6.0 to 0.6.1. - [Release notes](https://github.com/libp2p/go-libp2p/releases) - [Changelog](https://github.com/libp2p/go-libp2p/blob/master/NEWS.md) - [Commits](https://github.com/libp2p/go-libp2p/compare/v0.6.0...v0.6.1) Signed-off-by: dependabot-preview[bot] --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index cb74f0d5dbb..24813efa2cf 100644 --- a/go.mod +++ b/go.mod @@ -59,7 +59,7 @@ require ( github.com/jbenet/go-temp-err-catcher v0.1.0 github.com/jbenet/goprocess v0.1.3 github.com/libp2p/go-eventbus v0.1.0 - github.com/libp2p/go-libp2p v0.6.0 + github.com/libp2p/go-libp2p v0.6.1 github.com/libp2p/go-libp2p-autonat-svc v0.1.0 github.com/libp2p/go-libp2p-circuit v0.1.4 github.com/libp2p/go-libp2p-connmgr v0.2.1 diff --git a/go.sum b/go.sum index bf3d1616bab..2e93e3b94ed 100644 --- a/go.sum +++ b/go.sum @@ -444,6 +444,8 @@ github.com/libp2p/go-libp2p v0.5.2 h1:fjQUTyB7x/4XgO31OEWkJ5uFeHRgpoExlf0rXz5BO8 github.com/libp2p/go-libp2p v0.5.2/go.mod h1:o2r6AcpNl1eNGoiWhRtPji03NYOvZumeQ6u+X6gSxnM= github.com/libp2p/go-libp2p v0.6.0 h1:EFArryT9N7AVA70LCcOh8zxsW+FeDnxwcpWQx9k7+GM= github.com/libp2p/go-libp2p v0.6.0/go.mod h1:mfKWI7Soz3ABX+XEBR61lGbg+ewyMtJHVt043oWeqwg= +github.com/libp2p/go-libp2p v0.6.1 h1:mxabyJf4l6AmotDOKObwSfBNBWjL5VYXysVFLUMAuB8= +github.com/libp2p/go-libp2p v0.6.1/go.mod h1:CTFnWXogryAHjXAKEbOf1OWY+VeAP3lDMZkfEI5sT54= github.com/libp2p/go-libp2p-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 h1:aCWAu43Ri4nU0ZPO7NyLzUvvfqd0nE3dX0R/ZGYVgOU= From 26cd0d4a735357d10d29e36642a8c3b15136bfc0 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 19 Mar 2020 17:27:11 +0000 Subject: [PATCH 503/671] chore(deps): bump github.com/ipfs/go-bitswap from 0.2.4 to 0.2.5 Bumps [github.com/ipfs/go-bitswap](https://github.com/ipfs/go-bitswap) from 0.2.4 to 0.2.5. - [Release notes](https://github.com/ipfs/go-bitswap/releases) - [Commits](https://github.com/ipfs/go-bitswap/compare/v0.2.4...v0.2.5) Signed-off-by: dependabot-preview[bot] --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 24813efa2cf..ea43f1ef194 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/gogo/protobuf v1.3.1 github.com/hashicorp/go-multierror v1.0.0 github.com/hashicorp/golang-lru v0.5.4 - github.com/ipfs/go-bitswap v0.2.4 + github.com/ipfs/go-bitswap v0.2.5 github.com/ipfs/go-block-format v0.0.2 github.com/ipfs/go-blockservice v0.1.2 github.com/ipfs/go-cid v0.0.5 diff --git a/go.sum b/go.sum index 2e93e3b94ed..0584673df93 100644 --- a/go.sum +++ b/go.sum @@ -197,6 +197,8 @@ github.com/ipfs/go-bitswap v0.1.2/go.mod h1:qxSWS4NXGs7jQ6zQvoPY3+NmOfHHG47mhkiL github.com/ipfs/go-bitswap v0.1.3/go.mod h1:YEQlFy0kkxops5Vy+OxWdRSEZIoS7I7KDIwoa5Chkps= github.com/ipfs/go-bitswap v0.2.4 h1:dGP81oDfiJxDDlSpWRnGjQWyPfsobHcilYsBuzllTTw= github.com/ipfs/go-bitswap v0.2.4/go.mod h1:vHqjV7wGhpoEIT83n+NAD66YpqpZlKVKfLhAYlbbBDY= +github.com/ipfs/go-bitswap v0.2.5 h1:aRGBghux0IDbKBG6eifDigCOfCs9Xv+WUYXuDzx/0cc= +github.com/ipfs/go-bitswap v0.2.5/go.mod h1:vHqjV7wGhpoEIT83n+NAD66YpqpZlKVKfLhAYlbbBDY= github.com/ipfs/go-block-format v0.0.1/go.mod h1:DK/YYcsSUIVAFNwo/KZCdIIbpN0ROH/baNLgayt4pFc= github.com/ipfs/go-block-format v0.0.2 h1:qPDvcP19izTjU8rgo6p7gTXZlkMkF5bz5G3fqIsSCPE= github.com/ipfs/go-block-format v0.0.2/go.mod h1:AWR46JfpcObNfg3ok2JHDUfdiHRgWhJgCQF+KIgOPJY= From 62de9ba9d3d2856679ff7e2e6b67b000d5d987a5 Mon Sep 17 00:00:00 2001 From: Cornelius Toole Date: Sat, 15 Feb 2020 19:34:55 -0600 Subject: [PATCH 504/671] feat(file-ignore): add ignore opts to add cmd - add the `gitignore` or `ignore options to the add command --- core/commands/add.go | 2 ++ go.mod | 6 +++--- go.sum | 13 ++++++------ test/sharness/t0042-add-skip.sh | 36 ++++++++++++++++++++++++++++++++- 4 files changed, 47 insertions(+), 10 deletions(-) diff --git a/core/commands/add.go b/core/commands/add.go index 580cd5a422e..c66994b3726 100644 --- a/core/commands/add.go +++ b/core/commands/add.go @@ -118,6 +118,8 @@ only-hash, and progress/status related flags) will change the final hash. cmds.OptionDerefArgs, // a builtin option that resolves passed in filesystem links (--dereference-args) cmds.OptionStdinName, // a builtin option that optionally allows wrapping stdin into a named file cmds.OptionHidden, + cmds.OptionIgnore, + cmds.OptionIgnoreRules, cmds.BoolOption(quietOptionName, "q", "Write minimal output."), cmds.BoolOption(quieterOptionName, "Q", "Write only final hash."), cmds.BoolOption(silentOptionName, "Write no output."), diff --git a/go.mod b/go.mod index ea43f1ef194..141cc57c779 100644 --- a/go.mod +++ b/go.mod @@ -30,12 +30,12 @@ require ( github.com/ipfs/go-graphsync v0.0.5 github.com/ipfs/go-ipfs-blockstore v0.1.4 github.com/ipfs/go-ipfs-chunker v0.0.4 - github.com/ipfs/go-ipfs-cmds v0.1.2 + github.com/ipfs/go-ipfs-cmds v0.1.4 github.com/ipfs/go-ipfs-config v0.3.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.6 + github.com/ipfs/go-ipfs-files v0.0.7 github.com/ipfs/go-ipfs-pinner v0.0.4 github.com/ipfs/go-ipfs-posinfo v0.0.1 github.com/ipfs/go-ipfs-provider v0.4.1 @@ -105,4 +105,4 @@ require ( gopkg.in/cheggaaa/pb.v1 v1.0.28 ) -go 1.12 +go 1.13 diff --git a/go.sum b/go.sum index 0584673df93..26795b38494 100644 --- a/go.sum +++ b/go.sum @@ -73,6 +73,8 @@ github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7 github.com/coreos/go-systemd/v22 v22.0.0 h1:XJIw/+VlJ+87J+doOxznsAWIdmWuViOVhkQamW5YV28= github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3 h1:HVTnpeuvF6Owjd5mniCL8DEXo7uYXdQEmOP4FJbV5tg= +github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3/go.mod h1:p1d6YEZWvFzEh4KLyvBcVSnrfNDDvK2zfK/4x2v/4pE= github.com/cskr/pubsub v1.0.2 h1:vlOzMhl6PFn60gRlTQQsIfVwaPB/B/8MziK8FhEPt/0= github.com/cskr/pubsub v1.0.2/go.mod h1:/8MzYXk/NJAz782G8RPkFzXTZVu63VotefPnR9TIRis= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -195,8 +197,6 @@ github.com/ipfs/go-bitswap v0.0.9/go.mod h1:kAPf5qgn2W2DrgAcscZ3HrM9qh4pH+X8Fkk3 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.2.4 h1:dGP81oDfiJxDDlSpWRnGjQWyPfsobHcilYsBuzllTTw= -github.com/ipfs/go-bitswap v0.2.4/go.mod h1:vHqjV7wGhpoEIT83n+NAD66YpqpZlKVKfLhAYlbbBDY= github.com/ipfs/go-bitswap v0.2.5 h1:aRGBghux0IDbKBG6eifDigCOfCs9Xv+WUYXuDzx/0cc= github.com/ipfs/go-bitswap v0.2.5/go.mod h1:vHqjV7wGhpoEIT83n+NAD66YpqpZlKVKfLhAYlbbBDY= github.com/ipfs/go-block-format v0.0.1/go.mod h1:DK/YYcsSUIVAFNwo/KZCdIIbpN0ROH/baNLgayt4pFc= @@ -270,8 +270,8 @@ github.com/ipfs/go-ipfs-chunker v0.0.1 h1:cHUUxKFQ99pozdahi+uSC/3Y6HeRpi9oTeUHbE github.com/ipfs/go-ipfs-chunker v0.0.1/go.mod h1:tWewYK0we3+rMbOh7pPFGDyypCtvGcBFymgY4rSDLAw= github.com/ipfs/go-ipfs-chunker v0.0.4 h1:nb2ZIgtOk0TxJ5KDBEk+sv6iqJTF/PHg6owN2xCrUjE= github.com/ipfs/go-ipfs-chunker v0.0.4/go.mod h1:jhgdF8vxRHycr00k13FM8Y0E+6BoalYeobXmUyTreP8= -github.com/ipfs/go-ipfs-cmds v0.1.2 h1:02FLzTA9jYRle/xdMWYwGwxu3gzC3GhPUaz35dH+FrY= -github.com/ipfs/go-ipfs-cmds v0.1.2/go.mod h1:a9LyFOtQCnVc3BvbAgW+GrMXEuN29aLCNi3Wk0IM8wo= +github.com/ipfs/go-ipfs-cmds v0.1.4 h1:l5QAc1iaoMZeBd2vpanrHWs26haEBL4PVqgoHJNG2GE= +github.com/ipfs/go-ipfs-cmds v0.1.4/go.mod h1:wm+C6M8FYDcWPU/EdWqMuHvdyWborFh+GuDl6Ov6sM0= github.com/ipfs/go-ipfs-config v0.3.0 h1:fGs3JBqB9ia/Joi8up47uiKn150EOEqqVFwv8HZqXao= github.com/ipfs/go-ipfs-config v0.3.0/go.mod h1:nSLCFtlaL+2rbl3F+9D4gQZQbT1LjRKx7TJg/IHz6oM= github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= @@ -288,8 +288,8 @@ github.com/ipfs/go-ipfs-exchange-offline v0.0.1/go.mod h1:WhHSFCVYX36H/anEKQboAz 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.4/go.mod h1:INEFm0LL2LWXBhNJ2PMIIb2w45hpXgPjNoE7yA8Y1d4= -github.com/ipfs/go-ipfs-files v0.0.6 h1:sMRtPiSmDrTA2FEiFTtk1vWgO2Dkg7bxXKJ+s8/cDAc= -github.com/ipfs/go-ipfs-files v0.0.6/go.mod h1:lVYE6sgAdtZN5825beJjSAHibw7WOBNPDWz5LaJeukg= +github.com/ipfs/go-ipfs-files v0.0.7 h1:s5BRD12ndahqYifeH1S8Z73zqZhR+3IdKYAG9PiETs0= +github.com/ipfs/go-ipfs-files v0.0.7/go.mod h1:wiN/jSG8FKyk7N0WyctKSvq3ljIa2NNTiZB55kpTdOs= github.com/ipfs/go-ipfs-flags v0.0.1/go.mod h1:RnXBb9WV53GSfTrSDVK61NLTFKvWc60n+K9EgCDh+rA= github.com/ipfs/go-ipfs-pinner v0.0.4 h1:EmxhS3vDsCK/rZrsgxX0Le9m2drBcGlUd7ah/VyFYVE= github.com/ipfs/go-ipfs-pinner v0.0.4/go.mod h1:s4kFZWLWGDudN8Jyd/GTpt222A12C2snA2+OTdy/7p8= @@ -993,6 +993,7 @@ golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d h1:1ZiEyfaQIg3Qh0EoqpwAakHVhecoE5wlSg5GjnafJGw= golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4 h1:QmwruyY+bKbDDL0BaglrbZABEali68eoMFhTZpCjYVA= diff --git a/test/sharness/t0042-add-skip.sh b/test/sharness/t0042-add-skip.sh index 1bdea660779..9da78163c45 100755 --- a/test/sharness/t0042-add-skip.sh +++ b/test/sharness/t0042-add-skip.sh @@ -12,6 +12,7 @@ test_add_skip() { test_expect_success "'ipfs add -r' with hidden file succeeds" ' mkdir -p mountdir/planets/.asteroids && + echo "mars.txt" >mountdir/planets/.gitignore && echo "Hello Mars" >mountdir/planets/mars.txt && echo "Hello Venus" >mountdir/planets/venus.txt && echo "Hello Pluto" >mountdir/planets/.pluto.txt && @@ -39,11 +40,44 @@ EOF added QmcAREBcjgnUpKfyFmUGnfajA1NQS5ydqRp7WfqZ6JF8Dx planets/.asteroids/ceres.txt added QmZ5eaLybJ5GUZBNwy24AA9EEDTDpA4B8qXnuN3cGxu2uF planets/.asteroids/pallas.txt added QmaowqjedBkUrMUXgzt9c2ZnAJncM9jpJtkFfgdFstGr5a planets/.charon.txt +added QmPHrRjTH8FskN3C2iv6BLekDT94o23KSL2u5qLqQqGhVH planets/.gitignore added QmU4zFD5eJtRBsWC63AvpozM9Atiadg9kPVTuTrnCYJiNF planets/.pluto.txt added QmZy3khu7qf696i5HtkgL2NotsCZ8wzvNZJ1eUdA5n8KaV planets/mars.txt added QmQnv4m3Q5512zgVtpbJ9z85osQrzZzGRn934AGh6iVEXz planets/venus.txt added Qmf6rbs5GF85anDuoxpSAdtuZPM9D2Yt3HngzjUVSQ7kDV planets/.asteroids -added QmetajtFdmzhWYodAsZoVZSiqpeJDAiaw2NwbM3xcWcpDj planets +added QmczhHaXyb3bc9APMxe4MXbr87V5YDLKLaw3DZX3fK7HrK planets +EOF + test_cmp expected actual + ' + + test_expect_success "'ipfs add -r --ignore-rules-path=.gitignore --hidden' succeeds" ' + (cd mountdir/planets && ipfs add -r --ignore-rules-path=.gitignore --hidden .) > actual + ' + + test_expect_success "'ipfs add -r --ignore-rules-path=.gitignore --hidden' did not include mars.txt file" ' + cat >expected <<-\EOF && +added QmcAREBcjgnUpKfyFmUGnfajA1NQS5ydqRp7WfqZ6JF8Dx planets/.asteroids/ceres.txt +added QmZ5eaLybJ5GUZBNwy24AA9EEDTDpA4B8qXnuN3cGxu2uF planets/.asteroids/pallas.txt +added QmaowqjedBkUrMUXgzt9c2ZnAJncM9jpJtkFfgdFstGr5a planets/.charon.txt +added QmPHrRjTH8FskN3C2iv6BLekDT94o23KSL2u5qLqQqGhVH planets/.gitignore +added QmU4zFD5eJtRBsWC63AvpozM9Atiadg9kPVTuTrnCYJiNF planets/.pluto.txt +added QmQnv4m3Q5512zgVtpbJ9z85osQrzZzGRn934AGh6iVEXz planets/venus.txt +added Qmf6rbs5GF85anDuoxpSAdtuZPM9D2Yt3HngzjUVSQ7kDV planets/.asteroids +added QmaRsiaCYvc65RqHVAcv2tqyjZgQYgvaNqW1tQGsjfy4N5 planets +EOF + test_cmp expected actual + ' + + test_expect_success "'ipfs add -r --ignore-rules-path=.gitignore --ignore .asteroids --ignore venus.txt --hidden' succeeds" ' + (cd mountdir/planets && ipfs add -r --ignore-rules-path=.gitignore --ignore .asteroids --ignore venus.txt --hidden .) > actual + ' + + test_expect_success "'ipfs add -r --ignore-rules-path=.gitignore --ignore .asteroids --ignore venus.txt --hidden' did not include ignored files" ' + cat >expected <<-\EOF && +added QmaowqjedBkUrMUXgzt9c2ZnAJncM9jpJtkFfgdFstGr5a planets/.charon.txt +added QmPHrRjTH8FskN3C2iv6BLekDT94o23KSL2u5qLqQqGhVH planets/.gitignore +added QmU4zFD5eJtRBsWC63AvpozM9Atiadg9kPVTuTrnCYJiNF planets/.pluto.txt +added QmemuMahjSh7eYLY3hbz2q8sqMPnbQzBQeUdosqNiWChE6 planets EOF test_cmp expected actual ' From b5ad3be0603fd9c7803453874eab7f4565a8a4f3 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 23 Mar 2020 11:57:17 -0700 Subject: [PATCH 505/671] feat: improve key lookup * Support peer IDs encoded as CIDs. * Support looking up the identity key by peer ID. --- core/coreapi/name.go | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/core/coreapi/name.go b/core/coreapi/name.go index da38b929b18..4792196b626 100644 --- a/core/coreapi/name.go +++ b/core/coreapi/name.go @@ -139,10 +139,16 @@ func (api *NameAPI) Resolve(ctx context.Context, name string, opts ...caopts.Nam } func keylookup(self ci.PrivKey, kstore keystore.Keystore, k string) (ci.PrivKey, error) { + //////////////////// + // Lookup by name // + //////////////////// + + // First, lookup self. if k == "self" { return self, nil } + // Then, look in the keystore. res, err := kstore.Get(k) if res != nil { return res, nil @@ -157,20 +163,36 @@ func keylookup(self ci.PrivKey, kstore keystore.Keystore, k string) (ci.PrivKey, return nil, err } + ////////////////// + // Lookup by ID // + ////////////////// + targetPid, err := peer.Decode(k) + if err != nil { + return nil, keystore.ErrNoSuchKey + } + + // First, check self. + pid, err := peer.IDFromPrivateKey(self) + if err != nil { + return nil, fmt.Errorf("failed to determine peer ID for private key: %w", err) + } + if pid == targetPid { + return self, nil + } + + // Then, look in the keystore. for _, key := range keys { privKey, err := kstore.Get(key) if err != nil { return nil, err } - pubKey := privKey.GetPublic() - - pid, err := peer.IDFromPublicKey(pubKey) + pid, err := peer.IDFromPrivateKey(privKey) if err != nil { return nil, err } - if pid.Pretty() == k { + if targetPid == pid { return privKey, nil } } From 7fa1449e62f265f2bdde977116802676fc3e0d1c Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 23 Mar 2020 16:14:26 -0700 Subject: [PATCH 506/671] chore: update hard-coded dist URL for repo migrations --- repo/fsrepo/migrations/migrations.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/repo/fsrepo/migrations/migrations.go b/repo/fsrepo/migrations/migrations.go index d6be54947ad..f64e02bbf65 100644 --- a/repo/fsrepo/migrations/migrations.go +++ b/repo/fsrepo/migrations/migrations.go @@ -15,7 +15,7 @@ import ( "strings" ) -var DistPath = "https://ipfs.io/ipfs/QmZLYJBVBK8nqc5JTHp6CZU1v9Ja3MvGrkCe61PfCecc6E" +var DistPath = "https://ipfs.io/ipfs/QmUgfXycSjF9R8F4Tyauaz6LZ4bj5nbksg54G9GdF4fit6" func init() { if dist := os.Getenv("IPFS_DIST_PATH"); dist != "" { From d67a4e06cf65405489567701ef5fbda1fbbb48f2 Mon Sep 17 00:00:00 2001 From: Adam Uhlir Date: Thu, 21 Feb 2019 11:53:44 -0800 Subject: [PATCH 507/671] Introducing EncodedFSKeystore with base32 encoding (#5947) Encoding the key's filename with base32 introduces coherent behaviour across different platforms and their case-sensitive/case-insensitive file-systems. Moreover it allows wider character set to be used for the name of the keys as the original restriction for special FS's characters (e.g. '/', '.') will not apply. License: MIT Signed-off-by: Adam Uhlir --- keystore/keystore.go | 120 ++++++++++++++++++++++++++++++++++++++ keystore/keystore_test.go | 89 ++++++++++++++++++++++++++++ repo/fsrepo/fsrepo.go | 4 +- 3 files changed, 211 insertions(+), 2 deletions(-) diff --git a/keystore/keystore.go b/keystore/keystore.go index 991de5dd1d2..a40ab5cb060 100644 --- a/keystore/keystore.go +++ b/keystore/keystore.go @@ -9,6 +9,7 @@ import ( logging "github.com/ipfs/go-log" ci "github.com/libp2p/go-libp2p-core/crypto" + base32 "github.com/whyrusleeping/base32" ) var log = logging.Logger("keystore") @@ -52,6 +53,22 @@ func validateName(name string) error { return nil } +// NewKeystore is a factory for getting instance of Keystore interface implementation +func NewKeystore(dir string) (Keystore, error) { + return NewEncodedFSKeystore(dir) +} + +// NewEncodedFSKeystore is a factory for getting instance of EncodedFSKeystore +func NewEncodedFSKeystore(dir string) (*EncodedFSKeystore, error) { + keystore, err := NewFSKeystore(dir) + + if err != nil { + return nil, err + } + + return &EncodedFSKeystore{keystore}, nil +} + func NewFSKeystore(dir string) (*FSKeystore, error) { _, err := os.Stat(dir) if err != nil { @@ -174,3 +191,106 @@ func (ks *FSKeystore) List() ([]string, error) { return list, nil } + +const keyFilenamePrefix = "key_" + +func encode(name string) (string, error) { + if name == "" { + return "", fmt.Errorf("key name must be at least one character") + } + + encodedName := base32.RawStdEncoding.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):]) + data, err := base32.RawStdEncoding.DecodeString(nameWithoutPrefix) + + if err != nil { + return "", err + } + + decodedName := string(data[:]) + + log.Debugf("Decoded key name: %s to: %s", name, decodedName) + + return decodedName, nil +} + +// EncodedFSKeystore is extension of FSKeystore that encodes the key filenames in base32 +type EncodedFSKeystore struct { + *FSKeystore +} + +// Has indicates if key is in keystore +func (ks *EncodedFSKeystore) Has(name string) (bool, error) { + encodedName, err := encode(name) + + if err != nil { + return false, err + } + + return ks.FSKeystore.Has(encodedName) +} + +// Put places key into the keystore +func (ks *EncodedFSKeystore) Put(name string, k ci.PrivKey) error { + encodedName, err := encode(name) + + if err != nil { + return err + } + + return ks.FSKeystore.Put(encodedName, k) +} + +// Get retrieves key by its name from the keystore +func (ks *EncodedFSKeystore) Get(name string) (ci.PrivKey, error) { + encodedName, err := encode(name) + + if err != nil { + return nil, err + } + + return ks.FSKeystore.Get(encodedName) +} + +// Delete removes key from the keystore +func (ks *EncodedFSKeystore) Delete(name string) error { + encodedName, err := encode(name) + + if err != nil { + return err + } + + return ks.FSKeystore.Delete(encodedName) +} + +// List returns list of all keys in keystore +func (ks *EncodedFSKeystore) List() ([]string, error) { + dirs, err := ks.FSKeystore.List() + + 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.Warningf("Ignoring keyfile with invalid encoded filename: %s", name) + } + } + + return list, nil +} diff --git a/keystore/keystore_test.go b/keystore/keystore_test.go index 37f59ebffff..685e5d942ef 100644 --- a/keystore/keystore_test.go +++ b/keystore/keystore_test.go @@ -271,3 +271,92 @@ func assertDirContents(dir string, exp []string) error { } return nil } + +func TestEncodedKeystoreBasics(t *testing.T) { + tdir, err := ioutil.TempDir("", "encoded-keystore-test") + if err != nil { + t.Fatal(err) + } + + ks, err := NewEncodedFSKeystore(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) + k1Name, err := encode("foo") + if err != nil { + t.Fatal(err) + } + + k2 := privKeyOrFatal(t) + k2Name, err := encode("bar") + if err != nil { + t.Fatal(err) + } + + 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{k1Name, k2Name}); 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) + } + + if err := ks.Delete("bar"); err != nil { + t.Fatal(err) + } + + if err := assertDirContents(tdir, []string{k1Name}); err != nil { + t.Fatal(err) + } + + if err := assertGetKey(ks, "foo", k1); 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("shouldnt be able to put a key with no name") + } + + if err := ks.Put(".foo", k1); err != nil { + t.Fatal(err) + } +} diff --git a/repo/fsrepo/fsrepo.go b/repo/fsrepo/fsrepo.go index 6ee436605cc..59728dc466d 100644 --- a/repo/fsrepo/fsrepo.go +++ b/repo/fsrepo/fsrepo.go @@ -36,7 +36,7 @@ const LockFile = "repo.lock" var log = logging.Logger("fsrepo") // version number that we are currently expecting to see -var RepoVersion = 7 +var RepoVersion = 8 var migrationInstructions = `See https://github.com/ipfs/fs-repo-migrations/blob/master/run.md Sorry for the inconvenience. In the future, these will run automatically.` @@ -385,7 +385,7 @@ func (r *FSRepo) openConfig() error { func (r *FSRepo) openKeystore() error { ksp := filepath.Join(r.path, "keystore") - ks, err := keystore.NewFSKeystore(ksp) + ks, err := keystore.NewKeystore(ksp) if err != nil { return err } From 059f396baca17d96b69441d3788e913cf334a36d Mon Sep 17 00:00:00 2001 From: Hector Sanjuan Date: Thu, 5 Mar 2020 14:28:02 +0100 Subject: [PATCH 508/671] keystore: finish addressing encodedFSKeystore * Use Go's base32 library * Set repo to version 9 * Resolve linting problems and docs. * Merge EncodedFSKeystore into FSKeystore * Remove name limitations and adjust tests --- keystore/keystore.go | 158 +++++++---------------------------- keystore/keystore_test.go | 120 ++++---------------------- keystore/memkeystore.go | 19 ++--- keystore/memkeystore_test.go | 8 +- repo/fsrepo/fsrepo.go | 4 +- 5 files changed, 61 insertions(+), 248 deletions(-) diff --git a/keystore/keystore.go b/keystore/keystore.go index a40ab5cb060..463f90e007e 100644 --- a/keystore/keystore.go +++ b/keystore/keystore.go @@ -7,13 +7,16 @@ import ( "path/filepath" "strings" + base32 "encoding/base32" + logging "github.com/ipfs/go-log" ci "github.com/libp2p/go-libp2p-core/crypto" - base32 "github.com/whyrusleeping/base32" ) var log = logging.Logger("keystore") +var codec = base32.StdEncoding.WithPadding(base32.NoPadding) + // Keystore provides a key management interface type Keystore interface { // Has returns whether or not a key exist in the Keystore @@ -29,46 +32,20 @@ type Keystore interface { List() ([]string, error) } +// ErrNoSuchKey is an error message returned when no key of a given name was found. var ErrNoSuchKey = fmt.Errorf("no key by the given name was found") + +// ErrKeyExists is an error message returned when a key already exists var ErrKeyExists = fmt.Errorf("key by that name already exists, refusing to overwrite") +const keyFilenamePrefix = "key_" + // FSKeystore is a keystore backed by files in a given directory stored on disk. type FSKeystore struct { dir string } -func validateName(name string) error { - if name == "" { - return fmt.Errorf("key names must be at least one character") - } - - if strings.Contains(name, "/") { - return fmt.Errorf("key names may not contain slashes") - } - - if strings.HasPrefix(name, ".") { - return fmt.Errorf("key names may not begin with a period") - } - - return nil -} - -// NewKeystore is a factory for getting instance of Keystore interface implementation -func NewKeystore(dir string) (Keystore, error) { - return NewEncodedFSKeystore(dir) -} - -// NewEncodedFSKeystore is a factory for getting instance of EncodedFSKeystore -func NewEncodedFSKeystore(dir string) (*EncodedFSKeystore, error) { - keystore, err := NewFSKeystore(dir) - - if err != nil { - return nil, err - } - - return &EncodedFSKeystore{keystore}, nil -} - +// NewFSKeystore returns a new filesystem-backed keystore. func NewFSKeystore(dir string) (*FSKeystore, error) { _, err := os.Stat(dir) if err != nil { @@ -85,28 +62,25 @@ func NewFSKeystore(dir string) (*FSKeystore, error) { // Has returns whether or not a key exist in the Keystore func (ks *FSKeystore) Has(name string) (bool, error) { + name, err := encode(name) + if err != nil { + return false, err + } + kp := filepath.Join(ks.dir, name) - _, err := os.Stat(kp) + _, err = os.Stat(kp) if os.IsNotExist(err) { return false, nil } - - if err != nil { - return false, err - } - - if err := validateName(name); err != nil { - return false, err - } - - return true, nil + return err == nil, err } // Put stores a key in the Keystore, if a key with the same name already exists, returns ErrKeyExists func (ks *FSKeystore) Put(name string, k ci.PrivKey) error { - if err := validateName(name); err != nil { + name, err := encode(name) + if err != nil { return err } @@ -138,7 +112,8 @@ func (ks *FSKeystore) Put(name string, k ci.PrivKey) error { // Get retrieves a key from the Keystore if it exists, and returns ErrNoSuchKey // otherwise. func (ks *FSKeystore) Get(name string) (ci.PrivKey, error) { - if err := validateName(name); err != nil { + name, err := encode(name) + if err != nil { return nil, err } @@ -157,7 +132,8 @@ func (ks *FSKeystore) Get(name string) (ci.PrivKey, error) { // Delete removes a key from the Keystore func (ks *FSKeystore) Delete(name string) error { - if err := validateName(name); err != nil { + name, err := encode(name) + if err != nil { return err } @@ -181,25 +157,23 @@ func (ks *FSKeystore) List() ([]string, error) { list := make([]string, 0, len(dirs)) for _, name := range dirs { - err := validateName(name) + decodedName, err := decode(name) if err == nil { - list = append(list, name) + list = append(list, decodedName) } else { - log.Warnf("Ignoring the invalid keyfile: %s", name) + log.Errorf("Ignoring keyfile with invalid encoded filename: %s", name) } } return list, nil } -const keyFilenamePrefix = "key_" - func encode(name string) (string, error) { if name == "" { return "", fmt.Errorf("key name must be at least one character") } - encodedName := base32.RawStdEncoding.EncodeToString([]byte(name)) + encodedName := codec.EncodeToString([]byte(name)) log.Debugf("Encoded key name: %s to: %s", name, encodedName) return keyFilenamePrefix + strings.ToLower(encodedName), nil @@ -211,86 +185,12 @@ func decode(name string) (string, error) { } nameWithoutPrefix := strings.ToUpper(name[len(keyFilenamePrefix):]) - data, err := base32.RawStdEncoding.DecodeString(nameWithoutPrefix) - + decodedName, err := codec.DecodeString(nameWithoutPrefix) if err != nil { return "", err } - decodedName := string(data[:]) - log.Debugf("Decoded key name: %s to: %s", name, decodedName) - return decodedName, nil -} - -// EncodedFSKeystore is extension of FSKeystore that encodes the key filenames in base32 -type EncodedFSKeystore struct { - *FSKeystore -} - -// Has indicates if key is in keystore -func (ks *EncodedFSKeystore) Has(name string) (bool, error) { - encodedName, err := encode(name) - - if err != nil { - return false, err - } - - return ks.FSKeystore.Has(encodedName) -} - -// Put places key into the keystore -func (ks *EncodedFSKeystore) Put(name string, k ci.PrivKey) error { - encodedName, err := encode(name) - - if err != nil { - return err - } - - return ks.FSKeystore.Put(encodedName, k) -} - -// Get retrieves key by its name from the keystore -func (ks *EncodedFSKeystore) Get(name string) (ci.PrivKey, error) { - encodedName, err := encode(name) - - if err != nil { - return nil, err - } - - return ks.FSKeystore.Get(encodedName) -} - -// Delete removes key from the keystore -func (ks *EncodedFSKeystore) Delete(name string) error { - encodedName, err := encode(name) - - if err != nil { - return err - } - - return ks.FSKeystore.Delete(encodedName) -} - -// List returns list of all keys in keystore -func (ks *EncodedFSKeystore) List() ([]string, error) { - dirs, err := ks.FSKeystore.List() - - 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.Warningf("Ignoring keyfile with invalid encoded filename: %s", name) - } - } - - return list, nil + return string(decodedName), nil } diff --git a/keystore/keystore_test.go b/keystore/keystore_test.go index 685e5d942ef..2a48b43e569 100644 --- a/keystore/keystore_test.go +++ b/keystore/keystore_test.go @@ -132,16 +132,16 @@ func TestKeystoreBasics(t *testing.T) { t.Fatal(err) } - if err := ks.Put("..///foo/", k1); err == nil { - t.Fatal("shouldnt be able to put a poorly named key") + if err := ks.Put("..///foo/", k1); err != nil { + t.Fatal(err) } if err := ks.Put("", k1); err == nil { t.Fatal("shouldnt be able to put a key with no name") } - if err := ks.Put(".foo", k1); err == nil { - t.Fatal("shouldnt be able to put a key with a 'hidden' name") + if err := ks.Put(".foo", k1); err != nil { + t.Fatal(err) } } @@ -166,12 +166,17 @@ func TestInvalidKeyFiles(t *testing.T) { t.Fatal(err) } - err = ioutil.WriteFile(filepath.Join(ks.dir, "valid"), bytes, 0644) + encodedName, err := encode("valid") + if err != nil { + t.Fatal(err) + } + + err = ioutil.WriteFile(filepath.Join(ks.dir, encodedName), bytes, 0644) if err != nil { t.Fatal(err) } - err = ioutil.WriteFile(filepath.Join(ks.dir, ".invalid"), bytes, 0644) + err = ioutil.WriteFile(filepath.Join(ks.dir, "z.invalid"), bytes, 0644) if err != nil { t.Fatal(err) } @@ -197,10 +202,6 @@ func TestInvalidKeyFiles(t *testing.T) { if err != nil { t.Fatal(err) } - - if _, err = ks.Has(".invalid"); err == nil { - t.Fatal("shouldnt be able to put a key with a 'hidden' name") - } } func TestNonExistingKey(t *testing.T) { @@ -231,12 +232,12 @@ func TestMakeKeystoreNoDir(t *testing.T) { } func assertGetKey(ks Keystore, name string, exp ci.PrivKey) error { - out_k, err := ks.Get(name) + outK, err := ks.Get(name) if err != nil { return err } - if !out_k.Equals(exp) { + if !outK.Equals(exp) { return fmt.Errorf("key we got out didnt match expectation") } @@ -255,7 +256,11 @@ func assertDirContents(dir string, exp []string) error { var names []string for _, fi := range finfos { - names = append(names, fi.Name()) + decodedName, err := decode(fi.Name()) + if err != nil { + return err + } + names = append(names, decodedName) } sort.Strings(names) @@ -271,92 +276,3 @@ func assertDirContents(dir string, exp []string) error { } return nil } - -func TestEncodedKeystoreBasics(t *testing.T) { - tdir, err := ioutil.TempDir("", "encoded-keystore-test") - if err != nil { - t.Fatal(err) - } - - ks, err := NewEncodedFSKeystore(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) - k1Name, err := encode("foo") - if err != nil { - t.Fatal(err) - } - - k2 := privKeyOrFatal(t) - k2Name, err := encode("bar") - if err != nil { - t.Fatal(err) - } - - 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{k1Name, k2Name}); 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) - } - - if err := ks.Delete("bar"); err != nil { - t.Fatal(err) - } - - if err := assertDirContents(tdir, []string{k1Name}); err != nil { - t.Fatal(err) - } - - if err := assertGetKey(ks, "foo", k1); 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("shouldnt be able to put a key with no name") - } - - if err := ks.Put(".foo", k1); err != nil { - t.Fatal(err) - } -} diff --git a/keystore/memkeystore.go b/keystore/memkeystore.go index 4067bbce29a..c96985252ac 100644 --- a/keystore/memkeystore.go +++ b/keystore/memkeystore.go @@ -1,6 +1,10 @@ package keystore -import ci "github.com/libp2p/go-libp2p-core/crypto" +import ( + "errors" + + ci "github.com/libp2p/go-libp2p-core/crypto" +) // MemKeystore is an in memory keystore implementation that is not persisted to // any backing storage. @@ -8,6 +12,7 @@ type MemKeystore struct { keys map[string]ci.PrivKey } +// NewMemKeystore creates a MemKeystore. func NewMemKeystore() *MemKeystore { return &MemKeystore{make(map[string]ci.PrivKey)} } @@ -20,8 +25,8 @@ func (mk *MemKeystore) Has(name string) (bool, error) { // Put store a key in the Keystore func (mk *MemKeystore) Put(name string, k ci.PrivKey) error { - if err := validateName(name); err != nil { - return err + if name == "" { + return errors.New("key name must be at least one character") } _, ok := mk.keys[name] @@ -35,10 +40,6 @@ func (mk *MemKeystore) Put(name string, k ci.PrivKey) error { // Get retrieve a key from the Keystore func (mk *MemKeystore) Get(name string) (ci.PrivKey, error) { - if err := validateName(name); err != nil { - return nil, err - } - k, ok := mk.keys[name] if !ok { return nil, ErrNoSuchKey @@ -49,10 +50,6 @@ func (mk *MemKeystore) Get(name string) (ci.PrivKey, error) { // Delete remove a key from the Keystore func (mk *MemKeystore) Delete(name string) error { - if err := validateName(name); err != nil { - return err - } - delete(mk.keys, name) return nil } diff --git a/keystore/memkeystore_test.go b/keystore/memkeystore_test.go index 62533d54b92..a7214893a3f 100644 --- a/keystore/memkeystore_test.go +++ b/keystore/memkeystore_test.go @@ -85,15 +85,15 @@ func TestMemKeyStoreBasics(t *testing.T) { t.Fatal(err) } - if err := ks.Put("..///foo/", k1); err == nil { - t.Fatal("shouldnt be able to put a poorly named key") + if err := ks.Put("..///foo/", k1); err != nil { + t.Fatal(err) } if err := ks.Put("", k1); err == nil { t.Fatal("shouldnt be able to put a key with no name") } - if err := ks.Put(".foo", k1); err == nil { - t.Fatal("shouldnt be able to put a key with a 'hidden' name") + if err := ks.Put(".foo", k1); err != nil { + t.Fatal(err) } } diff --git a/repo/fsrepo/fsrepo.go b/repo/fsrepo/fsrepo.go index 59728dc466d..a14e96ff25c 100644 --- a/repo/fsrepo/fsrepo.go +++ b/repo/fsrepo/fsrepo.go @@ -36,7 +36,7 @@ const LockFile = "repo.lock" var log = logging.Logger("fsrepo") // version number that we are currently expecting to see -var RepoVersion = 8 +var RepoVersion = 9 var migrationInstructions = `See https://github.com/ipfs/fs-repo-migrations/blob/master/run.md Sorry for the inconvenience. In the future, these will run automatically.` @@ -385,7 +385,7 @@ func (r *FSRepo) openConfig() error { func (r *FSRepo) openKeystore() error { ksp := filepath.Join(r.path, "keystore") - ks, err := keystore.NewKeystore(ksp) + ks, err := keystore.NewFSKeystore(ksp) if err != nil { return err } From 0d9d6e94952f3393f2a5f08e9431413e70e87d85 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 23 Mar 2020 17:40:28 -0700 Subject: [PATCH 509/671] ci: checkout working interop commit --- .circleci/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index bc30f97f8c2..368359faac8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -174,6 +174,7 @@ jobs: name: Cloning command: | git clone https://github.com/ipfs/interop.git + git -C interop checkout "fix/disable-repo-interop-test" git -C interop log -1 - restore_cache: keys: From c6b2c66b202831c63fd103c1b75ca5de8e23cb5d Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 24 Mar 2020 11:29:55 +0000 Subject: [PATCH 510/671] chore(deps): bump github.com/ipfs/go-blockservice from 0.1.2 to 0.1.3 Bumps [github.com/ipfs/go-blockservice](https://github.com/ipfs/go-blockservice) from 0.1.2 to 0.1.3. - [Release notes](https://github.com/ipfs/go-blockservice/releases) - [Commits](https://github.com/ipfs/go-blockservice/compare/v0.1.2...v0.1.3) Signed-off-by: dependabot-preview[bot] --- go.mod | 2 +- go.sum | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 141cc57c779..ea0bf792bbb 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/hashicorp/golang-lru v0.5.4 github.com/ipfs/go-bitswap v0.2.5 github.com/ipfs/go-block-format v0.0.2 - github.com/ipfs/go-blockservice v0.1.2 + github.com/ipfs/go-blockservice v0.1.3 github.com/ipfs/go-cid v0.0.5 github.com/ipfs/go-cidutil v0.0.2 github.com/ipfs/go-datastore v0.4.4 diff --git a/go.sum b/go.sum index 26795b38494..864777fd95b 100644 --- a/go.sum +++ b/go.sum @@ -197,6 +197,7 @@ github.com/ipfs/go-bitswap v0.0.9/go.mod h1:kAPf5qgn2W2DrgAcscZ3HrM9qh4pH+X8Fkk3 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.5 h1:aRGBghux0IDbKBG6eifDigCOfCs9Xv+WUYXuDzx/0cc= github.com/ipfs/go-bitswap v0.2.5/go.mod h1:vHqjV7wGhpoEIT83n+NAD66YpqpZlKVKfLhAYlbbBDY= github.com/ipfs/go-block-format v0.0.1/go.mod h1:DK/YYcsSUIVAFNwo/KZCdIIbpN0ROH/baNLgayt4pFc= @@ -208,6 +209,8 @@ github.com/ipfs/go-blockservice v0.1.0/go.mod h1:hzmMScl1kXHg3M2BjTymbVPjv627N7s github.com/ipfs/go-blockservice v0.1.1/go.mod h1:t+411r7psEUhLueM8C7aPA7cxCclv4O3VsUVxt9kz2I= github.com/ipfs/go-blockservice v0.1.2 h1:fqFeeu1EG0lGVrqUo+BVJv7LZV31I4ZsyNthCOMAJRc= github.com/ipfs/go-blockservice v0.1.2/go.mod h1:t+411r7psEUhLueM8C7aPA7cxCclv4O3VsUVxt9kz2I= +github.com/ipfs/go-blockservice v0.1.3 h1:9XgsPMwwWJSC9uVr2pMDsW2qFTBSkxpGMhmna8mIjPM= +github.com/ipfs/go-blockservice v0.1.3/go.mod h1:OTZhFpkgY48kNzbgyvcexW9cHrpjBYIjSR0KoDOFOLU= github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= github.com/ipfs/go-cid v0.0.3 h1:UIAh32wymBpStoe83YCzwVQQ5Oy/H0FdxvUS6DJDzms= From a5ad19ae5271d424da2d527f0ba31e88fdfcba6a Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 24 Mar 2020 11:30:21 +0000 Subject: [PATCH 511/671] chore(deps): bump github.com/libp2p/go-libp2p-peerstore Bumps [github.com/libp2p/go-libp2p-peerstore](https://github.com/libp2p/go-libp2p-peerstore) from 0.2.0 to 0.2.1. - [Release notes](https://github.com/libp2p/go-libp2p-peerstore/releases) - [Commits](https://github.com/libp2p/go-libp2p-peerstore/compare/v0.2.0...v0.2.1) Signed-off-by: dependabot-preview[bot] --- go.mod | 2 +- go.sum | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 141cc57c779..27f6a0614af 100644 --- a/go.mod +++ b/go.mod @@ -70,7 +70,7 @@ require ( github.com/libp2p/go-libp2p-kbucket v0.2.3 github.com/libp2p/go-libp2p-loggables v0.1.0 github.com/libp2p/go-libp2p-mplex v0.2.2 - github.com/libp2p/go-libp2p-peerstore v0.2.0 + github.com/libp2p/go-libp2p-peerstore v0.2.1 github.com/libp2p/go-libp2p-pubsub v0.2.6 github.com/libp2p/go-libp2p-pubsub-router v0.2.1 github.com/libp2p/go-libp2p-quic-transport v0.3.1 diff --git a/go.sum b/go.sum index 26795b38494..9b302139f34 100644 --- a/go.sum +++ b/go.sum @@ -545,6 +545,8 @@ github.com/libp2p/go-libp2p-peerstore v0.1.4 h1:d23fvq5oYMJ/lkkbO4oTwBp/JP+I/1m5 github.com/libp2p/go-libp2p-peerstore v0.1.4/go.mod h1:+4BDbDiiKf4PzpANZDAT+knVdLxvqh7hXOujessqdzs= github.com/libp2p/go-libp2p-peerstore v0.2.0 h1:XcgJhI8WyUOCbHyRLNEX5542YNj8hnLSJ2G1InRjDhk= github.com/libp2p/go-libp2p-peerstore v0.2.0/go.mod h1:N2l3eVIeAitSg3Pi2ipSrJYnqhVnMNQZo9nkSCuAbnQ= +github.com/libp2p/go-libp2p-peerstore v0.2.1 h1:u+gOfsKgu73ZkGWhvckRm03z9C+iS9TrLqpANweELGs= +github.com/libp2p/go-libp2p-peerstore v0.2.1/go.mod h1:NQxhNjWxf1d4w6PihR8btWIRjwRLBr4TYKfNgrUkOPA= github.com/libp2p/go-libp2p-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= @@ -963,6 +965,7 @@ go.uber.org/fx v1.10.0 h1:S2K/H8oNied0Je/mLKdWzEWKZfv9jtxSDm8CnwK+5Fg= go.uber.org/fx v1.10.0/go.mod h1:vLRicqpG/qQEzno4SYU86iCwfT95EZza+Eba0ItuxqY= go.uber.org/goleak v0.10.0 h1:G3eWbSNIskeRqtsN/1uI5B+eP73y3JUuBsv9AZjehb4= go.uber.org/goleak v0.10.0/go.mod h1:VCZuO8V8mFPlL0F5J5GK1rtHV3DrFcQ1R8ryq7FK0aI= +go.uber.org/goleak v1.0.0/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.4.0 h1:f3WCSC2KzAcBXGATIxAB1E2XuCpNU255wNKZ505qi3E= @@ -1101,6 +1104,7 @@ golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191030062658-86caa796c7ab/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191114200427-caa0b0f7d508 h1:0FYNp0PF9kFm/ZUrvcJiQ12IUJJG7iAc6Cu01wbKrbU= golang.org/x/tools v0.0.0-20191114200427-caa0b0f7d508/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f h1:kDxGY2VmgABOe55qheT/TFqUMtcTHnomIPS1iv3G4Ms= From ad543f0724eccc57f6d49441932dd00eea6b7e05 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Tue, 24 Mar 2020 14:46:41 -0700 Subject: [PATCH 512/671] feat: update go-libp2p & go-bitswap Uses the new libp2p AutoNAT option. --- core/core.go | 2 -- core/node/groups.go | 2 +- core/node/helpers.go | 1 + core/node/libp2p/nat.go | 26 +------------------------- go.mod | 7 +++---- go.sum | 27 +++++++++++++++++++++++---- 6 files changed, 29 insertions(+), 36 deletions(-) diff --git a/core/core.go b/core/core.go index ce87cbf64ba..d3c3a5ae5e1 100644 --- a/core/core.go +++ b/core/core.go @@ -26,7 +26,6 @@ import ( mfs "github.com/ipfs/go-mfs" resolver "github.com/ipfs/go-path/resolver" goprocess "github.com/jbenet/goprocess" - autonat "github.com/libp2p/go-libp2p-autonat-svc" connmgr "github.com/libp2p/go-libp2p-core/connmgr" ic "github.com/libp2p/go-libp2p-core/crypto" p2phost "github.com/libp2p/go-libp2p-core/host" @@ -91,7 +90,6 @@ type IpfsNode struct { IpnsRepub *ipnsrp.Republisher `optional:"true"` GraphExchange graphsync.GraphExchange `optional:"true"` - AutoNAT *autonat.AutoNATService `optional:"true"` PubSub *pubsub.PubSub `optional:"true"` PSRouter *psrouter.PubsubValueStore `optional:"true"` DHT *dht.IpfsDHT `optional:"true"` diff --git a/core/node/groups.go b/core/node/groups.go index bb97cc0e04f..5cd3a84b176 100644 --- a/core/node/groups.go +++ b/core/node/groups.go @@ -110,9 +110,9 @@ func LibP2P(bcfg *BuildCfg, cfg *config.Config) fx.Option { maybeProvide(libp2p.BandwidthCounter, !cfg.Swarm.DisableBandwidthMetrics), maybeProvide(libp2p.NatPortMap, !cfg.Swarm.DisableNatPortMap), + maybeProvide(libp2p.AutoNATService, cfg.Swarm.EnableAutoNATService), maybeProvide(libp2p.AutoRelay, cfg.Swarm.EnableAutoRelay), maybeProvide(libp2p.QUIC, cfg.Experimental.QUIC), - maybeInvoke(libp2p.AutoNATService(cfg.Experimental.QUIC), cfg.Swarm.EnableAutoNATService), connmgr, ps, disc, diff --git a/core/node/helpers.go b/core/node/helpers.go index 9ecd8036b9f..5c27fb9ce00 100644 --- a/core/node/helpers.go +++ b/core/node/helpers.go @@ -43,6 +43,7 @@ func maybeProvide(opt interface{}, enable bool) fx.Option { return fx.Options() } +//nolint unused func maybeInvoke(opt interface{}, enable bool) fx.Option { if enable { return fx.Invoke(opt) diff --git a/core/node/libp2p/nat.go b/core/node/libp2p/nat.go index 6367d311b99..28ce03203c2 100644 --- a/core/node/libp2p/nat.go +++ b/core/node/libp2p/nat.go @@ -2,31 +2,7 @@ package libp2p import ( "github.com/libp2p/go-libp2p" - autonat "github.com/libp2p/go-libp2p-autonat-svc" - host "github.com/libp2p/go-libp2p-core/host" - libp2pquic "github.com/libp2p/go-libp2p-quic-transport" - "go.uber.org/fx" - - "github.com/ipfs/go-ipfs/core/node/helpers" - "github.com/ipfs/go-ipfs/repo" ) var NatPortMap = simpleOpt(libp2p.NATPortMap()) - -func AutoNATService(quic bool) func(repo repo.Repo, mctx helpers.MetricsCtx, lc fx.Lifecycle, host host.Host) error { - return func(repo repo.Repo, mctx helpers.MetricsCtx, lc fx.Lifecycle, host host.Host) error { - // collect private net option in case swarm.key is presented - opts, _, err := PNet(repo) - if err != nil { - // swarm key exists but was failed to decode - return err - } - - if quic { - opts.Opts = append(opts.Opts, libp2p.DefaultTransports, libp2p.Transport(libp2pquic.NewTransport)) - } - - _, err = autonat.NewAutoNATService(helpers.LifecycleCtx(mctx, lc), host, opts.Opts...) - return err - } -} +var AutoNATService = simpleOpt(libp2p.EnableNATService()) diff --git a/go.mod b/go.mod index b0dbf604fc6..5e198e2b9a8 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/gogo/protobuf v1.3.1 github.com/hashicorp/go-multierror v1.0.0 github.com/hashicorp/golang-lru v0.5.4 - github.com/ipfs/go-bitswap v0.2.5 + github.com/ipfs/go-bitswap v0.2.6 github.com/ipfs/go-block-format v0.0.2 github.com/ipfs/go-blockservice v0.1.3 github.com/ipfs/go-cid v0.0.5 @@ -57,10 +57,9 @@ require ( github.com/jbenet/go-is-domain v1.0.3 github.com/jbenet/go-random v0.0.0-20190219211222-123a90aedc0c github.com/jbenet/go-temp-err-catcher v0.1.0 - github.com/jbenet/goprocess v0.1.3 + github.com/jbenet/goprocess v0.1.4 github.com/libp2p/go-eventbus v0.1.0 - github.com/libp2p/go-libp2p v0.6.1 - github.com/libp2p/go-libp2p-autonat-svc v0.1.0 + github.com/libp2p/go-libp2p v0.7.0 github.com/libp2p/go-libp2p-circuit v0.1.4 github.com/libp2p/go-libp2p-connmgr v0.2.1 github.com/libp2p/go-libp2p-core v0.5.0 diff --git a/go.sum b/go.sum index a086af5c379..b99fd0ef3fb 100644 --- a/go.sum +++ b/go.sum @@ -198,8 +198,8 @@ github.com/ipfs/go-bitswap v0.1.0/go.mod h1:FFJEf18E9izuCqUtHxbWEvq+reg7o4CW5wSA 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.5 h1:aRGBghux0IDbKBG6eifDigCOfCs9Xv+WUYXuDzx/0cc= -github.com/ipfs/go-bitswap v0.2.5/go.mod h1:vHqjV7wGhpoEIT83n+NAD66YpqpZlKVKfLhAYlbbBDY= +github.com/ipfs/go-bitswap v0.2.6 h1:gdzEoVlV0uc4P79FX6HQ+46kzX1XeDF7kL8qPMPkVyo= +github.com/ipfs/go-bitswap v0.2.6/go.mod h1:2Yjog0GMdH8+AsxkE0DI9D2mANaUTxbVVav0pPoZoug= github.com/ipfs/go-block-format v0.0.1/go.mod h1:DK/YYcsSUIVAFNwo/KZCdIIbpN0ROH/baNLgayt4pFc= github.com/ipfs/go-block-format v0.0.2 h1:qPDvcP19izTjU8rgo6p7gTXZlkMkF5bz5G3fqIsSCPE= github.com/ipfs/go-block-format v0.0.2/go.mod h1:AWR46JfpcObNfg3ok2JHDUfdiHRgWhJgCQF+KIgOPJY= @@ -391,6 +391,8 @@ github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPw github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8/go.mod h1:Ly/wlsjFq/qrU3Rar62tu1gASgGw6chQbSh/XgIIXCY= github.com/jbenet/goprocess v0.1.3 h1:YKyIEECS/XvcfHtBzxtjBBbWK+MbvA6dG8ASiqwvr10= github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= +github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0o= +github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= @@ -451,14 +453,16 @@ github.com/libp2p/go-libp2p v0.6.0 h1:EFArryT9N7AVA70LCcOh8zxsW+FeDnxwcpWQx9k7+G github.com/libp2p/go-libp2p v0.6.0/go.mod h1:mfKWI7Soz3ABX+XEBR61lGbg+ewyMtJHVt043oWeqwg= github.com/libp2p/go-libp2p v0.6.1 h1:mxabyJf4l6AmotDOKObwSfBNBWjL5VYXysVFLUMAuB8= github.com/libp2p/go-libp2p v0.6.1/go.mod h1:CTFnWXogryAHjXAKEbOf1OWY+VeAP3lDMZkfEI5sT54= +github.com/libp2p/go-libp2p v0.7.0 h1:qWmciout2lJclKfRlxqdepsQB7JihcbRhgcRcssP4rc= +github.com/libp2p/go-libp2p v0.7.0/go.mod h1:hZJf8txWeCduQRDC/WSqBGMxaTHCOYHt2xSU1ivxn0k= github.com/libp2p/go-libp2p-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 h1:aCWAu43Ri4nU0ZPO7NyLzUvvfqd0nE3dX0R/ZGYVgOU= github.com/libp2p/go-libp2p-autonat v0.1.0/go.mod h1:1tLf2yXxiE/oKGtDwPYWTSYG3PtvYlJmg7NeVtPRqH8= github.com/libp2p/go-libp2p-autonat v0.1.1 h1:WLBZcIRsjZlWdAZj9CiBSvU2wQXoUOiS1Zk1tM7DTJI= github.com/libp2p/go-libp2p-autonat v0.1.1/go.mod h1:OXqkeGOY2xJVWKAGV2inNF5aKN/djNA3fdpCWloIudE= -github.com/libp2p/go-libp2p-autonat-svc v0.1.0 h1:28IM7iWMDclZeVkpiFQaWVANwXwE7zLlpbnS7yXxrfs= -github.com/libp2p/go-libp2p-autonat-svc v0.1.0/go.mod h1:fqi8Obl/z3R4PFVLm8xFtZ6PBL9MlV/xumymRFkKq5A= +github.com/libp2p/go-libp2p-autonat v0.2.0 h1:Kok+0M/4jiz6TTmxtBqAa5tLyHb/U+G/7o/JEeW7Wok= +github.com/libp2p/go-libp2p-autonat v0.2.0/go.mod h1:DX+9teU4pEEoZUqR1PiMlqliONQdNbfzE1C718tcViI= github.com/libp2p/go-libp2p-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.3/go.mod h1:KML1//wiKR8vuuJO0y3LUd1uLv+tlkGTAr3jC0S5cLg= @@ -704,6 +708,8 @@ github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00v github.com/miekg/dns v1.1.4/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.12 h1:WMhc1ik4LNkTg8U9l3hI1LvxKmIL+f1+WV/SZtCbDDA= github.com/miekg/dns v1.1.12/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.28 h1:gQhy5bsJa8zTlVI8lywCTZp1lguor+xevFoYlzeCTQY= +github.com/miekg/dns v1.1.28/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= @@ -962,21 +968,28 @@ go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk= +go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/dig v1.8.0 h1:1rR6hnL/bu1EVcjnRDN5kx1vbIjEJDTGhSQ2B3ddpcI= go.uber.org/dig v1.8.0/go.mod h1:X34SnWGr8Fyla9zQNO2GSO2D+TIuqB14OS8JhYocIyw= go.uber.org/fx v1.10.0 h1:S2K/H8oNied0Je/mLKdWzEWKZfv9jtxSDm8CnwK+5Fg= go.uber.org/fx v1.10.0/go.mod h1:vLRicqpG/qQEzno4SYU86iCwfT95EZza+Eba0ItuxqY= go.uber.org/goleak v0.10.0 h1:G3eWbSNIskeRqtsN/1uI5B+eP73y3JUuBsv9AZjehb4= go.uber.org/goleak v0.10.0/go.mod h1:VCZuO8V8mFPlL0F5J5GK1rtHV3DrFcQ1R8ryq7FK0aI= +go.uber.org/goleak v1.0.0 h1:qsup4IcBdlmsnGfqyLl4Ntn3C2XCCuKAE7DwHpScyUo= go.uber.org/goleak v1.0.0/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.4.0 h1:f3WCSC2KzAcBXGATIxAB1E2XuCpNU255wNKZ505qi3E= go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A= +go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.14.1 h1:nYDKopTbvAPq/NrUVZwT15y2lpROBiLLyoRTbXOYWOo= +go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= go4.org v0.0.0-20200104003542-c7e774b10ea0 h1:M6XsnQeLwG+rHQ+/rrGh3puBI3WZEy9TBWmf2H+enQA= go4.org v0.0.0-20200104003542-c7e774b10ea0/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= @@ -1014,6 +1027,7 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f h1:J5lckAjkw6qYlOZNj90mLYNTEKDvWeuc1yieZ8qUzUE= golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/net v0.0.0-20180524181706-dfa909b99c79/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1038,6 +1052,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwL golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 h1:Ao/3l156eZf2AW5wK8a7/smtodRU+gha3+BeqJ69lRk= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1074,6 +1090,7 @@ golang.org/x/sys v0.0.0-20190610200419-93c9922d18ae/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1112,6 +1129,8 @@ golang.org/x/tools v0.0.0-20191114200427-caa0b0f7d508 h1:0FYNp0PF9kFm/ZUrvcJiQ12 golang.org/x/tools v0.0.0-20191114200427-caa0b0f7d508/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f h1:kDxGY2VmgABOe55qheT/TFqUMtcTHnomIPS1iv3G4Ms= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216052735-49a3e744a425 h1:VvQyQJN0tSuecqgcIxMWnnfG5kSmgy9KZR9sW3W5QeA= +golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA= From c88a2bfd59f931eef8207985062f56545a4bf314 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 25 Mar 2020 11:29:55 +0000 Subject: [PATCH 513/671] chore(deps): bump github.com/ipfs/go-log from 1.0.2 to 1.0.3 Bumps [github.com/ipfs/go-log](https://github.com/ipfs/go-log) from 1.0.2 to 1.0.3. - [Release notes](https://github.com/ipfs/go-log/releases) - [Commits](https://github.com/ipfs/go-log/compare/v1.0.2...v1.0.3) Signed-off-by: dependabot-preview[bot] --- go.mod | 2 +- go.sum | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 5e198e2b9a8..389b51e7563 100644 --- a/go.mod +++ b/go.mod @@ -45,7 +45,7 @@ require ( github.com/ipfs/go-ipld-format v0.0.2 github.com/ipfs/go-ipld-git v0.0.3 github.com/ipfs/go-ipns v0.0.2 - github.com/ipfs/go-log v1.0.2 + github.com/ipfs/go-log v1.0.3 github.com/ipfs/go-merkledag v0.3.1 github.com/ipfs/go-metrics-interface v0.0.1 github.com/ipfs/go-metrics-prometheus v0.0.2 diff --git a/go.sum b/go.sum index b99fd0ef3fb..698eb5e7606 100644 --- a/go.sum +++ b/go.sum @@ -328,10 +328,14 @@ github.com/ipfs/go-log v1.0.1 h1:5lIEEOQTk/vd1WuPFBRqz2mcp+5G1fMVcW+Ib/H5Hfo= github.com/ipfs/go-log v1.0.1/go.mod h1:HuWlQttfN6FWNHRhlY5yMk/lW7evQC0HHGOxEwMRR8I= github.com/ipfs/go-log v1.0.2 h1:s19ZwJxH8rPWzypjcDpqPLIyV7BnbLqvpli3iZoqYK0= github.com/ipfs/go-log v1.0.2/go.mod h1:1MNjMxe0u6xvJZgeqbJ8vdo2TKaGwZ1a0Bpza+sr2Sk= +github.com/ipfs/go-log v1.0.3 h1:Gg7SUYSZ7BrqaKMwM+hRgcAkKv4QLfzP4XPQt5Sx/OI= +github.com/ipfs/go-log v1.0.3/go.mod h1:OsLySYkwIbiSUR/yBTdv1qPtcE4FW3WPWk/ewz9Ru+A= github.com/ipfs/go-log/v2 v2.0.1 h1:mnR9XFltezAtO8A6tj5U7nKkRzhEQNEw/wT11U2HhPM= github.com/ipfs/go-log/v2 v2.0.1/go.mod h1:O7P1lJt27vWHhOwQmcFEvlmo49ry2VY2+JfBWFaa9+0= github.com/ipfs/go-log/v2 v2.0.2 h1:xguurydRdfKMJjKyxNXNU8lYP0VZH1NUwJRwUorjuEw= github.com/ipfs/go-log/v2 v2.0.2/go.mod h1:O7P1lJt27vWHhOwQmcFEvlmo49ry2VY2+JfBWFaa9+0= +github.com/ipfs/go-log/v2 v2.0.3 h1:Q2gXcBoCALyLN/pUQlz1qgu0x3uFV6FzP9oXhpfyJpc= +github.com/ipfs/go-log/v2 v2.0.3/go.mod h1:O7P1lJt27vWHhOwQmcFEvlmo49ry2VY2+JfBWFaa9+0= github.com/ipfs/go-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= From 5be6e26f7b5e112c2da68d2e7d14e587009cc3bc Mon Sep 17 00:00:00 2001 From: Peter Rabbitson Date: Wed, 25 Mar 2020 15:03:17 +0100 Subject: [PATCH 514/671] Forgotten go-fmt Not sure why CI didn't catch this --- cmd/ipfs/daemon.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/ipfs/daemon.go b/cmd/ipfs/daemon.go index b8486f8aba1..0a24b907a7d 100644 --- a/cmd/ipfs/daemon.go +++ b/cmd/ipfs/daemon.go @@ -299,9 +299,9 @@ func daemonFunc(req *cmds.Request, re cmds.ResponseEmitter, env cmds.Environment // Start assembling node config ncfg := &core.BuildCfg{ - Repo: repo, - Permanent: true, // It is temporary way to signify that node is permanent - Online: !offline, + Repo: repo, + Permanent: true, // It is temporary way to signify that node is permanent + Online: !offline, DisableEncryptedConnections: unencrypted, ExtraOpts: map[string]bool{ "pubsub": pubsub, From 7a4c377bbb05b68e39c917c6a394885816504efa Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Sun, 15 Mar 2020 23:40:01 -0700 Subject: [PATCH 515/671] fix(keystore): avoid racy filesystem access Instead of checking then performing a file operation, perform the file operation and check the error. --- keystore/keystore.go | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/keystore/keystore.go b/keystore/keystore.go index 463f90e007e..a52b4ad1711 100644 --- a/keystore/keystore.go +++ b/keystore/keystore.go @@ -47,16 +47,13 @@ type FSKeystore struct { // NewFSKeystore returns a new filesystem-backed keystore. func NewFSKeystore(dir string) (*FSKeystore, error) { - _, err := os.Stat(dir) - if err != nil { - if !os.IsNotExist(err) { - return nil, err - } - if err := os.Mkdir(dir, 0700); err != nil { - return nil, err - } + err := os.Mkdir(dir, 0700) + switch { + case os.IsExist(err): + case err == nil: + default: + return nil, err } - return &FSKeystore{dir}, nil } @@ -91,15 +88,11 @@ func (ks *FSKeystore) Put(name string, k ci.PrivKey) error { kp := filepath.Join(ks.dir, name) - _, err = os.Stat(kp) - if err == nil { - return ErrKeyExists - } else if !os.IsNotExist(err) { - return err - } - - fi, err := os.Create(kp) + fi, err := os.OpenFile(kp, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0600) if err != nil { + if os.IsExist(err) { + err = ErrKeyExists + } return err } defer fi.Close() From 5129758122df4da295c3b28c44ee5af26ea5ec15 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 25 Mar 2020 12:32:14 -0700 Subject: [PATCH 516/671] chore: update deps Specifically, fix an autonat issue where the service wouldn't actually start. --- go.mod | 6 +++--- go.sum | 12 ++++++++---- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index 389b51e7563..196ca195c6d 100644 --- a/go.mod +++ b/go.mod @@ -59,7 +59,7 @@ require ( github.com/jbenet/go-temp-err-catcher v0.1.0 github.com/jbenet/goprocess v0.1.4 github.com/libp2p/go-eventbus v0.1.0 - github.com/libp2p/go-libp2p v0.7.0 + github.com/libp2p/go-libp2p v0.7.1 github.com/libp2p/go-libp2p-circuit v0.1.4 github.com/libp2p/go-libp2p-connmgr v0.2.1 github.com/libp2p/go-libp2p-core v0.5.0 @@ -99,8 +99,8 @@ require ( github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 github.com/whyrusleeping/tar-utils v0.0.0-20180509141711-8c6c8ba81d5c go.uber.org/fx v1.10.0 - golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4 - golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 + golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 + golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd gopkg.in/cheggaaa/pb.v1 v1.0.28 ) diff --git a/go.sum b/go.sum index 698eb5e7606..c0f706f10db 100644 --- a/go.sum +++ b/go.sum @@ -459,6 +459,8 @@ github.com/libp2p/go-libp2p v0.6.1 h1:mxabyJf4l6AmotDOKObwSfBNBWjL5VYXysVFLUMAuB github.com/libp2p/go-libp2p v0.6.1/go.mod h1:CTFnWXogryAHjXAKEbOf1OWY+VeAP3lDMZkfEI5sT54= github.com/libp2p/go-libp2p v0.7.0 h1:qWmciout2lJclKfRlxqdepsQB7JihcbRhgcRcssP4rc= github.com/libp2p/go-libp2p v0.7.0/go.mod h1:hZJf8txWeCduQRDC/WSqBGMxaTHCOYHt2xSU1ivxn0k= +github.com/libp2p/go-libp2p v0.7.1 h1:53lYHjkvB61SebIAMvVfJXYe21B1WEQ7rAKfblyLa7Q= +github.com/libp2p/go-libp2p v0.7.1/go.mod h1:f59Ddl3ofgyGdnhDCAjijcdCSuPY/wuvWDDt+grdfcI= 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 h1:aCWAu43Ri4nU0ZPO7NyLzUvvfqd0nE3dX0R/ZGYVgOU= @@ -467,6 +469,8 @@ github.com/libp2p/go-libp2p-autonat v0.1.1 h1:WLBZcIRsjZlWdAZj9CiBSvU2wQXoUOiS1Z github.com/libp2p/go-libp2p-autonat v0.1.1/go.mod h1:OXqkeGOY2xJVWKAGV2inNF5aKN/djNA3fdpCWloIudE= github.com/libp2p/go-libp2p-autonat v0.2.0 h1:Kok+0M/4jiz6TTmxtBqAa5tLyHb/U+G/7o/JEeW7Wok= github.com/libp2p/go-libp2p-autonat v0.2.0/go.mod h1:DX+9teU4pEEoZUqR1PiMlqliONQdNbfzE1C718tcViI= +github.com/libp2p/go-libp2p-autonat v0.2.1 h1:T0CRQhrvTBKfBSYw6Xo2K3ixtNpAnRCraxof3AAfgQA= +github.com/libp2p/go-libp2p-autonat v0.2.1/go.mod h1:MWtAhV5Ko1l6QBsHQNSuM6b1sRkXrpk0/LqCr+vCVxI= github.com/libp2p/go-libp2p-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.3/go.mod h1:KML1//wiKR8vuuJO0y3LUd1uLv+tlkGTAr3jC0S5cLg= @@ -1019,8 +1023,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d h1:1ZiEyfaQIg3Qh0EoqpwAakHVhecoE5wlSg5GjnafJGw= golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4 h1:QmwruyY+bKbDDL0BaglrbZABEali68eoMFhTZpCjYVA= -golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 h1:3zb4D3T4G8jdExgVU/95+vQXfpEPiMdCaZgmGVxjNHM= +golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1103,8 +1107,8 @@ golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 h1:uYVVQ9WP/Ds2ROhcaGPeIdVq0RIXVLwsHlnvJ+cT1So= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From aec498bbde7f5a20a13618d036b307693eb3ce04 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 25 Mar 2020 12:47:48 -0700 Subject: [PATCH 517/671] test(sharness): make sure we can actually enable autonat This isn't a real autonat test, but it's a regression test to make sure we don't blatantly break this. --- test/sharness/t0185-autonat.sh | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100755 test/sharness/t0185-autonat.sh diff --git a/test/sharness/t0185-autonat.sh b/test/sharness/t0185-autonat.sh new file mode 100755 index 00000000000..88ae053e217 --- /dev/null +++ b/test/sharness/t0185-autonat.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +test_description="Test autonat" + +. lib/test-lib.sh + +# NOTE: This is currently a really dumb test just to make sure this service +# starts. We need better tests but testing AutoNAT without public IP addresses +# is tricky. + +test_init_ipfs + +test_expect_success "enable autonat" ' + ipfs config --json Swarm.EnableAutoNATService true +' + +test_launch_ipfs_daemon + +test_kill_ipfs_daemon + +test_done From b4b8401827c453fb080946460f723a154ff4956d Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 26 Mar 2020 11:29:39 +0000 Subject: [PATCH 518/671] chore(deps): bump github.com/ipfs/go-bitswap from 0.2.6 to 0.2.7 Bumps [github.com/ipfs/go-bitswap](https://github.com/ipfs/go-bitswap) from 0.2.6 to 0.2.7. - [Release notes](https://github.com/ipfs/go-bitswap/releases) - [Commits](https://github.com/ipfs/go-bitswap/compare/v0.2.6...v0.2.7) Signed-off-by: dependabot-preview[bot] --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 196ca195c6d..2046db60f4e 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/gogo/protobuf v1.3.1 github.com/hashicorp/go-multierror v1.0.0 github.com/hashicorp/golang-lru v0.5.4 - github.com/ipfs/go-bitswap v0.2.6 + github.com/ipfs/go-bitswap v0.2.7 github.com/ipfs/go-block-format v0.0.2 github.com/ipfs/go-blockservice v0.1.3 github.com/ipfs/go-cid v0.0.5 diff --git a/go.sum b/go.sum index c0f706f10db..b34418c42c3 100644 --- a/go.sum +++ b/go.sum @@ -200,6 +200,8 @@ github.com/ipfs/go-bitswap v0.1.3/go.mod h1:YEQlFy0kkxops5Vy+OxWdRSEZIoS7I7KDIwo github.com/ipfs/go-bitswap v0.1.8/go.mod h1:TOWoxllhccevbWFUR2N7B1MTSVVge1s6XSMiCSA4MzM= github.com/ipfs/go-bitswap v0.2.6 h1:gdzEoVlV0uc4P79FX6HQ+46kzX1XeDF7kL8qPMPkVyo= github.com/ipfs/go-bitswap v0.2.6/go.mod h1:2Yjog0GMdH8+AsxkE0DI9D2mANaUTxbVVav0pPoZoug= +github.com/ipfs/go-bitswap v0.2.7 h1:3h2ba+6iSmHb4ik0VWq8Z6e3Qlsii+1paSDa9HG8KI4= +github.com/ipfs/go-bitswap v0.2.7/go.mod h1:2Yjog0GMdH8+AsxkE0DI9D2mANaUTxbVVav0pPoZoug= github.com/ipfs/go-block-format v0.0.1/go.mod h1:DK/YYcsSUIVAFNwo/KZCdIIbpN0ROH/baNLgayt4pFc= github.com/ipfs/go-block-format v0.0.2 h1:qPDvcP19izTjU8rgo6p7gTXZlkMkF5bz5G3fqIsSCPE= github.com/ipfs/go-block-format v0.0.2/go.mod h1:AWR46JfpcObNfg3ok2JHDUfdiHRgWhJgCQF+KIgOPJY= From 027f08ccba91580c921e852609af8601108c6d9c Mon Sep 17 00:00:00 2001 From: Peter Rabbitson Date: Thu, 26 Mar 2020 21:46:21 +0100 Subject: [PATCH 519/671] Upgrade go-ipfs-chunker Closes #6953 --- go.mod | 2 +- go.sum | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 2046db60f4e..2034488a54a 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/ipfs/go-fs-lock v0.0.4 github.com/ipfs/go-graphsync v0.0.5 github.com/ipfs/go-ipfs-blockstore v0.1.4 - github.com/ipfs/go-ipfs-chunker v0.0.4 + github.com/ipfs/go-ipfs-chunker v0.0.5 github.com/ipfs/go-ipfs-cmds v0.1.4 github.com/ipfs/go-ipfs-config v0.3.0 github.com/ipfs/go-ipfs-ds-help v0.1.1 diff --git a/go.sum b/go.sum index b34418c42c3..7bda142644c 100644 --- a/go.sum +++ b/go.sum @@ -198,8 +198,6 @@ github.com/ipfs/go-bitswap v0.1.0/go.mod h1:FFJEf18E9izuCqUtHxbWEvq+reg7o4CW5wSA 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.6 h1:gdzEoVlV0uc4P79FX6HQ+46kzX1XeDF7kL8qPMPkVyo= -github.com/ipfs/go-bitswap v0.2.6/go.mod h1:2Yjog0GMdH8+AsxkE0DI9D2mANaUTxbVVav0pPoZoug= github.com/ipfs/go-bitswap v0.2.7 h1:3h2ba+6iSmHb4ik0VWq8Z6e3Qlsii+1paSDa9HG8KI4= github.com/ipfs/go-bitswap v0.2.7/go.mod h1:2Yjog0GMdH8+AsxkE0DI9D2mANaUTxbVVav0pPoZoug= github.com/ipfs/go-block-format v0.0.1/go.mod h1:DK/YYcsSUIVAFNwo/KZCdIIbpN0ROH/baNLgayt4pFc= @@ -273,8 +271,8 @@ github.com/ipfs/go-ipfs-blocksutil v0.0.1 h1:Eh/H4pc1hsvhzsQoMEP3Bke/aW5P5rVM1IW github.com/ipfs/go-ipfs-blocksutil v0.0.1/go.mod h1:Yq4M86uIOmxmGPUHv/uI7uKqZNtLb449gwKqXjIsnRk= github.com/ipfs/go-ipfs-chunker v0.0.1 h1:cHUUxKFQ99pozdahi+uSC/3Y6HeRpi9oTeUHbE27SEw= github.com/ipfs/go-ipfs-chunker v0.0.1/go.mod h1:tWewYK0we3+rMbOh7pPFGDyypCtvGcBFymgY4rSDLAw= -github.com/ipfs/go-ipfs-chunker v0.0.4 h1:nb2ZIgtOk0TxJ5KDBEk+sv6iqJTF/PHg6owN2xCrUjE= -github.com/ipfs/go-ipfs-chunker v0.0.4/go.mod h1:jhgdF8vxRHycr00k13FM8Y0E+6BoalYeobXmUyTreP8= +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.1.4 h1:l5QAc1iaoMZeBd2vpanrHWs26haEBL4PVqgoHJNG2GE= github.com/ipfs/go-ipfs-cmds v0.1.4/go.mod h1:wm+C6M8FYDcWPU/EdWqMuHvdyWborFh+GuDl6Ov6sM0= github.com/ipfs/go-ipfs-config v0.3.0 h1:fGs3JBqB9ia/Joi8up47uiKn150EOEqqVFwv8HZqXao= From 37f38de6141aa20259cb82c28f07966fd82bf241 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 27 Mar 2020 11:30:20 +0000 Subject: [PATCH 520/671] chore(deps): bump github.com/libp2p/go-libp2p-yamux from 0.2.5 to 0.2.6 Bumps [github.com/libp2p/go-libp2p-yamux](https://github.com/libp2p/go-libp2p-yamux) from 0.2.5 to 0.2.6. - [Release notes](https://github.com/libp2p/go-libp2p-yamux/releases) - [Commits](https://github.com/libp2p/go-libp2p-yamux/compare/v0.2.5...v0.2.6) Signed-off-by: dependabot-preview[bot] --- go.mod | 2 +- go.sum | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 2034488a54a..0d9e1849147 100644 --- a/go.mod +++ b/go.mod @@ -79,7 +79,7 @@ require ( github.com/libp2p/go-libp2p-swarm v0.2.2 github.com/libp2p/go-libp2p-testing v0.1.1 github.com/libp2p/go-libp2p-tls v0.1.3 - github.com/libp2p/go-libp2p-yamux v0.2.5 + github.com/libp2p/go-libp2p-yamux v0.2.6 github.com/libp2p/go-maddr-filter v0.0.5 github.com/libp2p/go-socket-activation v0.0.2 github.com/mattn/go-runewidth v0.0.8 // indirect diff --git a/go.sum b/go.sum index 7bda142644c..84613423761 100644 --- a/go.sum +++ b/go.sum @@ -625,6 +625,8 @@ github.com/libp2p/go-libp2p-yamux v0.2.2 h1:eGvbqWqWY9S5lrpe2gA0UCOLCdzCgYSAR3vo github.com/libp2p/go-libp2p-yamux v0.2.2/go.mod h1:lIohaR0pT6mOt0AZ0L2dFze9hds9Req3OfS+B+dv4qw= github.com/libp2p/go-libp2p-yamux v0.2.5 h1:MuyItOqz03oi8npvjgMJxgnhllJLZnO/dKVOpTZ9+XI= github.com/libp2p/go-libp2p-yamux v0.2.5/go.mod h1:Zpgj6arbyQrmZ3wxSZxfBmbdnWtbZ48OpsfmQVTErwA= +github.com/libp2p/go-libp2p-yamux v0.2.6 h1:BXl4fEzzZwLUjoqoRJNx4co1UhvOwXaM+Qg2twEqEFU= +github.com/libp2p/go-libp2p-yamux v0.2.6/go.mod h1:YbnSVt8RYb3t6YBGPD9rLUT0vmmvcr/waaQ79PINpOM= github.com/libp2p/go-maddr-filter v0.0.1/go.mod h1:6eT12kSQMA9x2pvFQa+xesMKUBlj9VImZbj3B9FBH/Q= github.com/libp2p/go-maddr-filter v0.0.4/go.mod h1:6eT12kSQMA9x2pvFQa+xesMKUBlj9VImZbj3B9FBH/Q= github.com/libp2p/go-maddr-filter v0.0.5 h1:CW3AgbMO6vUvT4kf87y4N+0P8KUl2aqLYhrGyDUbLSg= @@ -683,6 +685,8 @@ github.com/libp2p/go-yamux v1.3.0 h1:FsYzT16Wq2XqUGJsBbOxoz9g+dFklvNi7jN6YFPfl7U github.com/libp2p/go-yamux v1.3.0/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= github.com/libp2p/go-yamux v1.3.3 h1:mWuzZRCAeTBFdynLlsYgA/EIeMOLr8XY04wa52NRhsE= github.com/libp2p/go-yamux v1.3.3/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= +github.com/libp2p/go-yamux v1.3.4 h1:CptmtNfQomI9RpM7LFJhVBFkwp2zwEXIskEfWwwtoHg= +github.com/libp2p/go-yamux v1.3.4/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= github.com/lucas-clemente/quic-go v0.15.2 h1:RgxRJ7rPde0Q/uXDeb3/UdblVvxrYGDAG9G9GO78LmI= github.com/lucas-clemente/quic-go v0.15.2/go.mod h1:qxmO5Y4ZMhdNkunGfxuZnZXnJwYpW9vjQkyrZ7BsgUI= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= From 56550c1b6104dd073d405c1a021a6b552bb58e34 Mon Sep 17 00:00:00 2001 From: Hector Sanjuan Date: Fri, 27 Mar 2020 12:57:53 +0100 Subject: [PATCH 521/671] keystore: Switch from Bytes() to MarshalPrivateKey() Bytes is deprecated. --- keystore/keystore.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/keystore/keystore.go b/keystore/keystore.go index a52b4ad1711..ed83c17e6a8 100644 --- a/keystore/keystore.go +++ b/keystore/keystore.go @@ -81,7 +81,7 @@ func (ks *FSKeystore) Put(name string, k ci.PrivKey) error { return err } - b, err := k.Bytes() + b, err := ci.MarshalPrivateKey(k) if err != nil { return err } From 4a7373bc6ac04cc552023d99b9a0c03bd2d677ab Mon Sep 17 00:00:00 2001 From: Hector Sanjuan Date: Fri, 27 Mar 2020 12:59:10 +0100 Subject: [PATCH 522/671] keystore: create new keys with 0400 permissions (as spec'ed) Spec is pretty much out of date but specifies this. https://github.com/ipfs/specs/blob/master/KEYSTORE.md --- keystore/keystore.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/keystore/keystore.go b/keystore/keystore.go index ed83c17e6a8..0a2fed3bfc6 100644 --- a/keystore/keystore.go +++ b/keystore/keystore.go @@ -88,7 +88,7 @@ func (ks *FSKeystore) Put(name string, k ci.PrivKey) error { kp := filepath.Join(ks.dir, name) - fi, err := os.OpenFile(kp, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0600) + fi, err := os.OpenFile(kp, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0400) if err != nil { if os.IsExist(err) { err = ErrKeyExists From 5d6d289ce8e001a4f33b5b791d64eb648adba601 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Fri, 27 Mar 2020 09:32:22 -0700 Subject: [PATCH 523/671] chore: update golang --- .circleci/config.yml | 4 ++-- Dockerfile | 2 +- mk/golang.mk | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 368359faac8..0c8fc874e3a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -33,7 +33,7 @@ default_environment: &default_environment executors: golang: docker: - - image: circleci/golang:1.14 + - image: circleci/golang:1.14.1 working_directory: ~/ipfs/go-ipfs environment: <<: *default_environment @@ -60,7 +60,7 @@ executors: E2E_IPFSD_TYPE: go dockerizer: docker: - - image: circleci/golang:1.14 + - image: circleci/golang:1.14.1 environment: IMAGE_NAME: ipfs/go-ipfs WIP_IMAGE_TAG: wip diff --git a/Dockerfile b/Dockerfile index 823d743db02..fdbbff88390 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.14-buster +FROM golang:1.14.1-buster LABEL maintainer="Steven Allen " # Install deps diff --git a/mk/golang.mk b/mk/golang.mk index 0aff6c12a6a..f6a007be792 100644 --- a/mk/golang.mk +++ b/mk/golang.mk @@ -1,5 +1,5 @@ # golang utilities -GO_MIN_VERSION = 1.14 +GO_MIN_VERSION = 1.14.1 export GO111MODULE=on From c18b3dafa04933513e00932e12979ea7f9eef8d2 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Sat, 28 Mar 2020 03:37:07 +0000 Subject: [PATCH 524/671] chore(deps): bump github.com/libp2p/go-libp2p from 0.7.1 to 0.7.2 Bumps [github.com/libp2p/go-libp2p](https://github.com/libp2p/go-libp2p) from 0.7.1 to 0.7.2. - [Release notes](https://github.com/libp2p/go-libp2p/releases) - [Changelog](https://github.com/libp2p/go-libp2p/blob/master/NEWS.md) - [Commits](https://github.com/libp2p/go-libp2p/compare/v0.7.1...v0.7.2) Signed-off-by: dependabot-preview[bot] --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 0d9e1849147..68031e75c0a 100644 --- a/go.mod +++ b/go.mod @@ -59,7 +59,7 @@ require ( github.com/jbenet/go-temp-err-catcher v0.1.0 github.com/jbenet/goprocess v0.1.4 github.com/libp2p/go-eventbus v0.1.0 - github.com/libp2p/go-libp2p v0.7.1 + github.com/libp2p/go-libp2p v0.7.2 github.com/libp2p/go-libp2p-circuit v0.1.4 github.com/libp2p/go-libp2p-connmgr v0.2.1 github.com/libp2p/go-libp2p-core v0.5.0 diff --git a/go.sum b/go.sum index 84613423761..1c7f9005bd2 100644 --- a/go.sum +++ b/go.sum @@ -461,6 +461,8 @@ github.com/libp2p/go-libp2p v0.7.0 h1:qWmciout2lJclKfRlxqdepsQB7JihcbRhgcRcssP4r github.com/libp2p/go-libp2p v0.7.0/go.mod h1:hZJf8txWeCduQRDC/WSqBGMxaTHCOYHt2xSU1ivxn0k= github.com/libp2p/go-libp2p v0.7.1 h1:53lYHjkvB61SebIAMvVfJXYe21B1WEQ7rAKfblyLa7Q= github.com/libp2p/go-libp2p v0.7.1/go.mod h1:f59Ddl3ofgyGdnhDCAjijcdCSuPY/wuvWDDt+grdfcI= +github.com/libp2p/go-libp2p v0.7.2 h1:f/HIWCgllub8g+Q3qhoirPUxCUDefaRjwjb6NBX5Xgw= +github.com/libp2p/go-libp2p v0.7.2/go.mod h1:ww6NouoEEIosjJ2LTXAhgtxuoY+1KWLEBlMqx2g+qj4= 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 h1:aCWAu43Ri4nU0ZPO7NyLzUvvfqd0nE3dX0R/ZGYVgOU= From 88bc8362a0ef8cf5ff512b97b3be6f11e721009e Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Sat, 28 Mar 2020 03:37:46 +0000 Subject: [PATCH 525/671] chore(deps): bump github.com/ipfs/go-ds-badger from 0.2.1 to 0.2.2 Bumps [github.com/ipfs/go-ds-badger](https://github.com/ipfs/go-ds-badger) from 0.2.1 to 0.2.2. - [Release notes](https://github.com/ipfs/go-ds-badger/releases) - [Commits](https://github.com/ipfs/go-ds-badger/compare/v0.2.1...v0.2.2) Signed-off-by: dependabot-preview[bot] --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 0d9e1849147..6d2913b6d75 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/ipfs/go-cidutil v0.0.2 github.com/ipfs/go-datastore v0.4.4 github.com/ipfs/go-detect-race v0.0.1 - github.com/ipfs/go-ds-badger v0.2.1 + github.com/ipfs/go-ds-badger v0.2.2 github.com/ipfs/go-ds-flatfs v0.4.0 github.com/ipfs/go-ds-leveldb v0.4.2 github.com/ipfs/go-ds-measure v0.1.0 diff --git a/go.sum b/go.sum index 84613423761..7a85885fbaa 100644 --- a/go.sum +++ b/go.sum @@ -245,6 +245,8 @@ github.com/ipfs/go-ds-badger v0.0.7 h1:NMyh88Q50HG6/S2YD58DLkq0c0/ZQPMbSojONH+PR github.com/ipfs/go-ds-badger v0.0.7/go.mod h1:qt0/fWzZDoPW6jpQeqUjR5kBfhDNB65jd9YlmAvpQBk= github.com/ipfs/go-ds-badger v0.2.1 h1:RsC9DDlwFhFdfT+s2PeC8joxbSp2YMufK8w/RBOxKtk= github.com/ipfs/go-ds-badger v0.2.1/go.mod h1:Tx7l3aTph3FMFrRS838dcSJh+jjA7cX9DrGVwx/NOwE= +github.com/ipfs/go-ds-badger v0.2.2 h1:Fvrep6Tbv/9hYkrMkavCmG03DJToySZ4x7HbAdfT4q8= +github.com/ipfs/go-ds-badger v0.2.2/go.mod h1:LIt1qUJF+Q6dEJI3f4/fJZUPdo6GoC6geFQkag32X8w= github.com/ipfs/go-ds-flatfs v0.4.0 h1:bmC3y4a2xvUXAYNjqXzI4QcnArBHov4ztGzeEKLMrS8= github.com/ipfs/go-ds-flatfs v0.4.0/go.mod h1:lrIyxYXO3yXdp+TnpB8jpdzYRxopDGVPLIGorjSZyxM= github.com/ipfs/go-ds-leveldb v0.0.1/go.mod h1:feO8V3kubwsEF22n0YRQCffeb79OOYIykR4L04tMOYc= From 968e70f1e27f79b55d13fc68b389e231b5c9612b Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Sun, 29 Mar 2020 18:41:47 -0700 Subject: [PATCH 526/671] fix: downgrade to go 1.13 Go 1.14 has a timer reset deadlock (https://github.com/golang/go/issues/38070). This also downgrades quic-go until either a go patch release fixes this issue or a version of quic-go is released that works with go 1.13. --- .circleci/config.yml | 4 +- Dockerfile | 2 +- go.mod | 2 +- go.sum | 136 ++++--------------------------------------- mk/golang.mk | 2 +- 5 files changed, 15 insertions(+), 131 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0c8fc874e3a..aa46ebca8e3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -33,7 +33,7 @@ default_environment: &default_environment executors: golang: docker: - - image: circleci/golang:1.14.1 + - image: circleci/golang:1.13.8 working_directory: ~/ipfs/go-ipfs environment: <<: *default_environment @@ -60,7 +60,7 @@ executors: E2E_IPFSD_TYPE: go dockerizer: docker: - - image: circleci/golang:1.14.1 + - image: circleci/golang:1.13.8 environment: IMAGE_NAME: ipfs/go-ipfs WIP_IMAGE_TAG: wip diff --git a/Dockerfile b/Dockerfile index fdbbff88390..c3ac30cc769 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.14.1-buster +FROM golang:1.13.8-buster LABEL maintainer="Steven Allen " # Install deps diff --git a/go.mod b/go.mod index d59b459bffc..ae15a374c4c 100644 --- a/go.mod +++ b/go.mod @@ -72,7 +72,7 @@ require ( github.com/libp2p/go-libp2p-peerstore v0.2.1 github.com/libp2p/go-libp2p-pubsub v0.2.6 github.com/libp2p/go-libp2p-pubsub-router v0.2.1 - github.com/libp2p/go-libp2p-quic-transport v0.3.1 + github.com/libp2p/go-libp2p-quic-transport v0.2.4-0.20200228032821-6d8b0e775c52 github.com/libp2p/go-libp2p-record v0.1.2 github.com/libp2p/go-libp2p-routing-helpers v0.1.0 github.com/libp2p/go-libp2p-secio v0.2.1 diff --git a/go.sum b/go.sum index b75009ff62a..ddb827ae85e 100644 --- a/go.sum +++ b/go.sum @@ -1,14 +1,6 @@ bazil.org/fuse v0.0.0-20200117225306-7b5117fecadc h1:utDghgcjE8u+EBjHOgYT+dJPcnDF05KqWMBcjuJy510= bazil.org/fuse v0.0.0-20200117225306-7b5117fecadc/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo= -dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= -dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= -dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= -dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= -git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIoKjsnZuH8vjyaysT/ses3EvZeaV/1UkF2M= @@ -27,7 +19,6 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -35,7 +26,6 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= -github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= github.com/bren2010/proquint v0.0.0-20160323162903-38337c27106d h1:QgeLLoPD3kRVmeu/1al9iIpIANMi9O1zXFm8BnYGCJg= github.com/bren2010/proquint v0.0.0-20160323162903-38337c27106d/go.mod h1:Jbj8eKecMNwf0KFI75skSUZqMB4UCRcndUScVBTWyUI= github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= @@ -54,7 +44,6 @@ github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVa github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= -github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= @@ -68,8 +57,6 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee github.com/coreos/go-semver v0.2.1-0.20180108230905-e214231b295a/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d h1:t5Wuyh53qYyg9eqn4BbnlIT+vmhyww0TatL+zT3uWgI= -github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.0.0 h1:XJIw/+VlJ+87J+doOxznsAWIdmWuViOVhkQamW5YV28= github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= @@ -100,20 +87,14 @@ github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5/go.mod h1:Jp github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fd/go-nat v1.0.0/go.mod h1:BTBu/CKvMmOMUPkKVef1pngt2WFH/lg7E6yQnulfp6E= -github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= -github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= -github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-bindata/go-bindata/v3 v3.1.3 h1:F0nVttLC3ws0ojc7p60veTurcOm//D4QBODNM7EGrCI= github.com/go-bindata/go-bindata/v3 v3.1.3/go.mod h1:1/zrpXsLD8YDIbhZRqXzm1Ghc7NhEvIN9+Z6R5/xH4I= github.com/go-check/check v0.0.0-20180628173108-788fd7840127 h1:0gkP6mzaMqkmpcJYCFOLkIBwI7xFExG03bbkOkCvUPI= github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= -github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= @@ -129,12 +110,9 @@ github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.4.0 h1:Rd1kQnQu0Hq3qvJppYSG0HtP+f5LPPUiDswTLiEegLg= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -142,7 +120,6 @@ github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -150,24 +127,16 @@ github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= -github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= -github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c h1:7lF+Vz0LqiRidnzC1Oq86fpX1q/iEv2KJdrCtttYjT4= github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU= github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= github.com/gxed/pubsub v0.0.0-20180201040156-26ebdf44f824/go.mod h1:OiEWyHgK+CWrmOlVquHaIK1vhpUJydC9m0Je6mhaiNE= @@ -399,13 +368,11 @@ github.com/jbenet/goprocess v0.1.3 h1:YKyIEECS/XvcfHtBzxtjBBbWK+MbvA6dG8ASiqwvr1 github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0o= github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= -github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= @@ -425,7 +392,6 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/libp2p/go-addr-util v0.0.1 h1:TpTQm9cXVRVSKsYbgQ7GKc3KbbHVTnbostgGaDEP+88= @@ -461,8 +427,6 @@ github.com/libp2p/go-libp2p v0.6.1 h1:mxabyJf4l6AmotDOKObwSfBNBWjL5VYXysVFLUMAuB github.com/libp2p/go-libp2p v0.6.1/go.mod h1:CTFnWXogryAHjXAKEbOf1OWY+VeAP3lDMZkfEI5sT54= github.com/libp2p/go-libp2p v0.7.0 h1:qWmciout2lJclKfRlxqdepsQB7JihcbRhgcRcssP4rc= github.com/libp2p/go-libp2p v0.7.0/go.mod h1:hZJf8txWeCduQRDC/WSqBGMxaTHCOYHt2xSU1ivxn0k= -github.com/libp2p/go-libp2p v0.7.1 h1:53lYHjkvB61SebIAMvVfJXYe21B1WEQ7rAKfblyLa7Q= -github.com/libp2p/go-libp2p v0.7.1/go.mod h1:f59Ddl3ofgyGdnhDCAjijcdCSuPY/wuvWDDt+grdfcI= github.com/libp2p/go-libp2p v0.7.2 h1:f/HIWCgllub8g+Q3qhoirPUxCUDefaRjwjb6NBX5Xgw= github.com/libp2p/go-libp2p v0.7.2/go.mod h1:ww6NouoEEIosjJ2LTXAhgtxuoY+1KWLEBlMqx2g+qj4= github.com/libp2p/go-libp2p-autonat v0.0.2/go.mod h1:fs71q5Xk+pdnKU014o2iq1RhMs9/PMaG5zXRFNnIIT4= @@ -576,8 +540,8 @@ github.com/libp2p/go-libp2p-pubsub v0.2.6 h1:ypZaukCFrtD8cNeeb9nnWG4MD2Y1T0p22aQ github.com/libp2p/go-libp2p-pubsub v0.2.6/go.mod h1:5jEp7R3ItQ0pgcEMrPZYE9DQTg/H3CTc7Mu1j2G4Y5o= github.com/libp2p/go-libp2p-pubsub-router v0.2.1 h1:F5JYaHQuuMKVbSgLsH2POQwT1rloWpc7fUCOq6PBjyE= github.com/libp2p/go-libp2p-pubsub-router v0.2.1/go.mod h1:cl46APmxgKgzgpCGFb8Ns7++cqnJ29CxESXCQATp55k= -github.com/libp2p/go-libp2p-quic-transport v0.3.1 h1:pd5LOTwY4czSoqtM+V/arYpzq54s/3QQaZDNWE+ZG08= -github.com/libp2p/go-libp2p-quic-transport v0.3.1/go.mod h1:yrvHJhwab6vjeJGf6tW0wvEsXBaPUjpz7Qh9upS7TbQ= +github.com/libp2p/go-libp2p-quic-transport v0.2.4-0.20200228032821-6d8b0e775c52 h1:2rpnIL9nXtYVX17Z4mjZYghCRcuU41bdVcBHeEEOoHA= +github.com/libp2p/go-libp2p-quic-transport v0.2.4-0.20200228032821-6d8b0e775c52/go.mod h1:X6hcn1DQ72RXa/LSWTSoWyCc30beTpHdjoiEkI5Ls20= github.com/libp2p/go-libp2p-record v0.0.1/go.mod h1:grzqg263Rug/sRex85QrDOLntdFAymLDLm7lxMgU79Q= github.com/libp2p/go-libp2p-record v0.1.0/go.mod h1:ujNc8iuE5dlKWVy6wuL6dd58t0n7xI4hAIl8pE6wu5Q= github.com/libp2p/go-libp2p-record v0.1.2 h1:M50VKzWnmUrk/M5/Dz99qO9Xh4vs8ijsK+7HkJvRP+0= @@ -691,17 +655,16 @@ github.com/libp2p/go-yamux v1.3.3 h1:mWuzZRCAeTBFdynLlsYgA/EIeMOLr8XY04wa52NRhsE github.com/libp2p/go-yamux v1.3.3/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= github.com/libp2p/go-yamux v1.3.4 h1:CptmtNfQomI9RpM7LFJhVBFkwp2zwEXIskEfWwwtoHg= github.com/libp2p/go-yamux v1.3.4/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= -github.com/lucas-clemente/quic-go v0.15.2 h1:RgxRJ7rPde0Q/uXDeb3/UdblVvxrYGDAG9G9GO78LmI= -github.com/lucas-clemente/quic-go v0.15.2/go.mod h1:qxmO5Y4ZMhdNkunGfxuZnZXnJwYpW9vjQkyrZ7BsgUI= -github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= +github.com/lucas-clemente/quic-go v0.14.4 h1:LdXgELrB93kvTqbZyEf+mcsGvmyE+EHsLFz1dqbR5PI= +github.com/lucas-clemente/quic-go v0.14.4/go.mod h1:Vn3/Fb0/77b02SGhQk36KzOUmXgVpFfizUfW5WMaqyU= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329 h1:2gxZ0XQIU/5z3Z3bUBu+FXuk2pFbkN6tcwi/pjyaDic= github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe h1:W/GaMY0y69G4cFlmsC6B9sbuo2fP8OFP1ABjt4kPz+w= -github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/marten-seemann/chacha20 v0.2.0 h1:f40vqzzx+3GdOmzQoItkLX5WLvHgPgyYqFFIO5Gh4hQ= +github.com/marten-seemann/chacha20 v0.2.0/go.mod h1:HSdjFau7GzYRj+ahFNwsO3ouVJr1HFkWoEwNDb4TMtE= github.com/marten-seemann/qpack v0.1.0/go.mod h1:LFt1NU/Ptjip0C2CPkhimBz5CGE3WGDAUWqna+CNTrI= -github.com/marten-seemann/qtls v0.8.0 h1:aj+MPLibzKByw8CmG0WvWgbtBkctYPAXeB11cQJC8mo= -github.com/marten-seemann/qtls v0.8.0/go.mod h1:Lao6jDqlCfxyLKYFmZXGm2LSHBgVn+P+ROOex6YkT+k= +github.com/marten-seemann/qtls v0.4.1 h1:YlT8QP3WCCvvok7MGEZkMldXbyqgr8oFg5/n8Gtbkks= +github.com/marten-seemann/qtls v0.4.1/go.mod h1:pxVXcHHw1pNIt8Qo0pwSYQEoZ8yYOOPXTCZLQQunvRc= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= @@ -720,7 +683,6 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0j github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= -github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= github.com/miekg/dns v1.1.4/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.12 h1:WMhc1ik4LNkTg8U9l3hI1LvxKmIL+f1+WV/SZtCbDDA= github.com/miekg/dns v1.1.12/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= @@ -802,28 +764,21 @@ github.com/multiformats/go-varint v0.0.2/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXS github.com/multiformats/go-varint v0.0.5 h1:XVZwSo04Cs3j/jS0uAEPpT3JY6DzMcVLLoWOSnCxOjg= github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= -github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw= -github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU= github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.8.1 h1:C5Dqfs/LeauYDX0jJXIe2SWmwCbGzx9yF8C8xy3Lh34= -github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.9.0 h1:R1uwffexN6Pr340GtYRIdZmAiN4J+iw6WG4wog1DUXg= github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= @@ -835,7 +790,6 @@ 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 h1:2m16U/rLwVaRdz7ANkHtHTodP3zTP3N451MADg64x5k= github.com/polydawn/refmt v0.0.0-20190408063855-01bf1e26dd14/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= -github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= @@ -846,12 +800,10 @@ github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1 h1:KOMtN28tlbam3/7ZKEYKHhKoJZYYj3gMH4uc62x7X7U= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= @@ -861,29 +813,6 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= -github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= -github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= -github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= -github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= -github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw= -github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI= -github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU= -github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag= -github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg= -github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw= -github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y= -github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= -github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q= -github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ= -github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I= -github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0= -github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ= -github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk= -github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4= -github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= @@ -896,8 +825,6 @@ github.com/smartystreets/goconvey v0.0.0-20190710185942-9d28bd7c0945 h1:N8Bg45zp github.com/smartystreets/goconvey v0.0.0-20190710185942-9d28bd7c0945/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smola/gocompat v0.2.0 h1:6b1oIMlUXIpz//VKEDzPVBK8KG7beVwmHIUEBIs/Pns= github.com/smola/gocompat v0.2.0/go.mod h1:1B0MlxbmoZNo3h8guHp8HztB3BSYR5itql9qtVc0ypY= -github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= -github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= @@ -922,14 +849,11 @@ github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= -github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e h1:T5PdfK/M1xyrHwynxMIVMWLS7f/qHwfslZphxtGnw7s= github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e/go.mod h1:XDKHRm5ThF8YJjx001LtgelzsoaEcvnA7lVWz9EeX3g= github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c h1:u6SKchux2yDvFQnDHS3lPnIRmfVJ5Sxy3ao2SIdysLQ= github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= -github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k= @@ -971,7 +895,6 @@ github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee/go.mod h1: github.com/whyrusleeping/yamux v1.1.5/go.mod h1:E8LnQQ8HKx5KD29HZFUwM1PxCOdPRzGwur1mcYhXcD8= github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.1 h1:8dP3SGL7MPB94crU3bEPplMPe83FI4EouesJUeFHv50= @@ -1006,19 +929,15 @@ go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.14.1 h1:nYDKopTbvAPq/NrUVZwT15y2lpROBiLLyoRTbXOYWOo= go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= -go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= go4.org v0.0.0-20200104003542-c7e774b10ea0 h1:M6XsnQeLwG+rHQ+/rrGh3puBI3WZEy9TBWmf2H+enQA= go4.org v0.0.0-20200104003542-c7e774b10ea0/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= -golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -1026,6 +945,7 @@ golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -1034,7 +954,6 @@ golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 h1:3zb4D3T4G8jdExgVU/95+vQXfpEPiMdCaZgmGVxjNHM= golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -1049,16 +968,12 @@ golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190228165749-92fc7df08ae7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= @@ -1071,10 +986,6 @@ golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1086,7 +997,6 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1094,7 +1004,6 @@ golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190302025703-b6889370fb10/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1105,6 +1014,7 @@ golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190610200419-93c9922d18ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1117,17 +1027,11 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepx golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181130052023-1c3d964395ce/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1135,7 +1039,6 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384 h1:TFlARGu6Czu1z7q93HTxcP1P+/ZFC/IKythI5RzrnRg= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1153,23 +1056,12 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbO golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= -google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= -google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= -google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= @@ -1183,7 +1075,6 @@ gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qS gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVYcSwSjGebuDL6176A1XskgbtNl64NSg+n8= gopkg.in/src-d/go-log.v1 v1.0.1/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= @@ -1194,13 +1085,6 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5 h1:ymVxjfMaHvXD8RqPRmzHHsB3VvucivSkIAvJFDI5O3c= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= -honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= -sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= diff --git a/mk/golang.mk b/mk/golang.mk index f6a007be792..5634c1d6b5f 100644 --- a/mk/golang.mk +++ b/mk/golang.mk @@ -1,5 +1,5 @@ # golang utilities -GO_MIN_VERSION = 1.14.1 +GO_MIN_VERSION = 1.13.8 export GO111MODULE=on From f28b8fce66ea127ddca6b10679cfd466438b5a3d Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Sun, 29 Mar 2020 18:58:54 -0700 Subject: [PATCH 527/671] feat: tls by default Switches to TLS as the default security transports. --- core/node/groups.go | 2 +- core/node/libp2p/transport.go | 8 ++----- .../library-experimental-features/README.md | 2 -- docs/experimental-features.md | 22 +++++-------------- go.mod | 2 +- go.sum | 4 ++-- 6 files changed, 11 insertions(+), 29 deletions(-) diff --git a/core/node/groups.go b/core/node/groups.go index 5cd3a84b176..5b5c8476abe 100644 --- a/core/node/groups.go +++ b/core/node/groups.go @@ -102,7 +102,7 @@ func LibP2P(bcfg *BuildCfg, cfg *config.Config) fx.Option { fx.Invoke(libp2p.StartListening(cfg.Addresses.Swarm)), fx.Invoke(libp2p.SetupDiscovery(cfg.Discovery.MDNS.Enabled, cfg.Discovery.MDNS.Interval)), - fx.Provide(libp2p.Security(!bcfg.DisableEncryptedConnections, cfg.Experimental.PreferTLS)), + fx.Provide(libp2p.Security(!bcfg.DisableEncryptedConnections)), fx.Provide(libp2p.Routing), fx.Provide(libp2p.BaseRouting), diff --git a/core/node/libp2p/transport.go b/core/node/libp2p/transport.go index 33465a18381..3994da5c521 100644 --- a/core/node/libp2p/transport.go +++ b/core/node/libp2p/transport.go @@ -11,7 +11,7 @@ import ( var DefaultTransports = simpleOpt(libp2p.DefaultTransports) var QUIC = simpleOpt(libp2p.Transport(libp2pquic.NewTransport)) -func Security(enabled, preferTLS bool) interface{} { +func Security(enabled bool) interface{} { if !enabled { return func() (opts Libp2pOpts) { // TODO: shouldn't this be Errorf to guarantee visibility? @@ -22,11 +22,7 @@ func Security(enabled, preferTLS bool) interface{} { } } return func() (opts Libp2pOpts) { - if preferTLS { - opts.Opts = append(opts.Opts, libp2p.ChainOptions(libp2p.Security(tls.ID, tls.New), libp2p.Security(secio.ID, secio.New))) - } else { - opts.Opts = append(opts.Opts, libp2p.ChainOptions(libp2p.Security(secio.ID, secio.New), libp2p.Security(tls.ID, tls.New))) - } + opts.Opts = append(opts.Opts, libp2p.ChainOptions(libp2p.Security(tls.ID, tls.New), libp2p.Security(secio.ID, secio.New))) return opts } } diff --git a/docs/examples/library-experimental-features/README.md b/docs/examples/library-experimental-features/README.md index 2f50d024d79..6387f3618a9 100644 --- a/docs/examples/library-experimental-features/README.md +++ b/docs/examples/library-experimental-features/README.md @@ -58,8 +58,6 @@ func createTempRepo(ctx context.Context) (string, error) { cfg.Experimental.P2pHttpProxy = true // https://github.com/ipfs/go-ipfs/blob/master/docs/experimental-features.md#quic cfg.Experimental.QUIC = true - // https://github.com/ipfs/go-ipfs/blob/master/docs/experimental-features.md#tls-13-as-default-handshake-protocol - cfg.Experimental.PreferTLS = true // https://github.com/ipfs/go-ipfs/blob/master/docs/experimental-features.md#strategic-providing cfg.Experimental.StrategicProviding = true diff --git a/docs/experimental-features.md b/docs/experimental-features.md index 6055f813cc8..64aa3b7c071 100644 --- a/docs/experimental-features.md +++ b/docs/experimental-features.md @@ -632,7 +632,7 @@ For listening on a QUIC address, add it the swarm addresses, e.g. `/ip4/0.0.0.0/ ### In Version -0.4.19-dev +0.4.19 ### State @@ -660,26 +660,14 @@ ipfs config --json Swarm.EnableAutoNATService true ## TLS 1.3 as default handshake protocol -### State - -Every go-ipfs node (>=0.4.21) accepts secio and TLS 1.3 connections but prefers -secio over TLS when dialing. To prefer TLS when dialing, you'll have to enable -this feature. - -### How to enable +### In Version -Modify your ipfs config: +0.5.0 -``` -ipfs config --json Experimental.PreferTLS true -``` - -### Road to being a real feature +### State -- [ ] needs testing -- [ ] needs adoption +Stable ---- ## Strategic Providing diff --git a/go.mod b/go.mod index ae15a374c4c..532bcc865dd 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,7 @@ require ( github.com/ipfs/go-ipfs-blockstore v0.1.4 github.com/ipfs/go-ipfs-chunker v0.0.5 github.com/ipfs/go-ipfs-cmds v0.1.4 - github.com/ipfs/go-ipfs-config v0.3.0 + github.com/ipfs/go-ipfs-config v0.4.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 diff --git a/go.sum b/go.sum index ddb827ae85e..512a1c48877 100644 --- a/go.sum +++ b/go.sum @@ -246,8 +246,8 @@ github.com/ipfs/go-ipfs-chunker v0.0.5 h1:ojCf7HV/m+uS2vhUGWcogIIxiO5ubl5O57Q7Na github.com/ipfs/go-ipfs-chunker v0.0.5/go.mod h1:jhgdF8vxRHycr00k13FM8Y0E+6BoalYeobXmUyTreP8= github.com/ipfs/go-ipfs-cmds v0.1.4 h1:l5QAc1iaoMZeBd2vpanrHWs26haEBL4PVqgoHJNG2GE= github.com/ipfs/go-ipfs-cmds v0.1.4/go.mod h1:wm+C6M8FYDcWPU/EdWqMuHvdyWborFh+GuDl6Ov6sM0= -github.com/ipfs/go-ipfs-config v0.3.0 h1:fGs3JBqB9ia/Joi8up47uiKn150EOEqqVFwv8HZqXao= -github.com/ipfs/go-ipfs-config v0.3.0/go.mod h1:nSLCFtlaL+2rbl3F+9D4gQZQbT1LjRKx7TJg/IHz6oM= +github.com/ipfs/go-ipfs-config v0.4.0 h1:MOXdj8EYQG55v1y+5e1QcctDKPEGobdwnXaDVa0/cc0= +github.com/ipfs/go-ipfs-config v0.4.0/go.mod h1:nSLCFtlaL+2rbl3F+9D4gQZQbT1LjRKx7TJg/IHz6oM= github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= github.com/ipfs/go-ipfs-delay v0.0.1 h1:r/UXYyRcddO6thwOnhiznIAiSvxMECGgtv35Xs1IeRQ= github.com/ipfs/go-ipfs-delay v0.0.1/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= From 2f565f1723c77a055651a51f7fe4eec901211f53 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2020 02:35:24 +0000 Subject: [PATCH 528/671] chore(deps): bump github.com/ipfs/go-ipfs-files from 0.0.7 to 0.0.8 Bumps [github.com/ipfs/go-ipfs-files](https://github.com/ipfs/go-ipfs-files) from 0.0.7 to 0.0.8. - [Release notes](https://github.com/ipfs/go-ipfs-files/releases) - [Commits](https://github.com/ipfs/go-ipfs-files/compare/v0.0.7...v0.0.8) Signed-off-by: dependabot-preview[bot] --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 532bcc865dd..19ef54f290f 100644 --- a/go.mod +++ b/go.mod @@ -35,7 +35,7 @@ require ( 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.7 + github.com/ipfs/go-ipfs-files v0.0.8 github.com/ipfs/go-ipfs-pinner v0.0.4 github.com/ipfs/go-ipfs-posinfo v0.0.1 github.com/ipfs/go-ipfs-provider v0.4.1 diff --git a/go.sum b/go.sum index 512a1c48877..d7dffc476c6 100644 --- a/go.sum +++ b/go.sum @@ -264,6 +264,8 @@ github.com/ipfs/go-ipfs-files v0.0.3/go.mod h1:INEFm0LL2LWXBhNJ2PMIIb2w45hpXgPjN github.com/ipfs/go-ipfs-files v0.0.4/go.mod h1:INEFm0LL2LWXBhNJ2PMIIb2w45hpXgPjNoE7yA8Y1d4= github.com/ipfs/go-ipfs-files v0.0.7 h1:s5BRD12ndahqYifeH1S8Z73zqZhR+3IdKYAG9PiETs0= github.com/ipfs/go-ipfs-files v0.0.7/go.mod h1:wiN/jSG8FKyk7N0WyctKSvq3ljIa2NNTiZB55kpTdOs= +github.com/ipfs/go-ipfs-files v0.0.8 h1:8o0oFJkJ8UkO/ABl8T6ac6tKF3+NIpj67aAB6ZpusRg= +github.com/ipfs/go-ipfs-files v0.0.8/go.mod h1:wiN/jSG8FKyk7N0WyctKSvq3ljIa2NNTiZB55kpTdOs= github.com/ipfs/go-ipfs-flags v0.0.1/go.mod h1:RnXBb9WV53GSfTrSDVK61NLTFKvWc60n+K9EgCDh+rA= github.com/ipfs/go-ipfs-pinner v0.0.4 h1:EmxhS3vDsCK/rZrsgxX0Le9m2drBcGlUd7ah/VyFYVE= github.com/ipfs/go-ipfs-pinner v0.0.4/go.mod h1:s4kFZWLWGDudN8Jyd/GTpt222A12C2snA2+OTdy/7p8= From 8531b242c3d2dd5c746cb47549b7f973340ebee1 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2020 02:36:03 +0000 Subject: [PATCH 529/671] chore(deps): bump github.com/libp2p/go-libp2p-peerstore Bumps [github.com/libp2p/go-libp2p-peerstore](https://github.com/libp2p/go-libp2p-peerstore) from 0.2.1 to 0.2.2. - [Release notes](https://github.com/libp2p/go-libp2p-peerstore/releases) - [Commits](https://github.com/libp2p/go-libp2p-peerstore/compare/v0.2.1...v0.2.2) Signed-off-by: dependabot-preview[bot] --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 532bcc865dd..522045c8b11 100644 --- a/go.mod +++ b/go.mod @@ -69,7 +69,7 @@ require ( github.com/libp2p/go-libp2p-kbucket v0.2.3 github.com/libp2p/go-libp2p-loggables v0.1.0 github.com/libp2p/go-libp2p-mplex v0.2.2 - github.com/libp2p/go-libp2p-peerstore v0.2.1 + github.com/libp2p/go-libp2p-peerstore v0.2.2 github.com/libp2p/go-libp2p-pubsub v0.2.6 github.com/libp2p/go-libp2p-pubsub-router v0.2.1 github.com/libp2p/go-libp2p-quic-transport v0.2.4-0.20200228032821-6d8b0e775c52 diff --git a/go.sum b/go.sum index 512a1c48877..2073eb2efdf 100644 --- a/go.sum +++ b/go.sum @@ -530,6 +530,8 @@ github.com/libp2p/go-libp2p-peerstore v0.2.0 h1:XcgJhI8WyUOCbHyRLNEX5542YNj8hnLS github.com/libp2p/go-libp2p-peerstore v0.2.0/go.mod h1:N2l3eVIeAitSg3Pi2ipSrJYnqhVnMNQZo9nkSCuAbnQ= github.com/libp2p/go-libp2p-peerstore v0.2.1 h1:u+gOfsKgu73ZkGWhvckRm03z9C+iS9TrLqpANweELGs= github.com/libp2p/go-libp2p-peerstore v0.2.1/go.mod h1:NQxhNjWxf1d4w6PihR8btWIRjwRLBr4TYKfNgrUkOPA= +github.com/libp2p/go-libp2p-peerstore v0.2.2 h1:iqc/m03jHn5doXN3+kS6JKvqQRHEltiXljQB85iVHWE= +github.com/libp2p/go-libp2p-peerstore v0.2.2/go.mod h1:NQxhNjWxf1d4w6PihR8btWIRjwRLBr4TYKfNgrUkOPA= github.com/libp2p/go-libp2p-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= From efdb8db276910bc177d4c0f758170623505609c4 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Sun, 29 Mar 2020 20:48:43 -0700 Subject: [PATCH 530/671] fix: get rid of shutdown errors Instead of feeding through the top-level context, feed through a cancel-free context (that still carries the same context values). Then, when the top-level context is canceled, call `stop` to shut everything down in-order. Finally, cancel the inner context to make sure everything has been cleaned up. Ideally, we just wouldn't use contexts for this. But this is strictly better than what we have. --- core/builder.go | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/core/builder.go b/core/builder.go index ff8fbd3275a..e93ceddb2e3 100644 --- a/core/builder.go +++ b/core/builder.go @@ -3,6 +3,7 @@ package core import ( "context" "sync" + "time" "github.com/ipfs/go-ipfs/core/bootstrap" "github.com/ipfs/go-ipfs/core/node" @@ -11,10 +12,26 @@ import ( "go.uber.org/fx" ) +// from https://stackoverflow.com/a/59348871 +type valueContext struct { + context.Context +} + +func (valueContext) Deadline() (deadline time.Time, ok bool) { return } +func (valueContext) Done() <-chan struct{} { return nil } +func (valueContext) Err() error { return nil } + type BuildCfg = node.BuildCfg // Alias for compatibility until we properly refactor the constructor interface // NewNode constructs and returns an IpfsNode using the given cfg. func NewNode(ctx context.Context, cfg *BuildCfg) (*IpfsNode, error) { + // save this context as the "lifetime" ctx. + lctx := ctx + + // derive a new context that ignores cancellations from the lifetime ctx. + ctx, cancel := context.WithCancel(valueContext{ctx}) + + // add a metrics scope. ctx = metrics.CtxScope(ctx, "ipfs") n := &IpfsNode{ @@ -33,18 +50,27 @@ func NewNode(ctx context.Context, cfg *BuildCfg) (*IpfsNode, error) { n.stop = func() error { once.Do(func() { stopErr = app.Stop(context.Background()) + if stopErr != nil { + log.Error("failure on stop: ", stopErr) + } + // Cancel the context _after_ the app has stopped. + cancel() }) return stopErr } n.IsOnline = cfg.Online go func() { - // Note that some services use contexts to signal shutting down, which is - // very suboptimal. This needs to be here until that's addressed somehow - <-ctx.Done() - err := n.stop() - if err != nil { - log.Error("failure on stop: ", err) + // Shut down the application if the lifetime context is canceled. + // NOTE: we _should_ stop the application by calling `Close()` + // on the process. But we currently manage everything with contexts. + select { + case <-lctx.Done(): + err := n.stop() + if err != nil { + log.Error("failure on stop: ", err) + } + case <-ctx.Done(): } }() From 0c08e0678ca483162710915bd678b689d3455b4b Mon Sep 17 00:00:00 2001 From: "@RubenKelevra" Date: Mon, 30 Mar 2020 18:03:12 +0200 Subject: [PATCH 531/671] docs/experimental-features.md: typo --- docs/experimental-features.md | 63 +++++++++++++++-------------------- 1 file changed, 27 insertions(+), 36 deletions(-) diff --git a/docs/experimental-features.md b/docs/experimental-features.md index 64aa3b7c071..1f44526858e 100644 --- a/docs/experimental-features.md +++ b/docs/experimental-features.md @@ -8,7 +8,7 @@ removed. Subscribe to https://github.com/ipfs/go-ipfs/issues/3397 to get updates. -When you add a new experimental feature to go-ipfs, or change an experimental +When you add a new experimental feature to go-ipfs or change an experimental feature, you MUST please make a PR updating this document, and link the PR in the above issue. @@ -53,7 +53,7 @@ run your daemon with the `--enable-pubsub-experiment` flag. Then use the Gossipsub is a new, experimental routing protocol for pubsub that should waste less bandwidth than floodsub, the current pubsub -protocol. It's backwards compatible with floodsub so enabling this +protocol. It's backward compatible with floodsub so enabling this feature shouldn't break compatibility with existing IPFS nodes. You can enable gossipsub via configuration: @@ -76,7 +76,7 @@ signed) by running: ### Road to being a real feature - [ ] Needs more people to use and report on how well it works -- [ ] Needs authenticated modes to be implemented +- [ ] Needs authenticating modes to be implemented - [ ] needs performance analyses to be done --- @@ -168,7 +168,7 @@ filestore instead of copying the files into your local IPFS repo. --- ## ipfs urlstore -Allows ipfs to retrieve blocks contents via a url instead of storing it in the datastore +Allows ipfs to retrieve blocks contents via a URL instead of storing it in the datastore ### State experimental. @@ -195,7 +195,7 @@ And then add a file at a specific URL using `ipfs urlstore add ` ## Private Networks -Allows ipfs to only connect to other peers who have a shared secret key. +It allows ipfs to only connect to other peers who have a shared secret key. ### State Experimental @@ -249,7 +249,7 @@ configured, the daemon will fail to start. ## ipfs p2p Allows tunneling of TCP connections through Libp2p streams. If you've ever used -port forwarding with SSH (the `-L` option in openssh), this feature is quite +port forwarding with SSH (the `-L` option in OpenSSH), this feature is quite similar. ### State @@ -262,7 +262,7 @@ master, 0.4.10 ### How to enable -The `p2p` command needs to be enabled in config: +The `p2p` command needs to be enabled in the config: ```sh > ipfs config --json Experimental.Libp2pStreamMounting true @@ -354,13 +354,13 @@ with `ssh [user]@127.0.0.1 -p 2222`. ### Road to being a real feature - [ ] Needs more people to use and report on how well it works / fits use cases - [ ] More documentation -- [ ] Support other protocols (e.g, unix domain sockets, websockets, etc.) +- [ ] Support other protocols (e.g, Unix domain sockets, WebSockets, etc.) --- ## p2p http proxy -Allows proxying of HTTP requests over p2p streams. This allows serving any standard http app over p2p streams. +Allows proxying of HTTP requests over p2p streams. This allows serving any standard HTTP app over p2p streams. ### State @@ -372,13 +372,13 @@ master, 0.4.19 ### How to enable -The `p2p` command needs to be enabled in config: +The `p2p` command needs to be enabled in the config: ```sh > ipfs config --json Experimental.Libp2pStreamMounting true ``` -On the client, the p2p http proxy needs to be enabled in the config: +On the client, the p2p HTTP proxy needs to be enabled in the config: ```sh > ipfs config --json Experimental.P2pHttpProxy true @@ -427,10 +427,10 @@ the remote machine (which needs to be a http server!) with path `$FORWARDED_PATH > curl http://localhost:8080/p2p/$SERVER_ID/http/ ``` -You should now see the resulting http response: IPFS rocks! +You should now see the resulting HTTP response: IPFS rocks! ### Custom protocol names -We also support use of protocol names of the form /x/$NAME/http where $NAME doesn't contain any "/"'s +We also support the use of protocol names of the form /x/$NAME/http where $NAME doesn't contain any "/"'s ### Road to being a real feature - [ ] Needs p2p streams to graduate from experiments @@ -453,7 +453,7 @@ master, 0.4.11 ### How to enable The relay transport is enabled by default, which allows peers to dial through -relay and listens for incoming relay connections. The transport can be disabled +a relay and listens for incoming relay connections. The transport can be disabled by setting `Swarm.DisableRelay = true` in the configuration. By default, peers don't act as intermediate nodes (relays). This can be enabled @@ -463,7 +463,7 @@ already online node would have to be restarted. ### Basic Usage: -In order to connect peers QmA and QmB through a relay node QmRelay: +To connect peers QmA and QmB through a relay node QmRelay: - Both peers should connect to the relay: `ipfs swarm connect /transport/address/p2p/QmRelay` @@ -483,8 +483,7 @@ Peers can see their (unspecific) relay address in the output of - [ ] Advertise relay addresses to the DHT for NATed or otherwise unreachable peers. - [ ] Active relay discovery for specific relay address advertisement. We would - like advertised relay addresses to designate specific relays for efficient - dialing. + like advertised relay addresses to designate specific relays for efficient dialing. - [ ] Dialing priorities for relay addresses; arguably, relay addresses should have lower priority than direct dials. @@ -496,7 +495,7 @@ Peers can see their (unspecific) relay address in the output of ### State Experimental -Plugins allow to add functionality without the need to recompile the daemon. +Plugins allow adding functionality without the need to recompile the daemon. ### Basic Usage: @@ -545,7 +544,7 @@ You can read more in the [datastore](./datastores.md#badgerds) documentation. ### State Experimental -Allows to create directories with unlimited number of entries - currently +Allows to create directories with an unlimited number of entries - currently size of unixfs directories is limited by the maximum block size ### Basic Usage: @@ -571,20 +570,15 @@ ipfs config --json Experimental.ShardingEnabled true Experimental, default-disabled. -Utilizes pubsub for publishing ipns records in real time. +Utilizes pubsub for publishing ipns records in real-time. When it is enabled: - IPNS publishers push records to a name-specific pubsub topic, in addition to publishing to the DHT. - IPNS resolvers subscribe to the name-specific topic on first - resolution and receive subsequently published records through pubsub - in real time. This makes subsequent resolutions instant, as they - are resolved through the local cache. Note that the initial - resolution still goes through the DHT, as there is no message - history in pubsub. + resolution and receive subsequently published records through pubsub in real-time. This makes subsequent resolutions instant, as they are resolved through the local cache. Note that the initial resolution still goes through the DHT, as there is no message history in pubsub. -Both the publisher and the resolver nodes need to have the feature enabled for it -to work effectively. +Both the publisher and the resolver nodes need to have the feature enabled for it to work effectively. ### How to enable @@ -617,14 +611,14 @@ Modify your ipfs config: ipfs config --json Experimental.QUIC true ``` -For listening on a QUIC address, add it the swarm addresses, e.g. `/ip4/0.0.0.0/udp/4001/quic`. +For listening on a QUIC address, add it to the swarm addresses, e.g. `/ip4/0.0.0.0/udp/4001/quic`. ### Road to being a real feature -- [ ] The IETF QUIC specification needs to be finalised. +- [ ] The IETF QUIC specification needs to be finalized. - [ ] Make sure QUIC connections work reliably -- [ ] Make sure QUIC connection offer equal or better performance than TCP connections on real world networks +- [ ] Make sure QUIC connection offer equal or better performance than TCP connections on real-world networks - [ ] Finalize libp2p-TLS handshake spec. @@ -687,9 +681,9 @@ ipfs config --json Experimental.StrategicProviding true ### Road to being a real feature -- [ ] needs real world testing +- [ ] needs real-world testing - [ ] needs adoption -- [ ] needs to support all providing features +- [ ] needs to support all provided features - [X] provide nothing - [ ] provide roots - [ ] provide all @@ -717,7 +711,4 @@ ipfs config --json Experimental.GraphsyncEnabled true ### Road to being a real feature -- [ ] We need to confirm that it can't be used to DoS a node. The server-side - logic for GraphSync is quite complex and, if we're not careful, the server - might end up performing unbounded work when responding to a malicious - request. +- [ ] We need to confirm that it can't be used to DoS a node. The server-side logic for GraphSync is quite complex and, if we're not careful, the server might end up performing unbounded work when responding to a malicious request. From 4611e41e5cf5c228acb5a0397bc9298a2ddb6dac Mon Sep 17 00:00:00 2001 From: "@RubenKelevra" Date: Mon, 30 Mar 2020 21:01:56 +0200 Subject: [PATCH 532/671] Apply suggestions from code review Co-Authored-By: Will --- docs/experimental-features.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/experimental-features.md b/docs/experimental-features.md index 1f44526858e..e94e38799ac 100644 --- a/docs/experimental-features.md +++ b/docs/experimental-features.md @@ -544,7 +544,7 @@ You can read more in the [datastore](./datastores.md#badgerds) documentation. ### State Experimental -Allows to create directories with an unlimited number of entries - currently +Allows creating directories with an unlimited number of entries - currently size of unixfs directories is limited by the maximum block size ### Basic Usage: @@ -570,13 +570,13 @@ ipfs config --json Experimental.ShardingEnabled true Experimental, default-disabled. -Utilizes pubsub for publishing ipns records in real-time. +Utilizes pubsub for publishing ipns records in real time. When it is enabled: - IPNS publishers push records to a name-specific pubsub topic, in addition to publishing to the DHT. - IPNS resolvers subscribe to the name-specific topic on first - resolution and receive subsequently published records through pubsub in real-time. This makes subsequent resolutions instant, as they are resolved through the local cache. Note that the initial resolution still goes through the DHT, as there is no message history in pubsub. + resolution and receive subsequently published records through pubsub in real time. This makes subsequent resolutions instant, as they are resolved through the local cache. Note that the initial resolution still goes through the DHT, as there is no message history in pubsub. Both the publisher and the resolver nodes need to have the feature enabled for it to work effectively. From 4743b3f3414cb25bf73eee40a2eb5b479855dba7 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 30 Mar 2020 13:15:18 -0700 Subject: [PATCH 533/671] docs: fix provided -> provider subsystem --- docs/experimental-features.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/experimental-features.md b/docs/experimental-features.md index e94e38799ac..b84602052c4 100644 --- a/docs/experimental-features.md +++ b/docs/experimental-features.md @@ -683,7 +683,7 @@ ipfs config --json Experimental.StrategicProviding true - [ ] needs real-world testing - [ ] needs adoption -- [ ] needs to support all provided features +- [ ] needs to support all provider subsystem features - [X] provide nothing - [ ] provide roots - [ ] provide all From 06ba6d0fc2472368f12478d5d6f3113da4ae0480 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Tue, 31 Mar 2020 11:39:37 -0700 Subject: [PATCH 534/671] fix: remove internal relay discovery This logic collects a list of known relays by testing every new connection. It exists so we can dial /p2p-circuit/p2p/QmFoobar addresses (circuit addresses that don't specify the relay). However, this kind of address is useless outside of basic demos as a random relay is practically guaranteed to not be connected to the target peer. Picking a random relay to connect to some peer is almost _never_ the desired behavior. --- core/node/libp2p/relay.go | 2 +- test/sharness/t0182-circuit-relay.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/node/libp2p/relay.go b/core/node/libp2p/relay.go index ac75aa6677c..d27466dbfd2 100644 --- a/core/node/libp2p/relay.go +++ b/core/node/libp2p/relay.go @@ -11,7 +11,7 @@ func Relay(disable, enableHop bool) func() (opts Libp2pOpts, err error) { // Enabled by default. opts.Opts = append(opts.Opts, libp2p.DisableRelay()) } else { - relayOpts := []relay.RelayOpt{relay.OptDiscovery} + relayOpts := []relay.RelayOpt{} if enableHop { relayOpts = append(relayOpts, relay.OptHop) } diff --git a/test/sharness/t0182-circuit-relay.sh b/test/sharness/t0182-circuit-relay.sh index 24e1b8ede8a..3dd12ed68fa 100755 --- a/test/sharness/t0182-circuit-relay.sh +++ b/test/sharness/t0182-circuit-relay.sh @@ -44,7 +44,7 @@ test_expect_success 'peer ids' ' ' test_expect_success 'connect A <-Relay-> B' ' - ipfsi 0 swarm connect /p2p-circuit/p2p/$PEERID_2 > peers_out + ipfsi 0 swarm connect /p2p/$PEERID_1/p2p-circuit/p2p/$PEERID_2 > peers_out ' test_expect_success 'output looks good' ' From b5aaf75e2501c504eb7527972d08a52fb2f27a3b Mon Sep 17 00:00:00 2001 From: Hector Sanjuan Date: Wed, 1 Apr 2020 12:08:48 +0200 Subject: [PATCH 535/671] Fix #4996: Improve help text for "ipfs files cp" --- core/commands/files.go | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/core/commands/files.go b/core/commands/files.go index d173ec53731..dcf2bbd6e95 100644 --- a/core/commands/files.go +++ b/core/commands/files.go @@ -321,7 +321,23 @@ func walkBlock(ctx context.Context, dagserv ipld.DAGService, nd ipld.Node) (bool var filesCpCmd = &cmds.Command{ Helptext: cmds.HelpText{ - Tagline: "Copy files into mfs.", + Tagline: "Copy any IPFS objects into mfs (or copy within MFS).", + ShortDescription: ` +"ipfs files cp" can be used to copy any IPFS object (usually in the form +/ipfs/, but also any resolvable path), into the Mutable File System +(MFS). + +It can also be used to copy files within MFS, but in the case when an +IPFS-path matches an existing MFS path, the IPFS path wins. + +In order to add content to MFS from disk, you can use "ipfs add" to obtain the +IPFS Content Identifier and then "ipfs files cp" to copy it into MFS: + +$ ipfs add --pin=false +# ... +# ... outputs the root CID at the end +$ ipfs cp /ipfs/ /your/desired/mfs/path +`, }, Arguments: []cmds.Argument{ cmds.StringArg("source", true, false, "Source object to copy."), From 9570efb20481a01175ebef7bfb867b99323e565d Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2020 11:24:42 +0000 Subject: [PATCH 536/671] chore(deps): bump github.com/hashicorp/go-multierror from 1.0.0 to 1.1.0 Bumps [github.com/hashicorp/go-multierror](https://github.com/hashicorp/go-multierror) from 1.0.0 to 1.1.0. - [Release notes](https://github.com/hashicorp/go-multierror/releases) - [Commits](https://github.com/hashicorp/go-multierror/compare/v1.0.0...v1.1.0) Signed-off-by: dependabot-preview[bot] --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 0c1af4406af..c0f89c50aa7 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/fsnotify/fsnotify v1.4.9 github.com/go-bindata/go-bindata/v3 v3.1.3 github.com/gogo/protobuf v1.3.1 - github.com/hashicorp/go-multierror v1.0.0 + github.com/hashicorp/go-multierror v1.1.0 github.com/hashicorp/golang-lru v0.5.4 github.com/ipfs/go-bitswap v0.2.7 github.com/ipfs/go-block-format v0.0.2 diff --git a/go.sum b/go.sum index 3b46038c53d..4191d175fb9 100644 --- a/go.sum +++ b/go.sum @@ -144,6 +144,8 @@ github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/U github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI= +github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.3 h1:YPkqC67at8FYaadspW/6uE0COsBxS2656RLEr8Bppgk= From 248153fc7151150df2b8051f77393254ca514857 Mon Sep 17 00:00:00 2001 From: Pretty Please Mark Darkly <55382229+pleasemarkdarkly@users.noreply.github.com> Date: Wed, 1 Apr 2020 20:28:52 -0700 Subject: [PATCH 537/671] changed brew to brew cask --- docs/fuse.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/fuse.md b/docs/fuse.md index f26b0e31d3e..4316b1ae281 100644 --- a/docs/fuse.md +++ b/docs/fuse.md @@ -31,7 +31,7 @@ ssh connection or by re-logging to the system. It has been discovered that versions of `osxfuse` prior to `2.7.0` will cause a kernel panic. For everyone's sake, please upgrade (latest at time of writing is `2.7.4`). The installer can be found at https://osxfuse.github.io/. There is -also a homebrew formula (`brew install osxfuse`) but users report best results +also a homebrew formula (`brew cask install osxfuse`) but users report best results installing from the official OSXFUSE installer package. Note that `ipfs` attempts an automatic version check on `osxfuse` to prevent you From 39510a1ad1f212af336a6f6adb92bd05659370e3 Mon Sep 17 00:00:00 2001 From: Pretty Please Mark Darkly <55382229+pleasemarkdarkly@users.noreply.github.com> Date: Wed, 1 Apr 2020 20:40:56 -0700 Subject: [PATCH 538/671] Added additional note about killing the daemon Mounting complained that the daemon was running. --- docs/fuse.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/docs/fuse.md b/docs/fuse.md index 4316b1ae281..a6399eeba44 100644 --- a/docs/fuse.md +++ b/docs/fuse.md @@ -62,7 +62,21 @@ sudo chown /ipfs sudo chown /ipns ``` -Depending on whether you are using OSX or Linux, follow the proceeding instructions. +Depending on whether you are using OSX or Linux, follow the proceeding instructions. + +## Make sure IPFS daemon is not running + +You'll need to stop the IPFS daemon if you have it started, otherwise the mount will complain. + +``` +# Check to see if IPFS daemon is running +ps aux | grep ipfs + +# Kill the IPFS daemon +pkill -f ipfs + +# Verify that it has been killed +``` ## Mounting IPFS From c7ab79054793db4aa2d165e884ab14c1022d9556 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2020 11:25:50 +0000 Subject: [PATCH 539/671] chore(deps): bump go.uber.org/fx from 1.10.0 to 1.11.0 Bumps [go.uber.org/fx](https://github.com/uber-go/fx) from 1.10.0 to 1.11.0. - [Release notes](https://github.com/uber-go/fx/releases) - [Changelog](https://github.com/uber-go/fx/blob/master/CHANGELOG.md) - [Commits](https://github.com/uber-go/fx/compare/v1.10.0...v1.11.0) Signed-off-by: dependabot-preview[bot] --- go.mod | 2 +- go.sum | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 0c1af4406af..d153d1f13ab 100644 --- a/go.mod +++ b/go.mod @@ -98,7 +98,7 @@ require ( github.com/whyrusleeping/go-sysinfo v0.0.0-20190219211824-4a357d4b90b1 github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 github.com/whyrusleeping/tar-utils v0.0.0-20180509141711-8c6c8ba81d5c - go.uber.org/fx v1.10.0 + go.uber.org/fx v1.11.0 golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd gopkg.in/cheggaaa/pb.v1 v1.0.28 diff --git a/go.sum b/go.sum index 3b46038c53d..40395d775b3 100644 --- a/go.sum +++ b/go.sum @@ -915,8 +915,12 @@ go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/dig v1.8.0 h1:1rR6hnL/bu1EVcjnRDN5kx1vbIjEJDTGhSQ2B3ddpcI= go.uber.org/dig v1.8.0/go.mod h1:X34SnWGr8Fyla9zQNO2GSO2D+TIuqB14OS8JhYocIyw= +go.uber.org/dig v1.9.0 h1:pJTDXKEhRqBI8W7rU7kwT5EgyRZuSMVSFcZolOvKK9U= +go.uber.org/dig v1.9.0/go.mod h1:X34SnWGr8Fyla9zQNO2GSO2D+TIuqB14OS8JhYocIyw= go.uber.org/fx v1.10.0 h1:S2K/H8oNied0Je/mLKdWzEWKZfv9jtxSDm8CnwK+5Fg= go.uber.org/fx v1.10.0/go.mod h1:vLRicqpG/qQEzno4SYU86iCwfT95EZza+Eba0ItuxqY= +go.uber.org/fx v1.11.0 h1:WTxcE9VicMCGSB//JfMtpD9XP500wJx6w8lYEcsdPQk= +go.uber.org/fx v1.11.0/go.mod h1:egT3Kyg1JFYQkvKLZ3EsykxkNrZxgXS+gKoKo7abERY= go.uber.org/goleak v0.10.0 h1:G3eWbSNIskeRqtsN/1uI5B+eP73y3JUuBsv9AZjehb4= go.uber.org/goleak v0.10.0/go.mod h1:VCZuO8V8mFPlL0F5J5GK1rtHV3DrFcQ1R8ryq7FK0aI= go.uber.org/goleak v1.0.0 h1:qsup4IcBdlmsnGfqyLl4Ntn3C2XCCuKAE7DwHpScyUo= From cb063a28a3a35140ef7ca49f07d4a15f3654ed5f Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2020 11:26:25 +0000 Subject: [PATCH 540/671] chore(deps): bump github.com/ipfs/go-ds-badger from 0.2.2 to 0.2.3 Bumps [github.com/ipfs/go-ds-badger](https://github.com/ipfs/go-ds-badger) from 0.2.2 to 0.2.3. - [Release notes](https://github.com/ipfs/go-ds-badger/releases) - [Commits](https://github.com/ipfs/go-ds-badger/compare/v0.2.2...v0.2.3) Signed-off-by: dependabot-preview[bot] --- go.mod | 2 +- go.sum | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 0c1af4406af..6ca424e578c 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/ipfs/go-cidutil v0.0.2 github.com/ipfs/go-datastore v0.4.4 github.com/ipfs/go-detect-race v0.0.1 - github.com/ipfs/go-ds-badger v0.2.2 + github.com/ipfs/go-ds-badger v0.2.3 github.com/ipfs/go-ds-flatfs v0.4.0 github.com/ipfs/go-ds-leveldb v0.4.2 github.com/ipfs/go-ds-measure v0.1.0 diff --git a/go.sum b/go.sum index 3b46038c53d..410c5eb3345 100644 --- a/go.sum +++ b/go.sum @@ -9,6 +9,7 @@ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Kubuxu/go-os-helper v0.0.1 h1:EJiD2VUQyh5A9hWJLmc6iWg6yIcJ7jpBcwC8GMGXfDk= github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= 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= @@ -46,6 +47,8 @@ github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtE github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= @@ -75,6 +78,10 @@ github.com/dgraph-io/badger v1.6.0-rc1 h1:JphPpoBZJ3WHha133BGYlQqltSGIhV+VsEID0+ github.com/dgraph-io/badger v1.6.0-rc1/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= github.com/dgraph-io/badger v1.6.0 h1:DshxFxZWXUcO0xX476VJC07Xsr6ZCBVRHKZ93Oh7Evo= github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= +github.com/dgraph-io/badger v1.6.1 h1:w9pSFNSdq/JPM1N12Fz/F/bzo993Is1W+Q7HjPzi7yg= +github.com/dgraph-io/badger v1.6.1/go.mod h1:FRmFw3uxvcpa8zG3Rxs0th+hCLIuaQg8HlNV5bjgnuU= +github.com/dgraph-io/ristretto v0.0.2 h1:a5WaUrDa0qm0YrAAS1tUykT5El3kt62KNZZeMxQn3po= +github.com/dgraph-io/ristretto v0.0.2/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= github.com/dgryski/go-farm v0.0.0-20190104051053-3adb47b1fb0f/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= @@ -216,6 +223,8 @@ github.com/ipfs/go-ds-badger v0.2.1 h1:RsC9DDlwFhFdfT+s2PeC8joxbSp2YMufK8w/RBOxK github.com/ipfs/go-ds-badger v0.2.1/go.mod h1:Tx7l3aTph3FMFrRS838dcSJh+jjA7cX9DrGVwx/NOwE= github.com/ipfs/go-ds-badger v0.2.2 h1:Fvrep6Tbv/9hYkrMkavCmG03DJToySZ4x7HbAdfT4q8= github.com/ipfs/go-ds-badger v0.2.2/go.mod h1:LIt1qUJF+Q6dEJI3f4/fJZUPdo6GoC6geFQkag32X8w= +github.com/ipfs/go-ds-badger v0.2.3 h1:J27YvAcpuA5IvZUbeBxOcQgqnYHUPxoygc6QxxkodZ4= +github.com/ipfs/go-ds-badger v0.2.3/go.mod h1:pEYw0rgg3FIrywKKnL+Snr+w/LjJZVMTBRn4FS6UHUk= github.com/ipfs/go-ds-flatfs v0.4.0 h1:bmC3y4a2xvUXAYNjqXzI4QcnArBHov4ztGzeEKLMrS8= github.com/ipfs/go-ds-flatfs v0.4.0/go.mod h1:lrIyxYXO3yXdp+TnpB8jpdzYRxopDGVPLIGorjSZyxM= github.com/ipfs/go-ds-leveldb v0.0.1/go.mod h1:feO8V3kubwsEF22n0YRQCffeb79OOYIykR4L04tMOYc= @@ -393,6 +402,7 @@ github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d/go.mod h1:5Ky9EC2xfo github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= From 32838843e419cd76794f0595bdfa3f170db4f4df Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2020 18:23:07 +0000 Subject: [PATCH 541/671] chore(deps): bump github.com/ipfs/go-ds-flatfs from 0.4.0 to 0.4.1 Bumps [github.com/ipfs/go-ds-flatfs](https://github.com/ipfs/go-ds-flatfs) from 0.4.0 to 0.4.1. - [Release notes](https://github.com/ipfs/go-ds-flatfs/releases) - [Commits](https://github.com/ipfs/go-ds-flatfs/compare/v0.4.0...v0.4.1) Signed-off-by: dependabot-preview[bot] --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 6ca424e578c..ac1b342c70a 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( github.com/ipfs/go-datastore v0.4.4 github.com/ipfs/go-detect-race v0.0.1 github.com/ipfs/go-ds-badger v0.2.3 - github.com/ipfs/go-ds-flatfs v0.4.0 + github.com/ipfs/go-ds-flatfs v0.4.1 github.com/ipfs/go-ds-leveldb v0.4.2 github.com/ipfs/go-ds-measure v0.1.0 github.com/ipfs/go-filestore v0.0.3 diff --git a/go.sum b/go.sum index 410c5eb3345..f2e8ea141de 100644 --- a/go.sum +++ b/go.sum @@ -227,6 +227,8 @@ github.com/ipfs/go-ds-badger v0.2.3 h1:J27YvAcpuA5IvZUbeBxOcQgqnYHUPxoygc6Qxxkod github.com/ipfs/go-ds-badger v0.2.3/go.mod h1:pEYw0rgg3FIrywKKnL+Snr+w/LjJZVMTBRn4FS6UHUk= github.com/ipfs/go-ds-flatfs v0.4.0 h1:bmC3y4a2xvUXAYNjqXzI4QcnArBHov4ztGzeEKLMrS8= github.com/ipfs/go-ds-flatfs v0.4.0/go.mod h1:lrIyxYXO3yXdp+TnpB8jpdzYRxopDGVPLIGorjSZyxM= +github.com/ipfs/go-ds-flatfs v0.4.1 h1:l43jeAUALOKRvoMMJ4rOddxUzcOACUjnd1u4AfKqeZo= +github.com/ipfs/go-ds-flatfs v0.4.1/go.mod h1:5fR0eUTIrFWJqa4zACd3mKUNm26wM/jVbVDo39/WRRo= github.com/ipfs/go-ds-leveldb v0.0.1/go.mod h1:feO8V3kubwsEF22n0YRQCffeb79OOYIykR4L04tMOYc= github.com/ipfs/go-ds-leveldb v0.1.0 h1:OsCuIIh1LMTk4WIQ1UJH7e3j01qlOP+KWVhNS6lBDZY= github.com/ipfs/go-ds-leveldb v0.1.0/go.mod h1:hqAW8y4bwX5LWcCtku2rFNX3vjDZCy5LZCg+cSZvYb8= From 3b30e8e2b00ddaeffe8702c132aa6263fdf3e472 Mon Sep 17 00:00:00 2001 From: Hector Sanjuan Date: Thu, 2 Apr 2020 20:46:31 +0200 Subject: [PATCH 542/671] ipfs files cp: improve docstring with better words. And align capitalization. --- core/commands/files.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/commands/files.go b/core/commands/files.go index dcf2bbd6e95..132598428bb 100644 --- a/core/commands/files.go +++ b/core/commands/files.go @@ -321,10 +321,10 @@ func walkBlock(ctx context.Context, dagserv ipld.DAGService, nd ipld.Node) (bool var filesCpCmd = &cmds.Command{ Helptext: cmds.HelpText{ - Tagline: "Copy any IPFS objects into mfs (or copy within MFS).", + Tagline: "Copy any IPFS files and directories into MFS (or copy within MFS).", ShortDescription: ` -"ipfs files cp" can be used to copy any IPFS object (usually in the form -/ipfs/, but also any resolvable path), into the Mutable File System +"ipfs files cp" can be used to copy any IPFS file or directory (usually in the +form /ipfs/, but also any resolvable path), into the Mutable File System (MFS). It can also be used to copy files within MFS, but in the case when an @@ -333,15 +333,15 @@ IPFS-path matches an existing MFS path, the IPFS path wins. In order to add content to MFS from disk, you can use "ipfs add" to obtain the IPFS Content Identifier and then "ipfs files cp" to copy it into MFS: -$ ipfs add --pin=false +$ ipfs add --quieter --pin=false # ... # ... outputs the root CID at the end $ ipfs cp /ipfs/ /your/desired/mfs/path `, }, Arguments: []cmds.Argument{ - cmds.StringArg("source", true, false, "Source object to copy."), - cmds.StringArg("dest", true, false, "Destination to copy object to."), + cmds.StringArg("source", true, false, "Source IPFS or MFS path to copy."), + cmds.StringArg("dest", true, false, "Destination within MFS."), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { nd, err := cmdenv.GetNode(env) From 8fc9ddfe1bddacb8aa6cc9354ae24d9c38ed9241 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Thu, 2 Apr 2020 23:25:38 -0700 Subject: [PATCH 543/671] chore: update libp2p deps Prepare for an RC. This also re-re-disables stream write coalescing till we get a chance to thoroughly profile it. --- go.mod | 22 +++++++++---------- go.sum | 67 ++++++++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 60 insertions(+), 29 deletions(-) diff --git a/go.mod b/go.mod index afcaba46234..55eb75ff1a1 100644 --- a/go.mod +++ b/go.mod @@ -59,27 +59,27 @@ require ( github.com/jbenet/go-temp-err-catcher v0.1.0 github.com/jbenet/goprocess v0.1.4 github.com/libp2p/go-eventbus v0.1.0 - github.com/libp2p/go-libp2p v0.7.2 - github.com/libp2p/go-libp2p-circuit v0.1.4 + github.com/libp2p/go-libp2p v0.7.4 + github.com/libp2p/go-libp2p-circuit v0.2.1 github.com/libp2p/go-libp2p-connmgr v0.2.1 - github.com/libp2p/go-libp2p-core v0.5.0 - github.com/libp2p/go-libp2p-discovery v0.2.0 + github.com/libp2p/go-libp2p-core v0.5.1 + github.com/libp2p/go-libp2p-discovery v0.3.0 github.com/libp2p/go-libp2p-http v0.1.5 github.com/libp2p/go-libp2p-kad-dht v0.5.2 github.com/libp2p/go-libp2p-kbucket v0.2.3 github.com/libp2p/go-libp2p-loggables v0.1.0 - github.com/libp2p/go-libp2p-mplex v0.2.2 + github.com/libp2p/go-libp2p-mplex v0.2.3 github.com/libp2p/go-libp2p-peerstore v0.2.2 github.com/libp2p/go-libp2p-pubsub v0.2.6 github.com/libp2p/go-libp2p-pubsub-router v0.2.1 github.com/libp2p/go-libp2p-quic-transport v0.2.4-0.20200228032821-6d8b0e775c52 github.com/libp2p/go-libp2p-record v0.1.2 github.com/libp2p/go-libp2p-routing-helpers v0.1.0 - github.com/libp2p/go-libp2p-secio v0.2.1 - github.com/libp2p/go-libp2p-swarm v0.2.2 + github.com/libp2p/go-libp2p-secio v0.2.2 + github.com/libp2p/go-libp2p-swarm v0.2.3 github.com/libp2p/go-libp2p-testing v0.1.1 github.com/libp2p/go-libp2p-tls v0.1.3 - github.com/libp2p/go-libp2p-yamux v0.2.6 + github.com/libp2p/go-libp2p-yamux v0.2.7 github.com/libp2p/go-maddr-filter v0.0.5 github.com/libp2p/go-socket-activation v0.0.2 github.com/mattn/go-runewidth v0.0.8 // indirect @@ -87,8 +87,8 @@ require ( github.com/mr-tron/base58 v1.1.3 github.com/multiformats/go-multiaddr v0.2.1 github.com/multiformats/go-multiaddr-dns v0.2.0 - github.com/multiformats/go-multiaddr-net v0.1.3 - github.com/multiformats/go-multibase v0.0.1 + github.com/multiformats/go-multiaddr-net v0.1.4 + github.com/multiformats/go-multibase v0.0.2 github.com/multiformats/go-multihash v0.0.13 github.com/opentracing/opentracing-go v1.1.0 github.com/pkg/errors v0.9.1 @@ -100,7 +100,7 @@ require ( github.com/whyrusleeping/tar-utils v0.0.0-20180509141711-8c6c8ba81d5c go.uber.org/fx v1.11.0 golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 - golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd + golang.org/x/sys v0.0.0-20200331124033-c3d80250170d gopkg.in/cheggaaa/pb.v1 v1.0.28 ) diff --git a/go.sum b/go.sum index 05e87d5b2f2..92a1fd9b86a 100644 --- a/go.sum +++ b/go.sum @@ -9,6 +9,7 @@ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Kubuxu/go-os-helper v0.0.1 h1:EJiD2VUQyh5A9hWJLmc6iWg6yIcJ7jpBcwC8GMGXfDk= github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y= +github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Stebalien/go-bitfield v0.0.0-20180330043415-076a62f9ce6e/go.mod h1:3oM7gXIttpYDAJXpVNnSCiUMYBLIZ6cb1t+Ip982MRo= github.com/Stebalien/go-bitfield v0.0.1 h1:X3kbSSPUaJK60wV2hjOPZwmpljr6VGCqdq4cBLhbQBo= @@ -135,6 +136,8 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gopacket v1.1.17 h1:rMrlX2ZY2UbvT+sdz3+6J+pp2z+msCq9MxTU6ymxbBY= +github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -144,6 +147,8 @@ github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c/go.mod h1:wJfORR github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= 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= @@ -210,8 +215,6 @@ github.com/ipfs/go-datastore v0.3.1 h1:SS1t869a6cctoSYmZXUk8eL6AzVXgASmKIWFNQkQ1 github.com/ipfs/go-datastore v0.3.1/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRVNdgPHtbHw= github.com/ipfs/go-datastore v0.4.0/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= github.com/ipfs/go-datastore v0.4.1/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= -github.com/ipfs/go-datastore v0.4.2 h1:h8/n7WPzhp239kkLws+epN3Ic7YtcBPgcaXfEfdVDWM= -github.com/ipfs/go-datastore v0.4.2/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= github.com/ipfs/go-datastore v0.4.4 h1:rjvQ9+muFaJ+QZ7dN5B1MSDNQ0JVZKkkES/rMZmA8X8= github.com/ipfs/go-datastore v0.4.4/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk= @@ -223,12 +226,8 @@ github.com/ipfs/go-ds-badger v0.0.7 h1:NMyh88Q50HG6/S2YD58DLkq0c0/ZQPMbSojONH+PR github.com/ipfs/go-ds-badger v0.0.7/go.mod h1:qt0/fWzZDoPW6jpQeqUjR5kBfhDNB65jd9YlmAvpQBk= github.com/ipfs/go-ds-badger v0.2.1 h1:RsC9DDlwFhFdfT+s2PeC8joxbSp2YMufK8w/RBOxKtk= github.com/ipfs/go-ds-badger v0.2.1/go.mod h1:Tx7l3aTph3FMFrRS838dcSJh+jjA7cX9DrGVwx/NOwE= -github.com/ipfs/go-ds-badger v0.2.2 h1:Fvrep6Tbv/9hYkrMkavCmG03DJToySZ4x7HbAdfT4q8= -github.com/ipfs/go-ds-badger v0.2.2/go.mod h1:LIt1qUJF+Q6dEJI3f4/fJZUPdo6GoC6geFQkag32X8w= github.com/ipfs/go-ds-badger v0.2.3 h1:J27YvAcpuA5IvZUbeBxOcQgqnYHUPxoygc6QxxkodZ4= github.com/ipfs/go-ds-badger v0.2.3/go.mod h1:pEYw0rgg3FIrywKKnL+Snr+w/LjJZVMTBRn4FS6UHUk= -github.com/ipfs/go-ds-flatfs v0.4.0 h1:bmC3y4a2xvUXAYNjqXzI4QcnArBHov4ztGzeEKLMrS8= -github.com/ipfs/go-ds-flatfs v0.4.0/go.mod h1:lrIyxYXO3yXdp+TnpB8jpdzYRxopDGVPLIGorjSZyxM= github.com/ipfs/go-ds-flatfs v0.4.1 h1:l43jeAUALOKRvoMMJ4rOddxUzcOACUjnd1u4AfKqeZo= github.com/ipfs/go-ds-flatfs v0.4.1/go.mod h1:5fR0eUTIrFWJqa4zACd3mKUNm26wM/jVbVDo39/WRRo= github.com/ipfs/go-ds-leveldb v0.0.1/go.mod h1:feO8V3kubwsEF22n0YRQCffeb79OOYIykR4L04tMOYc= @@ -367,6 +366,8 @@ github.com/jackpal/gateway v1.0.5 h1:qzXWUJfuMdlLMtt0a3Dgt+xkWQiA5itDEITVJtuSwMc github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= github.com/jackpal/go-nat-pmp v1.0.1 h1:i0LektDkO1QlrTm/cSuP+PyBCDnYvjPLGl4LdWEMiaA= github.com/jackpal/go-nat-pmp v1.0.1/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= +github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jbenet/go-cienv v0.0.0-20150120210510-1bb1476777ec/go.mod h1:rGaEvXB4uRSZMmzKNLoXvTu1sfx+1kv/DojUlPrSZGs= github.com/jbenet/go-cienv v0.1.0 h1:Vc/s0QbQtoxX8MwwSLWWh+xNNZvM3Lw7NsTcHrvvhMc= github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= @@ -406,6 +407,7 @@ github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d/go.mod h1:5Ky9EC2xfo github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= @@ -443,8 +445,8 @@ github.com/libp2p/go-libp2p v0.6.1 h1:mxabyJf4l6AmotDOKObwSfBNBWjL5VYXysVFLUMAuB github.com/libp2p/go-libp2p v0.6.1/go.mod h1:CTFnWXogryAHjXAKEbOf1OWY+VeAP3lDMZkfEI5sT54= github.com/libp2p/go-libp2p v0.7.0 h1:qWmciout2lJclKfRlxqdepsQB7JihcbRhgcRcssP4rc= github.com/libp2p/go-libp2p v0.7.0/go.mod h1:hZJf8txWeCduQRDC/WSqBGMxaTHCOYHt2xSU1ivxn0k= -github.com/libp2p/go-libp2p v0.7.2 h1:f/HIWCgllub8g+Q3qhoirPUxCUDefaRjwjb6NBX5Xgw= -github.com/libp2p/go-libp2p v0.7.2/go.mod h1:ww6NouoEEIosjJ2LTXAhgtxuoY+1KWLEBlMqx2g+qj4= +github.com/libp2p/go-libp2p v0.7.4 h1:xVj1oSlN0C+FlxqiLuHC8WruMvq24xxfeVxmNhTG0r0= +github.com/libp2p/go-libp2p v0.7.4/go.mod h1:oXsBlTLF1q7pxr+9w6lqzS1ILpyHsaBPniVO7zIHGMw= github.com/libp2p/go-libp2p-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 h1:aCWAu43Ri4nU0ZPO7NyLzUvvfqd0nE3dX0R/ZGYVgOU= @@ -465,6 +467,8 @@ github.com/libp2p/go-libp2p-circuit v0.0.9/go.mod h1:uU+IBvEQzCu953/ps7bYzC/D/R0 github.com/libp2p/go-libp2p-circuit v0.1.0/go.mod h1:Ahq4cY3V9VJcHcn1SBXjr78AbFkZeIRmfunbA7pmFh8= github.com/libp2p/go-libp2p-circuit v0.1.4 h1:Phzbmrg3BkVzbqd4ZZ149JxCuUWu2wZcXf/Kr6hZJj8= github.com/libp2p/go-libp2p-circuit v0.1.4/go.mod h1:CY67BrEjKNDhdTk8UgBX1Y/H5c3xkAcs3gnksxY7osU= +github.com/libp2p/go-libp2p-circuit v0.2.1 h1:BDiBcQxX/ZJJ/yDl3sqZt1bjj4PkZCEi7IEpwxXr13k= +github.com/libp2p/go-libp2p-circuit v0.2.1/go.mod h1:BXPwYDN5A8z4OEY9sOfr2DUQMLQvKt/6oku45YUmjIo= github.com/libp2p/go-libp2p-connmgr v0.2.1 h1:1ed0HFhCb39sIMK7QYgRBW0vibBBqFQMs4xt9a9AalY= github.com/libp2p/go-libp2p-connmgr v0.2.1/go.mod h1:JReKEFcgzSHKT9lL3rhYcUtXBs9uMIiMKJGM1tl3xJE= github.com/libp2p/go-libp2p-core v0.0.1/go.mod h1:g/VxnTZ/1ygHxH3dKok7Vno1VfpvGcGip57wjTU4fco= @@ -486,6 +490,8 @@ github.com/libp2p/go-libp2p-core v0.4.0 h1:LjZJP/Yy4q8kc724izkYQ9v6YkAmkKCOaE5jL github.com/libp2p/go-libp2p-core v0.4.0/go.mod h1:49XGI+kc38oGVwqSBhDEwytaAxgZasHhFfQKibzTls0= github.com/libp2p/go-libp2p-core v0.5.0 h1:FBQ1fpq2Fo/ClyjojVJ5AKXlKhvNc/B6U0O+7AN1ffE= github.com/libp2p/go-libp2p-core v0.5.0/go.mod h1:49XGI+kc38oGVwqSBhDEwytaAxgZasHhFfQKibzTls0= +github.com/libp2p/go-libp2p-core v0.5.1 h1:6Cu7WljPQtGY2krBlMoD8L/zH3tMUsCbqNFH7cZwCoI= +github.com/libp2p/go-libp2p-core v0.5.1/go.mod h1:uN7L2D4EvPCvzSH5SrhR72UWbnSGpt5/a35Sm4upn4Y= github.com/libp2p/go-libp2p-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 h1:k9MFy+o2zGDNGsaoZl0MA3iZ75qXxr9OOoAZF+sD5OQ= @@ -496,6 +502,8 @@ github.com/libp2p/go-libp2p-discovery v0.1.0 h1:j+R6cokKcGbnZLf4kcNwpx6mDEUPF3N6 github.com/libp2p/go-libp2p-discovery v0.1.0/go.mod h1:4F/x+aldVHjHDHuX85x1zWoFTGElt8HnoDzwkFZm29g= github.com/libp2p/go-libp2p-discovery v0.2.0 h1:1p3YSOq7VsgaL+xVHPi8XAmtGyas6D2J6rWBEfz/aiY= github.com/libp2p/go-libp2p-discovery v0.2.0/go.mod h1:s4VGaxYMbw4+4+tsoQTqh7wfxg97AEdo4GYBt6BadWg= +github.com/libp2p/go-libp2p-discovery v0.3.0 h1:+JnYBRLzZQtRq0mK3xhyjBwHytLmJXMTZkQfbw+UrGA= +github.com/libp2p/go-libp2p-discovery v0.3.0/go.mod h1:o03drFnz9BVAZdzC/QUQ+NeQOu38Fu7LJGEOK2gQltw= github.com/libp2p/go-libp2p-gostream v0.2.1 h1:JjA9roGokaR2BgWmaI/3HQu1/+jSbVVDLatQGnVdGjI= github.com/libp2p/go-libp2p-gostream v0.2.1/go.mod h1:1Mjp3LDmkqICe5tH9yLVNCqFaRTy6OwBvuJV6j1b9Nk= github.com/libp2p/go-libp2p-host v0.0.1/go.mod h1:qWd+H1yuU0m5CwzAkvbSjqKairayEHdR5MMl7Cwa7Go= @@ -520,11 +528,15 @@ github.com/libp2p/go-libp2p-mplex v0.2.1 h1:E1xaJBQnbSiTHGI1gaBKmKhu1TUKkErKJnE8 github.com/libp2p/go-libp2p-mplex v0.2.1/go.mod h1:SC99Rxs8Vuzrf/6WhmH41kNn13TiYdAWNYHrwImKLnE= github.com/libp2p/go-libp2p-mplex v0.2.2 h1:+Ld7YDAfVERQ0E+qqjE7o6fHwKuM0SqTzYiwN1lVVSA= github.com/libp2p/go-libp2p-mplex v0.2.2/go.mod h1:74S9eum0tVQdAfFiKxAyKzNdSuLqw5oadDq7+L/FELo= +github.com/libp2p/go-libp2p-mplex v0.2.3 h1:2zijwaJvpdesST2MXpI5w9wWFRgYtMcpRX7rrw0jmOo= +github.com/libp2p/go-libp2p-mplex v0.2.3/go.mod h1:CK3p2+9qH9x+7ER/gWWDYJ3QW5ZxWDkm+dVvjfuG3ek= github.com/libp2p/go-libp2p-nat v0.0.2/go.mod h1:QrjXQSD5Dj4IJOdEcjHRkWTSomyxRo6HnUkf/TfQpLQ= github.com/libp2p/go-libp2p-nat v0.0.4 h1:+KXK324yaY701On8a0aGjTnw8467kW3ExKcqW2wwmyw= github.com/libp2p/go-libp2p-nat v0.0.4/go.mod h1:N9Js/zVtAXqaeT99cXgTV9e75KpnWCvVOiGzlcHmBbY= github.com/libp2p/go-libp2p-nat v0.0.5 h1:/mH8pXFVKleflDL1YwqMg27W9GD8kjEx7NY0P6eGc98= github.com/libp2p/go-libp2p-nat v0.0.5/go.mod h1:1qubaE5bTZMJE+E/uu2URroMbzdubFz1ChgiN79yKPE= +github.com/libp2p/go-libp2p-nat v0.0.6 h1:wMWis3kYynCbHoyKLPBEMu4YRLltbm8Mk08HGSfvTkU= +github.com/libp2p/go-libp2p-nat v0.0.6/go.mod h1:iV59LVhB3IkFvS6S6sauVTSOrNEANnINbI/fkaLimiw= github.com/libp2p/go-libp2p-net v0.0.1/go.mod h1:Yt3zgmlsHOgUWSXmt5V/Jpz9upuJBE8EgNU9DrCcR8c= github.com/libp2p/go-libp2p-net v0.0.2/go.mod h1:Yt3zgmlsHOgUWSXmt5V/Jpz9upuJBE8EgNU9DrCcR8c= github.com/libp2p/go-libp2p-netutil v0.0.1/go.mod h1:GdusFvujWZI9Vt0X5BKqwWWmZFxecf9Gt03cKxm2f/Q= @@ -577,12 +589,16 @@ github.com/libp2p/go-libp2p-secio v0.2.0 h1:ywzZBsWEEz2KNTn5RtzauEDq5RFEefPsttXY github.com/libp2p/go-libp2p-secio v0.2.0/go.mod h1:2JdZepB8J5V9mBp79BmwsaPQhRPNN2NrnB2lKQcdy6g= github.com/libp2p/go-libp2p-secio v0.2.1 h1:eNWbJTdyPA7NxhP7J3c5lT97DC5d+u+IldkgCYFTPVA= github.com/libp2p/go-libp2p-secio v0.2.1/go.mod h1:cWtZpILJqkqrSkiYcDBh5lA3wbT2Q+hz3rJQq3iftD8= +github.com/libp2p/go-libp2p-secio v0.2.2 h1:rLLPvShPQAcY6eNurKNZq3eZjPWfU9kXF2eI9jIYdrg= +github.com/libp2p/go-libp2p-secio v0.2.2/go.mod h1:wP3bS+m5AUnFA+OFO7Er03uO1mncHG0uVwGrwvjYlNY= github.com/libp2p/go-libp2p-swarm v0.0.1/go.mod h1:mh+KZxkbd3lQnveQ3j2q60BM1Cw2mX36XXQqwfPOShs= github.com/libp2p/go-libp2p-swarm v0.0.6/go.mod h1:s5GZvzg9xXe8sbeESuFpjt8CJPTCa8mhEusweJqyFy8= github.com/libp2p/go-libp2p-swarm v0.1.0/go.mod h1:wQVsCdjsuZoc730CgOvh5ox6K8evllckjebkdiY5ta4= github.com/libp2p/go-libp2p-swarm v0.1.1/go.mod h1:4NVJaLwq/dr5kEq79Jo6pMin7ZFwLx73ln1FTefR91Q= github.com/libp2p/go-libp2p-swarm v0.2.2 h1:T4hUpgEs2r371PweU3DuH7EOmBIdTBCwWs+FLcgx3bQ= github.com/libp2p/go-libp2p-swarm v0.2.2/go.mod h1:fvmtQ0T1nErXym1/aa1uJEyN7JzaTNyBcHImCxRpPKU= +github.com/libp2p/go-libp2p-swarm v0.2.3 h1:uVkCb8Blfg7HQ/f30TyHn1g/uCwXsAET7pU0U59gx/A= +github.com/libp2p/go-libp2p-swarm v0.2.3/go.mod h1:P2VO/EpxRyDxtChXz/VPVXyTnszHvokHKRhfkEgFKNM= github.com/libp2p/go-libp2p-testing v0.0.1/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= github.com/libp2p/go-libp2p-testing v0.0.2/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= github.com/libp2p/go-libp2p-testing v0.0.3/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= @@ -611,8 +627,8 @@ github.com/libp2p/go-libp2p-yamux v0.2.2 h1:eGvbqWqWY9S5lrpe2gA0UCOLCdzCgYSAR3vo github.com/libp2p/go-libp2p-yamux v0.2.2/go.mod h1:lIohaR0pT6mOt0AZ0L2dFze9hds9Req3OfS+B+dv4qw= github.com/libp2p/go-libp2p-yamux v0.2.5 h1:MuyItOqz03oi8npvjgMJxgnhllJLZnO/dKVOpTZ9+XI= github.com/libp2p/go-libp2p-yamux v0.2.5/go.mod h1:Zpgj6arbyQrmZ3wxSZxfBmbdnWtbZ48OpsfmQVTErwA= -github.com/libp2p/go-libp2p-yamux v0.2.6 h1:BXl4fEzzZwLUjoqoRJNx4co1UhvOwXaM+Qg2twEqEFU= -github.com/libp2p/go-libp2p-yamux v0.2.6/go.mod h1:YbnSVt8RYb3t6YBGPD9rLUT0vmmvcr/waaQ79PINpOM= +github.com/libp2p/go-libp2p-yamux v0.2.7 h1:vzKu0NVtxvEIDGCv6mjKRcK0gipSgaXmJZ6jFv0d/dk= +github.com/libp2p/go-libp2p-yamux v0.2.7/go.mod h1:X28ENrBMU/nm4I3Nx4sZ4dgjZ6VhLEn0XhIoZ5viCwU= github.com/libp2p/go-maddr-filter v0.0.1/go.mod h1:6eT12kSQMA9x2pvFQa+xesMKUBlj9VImZbj3B9FBH/Q= github.com/libp2p/go-maddr-filter v0.0.4/go.mod h1:6eT12kSQMA9x2pvFQa+xesMKUBlj9VImZbj3B9FBH/Q= github.com/libp2p/go-maddr-filter v0.0.5 h1:CW3AgbMO6vUvT4kf87y4N+0P8KUl2aqLYhrGyDUbLSg= @@ -624,6 +640,8 @@ github.com/libp2p/go-mplex v0.1.0 h1:/nBTy5+1yRyY82YaO6HXQRnO5IAGsXTjEJaR3LdTPc0 github.com/libp2p/go-mplex v0.1.0/go.mod h1:SXgmdki2kwCUlCCbfGLEgHjC4pFqhTp0ZoV6aiKgxDU= github.com/libp2p/go-mplex v0.1.1 h1:huPH/GGRJzmsHR9IZJJsrSwIM5YE2gL4ssgl1YWb/ps= github.com/libp2p/go-mplex v0.1.1/go.mod h1:Xgz2RDCi3co0LeZfgjm4OgUF15+sVR8SRcu3SFXI1lk= +github.com/libp2p/go-mplex v0.1.2 h1:qOg1s+WdGLlpkrczDqmhYzyk3vCfsQ8+RxRTQjOZWwI= +github.com/libp2p/go-mplex v0.1.2/go.mod h1:Xgz2RDCi3co0LeZfgjm4OgUF15+sVR8SRcu3SFXI1lk= github.com/libp2p/go-msgio v0.0.1/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= github.com/libp2p/go-msgio v0.0.2/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= github.com/libp2p/go-msgio v0.0.3/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= @@ -633,6 +651,10 @@ github.com/libp2p/go-nat v0.0.3 h1:l6fKV+p0Xa354EqQOQP+d8CivdLM4kl5GxC1hSc/UeI= github.com/libp2p/go-nat v0.0.3/go.mod h1:88nUEt0k0JD45Bk93NIwDqjlhiOwOoV36GchpcVc1yI= github.com/libp2p/go-nat v0.0.4 h1:KbizNnq8YIf7+Hn7+VFL/xE0eDrkPru2zIO9NMwL8UQ= github.com/libp2p/go-nat v0.0.4/go.mod h1:Nmw50VAvKuk38jUBcmNh6p9lUJLoODbJRvYAa/+KSDo= +github.com/libp2p/go-nat v0.0.5 h1:qxnwkco8RLKqVh1NmjQ+tJ8p8khNLFxuElYG/TwqW4Q= +github.com/libp2p/go-nat v0.0.5/go.mod h1:B7NxsVNPZmRLvMOwiEO1scOSyjA56zxYAGv1yQgRkEU= +github.com/libp2p/go-netroute v0.1.2 h1:UHhB35chwgvcRI392znJA3RCBtZ3MpE3ahNCN5MR4Xg= +github.com/libp2p/go-netroute v0.1.2/go.mod h1:jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdmLPL2n9MKbk= github.com/libp2p/go-openssl v0.0.2 h1:9pP2d3Ubaxkv7ZisLjx9BFwgOGnQdQYnfcH29HNY3ls= github.com/libp2p/go-openssl v0.0.2/go.mod h1:v8Zw2ijCSWBQi8Pq5GAixw6DbFfa9u6VIYDXnvOXkc0= github.com/libp2p/go-openssl v0.0.3 h1:wjlG7HvQkt4Fq4cfH33Ivpwp0omaElYEi9z26qaIkIk= @@ -644,6 +666,10 @@ github.com/libp2p/go-reuseport v0.0.1/go.mod h1:jn6RmB1ufnQwl0Q1f+YxAj8isJgDCQza github.com/libp2p/go-reuseport-transport v0.0.1/go.mod h1:YkbSDrvjUVDL6b8XqriyA20obEtsW9BLkuOUyQAOCbs= github.com/libp2p/go-reuseport-transport v0.0.2 h1:WglMwyXyBu61CMkjCCtnmqNqnjib0GIEjMiHTwR/KN4= github.com/libp2p/go-reuseport-transport v0.0.2/go.mod h1:YkbSDrvjUVDL6b8XqriyA20obEtsW9BLkuOUyQAOCbs= +github.com/libp2p/go-reuseport-transport v0.0.3 h1:zzOeXnTooCkRvoH+bSXEfXhn76+LAiwoneM0gnXjF2M= +github.com/libp2p/go-reuseport-transport v0.0.3/go.mod h1:Spv+MPft1exxARzP2Sruj2Wb5JSyHNncjf1Oi2dEbzM= +github.com/libp2p/go-sockaddr v0.0.2 h1:tCuXfpA9rq7llM/v834RKc/Xvovy/AqM9kHvTV/jY/Q= +github.com/libp2p/go-sockaddr v0.0.2/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= github.com/libp2p/go-socket-activation v0.0.2 h1:VLU3IbrUUqu4DMhxA9857Q63qUpEAbCz5RqSnLCx5jE= github.com/libp2p/go-socket-activation v0.0.2/go.mod h1:KP44C+yZ7gA8sTxavgaD0b8vXVFJwam2CEW0s7+f094= github.com/libp2p/go-stream-muxer v0.0.1/go.mod h1:bAo8x7YkSpadMTbtTaxGVHWUQsR/l5MEaHbKaliuT14= @@ -656,6 +682,8 @@ github.com/libp2p/go-tcp-transport v0.0.4/go.mod h1:+E8HvC8ezEVOxIo3V5vCK9l1y/19 github.com/libp2p/go-tcp-transport v0.1.0/go.mod h1:oJ8I5VXryj493DEJ7OsBieu8fcg2nHGctwtInJVpipc= github.com/libp2p/go-tcp-transport v0.1.1 h1:yGlqURmqgNA2fvzjSgZNlHcsd/IulAnKM8Ncu+vlqnw= github.com/libp2p/go-tcp-transport v0.1.1/go.mod h1:3HzGvLbx6etZjnFlERyakbaYPdfjg2pWP97dFZworkY= +github.com/libp2p/go-tcp-transport v0.2.0 h1:YoThc549fzmNJIh7XjHVtMIFaEDRtIrtWciG5LyYAPo= +github.com/libp2p/go-tcp-transport v0.2.0/go.mod h1:vX2U0CnWimU4h0SGSEsg++AzvBcroCGYw28kh94oLe0= github.com/libp2p/go-testutil v0.0.1/go.mod h1:iAcJc/DKJQanJ5ws2V+u5ywdL2n12X1WbbEG+Jjy69I= github.com/libp2p/go-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= @@ -663,6 +691,8 @@ github.com/libp2p/go-ws-transport v0.0.5/go.mod h1:Qbl4BxPfXXhhd/o0wcrgoaItHqA9t github.com/libp2p/go-ws-transport v0.1.0/go.mod h1:rjw1MG1LU9YDC6gzmwObkPd/Sqwhw7yT74kj3raBFuo= github.com/libp2p/go-ws-transport v0.2.0 h1:MJCw2OrPA9+76YNRvdo1wMnSOxb9Bivj6sVFY1Xrj6w= github.com/libp2p/go-ws-transport v0.2.0/go.mod h1:9BHJz/4Q5A9ludYWKoGCFC5gUElzlHoKzu0yY9p/klM= +github.com/libp2p/go-ws-transport v0.3.0 h1:mjo6pL5aVR9rCjl9wNq3DupbaQlyR61pzoOT2MdtxaA= +github.com/libp2p/go-ws-transport v0.3.0/go.mod h1:bpgTJmRZAvVHrgHybCVyqoBmyLQ1fiZuEaBYusP5zsk= github.com/libp2p/go-yamux v1.2.1/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= github.com/libp2p/go-yamux v1.2.2/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= github.com/libp2p/go-yamux v1.2.3 h1:xX8A36vpXb59frIzWFdEgptLMsOANMFq2K7fPRlunYI= @@ -671,8 +701,8 @@ github.com/libp2p/go-yamux v1.3.0 h1:FsYzT16Wq2XqUGJsBbOxoz9g+dFklvNi7jN6YFPfl7U github.com/libp2p/go-yamux v1.3.0/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= github.com/libp2p/go-yamux v1.3.3 h1:mWuzZRCAeTBFdynLlsYgA/EIeMOLr8XY04wa52NRhsE= github.com/libp2p/go-yamux v1.3.3/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= -github.com/libp2p/go-yamux v1.3.4 h1:CptmtNfQomI9RpM7LFJhVBFkwp2zwEXIskEfWwwtoHg= -github.com/libp2p/go-yamux v1.3.4/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= +github.com/libp2p/go-yamux v1.3.5 h1:ibuz4naPAully0pN6J/kmUARiqLpnDQIzI/8GCOrljg= +github.com/libp2p/go-yamux v1.3.5/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= github.com/lucas-clemente/quic-go v0.14.4 h1:LdXgELrB93kvTqbZyEf+mcsGvmyE+EHsLFz1dqbR5PI= github.com/lucas-clemente/quic-go v0.14.4/go.mod h1:Vn3/Fb0/77b02SGhQk36KzOUmXgVpFfizUfW5WMaqyU= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= @@ -756,8 +786,12 @@ github.com/multiformats/go-multiaddr-net v0.1.2 h1:P7zcBH9FRETdPkDrylcXVjQLQ2t1J github.com/multiformats/go-multiaddr-net v0.1.2/go.mod h1:QsWt3XK/3hwvNxZJp92iMQKME1qHfpYmyIjFVsSOY6Y= github.com/multiformats/go-multiaddr-net v0.1.3 h1:q/IYAvoPKuRzGeERn3uacWgm0LIWkLZBAvO5DxSzq3g= github.com/multiformats/go-multiaddr-net v0.1.3/go.mod h1:ilNnaM9HbmVFqsb/qcNysjCu4PVONlrBZpHIrw/qQuA= +github.com/multiformats/go-multiaddr-net v0.1.4 h1:g6gwydsfADqFvrHoMkS0n9Ok9CG6F7ytOH/bJDkhIOY= +github.com/multiformats/go-multiaddr-net v0.1.4/go.mod h1:ilNnaM9HbmVFqsb/qcNysjCu4PVONlrBZpHIrw/qQuA= github.com/multiformats/go-multibase v0.0.1 h1:PN9/v21eLywrFWdFNsFKaU04kLJzuYzmrJR+ubhT9qA= github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= +github.com/multiformats/go-multibase v0.0.2 h1:2pAgScmS1g9XjH7EtAfNhTuyrWYEWcxy0G5Wo85hWDA= +github.com/multiformats/go-multibase v0.0.2/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po= github.com/multiformats/go-multihash v0.0.6/go.mod h1:XuKXPp8VHcTygube3OWZC+aZrA+H1IhmjoCDtJc7PXM= @@ -927,12 +961,8 @@ go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/dig v1.8.0 h1:1rR6hnL/bu1EVcjnRDN5kx1vbIjEJDTGhSQ2B3ddpcI= -go.uber.org/dig v1.8.0/go.mod h1:X34SnWGr8Fyla9zQNO2GSO2D+TIuqB14OS8JhYocIyw= go.uber.org/dig v1.9.0 h1:pJTDXKEhRqBI8W7rU7kwT5EgyRZuSMVSFcZolOvKK9U= go.uber.org/dig v1.9.0/go.mod h1:X34SnWGr8Fyla9zQNO2GSO2D+TIuqB14OS8JhYocIyw= -go.uber.org/fx v1.10.0 h1:S2K/H8oNied0Je/mLKdWzEWKZfv9jtxSDm8CnwK+5Fg= -go.uber.org/fx v1.10.0/go.mod h1:vLRicqpG/qQEzno4SYU86iCwfT95EZza+Eba0ItuxqY= go.uber.org/fx v1.11.0 h1:WTxcE9VicMCGSB//JfMtpD9XP500wJx6w8lYEcsdPQk= go.uber.org/fx v1.11.0/go.mod h1:egT3Kyg1JFYQkvKLZ3EsykxkNrZxgXS+gKoKo7abERY= go.uber.org/goleak v0.10.0 h1:G3eWbSNIskeRqtsN/1uI5B+eP73y3JUuBsv9AZjehb4= @@ -1026,6 +1056,7 @@ golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190302025703-b6889370fb10/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1047,8 +1078,8 @@ golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d h1:nc5K6ox/4lTFbMVSL9WRR81ixkcwXThoiF6yf+R9scA= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= From 7b750664fb0c5ca3ee40f624758e324f7894f843 Mon Sep 17 00:00:00 2001 From: "@RubenKelevra" Date: Sat, 4 Apr 2020 05:34:56 +0200 Subject: [PATCH 544/671] Revert last change (the default is now printed twice) --- core/commands/keystore.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/commands/keystore.go b/core/commands/keystore.go index e92e2b35766..f22d64afae3 100644 --- a/core/commands/keystore.go +++ b/core/commands/keystore.go @@ -63,7 +63,7 @@ var keyGenCmd = &cmds.Command{ Tagline: "Create a new keypair", }, Options: []cmds.Option{ - cmds.StringOption(keyStoreTypeOptionName, "t", "type of the key to create: rsa, ed25519. Default: rsa").WithDefault("rsa"), + cmds.StringOption(keyStoreTypeOptionName, "t", "type of the key to create: rsa, ed25519").WithDefault("rsa"), cmds.IntOption(keyStoreSizeOptionName, "s", "size of the key to generate"), }, Arguments: []cmds.Argument{ From 1b490476e5517931b8d31a6636e7008771db201d Mon Sep 17 00:00:00 2001 From: Hector Sanjuan Date: Sat, 4 Apr 2020 01:55:36 +0200 Subject: [PATCH 545/671] HTTP API: Disallow GET requests on API This commit upgrades go-ipfs-cmds and configures the commands HTTP API Handler to only allow POST/OPTIONS, disallowing GET and others in the handling of command requests in the IPFS HTTP API (where before every type of request method was handled, with GET/POST/PUT/PATCH being equivalent). The Read-Only commands that the HTTP API attaches to the gateway endpoint will additional handled GET as they did before (but stop handling PUT,DELETEs). By limiting the request types we address the possibility that a website accessed by a browser abuses the IPFS API by issuing GET requests to it which have no Origin or Referrer set, and are thus bypass CORS and CSRF protections. This is a breaking change for clients that relay on GET requests against the HTTP endpoint (usually :5001). Applications integrating on top of the gateway-read-only API should still work (including cross-domain access). Co-Authored-By: Steven Allen Co-Authored-By: Marcin Rataj --- core/corehttp/commands.go | 18 ++++++++++++------ core/corehttp/webui.go | 3 ++- go.mod | 2 +- go.sum | 6 ++---- test/dependencies/go.mod | 2 +- test/dependencies/go.sum | 4 ++-- test/sharness/t0051-object.sh | 8 ++++---- test/sharness/t0060-daemon.sh | 6 +++--- test/sharness/t0090-get.sh | 2 +- test/sharness/t0100-name.sh | 2 +- test/sharness/t0110-gateway.sh | 2 +- ...0230-channel-streaming-http-content-type.sh | 4 ++-- .../t0600-issues-and-regressions-online.sh | 12 ++++++------ 13 files changed, 38 insertions(+), 33 deletions(-) diff --git a/core/corehttp/commands.go b/core/corehttp/commands.go index d63099bfbfc..0f9b8d60309 100644 --- a/core/corehttp/commands.go +++ b/core/corehttp/commands.go @@ -117,11 +117,17 @@ func patchCORSVars(c *cmdsHttp.ServerConfig, addr net.Addr) { c.SetAllowedOrigins(newOrigins...) } -func commandsOption(cctx oldcmds.Context, command *cmds.Command) ServeOption { +func commandsOption(cctx oldcmds.Context, command *cmds.Command, allowGet bool) ServeOption { return func(n *core.IpfsNode, l net.Listener, mux *http.ServeMux) (*http.ServeMux, error) { cfg := cmdsHttp.NewServerConfig() - cfg.SetAllowedMethods(http.MethodGet, http.MethodPost, http.MethodPut) + cfg.AllowGet = allowGet + corsAllowedMethods := []string{http.MethodPost} + if allowGet { + corsAllowedMethods = append(corsAllowedMethods, http.MethodGet) + } + + cfg.SetAllowedMethods(corsAllowedMethods...) cfg.APIPath = APIPath rcfg, err := n.Repo.Config() if err != nil { @@ -140,15 +146,15 @@ func commandsOption(cctx oldcmds.Context, command *cmds.Command) ServeOption { } // CommandsOption constructs a ServerOption for hooking the commands into the -// HTTP server. +// HTTP server. It will NOT allow GET requests. func CommandsOption(cctx oldcmds.Context) ServeOption { - return commandsOption(cctx, corecommands.Root) + return commandsOption(cctx, corecommands.Root, false) } // CommandsROOption constructs a ServerOption for hooking the read-only commands -// into the HTTP server. +// into the HTTP server. It will allow GET requests. func CommandsROOption(cctx oldcmds.Context) ServeOption { - return commandsOption(cctx, corecommands.RootRO) + return commandsOption(cctx, corecommands.RootRO, true) } // CheckVersionOption returns a ServeOption that checks whether the client ipfs version matches. Does nothing when the user agent string does not contain `/go-ipfs/` diff --git a/core/corehttp/webui.go b/core/corehttp/webui.go index 21d3eeea61c..4a31f719a94 100644 --- a/core/corehttp/webui.go +++ b/core/corehttp/webui.go @@ -1,7 +1,7 @@ package corehttp // TODO: move to IPNS -const WebUIPath = "/ipfs/Qmexhq2sBHnXQbvyP2GfUdbnY7HCagH2Mw5vUNSBn2nxip" +const WebUIPath = "/ipfs/bafybeihpkhgv3jfnyx5qcexded7agjpwbgvtc3o6lnk6n3cs37fh4xx4fe" // this is a list of all past webUI paths. var WebUIPaths = []string{ @@ -33,6 +33,7 @@ var WebUIPaths = []string{ "/ipfs/QmcjeTciMNgEBe4xXvEaA4TQtwTRkXucx7DmKWViXSmX7m", "/ipfs/QmfNbSskgvTXYhuqP8tb9AKbCkyRcCy3WeiXwD9y5LeoqK", "/ipfs/QmPkojhjJkJ5LEGBDrAvdftrjAYmi9GU5Cq27mWvZTDieW", + "/ipfs/Qmexhq2sBHnXQbvyP2GfUdbnY7HCagH2Mw5vUNSBn2nxip", } var WebUIOption = RedirectOption("webui", WebUIPath) diff --git a/go.mod b/go.mod index 55eb75ff1a1..6322309e151 100644 --- a/go.mod +++ b/go.mod @@ -30,7 +30,7 @@ require ( github.com/ipfs/go-graphsync v0.0.5 github.com/ipfs/go-ipfs-blockstore v0.1.4 github.com/ipfs/go-ipfs-chunker v0.0.5 - github.com/ipfs/go-ipfs-cmds v0.1.4 + github.com/ipfs/go-ipfs-cmds v0.2.1 github.com/ipfs/go-ipfs-config v0.4.0 github.com/ipfs/go-ipfs-ds-help v0.1.1 github.com/ipfs/go-ipfs-exchange-interface v0.0.1 diff --git a/go.sum b/go.sum index 92a1fd9b86a..08c85f0c091 100644 --- a/go.sum +++ b/go.sum @@ -256,8 +256,8 @@ github.com/ipfs/go-ipfs-chunker v0.0.1 h1:cHUUxKFQ99pozdahi+uSC/3Y6HeRpi9oTeUHbE 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.1.4 h1:l5QAc1iaoMZeBd2vpanrHWs26haEBL4PVqgoHJNG2GE= -github.com/ipfs/go-ipfs-cmds v0.1.4/go.mod h1:wm+C6M8FYDcWPU/EdWqMuHvdyWborFh+GuDl6Ov6sM0= +github.com/ipfs/go-ipfs-cmds v0.2.1 h1:xnZJjonqngoQRsrugXTQPMRn2KZwdn5H8N5+bLLYpO0= +github.com/ipfs/go-ipfs-cmds v0.2.1/go.mod h1:kqlUrp6m2ceoaJe40cXpADCi5aS6NKRn0NIeuLp5CeM= github.com/ipfs/go-ipfs-config v0.4.0 h1:MOXdj8EYQG55v1y+5e1QcctDKPEGobdwnXaDVa0/cc0= github.com/ipfs/go-ipfs-config v0.4.0/go.mod h1:nSLCFtlaL+2rbl3F+9D4gQZQbT1LjRKx7TJg/IHz6oM= github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= @@ -274,8 +274,6 @@ github.com/ipfs/go-ipfs-exchange-offline v0.0.1/go.mod h1:WhHSFCVYX36H/anEKQboAz 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.4/go.mod h1:INEFm0LL2LWXBhNJ2PMIIb2w45hpXgPjNoE7yA8Y1d4= -github.com/ipfs/go-ipfs-files v0.0.7 h1:s5BRD12ndahqYifeH1S8Z73zqZhR+3IdKYAG9PiETs0= -github.com/ipfs/go-ipfs-files v0.0.7/go.mod h1:wiN/jSG8FKyk7N0WyctKSvq3ljIa2NNTiZB55kpTdOs= 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= diff --git a/test/dependencies/go.mod b/test/dependencies/go.mod index 288f131fba9..9c33af08235 100644 --- a/test/dependencies/go.mod +++ b/test/dependencies/go.mod @@ -17,7 +17,7 @@ require ( github.com/ipfs/go-unixfs v0.2.4 github.com/ipfs/hang-fds v0.0.2 github.com/ipfs/iptb v1.4.0 - github.com/ipfs/iptb-plugins v0.2.1 + github.com/ipfs/iptb-plugins v0.2.2 github.com/ipld/go-ipld-prime v0.0.2-0.20191108012745-28a82f04c785 github.com/jbenet/go-random v0.0.0-20190219211222-123a90aedc0c github.com/jbenet/go-random-files v0.0.0-20190219210431-31b3f20ebded diff --git a/test/dependencies/go.sum b/test/dependencies/go.sum index 1ca3ce20b39..f4ea381a1ad 100644 --- a/test/dependencies/go.sum +++ b/test/dependencies/go.sum @@ -295,8 +295,8 @@ github.com/ipfs/hang-fds v0.0.2 h1:ffZPd+OFbKpfjNAoBCI+G7okTQKd7oS1jCEDm2Kzm4c= github.com/ipfs/hang-fds v0.0.2/go.mod h1:Ajpp/qR2orKbv5LsZmotGRASTcH38MwcIG5vTlZ9y8k= github.com/ipfs/iptb v1.4.0 h1:YFYTrCkLMRwk/35IMyC6+yjoQSHTEcNcefBStLJzgvo= github.com/ipfs/iptb v1.4.0/go.mod h1:1rzHpCYtNp87/+hTxG5TfCVn/yMY3dKnLn8tBiMfdmg= -github.com/ipfs/iptb-plugins v0.2.1 h1:au4HWn9/pRPbkxA08pDx2oRAs4cnbgQWgV0teYXuuGA= -github.com/ipfs/iptb-plugins v0.2.1/go.mod h1:QXMbtIWZ+jRsW8a4h13qAKU7jcM7qaittO8wOsTP0Rs= +github.com/ipfs/iptb-plugins v0.2.2 h1:HleRKMeex/jmQrmNG36v51M3eZO5j9BhFplBPGs0qGQ= +github.com/ipfs/iptb-plugins v0.2.2/go.mod h1:QXMbtIWZ+jRsW8a4h13qAKU7jcM7qaittO8wOsTP0Rs= github.com/ipld/go-ipld-prime v0.0.2-0.20191108012745-28a82f04c785 h1:fASnkvtR+SmB2y453RxmDD3Uvd4LonVUgFGk9JoDaZs= github.com/ipld/go-ipld-prime v0.0.2-0.20191108012745-28a82f04c785/go.mod h1:bDDSvVz7vaK12FNvMeRYnpRFkSUPNQOiCYQezMD/P3w= github.com/ipld/go-ipld-prime-proto v0.0.0-20191113031812-e32bd156a1e5 h1:lSip43rAdyGA+yRQuy6ju0ucZkWpYc1F2CTQtZTVW/4= diff --git a/test/sharness/t0051-object.sh b/test/sharness/t0051-object.sh index 4f8e7e12d0f..363073efc32 100755 --- a/test/sharness/t0051-object.sh +++ b/test/sharness/t0051-object.sh @@ -419,19 +419,19 @@ test_object_cmd() { test_object_content_type() { test_expect_success "'ipfs object get --encoding=protobuf' returns the correct content type" ' - curl -sI "http://$API_ADDR/api/v0/object/get?arg=$HASH&encoding=protobuf" | grep -q "^Content-Type: application/protobuf" + curl -X POST -sI "http://$API_ADDR/api/v0/object/get?arg=$HASH&encoding=protobuf" | grep -q "^Content-Type: application/protobuf" ' test_expect_success "'ipfs object get --encoding=json' returns the correct content type" ' - curl -sI "http://$API_ADDR/api/v0/object/get?arg=$HASH&encoding=json" | grep -q "^Content-Type: application/json" + curl -X POST -sI "http://$API_ADDR/api/v0/object/get?arg=$HASH&encoding=json" | grep -q "^Content-Type: application/json" ' test_expect_success "'ipfs object get --encoding=text' returns the correct content type" ' - curl -sI "http://$API_ADDR/api/v0/object/get?arg=$HASH&encoding=text" | grep -q "^Content-Type: text/plain" + curl -X POST -sI "http://$API_ADDR/api/v0/object/get?arg=$HASH&encoding=text" | grep -q "^Content-Type: text/plain" ' test_expect_success "'ipfs object get --encoding=xml' returns the correct content type" ' - curl -sI "http://$API_ADDR/api/v0/object/get?arg=$HASH&encoding=xml" | grep -q "^Content-Type: application/xml" + curl -X POST -sI "http://$API_ADDR/api/v0/object/get?arg=$HASH&encoding=xml" | grep -q "^Content-Type: application/xml" ' } diff --git a/test/sharness/t0060-daemon.sh b/test/sharness/t0060-daemon.sh index 7e7c658fbea..f85a610ce0a 100755 --- a/test/sharness/t0060-daemon.sh +++ b/test/sharness/t0060-daemon.sh @@ -65,11 +65,11 @@ test_expect_success "ipfs peer id looks good" ' # this is for checking SetAllowedOrigins race condition for the api and gateway # See https://github.com/ipfs/go-ipfs/pull/1966 test_expect_success "ipfs API works with the correct allowed origin port" ' - curl -s -X GET -H "Origin:http://localhost:$API_PORT" -I "http://$API_ADDR/api/v0/version" + curl -s -X POST -H "Origin:http://localhost:$API_PORT" -I "http://$API_ADDR/api/v0/version" ' test_expect_success "ipfs gateway works with the correct allowed origin port" ' - curl -s -X GET -H "Origin:http://localhost:$GWAY_PORT" -I "http://$GWAY_ADDR/api/v0/version" + curl -s -X POST -H "Origin:http://localhost:$GWAY_PORT" -I "http://$GWAY_ADDR/api/v0/version" ' test_expect_success "ipfs daemon output looks good" ' @@ -134,7 +134,7 @@ test_expect_success SOCAT "transport should be encrypted ( needs socat )" ' ' test_expect_success "output from streaming commands works" ' - test_expect_code 28 curl -m 5 http://localhost:$API_PORT/api/v0/stats/bw\?poll=true > statsout + test_expect_code 28 curl -X POST -m 5 http://localhost:$API_PORT/api/v0/stats/bw\?poll=true > statsout ' test_expect_success "output looks good" ' diff --git a/test/sharness/t0090-get.sh b/test/sharness/t0090-get.sh index e19d5506d9c..750c3017238 100755 --- a/test/sharness/t0090-get.sh +++ b/test/sharness/t0090-get.sh @@ -184,7 +184,7 @@ test_launch_ipfs_daemon test_get_cmd test_expect_success "empty request to get doesn't panic and returns error" ' - curl "http://$API_ADDR/api/v0/get" > curl_out || true && + curl -X POST "http://$API_ADDR/api/v0/get" > curl_out || true && grep "argument \"ipfs-path\" is required" curl_out ' test_kill_ipfs_daemon diff --git a/test/sharness/t0100-name.sh b/test/sharness/t0100-name.sh index e03f1553cf9..96d2ce5ea82 100755 --- a/test/sharness/t0100-name.sh +++ b/test/sharness/t0100-name.sh @@ -195,7 +195,7 @@ test_expect_success "resolve output looks good" ' ' test_expect_success "empty request to name publish doesn't panic and returns error" ' - curl "http://$API_ADDR/api/v0/name/publish" > curl_out || true && + curl -X POST "http://$API_ADDR/api/v0/name/publish" > curl_out || true && grep "argument \"ipfs-path\" is required" curl_out ' diff --git a/test/sharness/t0110-gateway.sh b/test/sharness/t0110-gateway.sh index 68172cb5655..f64618f740f 100755 --- a/test/sharness/t0110-gateway.sh +++ b/test/sharness/t0110-gateway.sh @@ -104,7 +104,7 @@ test_expect_success "log output looks good" ' ' test_expect_success "GET /api/v0/version succeeds" ' - curl -v "http://127.0.0.1:$apiport/api/v0/version" 2> version_out + curl -X POST -v "http://127.0.0.1:$apiport/api/v0/version" 2> version_out ' test_expect_success "output only has one transfer encoding header" ' diff --git a/test/sharness/t0230-channel-streaming-http-content-type.sh b/test/sharness/t0230-channel-streaming-http-content-type.sh index deffffa2c2f..34ef57771fb 100755 --- a/test/sharness/t0230-channel-streaming-http-content-type.sh +++ b/test/sharness/t0230-channel-streaming-http-content-type.sh @@ -16,7 +16,7 @@ test_ls_cmd() { mkdir -p testdir && echo "hello test" >testdir/test.txt && ipfs add -r testdir && - curl -i "http://$API_ADDR/api/v0/refs?arg=QmTcJAn3JP8ZMAKS6WS75q8sbTyojWKbxcUHgLYGWur4Ym&stream-channels=true&encoding=text" >actual_output + curl -X POST -i "http://$API_ADDR/api/v0/refs?arg=QmTcJAn3JP8ZMAKS6WS75q8sbTyojWKbxcUHgLYGWur4Ym&stream-channels=true&encoding=text" >actual_output ' test_expect_success "Text encoded channel-streaming command output looks good" ' @@ -39,7 +39,7 @@ test_ls_cmd() { mkdir -p testdir && echo "hello test" >testdir/test.txt && ipfs add -r testdir && - curl -i "http://$API_ADDR/api/v0/refs?arg=QmTcJAn3JP8ZMAKS6WS75q8sbTyojWKbxcUHgLYGWur4Ym&stream-channels=true&encoding=json" >actual_output + curl -X POST -i "http://$API_ADDR/api/v0/refs?arg=QmTcJAn3JP8ZMAKS6WS75q8sbTyojWKbxcUHgLYGWur4Ym&stream-channels=true&encoding=json" >actual_output ' test_expect_success "JSON encoded channel-streaming command output looks good" ' diff --git a/test/sharness/t0600-issues-and-regressions-online.sh b/test/sharness/t0600-issues-and-regressions-online.sh index 8496a0f03e5..344d37fd1fa 100755 --- a/test/sharness/t0600-issues-and-regressions-online.sh +++ b/test/sharness/t0600-issues-and-regressions-online.sh @@ -11,16 +11,16 @@ test_launch_ipfs_daemon # Tests go here test_expect_success "commands command with flag flags works via HTTP API - #2301" ' - curl "http://$API_ADDR/api/v0/commands?flags" | grep "verbose" + curl -X POST "http://$API_ADDR/api/v0/commands?flags" | grep "verbose" ' test_expect_success "ipfs refs local over HTTP API returns NDJOSN not flat - #2803" ' echo "Hello World" | ipfs add && - curl "http://$API_ADDR/api/v0/refs/local" | grep "Ref" | grep "Err" + curl -X POST "http://$API_ADDR/api/v0/refs/local" | grep "Ref" | grep "Err" ' test_expect_success "args expecting stdin dont crash when not given" ' - curl "$API_ADDR/api/v0/bootstrap/add" > result + curl -X POST "$API_ADDR/api/v0/bootstrap/add" > result ' test_expect_success "no panic traces on daemon" ' @@ -28,20 +28,20 @@ test_expect_success "no panic traces on daemon" ' ' test_expect_success "metrics work" ' - curl "$API_ADDR/debug/metrics/prometheus" > pro_data && + curl -X POST "$API_ADDR/debug/metrics/prometheus" > pro_data && grep "ipfs_bs_cache_arc_hits_total" < pro_data || test_fsh cat pro_data ' test_expect_success "pin add api looks right - #3753" ' HASH=$(echo "foo" | ipfs add -q) && - curl "http://$API_ADDR/api/v0/pin/add/$HASH" > pinadd_out && + curl -X POST "http://$API_ADDR/api/v0/pin/add/$HASH" > pinadd_out && echo "{\"Pins\":[\"QmYNmQKp6SuaVrpgWRsPTgCQCnpxUYGq76YEKBXuj2N4H6\"]}" > pinadd_exp && test_cmp pinadd_out pinadd_exp ' test_expect_success "pin add api looks right - #3753" ' - curl "http://$API_ADDR/api/v0/pin/rm/$HASH" > pinrm_out && + curl -X POST "http://$API_ADDR/api/v0/pin/rm/$HASH" > pinrm_out && echo "{\"Pins\":[\"QmYNmQKp6SuaVrpgWRsPTgCQCnpxUYGq76YEKBXuj2N4H6\"]}" > pinrm_exp && test_cmp pinrm_out pinrm_exp ' From 73405436159b5953f6ed107f45d7aa3badf4bf44 Mon Sep 17 00:00:00 2001 From: Hector Sanjuan Date: Sat, 4 Apr 2020 02:06:06 +0200 Subject: [PATCH 546/671] corehttp: Gateway handler: add Allow headers when returning MethodNotAllowed Spec says that response with 405 must set Allow headers. --- core/corehttp/gateway_handler.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/corehttp/gateway_handler.go b/core/corehttp/gateway_handler.go index d3c4d26392d..d26f21d54a2 100644 --- a/core/corehttp/gateway_handler.go +++ b/core/corehttp/gateway_handler.go @@ -127,6 +127,9 @@ func (i *gatewayHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { if !i.config.Writable { status = http.StatusMethodNotAllowed errmsg = errmsg + "read only access" + w.Header().Add("Allow", http.MethodGet) + w.Header().Add("Allow", http.MethodHead) + w.Header().Add("Allow", http.MethodOptions) } else { status = http.StatusBadRequest errmsg = errmsg + "bad request for " + r.URL.Path From 51bf173f19e8a0506842f714f10d15d932cbbcb0 Mon Sep 17 00:00:00 2001 From: "@RubenKelevra" Date: Sun, 5 Apr 2020 18:47:49 +0200 Subject: [PATCH 547/671] update bash completion for `ipfs add` --- misc/completion/ipfs-completion.bash | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misc/completion/ipfs-completion.bash b/misc/completion/ipfs-completion.bash index c1487cb34bc..a75e4668610 100644 --- a/misc/completion/ipfs-completion.bash +++ b/misc/completion/ipfs-completion.bash @@ -19,7 +19,7 @@ _ipfs_add() elif [ "${prev}" == "--pin" ] ; then _ipfs_comp "true false" elif [[ ${word} == -* ]] ; then - _ipfs_comp "--recursive --quiet --silent --progress --trickle --only-hash --wrap-with-directory --hidden --chunker= --pin= --raw-leaves --help " + _ipfs_comp "--recursive --dereference-args --stdin-name= --hidden --ignore= --ignore-rules-path= --quiet --quieter --silent --progress --trickle --only-hash --wrap-with-directory --chunker= --pin= --raw-leaves --nocopy --fscache --cid-version= --hash= --inline --inline-limit= --help " else _ipfs_filesystem_complete fi From ae5bd6f6496fde6d0c3a5a6d3f7b113e16447cb0 Mon Sep 17 00:00:00 2001 From: "@RubenKelevra" Date: Wed, 1 Apr 2020 23:13:08 +0200 Subject: [PATCH 548/671] files.go: fix typos / wording --- core/commands/files.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/core/commands/files.go b/core/commands/files.go index 132598428bb..4300b5a9034 100644 --- a/core/commands/files.go +++ b/core/commands/files.go @@ -36,11 +36,11 @@ var FilesCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Interact with unixfs files.", ShortDescription: ` -Files is an API for manipulating IPFS objects as if they were a unix +Files is an API for manipulating IPFS objects as if they were a Unix filesystem. The files facility interacts with MFS (Mutable File System). MFS acts as a -single, dynamic filesystem mount. MFS has a root CID which is transparently +single, dynamic filesystem mount. MFS has a root CID that is transparently updated when a change happens (and can be checked with "ipfs files stat /"). All files and folders within MFS are respected and will not be cleaned up @@ -61,7 +61,7 @@ to true. Use caution when setting this flag to false. It will improve performance for large numbers of file operations, but it does so at the cost of consistency guarantees. If the daemon is unexpectedly killed before running 'ipfs files flush' on the files in question, then data may be lost. This also -applies to running 'ipfs repo gc' concurrently with '--flush=false' +applies to run 'ipfs repo gc' concurrently with '--flush=false' operations. `, }, @@ -552,10 +552,10 @@ const ( var filesReadCmd = &cmds.Command{ Helptext: cmds.HelpText{ - Tagline: "Read a file in a given mfs.", + Tagline: "Read a file in a given MFS.", ShortDescription: ` Read a specified number of bytes from a file at a given offset. By default, -will read the entire file similar to unix cat. +it will read the entire file similar to the Unix cat. Examples: @@ -647,7 +647,7 @@ var filesMvCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Move files.", ShortDescription: ` -Move files around. Just like traditional unix mv. +Move files around. Just like the traditional Unix mv. Example: @@ -702,7 +702,7 @@ a beginning offset to write to. The entire length of the input will be written. If the '--create' option is specified, the file will be created if it does not -exist. Nonexistant intermediate directories will not be created unless the +exist. Nonexistent intermediate directories will not be created unless the '--parents' option is specified. Newly created files will have the same CID version and hash function of the @@ -712,7 +712,7 @@ Newly created leaves will be in the legacy format (Protobuf) if the CID version is 0, or raw if the CID version is non-zero. Use of the '--raw-leaves' option will override this behavior. -If the '--flush' option is set to false, changes will not be propogated to the +If the '--flush' option is set to false, changes will not be propagated to the merkledag root. This can make operations much faster when doing a large number of writes to a deeper directory structure. @@ -895,7 +895,7 @@ var filesFlushCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Flush a given path's data to disk.", ShortDescription: ` -Flush a given path to disk. This is only useful when other commands +Flush a given path to the disk. This is only useful when other commands are run with the '--flush=false'. `, }, From afcba4f67c6b3735297e217817c396f93d8e12b3 Mon Sep 17 00:00:00 2001 From: "@RubenKelevra" Date: Mon, 6 Apr 2020 01:28:05 +0200 Subject: [PATCH 549/671] doc.md: fix typo --- .github/ISSUE_TEMPLATE/doc.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/doc.md b/.github/ISSUE_TEMPLATE/doc.md index 5a0d1982180..caa35a984fb 100644 --- a/.github/ISSUE_TEMPLATE/doc.md +++ b/.github/ISSUE_TEMPLATE/doc.md @@ -6,7 +6,7 @@ labels: documentation #### Location - + #### Description From 3612f5a7eb01343fc3816de492dd0f7414ef7a67 Mon Sep 17 00:00:00 2001 From: "@RubenKelevra" Date: Sun, 5 Apr 2020 23:09:33 +0200 Subject: [PATCH 550/671] init-doc: fix typo --- assets/init-doc/about | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/assets/init-doc/about b/assets/init-doc/about index eaa644b24b3..f33d6de1551 100644 --- a/assets/init-doc/about +++ b/assets/init-doc/about @@ -4,7 +4,7 @@ IPFS is a global, versioned, peer-to-peer filesystem. It combines good ideas from Git, BitTorrent, Kademlia, SFS, and the Web. It is like a single bit- torrent swarm, exchanging git objects. IPFS provides an interface as simple -as the HTTP web, but with permanence built in. You can also mount the world +as the HTTP web, but with permanence built-in. You can also mount the world at /ipfs. IPFS is a protocol: @@ -20,14 +20,14 @@ IPFS is a web: - can be used to view documents like the web - files accessible via HTTP at `http://ipfs.io/` - browsers or extensions can learn to use `ipfs://` directly -- hash-addressed content guarantees authenticity +- hash-addressed content guarantees the authenticity IPFS is modular: - connection layer over any network protocol - routing layer - uses a routing layer DHT (kademlia/coral) - uses a path-based naming service -- uses bittorrent-inspired block exchange +- uses BitTorrent-inspired block exchange IPFS uses crypto: - cryptographic-hash content addressing @@ -40,10 +40,10 @@ IPFS is p2p: - completely decentralized architecture - **no** central point of failure -IPFS is a cdn: +IPFS is a CDN: - add a file to the filesystem locally, and it's now available to the world - caching-friendly (content-hash naming) -- bittorrent-based bandwidth distribution +- BitTorrent-based bandwidth distribution IPFS has a name service: - IPNS, an SFS inspired name system From 2b3cbceaadd819df5326d06725c387f41954ca80 Mon Sep 17 00:00:00 2001 From: "@RubenKelevra" Date: Mon, 6 Apr 2020 03:02:35 +0200 Subject: [PATCH 551/671] question.md: fix typo --- .github/ISSUE_TEMPLATE/question.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md index a76e5de10ff..cb55e8e2afc 100644 --- a/.github/ISSUE_TEMPLATE/question.md +++ b/.github/ISSUE_TEMPLATE/question.md @@ -1,11 +1,11 @@ --- name: 'Question/Support' -about: 'DO NOT SELECT THIS OPTION: Ask questions on discuss.ipfs.io, IRC (#ipfs on freenode), or Matrix (#ipfs:matrix.org)' +about: 'DO NOT SELECT THIS OPTION: Ask questions on discuss.ipfs.io, IRC (#ipfs on Freenode), or Matrix (#ipfs:matrix.org)' labels: question --- DO NOT ASK QUESTIONS HERE -This bug tracker is only for actionable bug reports and feature requests. Please direct any questions to https://discuss.ipfs.io or to our Matrix (#ipfs:matrix.org) or IRC (#ipfs on freenode) channels. +This bug tracker is only for actionable bug reports and feature requests. Please direct any questions to https://discuss.ipfs.io or our Matrix (#ipfs:matrix.org) or IRC (#ipfs on Freenode) channels. If you don't get an immediate response, please keep trying. From 5201f11a543fac58c3c44adad5c6fa89b81f7228 Mon Sep 17 00:00:00 2001 From: "@RubenKelevra" Date: Mon, 6 Apr 2020 03:06:24 +0200 Subject: [PATCH 552/671] help: fix typo --- assets/init-doc/help | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/init-doc/help b/assets/init-doc/help index d069d6ba762..5794ed642c4 100644 --- a/assets/init-doc/help +++ b/assets/init-doc/help @@ -4,4 +4,4 @@ Some helpful resources for finding your way around ipfs: - ipfs commands: a list of all commands - ipfs --help: every command describes itself - https://github.com/ipfs/go-ipfs -- the src repository -- #ipfs on irc.freenode.org -- the community irc channel +- #ipfs on irc.freenode.org -- the community IRC channel From 613cd78ee956092437beb95e7032eb410caaeb89 Mon Sep 17 00:00:00 2001 From: "@RubenKelevra" Date: Mon, 6 Apr 2020 03:15:45 +0200 Subject: [PATCH 553/671] quick-start: fix typo --- assets/init-doc/quick-start | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/init-doc/quick-start b/assets/init-doc/quick-start index 9de98357f84..04c5ca9d287 100644 --- a/assets/init-doc/quick-start +++ b/assets/init-doc/quick-start @@ -96,7 +96,7 @@ Tool: Browse: - webui: + WebUI: http://localhost:5001/webui From 0e39f3da6e1c6f2c18073e3088f98dc2f4353249 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 6 Apr 2020 13:09:23 -0700 Subject: [PATCH 554/671] chore: update deps --- go.mod | 12 ++++++------ go.sum | 23 ++++++++++++----------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/go.mod b/go.mod index 6322309e151..ff116aee05b 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/gogo/protobuf v1.3.1 github.com/hashicorp/go-multierror v1.1.0 github.com/hashicorp/golang-lru v0.5.4 - github.com/ipfs/go-bitswap v0.2.7 + github.com/ipfs/go-bitswap v0.2.8 github.com/ipfs/go-block-format v0.0.2 github.com/ipfs/go-blockservice v0.1.3 github.com/ipfs/go-cid v0.0.5 @@ -30,7 +30,7 @@ require ( github.com/ipfs/go-graphsync v0.0.5 github.com/ipfs/go-ipfs-blockstore v0.1.4 github.com/ipfs/go-ipfs-chunker v0.0.5 - github.com/ipfs/go-ipfs-cmds v0.2.1 + github.com/ipfs/go-ipfs-cmds v0.2.2 github.com/ipfs/go-ipfs-config v0.4.0 github.com/ipfs/go-ipfs-ds-help v0.1.1 github.com/ipfs/go-ipfs-exchange-interface v0.0.1 @@ -38,7 +38,7 @@ require ( github.com/ipfs/go-ipfs-files v0.0.8 github.com/ipfs/go-ipfs-pinner v0.0.4 github.com/ipfs/go-ipfs-posinfo v0.0.1 - github.com/ipfs/go-ipfs-provider v0.4.1 + github.com/ipfs/go-ipfs-provider v0.4.2 github.com/ipfs/go-ipfs-routing v0.1.0 github.com/ipfs/go-ipfs-util v0.0.1 github.com/ipfs/go-ipld-cbor v0.0.4 @@ -69,7 +69,7 @@ require ( github.com/libp2p/go-libp2p-kbucket v0.2.3 github.com/libp2p/go-libp2p-loggables v0.1.0 github.com/libp2p/go-libp2p-mplex v0.2.3 - github.com/libp2p/go-libp2p-peerstore v0.2.2 + github.com/libp2p/go-libp2p-peerstore v0.2.3 github.com/libp2p/go-libp2p-pubsub v0.2.6 github.com/libp2p/go-libp2p-pubsub-router v0.2.1 github.com/libp2p/go-libp2p-quic-transport v0.2.4-0.20200228032821-6d8b0e775c52 @@ -99,8 +99,8 @@ require ( github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 github.com/whyrusleeping/tar-utils v0.0.0-20180509141711-8c6c8ba81d5c go.uber.org/fx v1.11.0 - golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 - golang.org/x/sys v0.0.0-20200331124033-c3d80250170d + golang.org/x/crypto v0.0.0-20200406173513-056763e48d71 + golang.org/x/sys v0.0.0-20200406155108-e3b113bbe6a4 gopkg.in/cheggaaa/pb.v1 v1.0.28 ) diff --git a/go.sum b/go.sum index 08c85f0c091..3250fabd0ec 100644 --- a/go.sum +++ b/go.sum @@ -181,8 +181,8 @@ github.com/ipfs/go-bitswap v0.1.0/go.mod h1:FFJEf18E9izuCqUtHxbWEvq+reg7o4CW5wSA 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.7 h1:3h2ba+6iSmHb4ik0VWq8Z6e3Qlsii+1paSDa9HG8KI4= -github.com/ipfs/go-bitswap v0.2.7/go.mod h1:2Yjog0GMdH8+AsxkE0DI9D2mANaUTxbVVav0pPoZoug= +github.com/ipfs/go-bitswap v0.2.8 h1:5tQrbyyRS3DkzvcM5n+bVjdSAHLgvH7D+1LopndhUII= +github.com/ipfs/go-bitswap v0.2.8/go.mod h1:2Yjog0GMdH8+AsxkE0DI9D2mANaUTxbVVav0pPoZoug= github.com/ipfs/go-block-format v0.0.1/go.mod h1:DK/YYcsSUIVAFNwo/KZCdIIbpN0ROH/baNLgayt4pFc= github.com/ipfs/go-block-format v0.0.2 h1:qPDvcP19izTjU8rgo6p7gTXZlkMkF5bz5G3fqIsSCPE= github.com/ipfs/go-block-format v0.0.2/go.mod h1:AWR46JfpcObNfg3ok2JHDUfdiHRgWhJgCQF+KIgOPJY= @@ -256,8 +256,8 @@ github.com/ipfs/go-ipfs-chunker v0.0.1 h1:cHUUxKFQ99pozdahi+uSC/3Y6HeRpi9oTeUHbE 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.2.1 h1:xnZJjonqngoQRsrugXTQPMRn2KZwdn5H8N5+bLLYpO0= -github.com/ipfs/go-ipfs-cmds v0.2.1/go.mod h1:kqlUrp6m2ceoaJe40cXpADCi5aS6NKRn0NIeuLp5CeM= +github.com/ipfs/go-ipfs-cmds v0.2.2 h1:F2pro/Q3ifRUsdxEKIS8cg8lO4R6WiwAyERiaG8I9no= +github.com/ipfs/go-ipfs-cmds v0.2.2/go.mod h1:kqlUrp6m2ceoaJe40cXpADCi5aS6NKRn0NIeuLp5CeM= github.com/ipfs/go-ipfs-config v0.4.0 h1:MOXdj8EYQG55v1y+5e1QcctDKPEGobdwnXaDVa0/cc0= github.com/ipfs/go-ipfs-config v0.4.0/go.mod h1:nSLCFtlaL+2rbl3F+9D4gQZQbT1LjRKx7TJg/IHz6oM= github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= @@ -285,8 +285,8 @@ github.com/ipfs/go-ipfs-pq v0.0.1 h1:zgUotX8dcAB/w/HidJh1zzc1yFq6Vm8J7T2F4itj/RU github.com/ipfs/go-ipfs-pq v0.0.1/go.mod h1:LWIqQpqfRG3fNc5XsnIhz/wQ2XXGyugQwls7BgUmUfY= github.com/ipfs/go-ipfs-pq v0.0.2 h1:e1vOOW6MuOwG2lqxcLA+wEn93i/9laCY8sXAw76jFOY= github.com/ipfs/go-ipfs-pq v0.0.2/go.mod h1:LWIqQpqfRG3fNc5XsnIhz/wQ2XXGyugQwls7BgUmUfY= -github.com/ipfs/go-ipfs-provider v0.4.1 h1:2v+goT3JofDWvPAX6wo8D686qS1OOyTnFTYtormp7QY= -github.com/ipfs/go-ipfs-provider v0.4.1/go.mod h1:rcQBVqfblDQRk5LaCtf2uxuKxMJxvKmF5pLS0pO4au4= +github.com/ipfs/go-ipfs-provider v0.4.2 h1:FIsBFXKVo8ZXP8XNVnjhZWPjMRLFJeV07BSNVDpJXVY= +github.com/ipfs/go-ipfs-provider v0.4.2/go.mod h1:rcQBVqfblDQRk5LaCtf2uxuKxMJxvKmF5pLS0pO4au4= github.com/ipfs/go-ipfs-routing v0.0.1/go.mod h1:k76lf20iKFxQTjcJokbPM9iBXVXVZhcOwc360N4nuKs= github.com/ipfs/go-ipfs-routing v0.1.0 h1:gAJTT1cEeeLj6/DlLX6t+NxD9fQe2ymTO6qWRDI/HQQ= github.com/ipfs/go-ipfs-routing v0.1.0/go.mod h1:hYoUkJLyAUKhF58tysKpids8RNDPO42BVMgK5dNsoqY= @@ -435,7 +435,6 @@ github.com/libp2p/go-libp2p v0.0.30/go.mod h1:XWT8FGHlhptAv1+3V/+J5mEpzyui/5bvFs github.com/libp2p/go-libp2p v0.1.0/go.mod h1:6D/2OBauqLUoqcADOJpn9WbKqvaM07tDw68qHM0BxUM= github.com/libp2p/go-libp2p v0.1.1/go.mod h1:I00BRo1UuUSdpuc8Q2mN7yDF/oTUTRAX6JWpTiK9Rp8= github.com/libp2p/go-libp2p v0.2.1/go.mod h1:HZbtEOrgZN4F1fGZVvkV+930Wx3DkqlpBlO8dIoZWds= -github.com/libp2p/go-libp2p v0.5.2 h1:fjQUTyB7x/4XgO31OEWkJ5uFeHRgpoExlf0rXz5BO8k= github.com/libp2p/go-libp2p v0.5.2/go.mod h1:o2r6AcpNl1eNGoiWhRtPji03NYOvZumeQ6u+X6gSxnM= github.com/libp2p/go-libp2p v0.6.0 h1:EFArryT9N7AVA70LCcOh8zxsW+FeDnxwcpWQx9k7+GM= github.com/libp2p/go-libp2p v0.6.0/go.mod h1:mfKWI7Soz3ABX+XEBR61lGbg+ewyMtJHVt043oWeqwg= @@ -558,6 +557,8 @@ github.com/libp2p/go-libp2p-peerstore v0.2.1 h1:u+gOfsKgu73ZkGWhvckRm03z9C+iS9Tr github.com/libp2p/go-libp2p-peerstore v0.2.1/go.mod h1:NQxhNjWxf1d4w6PihR8btWIRjwRLBr4TYKfNgrUkOPA= github.com/libp2p/go-libp2p-peerstore v0.2.2 h1:iqc/m03jHn5doXN3+kS6JKvqQRHEltiXljQB85iVHWE= github.com/libp2p/go-libp2p-peerstore v0.2.2/go.mod h1:NQxhNjWxf1d4w6PihR8btWIRjwRLBr4TYKfNgrUkOPA= +github.com/libp2p/go-libp2p-peerstore v0.2.3 h1:MofRq2l3c15vQpEygTetV+zRRrncz+ktiXW7H2EKoEQ= +github.com/libp2p/go-libp2p-peerstore v0.2.3/go.mod h1:K8ljLdFn590GMttg/luh4caB/3g0vKuY01psze0upRw= github.com/libp2p/go-libp2p-pnet v0.2.0 h1:J6htxttBipJujEjz1y0a5+eYoiPcFHhSYHH6na5f0/k= github.com/libp2p/go-libp2p-pnet v0.2.0/go.mod h1:Qqvq6JH/oMZGwqs3N1Fqhv8NVhrdYcO0BW4wssv21LA= github.com/libp2p/go-libp2p-protocol v0.0.1/go.mod h1:Af9n4PiruirSDjHycM1QuiMi/1VZNHYcK8cLgFJLZ4s= @@ -1001,8 +1002,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d h1:1ZiEyfaQIg3Qh0EoqpwAakHVhecoE5wlSg5GjnafJGw= golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 h1:3zb4D3T4G8jdExgVU/95+vQXfpEPiMdCaZgmGVxjNHM= -golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200406173513-056763e48d71 h1:DOmugCavvUtnUD114C1Wh+UgTgQZ4pMLzXxi1pSt+/Y= +golang.org/x/crypto v0.0.0-20200406173513-056763e48d71/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -1076,8 +1077,8 @@ golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d h1:nc5K6ox/4lTFbMVSL9WRR81ixkcwXThoiF6yf+R9scA= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200406155108-e3b113bbe6a4 h1:c1Sgqkh8v6ZxafNGG64r8C8UisIW2TKMJN8P86tKjr0= +golang.org/x/sys v0.0.0-20200406155108-e3b113bbe6a4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= From 70fe64581d63375512533965b2d2af61263296d7 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 18 Mar 2020 11:14:55 -0700 Subject: [PATCH 555/671] feat(dht): update to cypress DHT in backwards compatibility mode This upgrades to the next DHT version, but in backwards compatibility mode. --- core/node/libp2p/routingopt.go | 28 ++++++++++++++++++++++------ go.mod | 6 +++--- go.sum | 19 +++++++------------ 3 files changed, 32 insertions(+), 21 deletions(-) diff --git a/core/node/libp2p/routingopt.go b/core/node/libp2p/routingopt.go index 35389d857f5..0b2accc237e 100644 --- a/core/node/libp2p/routingopt.go +++ b/core/node/libp2p/routingopt.go @@ -8,26 +8,42 @@ import ( host "github.com/libp2p/go-libp2p-core/host" routing "github.com/libp2p/go-libp2p-core/routing" dht "github.com/libp2p/go-libp2p-kad-dht" - dhtopts "github.com/libp2p/go-libp2p-kad-dht/opts" record "github.com/libp2p/go-libp2p-record" ) +var baseDhtOptions = []dht.Option{ + dht.Concurrency(10), + // TODO: Enable this once we have the dual-DHTs. At the moment, this + // will break DHTs on private IP addresses (VPNs, etc.). + //dht.RoutingTableFilter(dht.PublicRoutingTableFilter), + //dht.QueryFilter(dht.PublicQueryFilter), +} + type RoutingOption func(context.Context, host.Host, datastore.Batching, record.Validator) (routing.Routing, error) func constructDHTRouting(ctx context.Context, host host.Host, dstore datastore.Batching, validator record.Validator) (routing.Routing, error) { return dht.New( ctx, host, - dhtopts.Datastore(dstore), - dhtopts.Validator(validator), + append([]dht.Option{ + // TODO: switch to "auto" when we add dual-dht support. + // Unfortunately, we can't set this to auto yet or + // nobody will become a server when everyone is running + // on a private network. + dht.Mode(dht.ModeServer), + dht.Datastore(dstore), + dht.Validator(validator), + }, baseDhtOptions...)..., ) } func constructClientDHTRouting(ctx context.Context, host host.Host, dstore datastore.Batching, validator record.Validator) (routing.Routing, error) { return dht.New( ctx, host, - dhtopts.Client(true), - dhtopts.Datastore(dstore), - dhtopts.Validator(validator), + append([]dht.Option{ + dht.Mode(dht.ModeClient), + dht.Datastore(dstore), + dht.Validator(validator), + }, baseDhtOptions...)..., ) } diff --git a/go.mod b/go.mod index ff116aee05b..3f95e79a4c6 100644 --- a/go.mod +++ b/go.mod @@ -65,8 +65,8 @@ require ( github.com/libp2p/go-libp2p-core v0.5.1 github.com/libp2p/go-libp2p-discovery v0.3.0 github.com/libp2p/go-libp2p-http v0.1.5 - github.com/libp2p/go-libp2p-kad-dht v0.5.2 - github.com/libp2p/go-libp2p-kbucket v0.2.3 + github.com/libp2p/go-libp2p-kad-dht v0.6.1 + github.com/libp2p/go-libp2p-kbucket v0.3.3 github.com/libp2p/go-libp2p-loggables v0.1.0 github.com/libp2p/go-libp2p-mplex v0.2.3 github.com/libp2p/go-libp2p-peerstore v0.2.3 @@ -74,7 +74,7 @@ require ( github.com/libp2p/go-libp2p-pubsub-router v0.2.1 github.com/libp2p/go-libp2p-quic-transport v0.2.4-0.20200228032821-6d8b0e775c52 github.com/libp2p/go-libp2p-record v0.1.2 - github.com/libp2p/go-libp2p-routing-helpers v0.1.0 + github.com/libp2p/go-libp2p-routing-helpers v0.2.0 github.com/libp2p/go-libp2p-secio v0.2.2 github.com/libp2p/go-libp2p-swarm v0.2.3 github.com/libp2p/go-libp2p-testing v0.1.1 diff --git a/go.sum b/go.sum index 3250fabd0ec..052113e9a1d 100644 --- a/go.sum +++ b/go.sum @@ -343,8 +343,6 @@ github.com/ipfs/go-peertaskqueue v0.1.1 h1:+gPjbI+V3NktXZOqJA1kzbms2pYmhjgQQal0M github.com/ipfs/go-peertaskqueue v0.1.1/go.mod h1:Jmk3IyCcfl1W3jTW3YpghSwSEC6IJ3Vzz/jUmWw8Z0U= github.com/ipfs/go-peertaskqueue v0.2.0 h1:2cSr7exUGKYyDeUyQ7P/nHPs9P7Ht/B+ROrpN1EJOjc= github.com/ipfs/go-peertaskqueue v0.2.0/go.mod h1:5/eNrBEbtSKWCG+kQK8K8fGNixoYUnr+P7jivavs9lY= -github.com/ipfs/go-todocounter v0.0.2 h1:9UBngSQhylg2UDcxSAtpkT+rEWFr26hDPXVStE8LFyc= -github.com/ipfs/go-todocounter v0.0.2/go.mod h1:l5aErvQc8qKE2r7NDMjmq5UNAvuZy0rC8BHOplkWvZ4= 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.2-0.20190827150610-868af2e9e5cb/go.mod h1:IwAAgul1UQIcNZzKPYZWOCijryFBeCV79cNubPzol+k= @@ -435,7 +433,6 @@ github.com/libp2p/go-libp2p v0.0.30/go.mod h1:XWT8FGHlhptAv1+3V/+J5mEpzyui/5bvFs github.com/libp2p/go-libp2p v0.1.0/go.mod h1:6D/2OBauqLUoqcADOJpn9WbKqvaM07tDw68qHM0BxUM= github.com/libp2p/go-libp2p v0.1.1/go.mod h1:I00BRo1UuUSdpuc8Q2mN7yDF/oTUTRAX6JWpTiK9Rp8= github.com/libp2p/go-libp2p v0.2.1/go.mod h1:HZbtEOrgZN4F1fGZVvkV+930Wx3DkqlpBlO8dIoZWds= -github.com/libp2p/go-libp2p v0.5.2/go.mod h1:o2r6AcpNl1eNGoiWhRtPji03NYOvZumeQ6u+X6gSxnM= github.com/libp2p/go-libp2p v0.6.0 h1:EFArryT9N7AVA70LCcOh8zxsW+FeDnxwcpWQx9k7+GM= github.com/libp2p/go-libp2p v0.6.0/go.mod h1:mfKWI7Soz3ABX+XEBR61lGbg+ewyMtJHVt043oWeqwg= github.com/libp2p/go-libp2p v0.6.1 h1:mxabyJf4l6AmotDOKObwSfBNBWjL5VYXysVFLUMAuB8= @@ -511,10 +508,10 @@ github.com/libp2p/go-libp2p-interface-connmgr v0.0.1/go.mod h1:GarlRLH0LdeWcLnYM 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.5.2 h1:b10l1YIQk1R23skrvfbcU09yvepdkuMLIGdGuX/JRiA= -github.com/libp2p/go-libp2p-kad-dht v0.5.2/go.mod h1:vRwh1sMmuxym6YFIHxICbxQ7rgY0ALkKuMKdmQSUnHE= -github.com/libp2p/go-libp2p-kbucket v0.2.3 h1:XtNfN4WUy0cfeJoJgWCf1lor4Pp3kBkFJ9vQ+Zs+VUM= -github.com/libp2p/go-libp2p-kbucket v0.2.3/go.mod h1:opWrBZSWnBYPc315q497huxY3sz1t488X6OiXUEYWKA= +github.com/libp2p/go-libp2p-kad-dht v0.6.1 h1:ijPmjn6arIzxaIsX9MsnA3yfm3QgS4fNlWxd7cgYeZ4= +github.com/libp2p/go-libp2p-kad-dht v0.6.1/go.mod h1:tQM3dloie3MUDj2Cam13H4Lwq/piSxY+HLQshOOrngg= +github.com/libp2p/go-libp2p-kbucket v0.3.3 h1:V2Zwv6QnCK6Who0iiJW2eUKwdlTYGJ2HnLViaolDOcs= +github.com/libp2p/go-libp2p-kbucket v0.3.3/go.mod h1:IWFdYRBOYzaLEHnvrfzEkr+UcuveCXIoeO8QeFZSI6A= github.com/libp2p/go-libp2p-loggables v0.0.1/go.mod h1:lDipDlBNYbpyqyPX/KcoO+eq0sJYEVR2JgOexcivchg= github.com/libp2p/go-libp2p-loggables v0.1.0 h1:h3w8QFfCt2UJl/0/NW4K829HX/0S4KD31PQ7m8UXXO8= github.com/libp2p/go-libp2p-loggables v0.1.0/go.mod h1:EyumB2Y6PrYjr55Q3/tiJ/o3xoDasoRYM7nOzEpoa90= @@ -576,10 +573,8 @@ github.com/libp2p/go-libp2p-record v0.1.0/go.mod h1:ujNc8iuE5dlKWVy6wuL6dd58t0n7 github.com/libp2p/go-libp2p-record v0.1.2 h1:M50VKzWnmUrk/M5/Dz99qO9Xh4vs8ijsK+7HkJvRP+0= github.com/libp2p/go-libp2p-record v0.1.2/go.mod h1:pal0eNcT5nqZaTV7UGhqeGqxFgGdsU/9W//C8dqjQDk= github.com/libp2p/go-libp2p-routing v0.0.1/go.mod h1:N51q3yTr4Zdr7V8Jt2JIktVU+3xBBylx1MZeVA6t1Ys= -github.com/libp2p/go-libp2p-routing v0.1.0 h1:hFnj3WR3E2tOcKaGpyzfP4gvFZ3t8JkQmbapN0Ct+oU= -github.com/libp2p/go-libp2p-routing v0.1.0/go.mod h1:zfLhI1RI8RLEzmEaaPwzonRvXeeSHddONWkcTcB54nE= -github.com/libp2p/go-libp2p-routing-helpers v0.1.0 h1:BaFvpyv8TyhCN7TihawTiKuzeu8/Pyw7ZnMA4IvqIN8= -github.com/libp2p/go-libp2p-routing-helpers v0.1.0/go.mod h1:oUs0h39vNwYtYXnQWOTU5BaafbedSyWCCal3gqHuoOQ= +github.com/libp2p/go-libp2p-routing-helpers v0.2.0 h1:+QKTsx2Bg0q3oueQ9CopTwKN5NsnF+qEC+sbkSVXnsU= +github.com/libp2p/go-libp2p-routing-helpers v0.2.0/go.mod h1:Db+7LRSPImkV9fOKsNWVW5IXyy9XDse92lUtO3O+jlo= 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= @@ -909,6 +904,7 @@ github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJ github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= +github.com/wangjia184/sortedset v0.0.0-20160527075905-f5d03557ba30/go.mod h1:YkocrP2K2tcw938x9gCOmT5G5eCD6jsTz0SZuyAqwIE= github.com/warpfork/go-wish v0.0.0-20180510122957-5ad1f5abf436/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= github.com/warpfork/go-wish v0.0.0-20190328234359-8b3e70f8e830 h1:8kxMKmKzXXL4Ru1nyhvdms/JjWt+3YLpvRb/bAjO/y0= github.com/warpfork/go-wish v0.0.0-20190328234359-8b3e70f8e830/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= @@ -1067,7 +1063,6 @@ golang.org/x/sys v0.0.0-20190610200419-93c9922d18ae/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= From 56e0e18294e37fdfa5a1ab488a3b9d3dd7ba5d92 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 6 Apr 2020 13:55:46 -0700 Subject: [PATCH 556/671] feat: add a dhtserver option --- cmd/ipfs/daemon.go | 3 +++ core/node/libp2p/routingopt.go | 47 ++++++++++------------------------ 2 files changed, 17 insertions(+), 33 deletions(-) diff --git a/cmd/ipfs/daemon.go b/cmd/ipfs/daemon.go index 0a24b907a7d..26761fa4266 100644 --- a/cmd/ipfs/daemon.go +++ b/cmd/ipfs/daemon.go @@ -53,6 +53,7 @@ const ( routingOptionSupernodeKwd = "supernode" routingOptionDHTClientKwd = "dhtclient" routingOptionDHTKwd = "dht" + routingOptionDHTServerKwd = "dhtserver" routingOptionNoneKwd = "none" routingOptionDefaultKwd = "default" unencryptTransportKwd = "disable-transport-encryption" @@ -330,6 +331,8 @@ func daemonFunc(req *cmds.Request, re cmds.ResponseEmitter, env cmds.Environment ncfg.Routing = libp2p.DHTClientOption case routingOptionDHTKwd: ncfg.Routing = libp2p.DHTOption + case routingOptionDHTServerKwd: + ncfg.Routing = libp2p.DHTServerOption case routingOptionNoneKwd: ncfg.Routing = libp2p.NilRouterOption default: diff --git a/core/node/libp2p/routingopt.go b/core/node/libp2p/routingopt.go index 0b2accc237e..39d8cf9773a 100644 --- a/core/node/libp2p/routingopt.go +++ b/core/node/libp2p/routingopt.go @@ -11,42 +11,23 @@ import ( record "github.com/libp2p/go-libp2p-record" ) -var baseDhtOptions = []dht.Option{ - dht.Concurrency(10), - // TODO: Enable this once we have the dual-DHTs. At the moment, this - // will break DHTs on private IP addresses (VPNs, etc.). - //dht.RoutingTableFilter(dht.PublicRoutingTableFilter), - //dht.QueryFilter(dht.PublicQueryFilter), -} - type RoutingOption func(context.Context, host.Host, datastore.Batching, record.Validator) (routing.Routing, error) -func constructDHTRouting(ctx context.Context, host host.Host, dstore datastore.Batching, validator record.Validator) (routing.Routing, error) { - return dht.New( - ctx, host, - append([]dht.Option{ - // TODO: switch to "auto" when we add dual-dht support. - // Unfortunately, we can't set this to auto yet or - // nobody will become a server when everyone is running - // on a private network. - dht.Mode(dht.ModeServer), +func constructDHTRouting(mode dht.ModeOpt) func(ctx context.Context, host host.Host, dstore datastore.Batching, validator record.Validator) (routing.Routing, error) { + return func(ctx context.Context, host host.Host, dstore datastore.Batching, validator record.Validator) (routing.Routing, error) { + return dht.New( + ctx, host, + dht.Concurrency(10), + dht.Mode(mode), dht.Datastore(dstore), dht.Validator(validator), - }, baseDhtOptions...)..., - ) + ) + } } -func constructClientDHTRouting(ctx context.Context, host host.Host, dstore datastore.Batching, validator record.Validator) (routing.Routing, error) { - return dht.New( - ctx, host, - append([]dht.Option{ - dht.Mode(dht.ModeClient), - dht.Datastore(dstore), - dht.Validator(validator), - }, baseDhtOptions...)..., - ) -} - -var DHTOption RoutingOption = constructDHTRouting -var DHTClientOption RoutingOption = constructClientDHTRouting -var NilRouterOption RoutingOption = nilrouting.ConstructNilRouting +var ( + DHTOption RoutingOption = constructDHTRouting(dht.ModeAuto) + DHTClientOption = constructDHTRouting(dht.ModeClient) + DHTServerOption = constructDHTRouting(dht.ModeServer) + NilRouterOption = nilrouting.ConstructNilRouting +) From 3e6f0a79426173c1a53828716ede7cfccb2a83bc Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 6 Apr 2020 13:57:51 -0700 Subject: [PATCH 557/671] doc: cleanup experimental features a bit --- docs/config.md | 32 ++++++++++++++++++++++++-------- docs/experimental-features.md | 18 +++++++++++------- 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/docs/config.md b/docs/config.md index 9efe56c5359..03b64ef45f1 100644 --- a/docs/config.md +++ b/docs/config.md @@ -316,18 +316,34 @@ A number of seconds to wait between discovery checks. ## `Routing` -Contains options for content routing mechanisms. +Contains options for content, peer, and IPNS routing mechanisms. ### `Routing.Type` -Content routing mode. Can be overridden with daemon `--routing` flag. When set -to `dhtclient`, the node won't join the DHT but can still use it to find -content. +Content routing mode. Can be overridden with daemon `--routing` flag. -Valid modes are: - - `dht` (default) - - `dhtclient` - - `none` +There are two core routing options: "none" and "dht" (default). + +* If set to "none", your node will use _no_ routing system. You'll have to + explicitly connect to peers that have the content you're looking for. +* If set to "dht" (or "dhtclient"/"dhtserver"), your node will use the IPFS DHT. + +When the DHT is enabled, it can operate in two modes: client and server. + +* In server mode, your node will query other peers for DHT records, and will + respond to requests from other peers (both requests to store records and + requests to retrieve records). +* In client mode, your node will query the DHT as a client but will not respond + to requests from other peers. This mode is less resource intensive than server + mode. + +When `Routing.Type` is set to `dht`, your node will start as a DHT client, and +switch to a DHT server when and if it determines that it's reachable from the +public internet (e.g., it's not behind a firewall). + +To force a specific DHT mode, client or server, set `Routing.Type` to +`dhtclient` or `dhtserver` respectively. Please do not set this to `dhtserver` +unless you're sure your node is reachable from the public network. **Example:** diff --git a/docs/experimental-features.md b/docs/experimental-features.md index b84602052c4..3d54b9cb7a8 100644 --- a/docs/experimental-features.md +++ b/docs/experimental-features.md @@ -82,21 +82,20 @@ signed) by running: --- ## Client mode DHT routing + Allows the dht to be run in a mode that doesn't serve requests to the network, saving bandwidth. ### State -experimental. +stable ### In Version -0.4.5 + +0.5.0 ### How to enable -run your daemon with the `--routing=dhtclient` flag. -### Road to being a real feature -- [ ] Needs more people to use and report on how well it works. -- [ ] Needs analysis of effect it has on the network as a whole. +run your daemon with the `--routing=dhtclient` flag. --- @@ -507,6 +506,8 @@ See [Plugin docs](./plugins.md) - [ ] More plugins and plugin types - [ ] Feedback on stability +--- + ## Badger datastore ### In Version @@ -591,7 +592,7 @@ run your daemon with the `--enable-namesys-pubsub` flag; enables pubsub. so that we don't have to hit the DHT for the initial resolution. Alternatively, we could republish the last record periodically. - +--- ## QUIC @@ -662,6 +663,7 @@ ipfs config --json Swarm.EnableAutoNATService true Stable +--- ## Strategic Providing @@ -688,6 +690,8 @@ ipfs config --json Experimental.StrategicProviding true - [ ] provide roots - [ ] provide all - [ ] provide strategic + +--- ## GraphSync From ba631bbab0c8b50e9937089d63eee8f16b68c07c Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 6 Apr 2020 18:52:02 -0700 Subject: [PATCH 558/671] fix: start the IPFS dht in server mode by default for now --- core/node/libp2p/routingopt.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/node/libp2p/routingopt.go b/core/node/libp2p/routingopt.go index 39d8cf9773a..d7f4f7a18a0 100644 --- a/core/node/libp2p/routingopt.go +++ b/core/node/libp2p/routingopt.go @@ -26,7 +26,9 @@ func constructDHTRouting(mode dht.ModeOpt) func(ctx context.Context, host host.H } var ( - DHTOption RoutingOption = constructDHTRouting(dht.ModeAuto) + // FIXME: Set this to dht.ModeAuto once we resolve + // https://github.com/libp2p/go-libp2p-kad-dht/issues/564 + DHTOption RoutingOption = constructDHTRouting(dht.ModeServer) DHTClientOption = constructDHTRouting(dht.ModeClient) DHTServerOption = constructDHTRouting(dht.ModeServer) NilRouterOption = nilrouting.ConstructNilRouting From 31a13428331974949b0187f4da9ec4f38359ca0d Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Tue, 10 Mar 2020 23:45:44 -0700 Subject: [PATCH 559/671] feat: initial update to the changelog for 0.5.0 --- CHANGELOG.md | 327 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 327 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ad49445a91a..09c077be638 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,332 @@ # go-ipfs changelog +## 0.5.0 RC1 2020-04-06 + +**WARNING** THIS IS A DRAFT! It highlights some of the new features, along with +a bunch of important errata. But it's _definitely_ missing a _ton_ of shiny new +features. + +### Highlights & Errata + +This release includes many important changes users should be aware of. + +#### New DHT + +This release includes an almost completely rewritten DHT implementation with a +new protocol version. From a user's perspective, providing content, finding +content, and resolving IPNS records should simply get faster. However, this is a +_significant_ (albeit well tested) change and significant changes are always +risky, so heads up. + +##### Old v. New + +The current DHT suffers from three core issues addressed in this release: + +1. Most peers in the DHT cannot be dialed (e.g., due to firewalls and NATs). + Much of a DHT query time is wasted trying to connect to peers that cannot be + reached. +2. The DHT query logic doesn't properly terminate when it hits the end of the + query and, instead, aggressively keeps on searching. +3. The routing tables are poorly maintained. This can cause a search that should + be logarithmic in the size of the network to be linear. + +###### Reachable + +We have addressed the problem of undialable nodes by having nodes wait to join +the DHT as "server" nodes until they've confirmed that they are reachable from +the public internet. Additionally, we've introduced: + +* A new libp2p protocol to push updates to our peers when we start/stop listen + on protocols. +* A libp2p event bus for processing updates like these. +* A new DHT protocol version. New DHT nodes will not admit old DHT nodes into + their routing tables. Old DHT nodes will still be able to issue queries + against the new DHT, they just won't be queried or referred by new DHT nodes. + This way, old, potentially unreachable nodes with bad routing tables won't + pollute the new DHT. + +Unfortunately, there's a significant downside to this approach: VPNs, offline +LANs, etc. where _all_ nodes on the network have private IP addresses and never +communicate over the public internet. In this case, none of these nodes would be +"publicly reachable". + +To address this last point, go-ipfs 0.5.0 will run _two_ DHTs: one for private +networks and one for the public internet. That is, every node will participate +in a LAN DHT and a public WAN DHT. + +**RC1 NOTE:** Several of these features have not been enabled in RC1: + +1. We haven't yet switched the protocol version and will be running the DHT in + "compatibility mode" with the old DHT. Once we flip the switch and enable the + new protocol version, we will need to ensure that at least 20% of the + publicly reachable DHT speaks the new protocol, all at once. The plan is to + introduce a large number of "booster" nodes while the network transitions. +2. We haven't yet introduced the split LAN/WAN DHTs. We're still testing this + approach and considering alternatives. +3. Because we haven't introduced the LAN/WAN DHT split, IPFS nodes running in + DHT server mode will continue to run in DHT server mode _without_ waiting to + confirm that they're reachable from the public internet. Otherwise, we'd + break IPFS nodes running DHTs in VPNs and disconnected LANs. + +###### Query Logic + +We've fixed the DHT query logic by correctly implementing Kademlia (with a few +tweaks). This should significantly speed up: + +* Publishing IPNS & provider records. We previously continued searching for + closer and closer peers to the "target" until we timed out, then we put to the + closest peers we found. +* Resolving IPNS addresses. We previously continued IPNS record searches until + we ran out of peers to query, timed out, or found 16 records. + +In both cases, we now continue till we find the closest peers then stop. + +###### Routing Tables + +Finally, we've addressed the poorly maintained routing tables by: + +* Reducing the likelihood that the connection manager will kill connections to + peers in the routing table. +* Keeping peers in the routing table, even if we get disconnected from them. +* Actively and frequently querying the DHT to keep our routing table full. + +##### Testing + +The DHT rewrite was made possible by our new testing framework, +[testground](https://github.com/ipfs/testground), which allows us to spin up +multi-thousand node tests with simulated real-world network conditions. With +testground and some custom analysis tools, we were able to gain confidence that +the new DHT implementation behaves correctly. + +#### Refactored Bitswap + +This release includes a _major_ [bitswap refactor][bitswap-refactor] running a +new, but backwards compatible, bitswap protocol. We expect these changes to +improve performance significantly. + +With the refactored bitswap, we expect: + +* Few to no duplicate blocks when fetching data from other nodes speaking the + _new_ protocol. +* Better parallelism when fetching from multiple peers. + +Note, the new bitswap won't magically make downloading content any faster until +both seeds and leaches have updated. If you're one of the first to upgrade to +0.5.0 and try downloading from peers that haven't upgraded, you're unlikely to +see much of a performance improvement, if any. + +[bitswap-refactor]: https://blog.ipfs.io/2020-02-14-improved-bitswap-for-container-distribution/ + +#### Provider Record Changes + +When you add content to your IPFS node, you advertise this content to the +network by announcing it in the DHT. We call this "providing". + +However, go-ipfs has multiple ways to address the same underlying bytes. +Specifically, we address content by content ID (CID) and the same underlying +bytes can be addressed using (a) two different versions of CIDs (CIDv1 and +CIDv2) and (b) with different "codecs" depending on how we're interpreting the +data. + +Prior to go-ipfs 0.5.0, we used the content id (CID) in the DHT when sending out +provider records for content. Unfortunately, this meant that users trying to +find data announced using one CID wouldn't find nodes providing the content +under a different CID. + +In go-ipfs 0.5.0, we're announcing data by _multihash_, not _CID_. This way, +regardless of the CID version used by the peer adding the content, the peer +trying to download the content should still be able to find it. + +**Warning:** as part of the network, this could impact finding content added +with CIDv1. Because go-ipfs 0.5.0 will announce and search for content using the +bare multihash (equivalent to the v0 CID), go-ipfs 0.5.0 will be unable to find +CIDv1 content published by nodes prior to go-ipfs 0.5.0 and vice-versa. As CIDv1 +is _not_ enabled by default so we believe this will have minimal impact. +However, users are _strongly_ encouraged to upgrade as soon as possible. + +#### IPFS/Libp2p Address Format + +If you've ever run a command like `ipfs swarm peers`, you've likely seen paths +that look like `/ip4/193.45.1.24/tcp/4001/ipfs/QmSomePeerID`. These paths are +_not_ file paths, they're multiaddrs; addresses of peers on the network. + +Unfortunately, `/ipfs/Qm...` is _also_ the same path format we use for files. +This release, changes the multiaddr format from +/ip4/193.45.1.24/tcp/4001/ipfs/QmSomePeerID to +/ip4/193.45.1.24/tcp/4001/p2p/QmSomePeerID to make the +distinction clear. + +What this means for users: + +* Old-style multiaddrs will still be accepted as inputs to IPFS. +* If you were using a multiaddr library (go, js, etc.) to name _files_ because + `/ipfs/QmSomePeerID` looks like `/ipfs/QmSomeFile`, your tool may break if you + upgrade this library. +* If you're manually parsing multiaddrs and are searching for the string + `/ipfs/`..., you'll need to search for `/p2p/...`. + + +#### Minimum RSA Key Size + +Previously, IPFS did not enforce a minimum RSA key size. In this release, we've +introduced a minimum 2048 bit RSA key size. IPFS generates 2048 bit RSA keys by +default so this shouldn't be an issue for anyone in practice. However, users who +explicitly chose a smaller key size will not be able to communicate with new +nodes. + +Unfortunately, the some of the bootstrap peers _did_ intentionally generate 1024 +bit RSA keys so they'd have vanity peer addresses (starting with QmSoL for +"solar net"). All IPFS nodes should _also_ have peers with >= 2048 bit RSA keys +in their bootstrap list, but we've introduced a migration to ensure this. + +We implemented this change to follow security best practices and to remove a +potential foot-gun. However, in practice, the security impact of allowing +insecure RSA keys should have been next to none because IPFS doesn't trust other +peers on the network anyways. + +#### Subdomain Gateway + +The gateway will redirect from `http://localhost:5001/ipfs/CID/...` to +`http://CID.ipfs.localhost:5001/...` by default. This will: + +* Ensure that every dapp gets its own browser origin. +* Make it easier to write websites that "just work" with IPFS because absolute + paths will now work. + +Paths addressing the gateway by IP address (`http://127.0.0.1:5001/ipfs/CID`) +will not be altered as IP addresses can't have subdomains. + +Note: cURL doesn't follow redirects by default. To avoid breaking cURL and other +clients that don't support redirects, go-ipfs will return the requested file +along with the redirect. Browsers will follow the redirect and abort the +download while cURL will ignore the redirect and finish the download. + +#### TLS By Default + +In this release, we're switching TLS to be the _default_ transport. This means +we'll try to encrypt the connection with TLS before re-trying with SECIO. + +Contrary to the announcement in the go-ipfs 0.4.23 release notes, this release +does not remove SECIO support to maintain compatibility with js-ipfs. + +#### SECIO Deprecation Notice + +SECIO should be considered to be well on the way to deprecation and will be +completely disabled in either the next release (0.6.0, ~mid May) or the one +following that (0.7.0, ~end of June). Before SECIO is disabled, support will be +added for the NOISE transport for compatibility with other IPFS implementations. + +#### QUIC Upgrade + +If you've been using the experimental QUIC support, this release includes + +**RC1 NOTE:** We've temporarily backed out of the new QUIC version because it +currently requires go 1.14 and go 1.14 has some scheduler bugs that go-ipfs can +reliably trigger. + +#### Badger Datastore + +In this release, we're calling the badger datastore (enabled at initialization +with `ipfs init --profile=badgerds`) as stable. However, we're not yet enabling +it by default. + +The benefit of badger is that adding/fetching data to/from badger is +_significantly_ faster than adding/fetching data to/from the default datastore, +flatfs. In some tests, adding data to badger is 32x faster than flatfs (in this +release). + +However, + +1. Badger is complicated while flatfs pushes all the complexity down into the + filesystem itself. That means that flatfs is only likely to loose your data + if your underlying filesystem gets corrupted while there are more + opportunities for badger itself to get corrupted. +2. Badger can use a lot of memory. In this release, we've tuned badger to use + very little (~20MiB) of memory by default. However, it can still produce + large (1GiB) spikes in memory usage when garbage collecting. +3. Badger isn't very aggressive when it comes to garbage collection and we're + still investigating ways to get it to more aggressively clean up after + itself. + +TL;DR: Use badger if performance is your main requirement, you rarely/never +delete anything, and you have some memory to spare. + +#### Systemd Support + +For Linux users, this release includes support for two systemd features: socket +activation and startup/shutdown notifications. This makes it possible to: + +* Start IPFS on demand on first use. +* Wait for IPFS to finish starting before starting services that depend on it. + +You can find the new systemd units in the go-ipfs repo under misc/systemd. + +#### IPFS API Over Unix Domain Sockets + +This release supports exposing the IPFS API over a unix domain socket in the +filesystem. You use this feature, run: + +```bash +> ipfs config Addresses.API "/unix/path/to/socket/location" +``` + +#### Repo Migration + +IPFS uses repo migrations to make structural changes to the "repo" (the config, +data storage, etc.) on upgrade. + +This release includes two very simple repo migrations: a config migration to +ensure that the config contains working bootstrap nodes and a keystore migration +to base32 encode all key filenames. + +In general, migrations should not require significant manual intervention. +However, you should be aware of migrations and plan for them. + +* If you update go-ipfs with `ipfs update`, `ipfs update` will run the migration + for you. +* If you start the ipfs daemon with `ipfs daemon --migrate`, ipfs will migrate + your repo for you on start. + +Otherwise, if you want more control over the repo migration process, you can +manually install and run the [repo migration +tool](http://dist.ipfs.io/#fs-repo-migrations). + +#### Bootstrap Peer Changes + +**AUTOMATIC MIGRATION REQUIRED** + +The first migration will update the bootstrap peer list to: + +1. Replace the old bootstrap nodes (ones with peer IDs starting with QmSoL), + with new bootstrap nodes (ones with addresses that start with + `/dnsaddr/bootstrap.libp2p.io`. +2. Rewrite the address format from `/ipfs/QmPeerID` to `/p2p/QmPeerID`. + +We're migrating addresses for a few reasons: + +1. We're using DNS to address the new bootstrap nodes so we can change the + underlying IP addresses as necessary. +2. The new bootstrap nodes use 2048 bit keys while the old bootstrap nodes use + 1024 bit keys. +3. We're normalizing the address format to `/p2p/Qm...`. + +Note: This migration won't _add_ the new bootstrap peers to your config if +you've explicitly removed the old bootstrap peers. It will also leave custom +entries in the list alone. In other words, if you've customized your bootstrap +list, this migration won't clobber your changes. + +#### Keystore Changes + +**AUTOMATIC MIGRATION REQUIRED** + +Go-IPFS stores additional keys (i.e., all keys other than the "identity" key) in +the keystore. You can list these keys with `ipfs key`. + +Currently, the keystore stores keys as regular files, named after the key +itself. Unfortunately, filename restrictions and case-insensitivity are platform +specific. To avoid platform specific issues, we're base32 encoding all key names +and renaming all keys on-disk. + ## 0.4.23 2020-01-29 Given the large number of fixes merged since 0.4.22, we've decided to cut another patch release. From 3a37423530dbb5423dccfa65fbefa0d0091d8df9 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Tue, 7 Apr 2020 00:00:37 -0700 Subject: [PATCH 560/671] feat: bump version --- version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.go b/version.go index 39a5d692fba..0bf72334c72 100644 --- a/version.go +++ b/version.go @@ -4,7 +4,7 @@ package ipfs var CurrentCommit string // CurrentVersionNumber is the current application's version literal -const CurrentVersionNumber = "0.5.0-dev" +const CurrentVersionNumber = "0.5.0-rc1" const ApiVersion = "/go-ipfs/" + CurrentVersionNumber + "/" From b53054359987d2ce0b3497fd44edb34235ea981e Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Tue, 7 Apr 2020 20:08:28 -0700 Subject: [PATCH 561/671] chore: update go-ds-badger fixes https://github.com/ipfs/go-ipfs/issues/6986 --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 3f95e79a4c6..fab16101adb 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/ipfs/go-cidutil v0.0.2 github.com/ipfs/go-datastore v0.4.4 github.com/ipfs/go-detect-race v0.0.1 - github.com/ipfs/go-ds-badger v0.2.3 + github.com/ipfs/go-ds-badger v0.2.4 github.com/ipfs/go-ds-flatfs v0.4.1 github.com/ipfs/go-ds-leveldb v0.4.2 github.com/ipfs/go-ds-measure v0.1.0 diff --git a/go.sum b/go.sum index 052113e9a1d..0e3cbf12895 100644 --- a/go.sum +++ b/go.sum @@ -228,6 +228,8 @@ github.com/ipfs/go-ds-badger v0.2.1 h1:RsC9DDlwFhFdfT+s2PeC8joxbSp2YMufK8w/RBOxK github.com/ipfs/go-ds-badger v0.2.1/go.mod h1:Tx7l3aTph3FMFrRS838dcSJh+jjA7cX9DrGVwx/NOwE= github.com/ipfs/go-ds-badger v0.2.3 h1:J27YvAcpuA5IvZUbeBxOcQgqnYHUPxoygc6QxxkodZ4= github.com/ipfs/go-ds-badger v0.2.3/go.mod h1:pEYw0rgg3FIrywKKnL+Snr+w/LjJZVMTBRn4FS6UHUk= +github.com/ipfs/go-ds-badger v0.2.4 h1:UPGB0y7luFHk+mY/tUZrif/272M8o+hFsW+avLUeWrM= +github.com/ipfs/go-ds-badger v0.2.4/go.mod h1:pEYw0rgg3FIrywKKnL+Snr+w/LjJZVMTBRn4FS6UHUk= github.com/ipfs/go-ds-flatfs v0.4.1 h1:l43jeAUALOKRvoMMJ4rOddxUzcOACUjnd1u4AfKqeZo= github.com/ipfs/go-ds-flatfs v0.4.1/go.mod h1:5fR0eUTIrFWJqa4zACd3mKUNm26wM/jVbVDo39/WRRo= github.com/ipfs/go-ds-leveldb v0.0.1/go.mod h1:feO8V3kubwsEF22n0YRQCffeb79OOYIykR4L04tMOYc= From 2a42d44deef68a93403f26ecf0d9d84a4b075990 Mon Sep 17 00:00:00 2001 From: Boris Mann Date: Wed, 8 Apr 2020 11:46:25 -0700 Subject: [PATCH 562/671] Adding Fission to IPFS early testers page --- docs/EARLY_TESTERS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/EARLY_TESTERS.md b/docs/EARLY_TESTERS.md index 3b302d95561..f2332165211 100644 --- a/docs/EARLY_TESTERS.md +++ b/docs/EARLY_TESTERS.md @@ -29,6 +29,7 @@ We will ask early testers to participate at two points in the process: - [ ] QRI (@b5) - [ ] Siderus (@koalalorenzo) - [ ] Charity Engine (@rytiss, @tristanolive) +- [ ] Fission (@bmann) ## How to sign up? From 635e333d609ee53791f0415efcc8b957d7abcf3b Mon Sep 17 00:00:00 2001 From: Peter Rabbitson Date: Wed, 4 Mar 2020 16:11:14 +0100 Subject: [PATCH 563/671] Dag export command, silent, no progress --- .gitattributes | 1 + core/commands/commands_test.go | 2 + core/commands/dag/dag.go | 109 ++++++++++++++++++- core/commands/root.go | 1 + go.mod | 1 + go.sum | 10 +- test/sharness/t0054-dag-car-import-export.sh | 25 +++++ 7 files changed, 144 insertions(+), 5 deletions(-) create mode 100755 test/sharness/t0054-dag-car-import-export.sh diff --git a/.gitattributes b/.gitattributes index d6b38c11dd0..633d55c3b9f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -9,6 +9,7 @@ LICENSE text eol=auto *.png binary *.tar binary *.gz binary +*.car binary # Binary assets assets/init-doc/* binary diff --git a/core/commands/commands_test.go b/core/commands/commands_test.go index e34c5070c94..ee6fd45776e 100644 --- a/core/commands/commands_test.go +++ b/core/commands/commands_test.go @@ -24,6 +24,7 @@ func TestROCommands(t *testing.T) { "/commands", "/dag", "/dag/get", + "/dag/export", "/dag/resolve", "/dns", "/get", @@ -95,6 +96,7 @@ func TestCommands(t *testing.T) { "/config/profile/apply", "/dag", "/dag/get", + "/dag/export", "/dag/put", "/dag/resolve", "/dht", diff --git a/core/commands/dag/dag.go b/core/commands/dag/dag.go index 66d50feb1f5..31ea850608d 100644 --- a/core/commands/dag/dag.go +++ b/core/commands/dag/dag.go @@ -14,16 +14,22 @@ import ( cmds "github.com/ipfs/go-ipfs-cmds" files "github.com/ipfs/go-ipfs-files" ipld "github.com/ipfs/go-ipld-format" + mdag "github.com/ipfs/go-merkledag" ipfspath "github.com/ipfs/go-path" path "github.com/ipfs/interface-go-ipfs-core/path" mh "github.com/multiformats/go-multihash" + + gocar "github.com/ipld/go-car" + //gipfree "github.com/ipld/go-ipld-prime/impl/free" + //gipselector "github.com/ipld/go-ipld-prime/traversal/selector" + //gipselectorbuilder "github.com/ipld/go-ipld-prime/traversal/selector/builder" ) var DagCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Interact with ipld dag objects.", ShortDescription: ` -'ipfs dag' is used for creating and manipulating dag objects. +'ipfs dag' is used for creating and manipulating dag objects/hierarchies. This subcommand is currently an experimental feature, but it is intended to deprecate and replace the existing 'ipfs object' command moving forward. @@ -33,6 +39,7 @@ to deprecate and replace the existing 'ipfs object' command moving forward. "put": DagPutCmd, "get": DagGetCmd, "resolve": DagResolveCmd, + "export": DagExportCmd, }, } @@ -241,3 +248,103 @@ var DagResolveCmd = &cmds.Command{ }, Type: ResolveOutput{}, } + +var DagExportCmd = &cmds.Command{ + Helptext: cmds.HelpText{ + Tagline: "Streams the selected DAG as a .car stream on stdout.", + ShortDescription: ` +'ipfs dag export' fetches a dag and streams it out as a well-formed .car file. +Note that at prsent only single root selections / .car files are supported. +The output of blocks happens in strict DAG-traversal, first-seen, order. +`, + }, + Arguments: []cmds.Argument{ + cmds.StringArg("root", true, false, "Expression evaluting to a single root of a dag to export").EnableStdin(), + }, + Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { + + c, err := cid.Decode(req.Arguments[0]) + if err != nil { + return fmt.Errorf( + "unable to parse root specification (currently only bare CIDs are supported): %s", + err, + ) + } + + // The current interface of go-car is rather suboptimal as it + // only takes a blockstore, instead of accepting a dagservice, + // and leveraging parallel-fetch capabilities + // https://github.com/ipld/go-car/issues/27 + // + // Until the above is fixed, pre-warm the blockstore before doing + // anything else. We explicitly *DO NOT* take a lock during this + // operation: even if we lose some of the blocks we just received + // due to a conflicting GC: we will just re-retrieve anything we + // potentially lost when the car is being streamed out + node, err := cmdenv.GetNode(env) + if err != nil { + return err + } + + if err := mdag.FetchGraph(req.Context, c, node.DAG); err != nil { + if !node.IsOnline { + err = fmt.Errorf("%s (currently offline, perhaps retry after attaching to the network)", err) + } + return err + } + + // Code disabled until descent-issue in go-ipld-prime is fixed + // + // The second part of the above - make a super-thin wrapper around + // a blockservice session, translating Session.GetBlock() to Blockstore.Get() + // + // sess := blockservice.NewSession( + // req.Context, + // node.Blocks, + // ) + // var wrapper getBlockFromSessionWrapper = func(c cid.Cid) (blk.Block, error) { + // return sess.GetBlock(req.Context, c) + // } + // sb := gipselectorbuilder.NewSelectorSpecBuilder(gipfree.NodeBuilder()) + // car := gocar.NewSelectiveCar( + // req.Context, + // &wrapper, + // []gocar.Dag{gocar.Dag{ + // Root: c, + // Selector: sb.ExploreRecursive( + // gipselector.RecursionLimitNone(), + // sb.ExploreAll(sb.ExploreRecursiveEdge()), + // ).Node(), + // }}, + // ) + + pipeR, pipeW := io.Pipe() + + errCh := make(chan error, 2) // we only report the 1st error + go func() { + defer func() { + if err := pipeW.Close(); err != nil { + errCh <- fmt.Errorf("stream flush failed: %s", err) + } + close(errCh) + }() + + //if err := car.Write(pipeW); err != nil { + if err := gocar.WriteCar( + req.Context, + node.DAG, + []cid.Cid{c}, + pipeW, + ); err != nil { + errCh <- err + } + }() + + if err := res.Emit(pipeR); err != nil { + pipeW.Close() // ignore errors if any + return err + } + + return <-errCh + }, +} diff --git a/core/commands/root.go b/core/commands/root.go index 752cfd4e3f3..c31199308e8 100644 --- a/core/commands/root.go +++ b/core/commands/root.go @@ -190,6 +190,7 @@ var rootROSubcommands = map[string]*cmds.Command{ "dag": { Subcommands: map[string]*cmds.Command{ "get": dag.DagGetCmd, + "export": dag.DagExportCmd, "resolve": dag.DagResolveCmd, }, }, diff --git a/go.mod b/go.mod index fab16101adb..b9b3f513e42 100644 --- a/go.mod +++ b/go.mod @@ -54,6 +54,7 @@ require ( github.com/ipfs/go-unixfs v0.2.4 github.com/ipfs/go-verifcid v0.0.1 github.com/ipfs/interface-go-ipfs-core v0.2.6 + github.com/ipld/go-car v0.0.5-0.20200316204026-3e2cf7af0fab github.com/jbenet/go-is-domain v1.0.3 github.com/jbenet/go-random v0.0.0-20190219211222-123a90aedc0c github.com/jbenet/go-temp-err-catcher v0.1.0 diff --git a/go.sum b/go.sum index 0e3cbf12895..6de9d504607 100644 --- a/go.sum +++ b/go.sum @@ -18,8 +18,10 @@ github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBA github.com/alangpierce/go-forceexport v0.0.0-20160317203124-8f1d6941cd75 h1:3ILjVyslFbc4jl1w5TWuvvslFD/nDfR2H8tVaMVLrEY= github.com/alangpierce/go-forceexport v0.0.0-20160317203124-8f1d6941cd75/go.mod h1:uAXEEpARkRhCZfEvy/y0Jcc888f9tHCc1W7/UeEtreE= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4 h1:Hs82Z41s6SdL1CELW+XaDYmOH4hkBN4/N9og/AsOv7E= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -190,15 +192,12 @@ github.com/ipfs/go-blockservice v0.0.3/go.mod h1:/NNihwTi6V2Yr6g8wBI+BSwPuURpBRM github.com/ipfs/go-blockservice v0.0.7/go.mod h1:EOfb9k/Y878ZTRY/CH0x5+ATtaipfbRhbvNSdgc/7So= github.com/ipfs/go-blockservice v0.1.0/go.mod h1:hzmMScl1kXHg3M2BjTymbVPjv627N7sYcvYaKbop39M= github.com/ipfs/go-blockservice v0.1.1/go.mod h1:t+411r7psEUhLueM8C7aPA7cxCclv4O3VsUVxt9kz2I= -github.com/ipfs/go-blockservice v0.1.2 h1:fqFeeu1EG0lGVrqUo+BVJv7LZV31I4ZsyNthCOMAJRc= github.com/ipfs/go-blockservice v0.1.2/go.mod h1:t+411r7psEUhLueM8C7aPA7cxCclv4O3VsUVxt9kz2I= github.com/ipfs/go-blockservice v0.1.3 h1:9XgsPMwwWJSC9uVr2pMDsW2qFTBSkxpGMhmna8mIjPM= github.com/ipfs/go-blockservice v0.1.3/go.mod h1:OTZhFpkgY48kNzbgyvcexW9cHrpjBYIjSR0KoDOFOLU= github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= -github.com/ipfs/go-cid v0.0.3 h1:UIAh32wymBpStoe83YCzwVQQ5Oy/H0FdxvUS6DJDzms= github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= -github.com/ipfs/go-cid v0.0.4 h1:UlfXKrZx1DjZoBhQHmNHLC1fK1dUJDN20Y28A7s+gJ8= github.com/ipfs/go-cid v0.0.4/go.mod h1:4LLaPOQwmk5z9LBgQnpkivrx8BJjUyGwTXCd5Xfj6+M= github.com/ipfs/go-cid v0.0.5 h1:o0Ix8e/ql7Zb5UVUJEUfjsWCIY8t48++9lR8qi6oiJU= github.com/ipfs/go-cid v0.0.5/go.mod h1:plgt+Y5MnOey4vO4UlUazGqdbEXuFYitED67FexhXog= @@ -326,6 +325,7 @@ github.com/ipfs/go-merkledag v0.0.6/go.mod h1:QYPdnlvkOg7GnQRofu9XZimC5ZW5Wi3bKy github.com/ipfs/go-merkledag v0.1.0/go.mod h1:SQiXrtSts3KGNmgOzMICy5c0POOpUNQLvB3ClKnBAlk= github.com/ipfs/go-merkledag v0.2.3 h1:aMdkK9G1hEeNvn3VXfiEMLY0iJnbiQQUHnM0HFJREsE= github.com/ipfs/go-merkledag v0.2.3/go.mod h1:SQiXrtSts3KGNmgOzMICy5c0POOpUNQLvB3ClKnBAlk= +github.com/ipfs/go-merkledag v0.2.4/go.mod h1:SQiXrtSts3KGNmgOzMICy5c0POOpUNQLvB3ClKnBAlk= github.com/ipfs/go-merkledag v0.3.0 h1:1bXv/ZRPZLVdij/a33CkXMVdxUdred9sz4xyph+0ls0= github.com/ipfs/go-merkledag v0.3.0/go.mod h1:4pymaZLhSLNVuiCITYrpViD6vmfZ/Ws4n/L9tfNv3S4= github.com/ipfs/go-merkledag v0.3.1 h1:3UqWINBEr3/N+r6OwgFXAddDP/8zpQX/8J7IGVOCqRQ= @@ -354,6 +354,8 @@ github.com/ipfs/go-verifcid v0.0.1 h1:m2HI7zIuR5TFyQ1b79Da5N9dnnCP1vcu2QqawmWlK2 github.com/ipfs/go-verifcid v0.0.1/go.mod h1:5Hrva5KBeIog4A+UpqlaIU+DEstipcJYQQZc0g37pY0= github.com/ipfs/interface-go-ipfs-core v0.2.6 h1:4eeGPJUDWblEurSzpAtL2znDG1xqAoX2aNNIoOFwyuc= github.com/ipfs/interface-go-ipfs-core v0.2.6/go.mod h1:Tihp8zxGpUeE3Tokr94L6zWZZdkRQvG5TL6i9MuNE+s= +github.com/ipld/go-car v0.0.5-0.20200316204026-3e2cf7af0fab h1:+3Y6Jb3IBmG3t6e3r6TItnuciOaMOuGW7QIVEUa5vy4= +github.com/ipld/go-car v0.0.5-0.20200316204026-3e2cf7af0fab/go.mod h1:yR5AsJ38xTwwgwGpbh60ICtdLPp5lGfuH28PAAzaEhM= github.com/ipld/go-ipld-prime v0.0.2-0.20191108012745-28a82f04c785 h1:fASnkvtR+SmB2y453RxmDD3Uvd4LonVUgFGk9JoDaZs= github.com/ipld/go-ipld-prime v0.0.2-0.20191108012745-28a82f04c785/go.mod h1:bDDSvVz7vaK12FNvMeRYnpRFkSUPNQOiCYQezMD/P3w= github.com/ipld/go-ipld-prime-proto v0.0.0-20191113031812-e32bd156a1e5 h1:lSip43rAdyGA+yRQuy6ju0ucZkWpYc1F2CTQtZTVW/4= @@ -554,7 +556,6 @@ github.com/libp2p/go-libp2p-peerstore v0.2.0 h1:XcgJhI8WyUOCbHyRLNEX5542YNj8hnLS github.com/libp2p/go-libp2p-peerstore v0.2.0/go.mod h1:N2l3eVIeAitSg3Pi2ipSrJYnqhVnMNQZo9nkSCuAbnQ= github.com/libp2p/go-libp2p-peerstore v0.2.1 h1:u+gOfsKgu73ZkGWhvckRm03z9C+iS9TrLqpANweELGs= github.com/libp2p/go-libp2p-peerstore v0.2.1/go.mod h1:NQxhNjWxf1d4w6PihR8btWIRjwRLBr4TYKfNgrUkOPA= -github.com/libp2p/go-libp2p-peerstore v0.2.2 h1:iqc/m03jHn5doXN3+kS6JKvqQRHEltiXljQB85iVHWE= github.com/libp2p/go-libp2p-peerstore v0.2.2/go.mod h1:NQxhNjWxf1d4w6PihR8btWIRjwRLBr4TYKfNgrUkOPA= github.com/libp2p/go-libp2p-peerstore v0.2.3 h1:MofRq2l3c15vQpEygTetV+zRRrncz+ktiXW7H2EKoEQ= github.com/libp2p/go-libp2p-peerstore v0.2.3/go.mod h1:K8ljLdFn590GMttg/luh4caB/3g0vKuY01psze0upRw= @@ -902,6 +903,7 @@ github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e/go. github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c h1:u6SKchux2yDvFQnDHS3lPnIRmfVJ5Sxy3ao2SIdysLQ= github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k= diff --git a/test/sharness/t0054-dag-car-import-export.sh b/test/sharness/t0054-dag-car-import-export.sh new file mode 100755 index 00000000000..d40dd666fe3 --- /dev/null +++ b/test/sharness/t0054-dag-car-import-export.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +# + +test_description="Test car file import/export functionality" + +. lib/test-lib.sh + +test_init_ipfs + + +echo "Error: merkledag: not found (currently offline, perhaps retry after attaching to the network)" > offline_fetch_error_expected + +test_expect_success "basic offline export of nonexistent cid" ' + ! ipfs dag export QmYwAPJXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 2> offline_fetch_error_actual +' + +test_expect_success "correct error" ' + test_cmp offline_fetch_error_expected offline_fetch_error_actual +' + +test_expect_success "basic offline export of 'getting started' dag" ' + ipfs dag export QmS4ustL54uo8FzR9455qaxZwuMiUhyvMcX9Ba8nUH4uVv >/dev/null +' + +test_done From b0a461ca5c8e413034994ebfe21bfa94f72c2fa2 Mon Sep 17 00:00:00 2001 From: Peter Rabbitson Date: Thu, 26 Mar 2020 16:38:20 +0100 Subject: [PATCH 564/671] Typo fix --- core/commands/dag/dag.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/commands/dag/dag.go b/core/commands/dag/dag.go index 31ea850608d..9676e935b34 100644 --- a/core/commands/dag/dag.go +++ b/core/commands/dag/dag.go @@ -254,7 +254,7 @@ var DagExportCmd = &cmds.Command{ Tagline: "Streams the selected DAG as a .car stream on stdout.", ShortDescription: ` 'ipfs dag export' fetches a dag and streams it out as a well-formed .car file. -Note that at prsent only single root selections / .car files are supported. +Note that at present only single root selections / .car files are supported. The output of blocks happens in strict DAG-traversal, first-seen, order. `, }, From a5f19c4f9c738fec4edf9baacb82161ba4e0c170 Mon Sep 17 00:00:00 2001 From: Peter Rabbitson Date: Fri, 27 Mar 2020 06:56:17 +0100 Subject: [PATCH 565/671] Remove unnecessay prefetch --- core/commands/dag/dag.go | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/core/commands/dag/dag.go b/core/commands/dag/dag.go index 9676e935b34..57458849c7d 100644 --- a/core/commands/dag/dag.go +++ b/core/commands/dag/dag.go @@ -14,7 +14,6 @@ import ( cmds "github.com/ipfs/go-ipfs-cmds" files "github.com/ipfs/go-ipfs-files" ipld "github.com/ipfs/go-ipld-format" - mdag "github.com/ipfs/go-merkledag" ipfspath "github.com/ipfs/go-path" path "github.com/ipfs/interface-go-ipfs-core/path" mh "github.com/multiformats/go-multihash" @@ -271,33 +270,22 @@ The output of blocks happens in strict DAG-traversal, first-seen, order. ) } - // The current interface of go-car is rather suboptimal as it - // only takes a blockstore, instead of accepting a dagservice, - // and leveraging parallel-fetch capabilities - // https://github.com/ipld/go-car/issues/27 - // - // Until the above is fixed, pre-warm the blockstore before doing - // anything else. We explicitly *DO NOT* take a lock during this - // operation: even if we lose some of the blocks we just received - // due to a conflicting GC: we will just re-retrieve anything we - // potentially lost when the car is being streamed out node, err := cmdenv.GetNode(env) if err != nil { return err } - if err := mdag.FetchGraph(req.Context, c, node.DAG); err != nil { - if !node.IsOnline { - err = fmt.Errorf("%s (currently offline, perhaps retry after attaching to the network)", err) - } - return err - } - // Code disabled until descent-issue in go-ipld-prime is fixed // // The second part of the above - make a super-thin wrapper around // a blockservice session, translating Session.GetBlock() to Blockstore.Get() // + // The current interface of go-car is rather suboptimal as it + // only takes a blockstore, instead of accepting a dagservice, + // and leveraging parallel-fetch capabilities + // https://github.com/ipld/go-car/issues/27 + // + // // sess := blockservice.NewSession( // req.Context, // node.Blocks, From 7a749ea7cb924e57b93312e74f0bd2f229526177 Mon Sep 17 00:00:00 2001 From: Peter Rabbitson Date: Fri, 27 Mar 2020 06:57:48 +0100 Subject: [PATCH 566/671] Less confusing CLI helptext --- core/commands/dag/dag.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/commands/dag/dag.go b/core/commands/dag/dag.go index 57458849c7d..a0682446129 100644 --- a/core/commands/dag/dag.go +++ b/core/commands/dag/dag.go @@ -258,7 +258,7 @@ The output of blocks happens in strict DAG-traversal, first-seen, order. `, }, Arguments: []cmds.Argument{ - cmds.StringArg("root", true, false, "Expression evaluting to a single root of a dag to export").EnableStdin(), + cmds.StringArg("root", true, false, "CID of a root to recursively export").EnableStdin(), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { From 3dca025f05ba84b48e58f59dbbc806a0c08501fc Mon Sep 17 00:00:00 2001 From: Peter Rabbitson Date: Fri, 27 Mar 2020 07:02:57 +0100 Subject: [PATCH 567/671] Remove pipe close since we are already in error --- core/commands/dag/dag.go | 1 - 1 file changed, 1 deletion(-) diff --git a/core/commands/dag/dag.go b/core/commands/dag/dag.go index a0682446129..4eb2283b534 100644 --- a/core/commands/dag/dag.go +++ b/core/commands/dag/dag.go @@ -329,7 +329,6 @@ The output of blocks happens in strict DAG-traversal, first-seen, order. }() if err := res.Emit(pipeR); err != nil { - pipeW.Close() // ignore errors if any return err } From f129f24bd74ad7692bd345399fb9f40aa033af9f Mon Sep 17 00:00:00 2001 From: Peter Rabbitson Date: Fri, 27 Mar 2020 07:57:31 +0100 Subject: [PATCH 568/671] Bring back error-prettifyer removed in f6b707d85f4 --- core/commands/dag/dag.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/core/commands/dag/dag.go b/core/commands/dag/dag.go index 4eb2283b534..08981c24f1f 100644 --- a/core/commands/dag/dag.go +++ b/core/commands/dag/dag.go @@ -332,6 +332,15 @@ The output of blocks happens in strict DAG-traversal, first-seen, order. return err } - return <-errCh + err = <-errCh + + // minimal user friendliness + if err != nil && + !node.IsOnline && + err.Error() == "merkledag: not found" { + err = fmt.Errorf("%s (currently offline, perhaps retry after attaching to the network)", err) + } + + return err }, } From c2f9849a2be6b6c6a156b6f0978afed916bc7e67 Mon Sep 17 00:00:00 2001 From: Peter Rabbitson Date: Fri, 27 Mar 2020 19:24:08 +0100 Subject: [PATCH 569/671] Fastify with go-car version taking a session --- core/commands/dag/dag.go | 25 +++++++------------------ go.mod | 2 +- go.sum | 4 ++-- 3 files changed, 10 insertions(+), 21 deletions(-) diff --git a/core/commands/dag/dag.go b/core/commands/dag/dag.go index 08981c24f1f..2ac956daa83 100644 --- a/core/commands/dag/dag.go +++ b/core/commands/dag/dag.go @@ -8,6 +8,7 @@ import ( "github.com/ipfs/go-ipfs/core/commands/cmdenv" "github.com/ipfs/go-ipfs/core/coredag" + mdag "github.com/ipfs/go-merkledag" cid "github.com/ipfs/go-cid" cidenc "github.com/ipfs/go-cidutil/cidenc" @@ -276,27 +277,12 @@ The output of blocks happens in strict DAG-traversal, first-seen, order. } // Code disabled until descent-issue in go-ipld-prime is fixed + // https://github.com/ribasushi/gip-muddle-up // - // The second part of the above - make a super-thin wrapper around - // a blockservice session, translating Session.GetBlock() to Blockstore.Get() - // - // The current interface of go-car is rather suboptimal as it - // only takes a blockstore, instead of accepting a dagservice, - // and leveraging parallel-fetch capabilities - // https://github.com/ipld/go-car/issues/27 - // - // - // sess := blockservice.NewSession( - // req.Context, - // node.Blocks, - // ) - // var wrapper getBlockFromSessionWrapper = func(c cid.Cid) (blk.Block, error) { - // return sess.GetBlock(req.Context, c) - // } // sb := gipselectorbuilder.NewSelectorSpecBuilder(gipfree.NodeBuilder()) // car := gocar.NewSelectiveCar( // req.Context, - // &wrapper, + // , // []gocar.Dag{gocar.Dag{ // Root: c, // Selector: sb.ExploreRecursive( @@ -320,7 +306,10 @@ The output of blocks happens in strict DAG-traversal, first-seen, order. //if err := car.Write(pipeW); err != nil { if err := gocar.WriteCar( req.Context, - node.DAG, + mdag.NewSession( + req.Context, + node.DAG, + ), []cid.Cid{c}, pipeW, ); err != nil { diff --git a/go.mod b/go.mod index b9b3f513e42..dcc9639f5c8 100644 --- a/go.mod +++ b/go.mod @@ -54,7 +54,7 @@ require ( github.com/ipfs/go-unixfs v0.2.4 github.com/ipfs/go-verifcid v0.0.1 github.com/ipfs/interface-go-ipfs-core v0.2.6 - github.com/ipld/go-car v0.0.5-0.20200316204026-3e2cf7af0fab + github.com/ipld/go-car v0.0.5-0.20200327173242-8a3014575e8e github.com/jbenet/go-is-domain v1.0.3 github.com/jbenet/go-random v0.0.0-20190219211222-123a90aedc0c github.com/jbenet/go-temp-err-catcher v0.1.0 diff --git a/go.sum b/go.sum index 6de9d504607..e5f775d887d 100644 --- a/go.sum +++ b/go.sum @@ -354,8 +354,8 @@ github.com/ipfs/go-verifcid v0.0.1 h1:m2HI7zIuR5TFyQ1b79Da5N9dnnCP1vcu2QqawmWlK2 github.com/ipfs/go-verifcid v0.0.1/go.mod h1:5Hrva5KBeIog4A+UpqlaIU+DEstipcJYQQZc0g37pY0= github.com/ipfs/interface-go-ipfs-core v0.2.6 h1:4eeGPJUDWblEurSzpAtL2znDG1xqAoX2aNNIoOFwyuc= github.com/ipfs/interface-go-ipfs-core v0.2.6/go.mod h1:Tihp8zxGpUeE3Tokr94L6zWZZdkRQvG5TL6i9MuNE+s= -github.com/ipld/go-car v0.0.5-0.20200316204026-3e2cf7af0fab h1:+3Y6Jb3IBmG3t6e3r6TItnuciOaMOuGW7QIVEUa5vy4= -github.com/ipld/go-car v0.0.5-0.20200316204026-3e2cf7af0fab/go.mod h1:yR5AsJ38xTwwgwGpbh60ICtdLPp5lGfuH28PAAzaEhM= +github.com/ipld/go-car v0.0.5-0.20200327173242-8a3014575e8e h1:Sono8LppfRvQhSp6ozSmjdW7xtv45BYRMFU4xqJQs34= +github.com/ipld/go-car v0.0.5-0.20200327173242-8a3014575e8e/go.mod h1:yR5AsJ38xTwwgwGpbh60ICtdLPp5lGfuH28PAAzaEhM= github.com/ipld/go-ipld-prime v0.0.2-0.20191108012745-28a82f04c785 h1:fASnkvtR+SmB2y453RxmDD3Uvd4LonVUgFGk9JoDaZs= github.com/ipld/go-ipld-prime v0.0.2-0.20191108012745-28a82f04c785/go.mod h1:bDDSvVz7vaK12FNvMeRYnpRFkSUPNQOiCYQezMD/P3w= github.com/ipld/go-ipld-prime-proto v0.0.0-20191113031812-e32bd156a1e5 h1:lSip43rAdyGA+yRQuy6ju0ucZkWpYc1F2CTQtZTVW/4= From 73bb0e8353878e883e860f093a2eaf3b725a9c6b Mon Sep 17 00:00:00 2001 From: Peter Rabbitson Date: Fri, 27 Mar 2020 19:26:39 +0100 Subject: [PATCH 570/671] Check against error veriable --- core/commands/dag/dag.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/commands/dag/dag.go b/core/commands/dag/dag.go index 2ac956daa83..d1cc06f7c9f 100644 --- a/core/commands/dag/dag.go +++ b/core/commands/dag/dag.go @@ -326,7 +326,7 @@ The output of blocks happens in strict DAG-traversal, first-seen, order. // minimal user friendliness if err != nil && !node.IsOnline && - err.Error() == "merkledag: not found" { + err == ipld.ErrNotFound { err = fmt.Errorf("%s (currently offline, perhaps retry after attaching to the network)", err) } From 380bffa14692ad3ea0c79c0bd6224f077354f599 Mon Sep 17 00:00:00 2001 From: Peter Rabbitson Date: Fri, 27 Mar 2020 19:32:31 +0100 Subject: [PATCH 571/671] Move commented out code together --- core/commands/dag/dag.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/commands/dag/dag.go b/core/commands/dag/dag.go index d1cc06f7c9f..3a6cfb27266 100644 --- a/core/commands/dag/dag.go +++ b/core/commands/dag/dag.go @@ -291,6 +291,8 @@ The output of blocks happens in strict DAG-traversal, first-seen, order. // ).Node(), // }}, // ) + // ... + // if err := car.Write(pipeW); err != nil {} pipeR, pipeW := io.Pipe() @@ -303,7 +305,6 @@ The output of blocks happens in strict DAG-traversal, first-seen, order. close(errCh) }() - //if err := car.Write(pipeW); err != nil { if err := gocar.WriteCar( req.Context, mdag.NewSession( From ae5a9e0549f20497075a35e7fe3c436e92005ad9 Mon Sep 17 00:00:00 2001 From: Peter Rabbitson Date: Fri, 27 Mar 2020 19:53:56 +0100 Subject: [PATCH 572/671] Bring back pipe closure from other end --- core/commands/dag/dag.go | 1 + 1 file changed, 1 insertion(+) diff --git a/core/commands/dag/dag.go b/core/commands/dag/dag.go index 3a6cfb27266..6835d0945f4 100644 --- a/core/commands/dag/dag.go +++ b/core/commands/dag/dag.go @@ -319,6 +319,7 @@ The output of blocks happens in strict DAG-traversal, first-seen, order. }() if err := res.Emit(pipeR); err != nil { + pipeR.Close() // ignore the error if any return err } From 7b489bed806b62b41d6b45fe046b1760b280880f Mon Sep 17 00:00:00 2001 From: Peter Rabbitson Date: Fri, 27 Mar 2020 19:55:00 +0100 Subject: [PATCH 573/671] Depend on now-released go-car tag --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index dcc9639f5c8..6ed0e358175 100644 --- a/go.mod +++ b/go.mod @@ -54,7 +54,7 @@ require ( github.com/ipfs/go-unixfs v0.2.4 github.com/ipfs/go-verifcid v0.0.1 github.com/ipfs/interface-go-ipfs-core v0.2.6 - github.com/ipld/go-car v0.0.5-0.20200327173242-8a3014575e8e + github.com/ipld/go-car v0.0.5 github.com/jbenet/go-is-domain v1.0.3 github.com/jbenet/go-random v0.0.0-20190219211222-123a90aedc0c github.com/jbenet/go-temp-err-catcher v0.1.0 diff --git a/go.sum b/go.sum index e5f775d887d..6f2abc6971a 100644 --- a/go.sum +++ b/go.sum @@ -354,8 +354,8 @@ github.com/ipfs/go-verifcid v0.0.1 h1:m2HI7zIuR5TFyQ1b79Da5N9dnnCP1vcu2QqawmWlK2 github.com/ipfs/go-verifcid v0.0.1/go.mod h1:5Hrva5KBeIog4A+UpqlaIU+DEstipcJYQQZc0g37pY0= github.com/ipfs/interface-go-ipfs-core v0.2.6 h1:4eeGPJUDWblEurSzpAtL2znDG1xqAoX2aNNIoOFwyuc= github.com/ipfs/interface-go-ipfs-core v0.2.6/go.mod h1:Tihp8zxGpUeE3Tokr94L6zWZZdkRQvG5TL6i9MuNE+s= -github.com/ipld/go-car v0.0.5-0.20200327173242-8a3014575e8e h1:Sono8LppfRvQhSp6ozSmjdW7xtv45BYRMFU4xqJQs34= -github.com/ipld/go-car v0.0.5-0.20200327173242-8a3014575e8e/go.mod h1:yR5AsJ38xTwwgwGpbh60ICtdLPp5lGfuH28PAAzaEhM= +github.com/ipld/go-car v0.0.5 h1:YtOdQdvyvbAQwCAErHvi/sjFwGhMRoihFx8X2XNgO1c= +github.com/ipld/go-car v0.0.5/go.mod h1:yR5AsJ38xTwwgwGpbh60ICtdLPp5lGfuH28PAAzaEhM= github.com/ipld/go-ipld-prime v0.0.2-0.20191108012745-28a82f04c785 h1:fASnkvtR+SmB2y453RxmDD3Uvd4LonVUgFGk9JoDaZs= github.com/ipld/go-ipld-prime v0.0.2-0.20191108012745-28a82f04c785/go.mod h1:bDDSvVz7vaK12FNvMeRYnpRFkSUPNQOiCYQezMD/P3w= github.com/ipld/go-ipld-prime-proto v0.0.0-20191113031812-e32bd156a1e5 h1:lSip43rAdyGA+yRQuy6ju0ucZkWpYc1F2CTQtZTVW/4= From 4772ca6134d77b77b59e60a36297badcdab3a4e8 Mon Sep 17 00:00:00 2001 From: Peter Rabbitson Date: Thu, 26 Mar 2020 16:35:04 +0100 Subject: [PATCH 574/671] Add simple byte-counting export progress-bar --- core/commands/dag/dag.go | 69 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/core/commands/dag/dag.go b/core/commands/dag/dag.go index 6835d0945f4..572a5230efa 100644 --- a/core/commands/dag/dag.go +++ b/core/commands/dag/dag.go @@ -1,10 +1,13 @@ package dagcmd import ( + "errors" "fmt" "io" "math" + "os" "strings" + "time" "github.com/ipfs/go-ipfs/core/commands/cmdenv" "github.com/ipfs/go-ipfs/core/coredag" @@ -23,6 +26,12 @@ import ( //gipfree "github.com/ipld/go-ipld-prime/impl/free" //gipselector "github.com/ipld/go-ipld-prime/traversal/selector" //gipselectorbuilder "github.com/ipld/go-ipld-prime/traversal/selector/builder" + + "gopkg.in/cheggaaa/pb.v1" +) + +const ( + progressOptionName = "progress" ) var DagCmd = &cmds.Command{ @@ -261,6 +270,9 @@ The output of blocks happens in strict DAG-traversal, first-seen, order. Arguments: []cmds.Argument{ cmds.StringArg("root", true, false, "CID of a root to recursively export").EnableStdin(), }, + Options: []cmds.Option{ + cmds.BoolOption(progressOptionName, "p", "Display progress on CLI. Defaults to true when STDERR is a TTY."), + }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { c, err := cid.Decode(req.Arguments[0]) @@ -334,4 +346,61 @@ The output of blocks happens in strict DAG-traversal, first-seen, order. return err }, + PostRun: cmds.PostRunMap{ + cmds.CLI: func(res cmds.Response, re cmds.ResponseEmitter) error { + + var showProgress bool + val, specified := res.Request().Options[progressOptionName] + if !specified { + // default based on TTY availability + errStat, _ := os.Stderr.Stat() + if 0 != (errStat.Mode() & os.ModeCharDevice) { + showProgress = true + } + } else if val.(bool) { + showProgress = true + } + + // simple passthrough, no progress + if !showProgress { + return cmds.Copy(re, res) + } + + bar := pb.New64(0).SetUnits(pb.U_BYTES) + bar.Output = os.Stderr + bar.ShowSpeed = true + bar.ShowElapsedTime = true + bar.RefreshRate = 500 * time.Millisecond + bar.Start() + + var processedOneResponse bool + for { + v, err := res.Next() + if err == io.EOF { + + // We only write the final bar update on success + // On error it looks too weird + bar.Finish() + + return re.Close() + } else if err != nil { + return re.CloseWithError(err) + } else if processedOneResponse { + return re.CloseWithError(errors.New("unexpected multipart response during emit, please file a bugreport")) + } + + r, ok := v.(io.Reader) + if !ok { + // some sort of encoded response, this should not be happening + return errors.New("unexpected non-stream passed to PostRun: please file a bugreport") + } + + processedOneResponse = true + + if err := re.Emit(bar.NewProxyReader(r)); err != nil { + return err + } + } + }, + }, } From 871c70a31c7a16cda1e841098e70f3e3a7965506 Mon Sep 17 00:00:00 2001 From: Peter Rabbitson Date: Wed, 8 Apr 2020 22:52:28 +0200 Subject: [PATCH 575/671] Ditch urfave/cli --- go.mod | 2 +- go.sum | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 6ed0e358175..42f501497d8 100644 --- a/go.mod +++ b/go.mod @@ -54,7 +54,7 @@ require ( github.com/ipfs/go-unixfs v0.2.4 github.com/ipfs/go-verifcid v0.0.1 github.com/ipfs/interface-go-ipfs-core v0.2.6 - github.com/ipld/go-car v0.0.5 + github.com/ipld/go-car v0.1.0 github.com/jbenet/go-is-domain v1.0.3 github.com/jbenet/go-random v0.0.0-20190219211222-123a90aedc0c github.com/jbenet/go-temp-err-catcher v0.1.0 diff --git a/go.sum b/go.sum index 6f2abc6971a..1cd6fd8c52e 100644 --- a/go.sum +++ b/go.sum @@ -354,8 +354,8 @@ github.com/ipfs/go-verifcid v0.0.1 h1:m2HI7zIuR5TFyQ1b79Da5N9dnnCP1vcu2QqawmWlK2 github.com/ipfs/go-verifcid v0.0.1/go.mod h1:5Hrva5KBeIog4A+UpqlaIU+DEstipcJYQQZc0g37pY0= github.com/ipfs/interface-go-ipfs-core v0.2.6 h1:4eeGPJUDWblEurSzpAtL2znDG1xqAoX2aNNIoOFwyuc= github.com/ipfs/interface-go-ipfs-core v0.2.6/go.mod h1:Tihp8zxGpUeE3Tokr94L6zWZZdkRQvG5TL6i9MuNE+s= -github.com/ipld/go-car v0.0.5 h1:YtOdQdvyvbAQwCAErHvi/sjFwGhMRoihFx8X2XNgO1c= -github.com/ipld/go-car v0.0.5/go.mod h1:yR5AsJ38xTwwgwGpbh60ICtdLPp5lGfuH28PAAzaEhM= +github.com/ipld/go-car v0.1.0 h1:AaIEA5ITRnFA68uMyuIPYGM2XXllxsu8sNjFJP797us= +github.com/ipld/go-car v0.1.0/go.mod h1:RCWzaUh2i4mOEkB3W45Vc+9jnS/M6Qay5ooytiBHl3g= github.com/ipld/go-ipld-prime v0.0.2-0.20191108012745-28a82f04c785 h1:fASnkvtR+SmB2y453RxmDD3Uvd4LonVUgFGk9JoDaZs= github.com/ipld/go-ipld-prime v0.0.2-0.20191108012745-28a82f04c785/go.mod h1:bDDSvVz7vaK12FNvMeRYnpRFkSUPNQOiCYQezMD/P3w= github.com/ipld/go-ipld-prime-proto v0.0.0-20191113031812-e32bd156a1e5 h1:lSip43rAdyGA+yRQuy6ju0ucZkWpYc1F2CTQtZTVW/4= @@ -903,7 +903,6 @@ github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e/go. github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c h1:u6SKchux2yDvFQnDHS3lPnIRmfVJ5Sxy3ao2SIdysLQ= github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k= From 1a85fddfeb80a832866a5623e9d378bad6451ed7 Mon Sep 17 00:00:00 2001 From: Peter Rabbitson Date: Wed, 8 Apr 2020 23:00:17 +0200 Subject: [PATCH 576/671] For now remove export from the gateway whitelist --- core/commands/commands_test.go | 1 - core/commands/root.go | 1 - 2 files changed, 2 deletions(-) diff --git a/core/commands/commands_test.go b/core/commands/commands_test.go index ee6fd45776e..a543eaa6296 100644 --- a/core/commands/commands_test.go +++ b/core/commands/commands_test.go @@ -24,7 +24,6 @@ func TestROCommands(t *testing.T) { "/commands", "/dag", "/dag/get", - "/dag/export", "/dag/resolve", "/dns", "/get", diff --git a/core/commands/root.go b/core/commands/root.go index c31199308e8..752cfd4e3f3 100644 --- a/core/commands/root.go +++ b/core/commands/root.go @@ -190,7 +190,6 @@ var rootROSubcommands = map[string]*cmds.Command{ "dag": { Subcommands: map[string]*cmds.Command{ "get": dag.DagGetCmd, - "export": dag.DagExportCmd, "resolve": dag.DagResolveCmd, }, }, From 90c58d6cac4c639379bb7730b62346eac9a989b8 Mon Sep 17 00:00:00 2001 From: Peter Rabbitson Date: Wed, 4 Mar 2020 16:11:14 +0100 Subject: [PATCH 577/671] Dag import functionality only ( no progress ) This still works over "loosely defined" .car files Please refer to the sharness tests for extra info We can tighten this up if the sentiment is "Postel was wrong" --- .gitattributes | 1 + .gitignore | 1 + core/commands/commands_test.go | 1 + core/commands/dag/dag.go | 278 +++++++++++++++++- go.mod | 2 +- go.sum | 8 +- .../README.md | 24 ++ .../test_dataset_car_v0.tar.xz | Bin 0 -> 379056 bytes test/sharness/t0054-dag-car-import-export.sh | 159 +++++++++- 9 files changed, 465 insertions(+), 9 deletions(-) create mode 100644 test/sharness/t0054-dag-car-import-export-data/README.md create mode 100644 test/sharness/t0054-dag-car-import-export-data/test_dataset_car_v0.tar.xz diff --git a/.gitattributes b/.gitattributes index 633d55c3b9f..831606f194f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -9,6 +9,7 @@ LICENSE text eol=auto *.png binary *.tar binary *.gz binary +*.xz binary *.car binary # Binary assets diff --git a/.gitignore b/.gitignore index 41f66ac9110..90109ade45a 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,4 @@ vendor .tarball go-ipfs-source.tar.gz docs/examples/go-ipfs-as-a-library/example-folder/Qm* +/test/sharness/t0054-dag-car-import-export-data/*.car diff --git a/core/commands/commands_test.go b/core/commands/commands_test.go index a543eaa6296..7c8065bb32d 100644 --- a/core/commands/commands_test.go +++ b/core/commands/commands_test.go @@ -97,6 +97,7 @@ func TestCommands(t *testing.T) { "/dag/get", "/dag/export", "/dag/put", + "/dag/import", "/dag/resolve", "/dht", "/dht/findpeer", diff --git a/core/commands/dag/dag.go b/core/commands/dag/dag.go index 572a5230efa..34ea70917a5 100644 --- a/core/commands/dag/dag.go +++ b/core/commands/dag/dag.go @@ -11,14 +11,16 @@ import ( "github.com/ipfs/go-ipfs/core/commands/cmdenv" "github.com/ipfs/go-ipfs/core/coredag" - mdag "github.com/ipfs/go-merkledag" + iface "github.com/ipfs/interface-go-ipfs-core" cid "github.com/ipfs/go-cid" cidenc "github.com/ipfs/go-cidutil/cidenc" cmds "github.com/ipfs/go-ipfs-cmds" files "github.com/ipfs/go-ipfs-files" ipld "github.com/ipfs/go-ipld-format" + mdag "github.com/ipfs/go-merkledag" ipfspath "github.com/ipfs/go-path" + "github.com/ipfs/interface-go-ipfs-core/options" path "github.com/ipfs/interface-go-ipfs-core/path" mh "github.com/multiformats/go-multihash" @@ -32,6 +34,8 @@ import ( const ( progressOptionName = "progress" + silentOptionName = "silent" + pinRootsOptionName = "pin-roots" ) var DagCmd = &cmds.Command{ @@ -48,6 +52,7 @@ to deprecate and replace the existing 'ipfs object' command moving forward. "put": DagPutCmd, "get": DagGetCmd, "resolve": DagResolveCmd, + "import": DagImportCmd, "export": DagExportCmd, }, } @@ -63,6 +68,16 @@ type ResolveOutput struct { RemPath string } +// CarImportOutput is the output type of the 'dag import' commands +type CarImportOutput struct { + Root RootMeta +} +type RootMeta struct { + Cid cid.Cid + PresentInImport bool + PinErrorMsg string +} + var DagPutCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Add a dag node to ipfs.", @@ -258,6 +273,267 @@ var DagResolveCmd = &cmds.Command{ Type: ResolveOutput{}, } +type importResult struct { + roots map[cid.Cid]bool + err error +} + +var DagImportCmd = &cmds.Command{ + Helptext: cmds.HelpText{ + Tagline: "Import the contents of .car files", + ShortDescription: ` +'ipfs dag import' imports all blocks present in supplied .car +( Content Address aRchive ) files, recursively pinning any roots +specified in the CAR file headers, unless --pin-roots is set to false. + +Note: + This command will import all blocks in the CAR file, not just those + reachable from the specified roots. However, these other blocks will + not be pinned and may be garbage collected later. + + The pinning of the roots happens after all car files are processed, + permitting import of DAGs spanning multiple files. + + Pinning takes place in offline-mode exclusively, one root at a time. + If the combination of blocks from the imported CAR files and what is + currently present in the blockstore does not represent a complete DAG, + pinning of that individual root will fail. + +Maximum supported CAR version: 1 +`, + }, + Arguments: []cmds.Argument{ + cmds.FileArg("path", true, true, "The path of a .car file.").EnableStdin(), + }, + Options: []cmds.Option{ + cmds.BoolOption(silentOptionName, "No output."), + cmds.BoolOption(pinRootsOptionName, "Pin optional roots listed in the .car headers after importing.").WithDefault(true), + }, + Type: CarImportOutput{}, + Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { + + node, err := cmdenv.GetNode(env) + if err != nil { + return err + } + + api, err := cmdenv.GetApi(env, req) + if err != nil { + return err + } + + // on import ensure we do not reach out to the network for any reason + // if a pin based on what is imported + what is in the blockstore + // isn't possible: tough luck + api, err = api.WithOptions(options.Api.Offline(true)) + if err != nil { + return err + } + + // grab a pinlock ( which doubles as a GC lock ) so that regardless of the + // size of the streamed-in cars nothing will disappear on us before we had + // a chance to roots that may show up at the very end + // This is especially important for use cases like dagger: + // ipfs dag import $( ... | ipfs-dagger --stdout=carfifos ) + // + unlocker := node.Blockstore.PinLock() + defer unlocker.Unlock() + + doPinRoots, _ := req.Options[pinRootsOptionName].(bool) + + retCh := make(chan importResult, 1) + go importWorker(req, res, api, retCh) + + done := <-retCh + if done.err != nil { + return done.err + } + + // It is not guaranteed that a root in a header is actually present in the same ( or any ) + // .car file. This is the case in version 1, and ideally in further versions too + // Accumulate any root CID seen in a header, and supplement its actual node if/when encountered + // We will attempt a pin *only* at the end in case all car files were well formed + // + // The boolean value indicates whether we have encountered the root within the car file's + roots := done.roots + + // opportunistic pinning: try whatever sticks + if doPinRoots { + + var failedPins int + for c, seen := range roots { + + // We need to re-retrieve a block, convert it to ipld, and feed it + // to the Pinning interface, sigh... + // + // If we didn't have the problem of inability to take multiple pinlocks, + // we could use the Api directly like so (though internally it does the same): + // + // // not ideal, but the pinning api takes only paths :( + // rp := path.NewResolvedPath( + // ipfspath.FromCid(c), + // c, + // c, + // "", + // ) + // + // if err := api.Pin().Add(req.Context, rp, options.Pin.Recursive(true)); err != nil { + + ret := RootMeta{Cid: c, PresentInImport: seen} + + if block, err := node.Blockstore.Get(c); err != nil { + ret.PinErrorMsg = err.Error() + } else if nd, err := ipld.Decode(block); err != nil { + ret.PinErrorMsg = err.Error() + } else if err := node.Pinning.Pin(req.Context, nd, true); err != nil { + ret.PinErrorMsg = err.Error() + } else if err := node.Pinning.Flush(req.Context); err != nil { + ret.PinErrorMsg = err.Error() + } + + if ret.PinErrorMsg != "" { + failedPins++ + } + + if err := res.Emit(&CarImportOutput{Root: ret}); err != nil { + return err + } + } + + if failedPins > 0 { + return fmt.Errorf( + "unable to pin all roots: %d out of %d failed", + failedPins, + len(roots), + ) + } + } + + return nil + }, + Encoders: cmds.EncoderMap{ + cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, event *CarImportOutput) error { + + silent, _ := req.Options[silentOptionName].(bool) + if silent { + return nil + } + + enc, err := cmdenv.GetLowLevelCidEncoder(req) + if err != nil { + return err + } + + if event.Root.PinErrorMsg != "" { + event.Root.PinErrorMsg = fmt.Sprintf("FAILED: %s", event.Root.PinErrorMsg) + } else { + event.Root.PinErrorMsg = "success" + } + + if !event.Root.PresentInImport { + event.Root.PinErrorMsg += " (root specified in .car header without available data)" + } + + _, err = fmt.Fprintf( + w, + "Pinned root\t%s\t%s\n", + enc.Encode(event.Root.Cid), + event.Root.PinErrorMsg, + ) + return err + }), + }, +} + +func importWorker(req *cmds.Request, re cmds.ResponseEmitter, api iface.CoreAPI, ret chan importResult) { + + // this is *not* a transaction + // it is simply a way to relieve pressure on the blockstore + // similar to pinner.Pin/pinner.Flush + batch := ipld.NewBatch(req.Context, api.Dag()) + + roots := make(map[cid.Cid]bool) + + it := req.Files.Entries() + for it.Next() { + + file := files.FileFromEntry(it) + if file == nil { + ret <- importResult{err: errors.New("expected a file handle")} + return + } + + // wrap a defer-closer-scope + // + // every single file in it() is already open before we start + // just close here sooner rather than later for neatness + // and to surface potential erorrs writing on closed fifos + // this won't/can't help with not running out of handles + err := func() error { + defer file.Close() + + car, err := gocar.NewCarReader(file) + if err != nil { + return err + } + + // Be explicit here, until the spec is finished + if car.Header.Version != 1 { + return errors.New("only car files version 1 supported at present") + } + + for _, c := range car.Header.Roots { + if _, exists := roots[c]; !exists { + roots[c] = false + } + } + + for { + block, err := car.Next() + if err != nil && err != io.EOF { + return err + } else if block == nil { + break + } + + // the double-decode is suboptimal, but we need it for batching + nd, err := ipld.Decode(block) + if err != nil { + return err + } + + if err := batch.Add(req.Context, nd); err != nil { + return err + } + + // encountered something known to be a root, for the first time + if seen, exists := roots[nd.Cid()]; exists && !seen { + roots[nd.Cid()] = true + } + } + + return nil + }() + + if err != nil { + ret <- importResult{err: err} + return + } + } + + if err := it.Err(); err != nil { + ret <- importResult{err: err} + return + } + + if err := batch.Commit(); err != nil { + ret <- importResult{err: err} + return + } + + ret <- importResult{roots: roots} +} + var DagExportCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Streams the selected DAG as a .car stream on stdout.", diff --git a/go.mod b/go.mod index 42f501497d8..a6d52b0cfab 100644 --- a/go.mod +++ b/go.mod @@ -42,7 +42,7 @@ require ( github.com/ipfs/go-ipfs-routing v0.1.0 github.com/ipfs/go-ipfs-util v0.0.1 github.com/ipfs/go-ipld-cbor v0.0.4 - github.com/ipfs/go-ipld-format v0.0.2 + github.com/ipfs/go-ipld-format v0.2.0 github.com/ipfs/go-ipld-git v0.0.3 github.com/ipfs/go-ipns v0.0.2 github.com/ipfs/go-log v1.0.3 diff --git a/go.sum b/go.sum index 1cd6fd8c52e..7d836da7f6d 100644 --- a/go.sum +++ b/go.sum @@ -18,10 +18,8 @@ github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBA github.com/alangpierce/go-forceexport v0.0.0-20160317203124-8f1d6941cd75 h1:3ILjVyslFbc4jl1w5TWuvvslFD/nDfR2H8tVaMVLrEY= github.com/alangpierce/go-forceexport v0.0.0-20160317203124-8f1d6941cd75/go.mod h1:uAXEEpARkRhCZfEvy/y0Jcc888f9tHCc1W7/UeEtreE= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4 h1:Hs82Z41s6SdL1CELW+XaDYmOH4hkBN4/N9og/AsOv7E= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -192,12 +190,15 @@ github.com/ipfs/go-blockservice v0.0.3/go.mod h1:/NNihwTi6V2Yr6g8wBI+BSwPuURpBRM github.com/ipfs/go-blockservice v0.0.7/go.mod h1:EOfb9k/Y878ZTRY/CH0x5+ATtaipfbRhbvNSdgc/7So= github.com/ipfs/go-blockservice v0.1.0/go.mod h1:hzmMScl1kXHg3M2BjTymbVPjv627N7sYcvYaKbop39M= github.com/ipfs/go-blockservice v0.1.1/go.mod h1:t+411r7psEUhLueM8C7aPA7cxCclv4O3VsUVxt9kz2I= +github.com/ipfs/go-blockservice v0.1.2 h1:fqFeeu1EG0lGVrqUo+BVJv7LZV31I4ZsyNthCOMAJRc= github.com/ipfs/go-blockservice v0.1.2/go.mod h1:t+411r7psEUhLueM8C7aPA7cxCclv4O3VsUVxt9kz2I= github.com/ipfs/go-blockservice v0.1.3 h1:9XgsPMwwWJSC9uVr2pMDsW2qFTBSkxpGMhmna8mIjPM= github.com/ipfs/go-blockservice v0.1.3/go.mod h1:OTZhFpkgY48kNzbgyvcexW9cHrpjBYIjSR0KoDOFOLU= github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= +github.com/ipfs/go-cid v0.0.3 h1:UIAh32wymBpStoe83YCzwVQQ5Oy/H0FdxvUS6DJDzms= github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= +github.com/ipfs/go-cid v0.0.4 h1:UlfXKrZx1DjZoBhQHmNHLC1fK1dUJDN20Y28A7s+gJ8= github.com/ipfs/go-cid v0.0.4/go.mod h1:4LLaPOQwmk5z9LBgQnpkivrx8BJjUyGwTXCd5Xfj6+M= github.com/ipfs/go-cid v0.0.5 h1:o0Ix8e/ql7Zb5UVUJEUfjsWCIY8t48++9lR8qi6oiJU= github.com/ipfs/go-cid v0.0.5/go.mod h1:plgt+Y5MnOey4vO4UlUazGqdbEXuFYitED67FexhXog= @@ -302,6 +303,8 @@ github.com/ipfs/go-ipld-cbor v0.0.4/go.mod h1:BkCduEx3XBCO6t2Sfo5BaHzuok7hbhdMm9 github.com/ipfs/go-ipld-format v0.0.1/go.mod h1:kyJtbkDALmFHv3QR6et67i35QzO3S0dCDnkOJhcZkms= github.com/ipfs/go-ipld-format v0.0.2 h1:OVAGlyYT6JPZ0pEfGntFPS40lfrDmaDbQwNHEY2G9Zs= github.com/ipfs/go-ipld-format v0.0.2/go.mod h1:4B6+FM2u9OJ9zCV+kSbgFAZlOrv1Hqbf0INGQgiKf9k= +github.com/ipfs/go-ipld-format v0.2.0 h1:xGlJKkArkmBvowr+GMCX0FEZtkro71K1AwiKnL37mwA= +github.com/ipfs/go-ipld-format v0.2.0/go.mod h1:3l3C1uKoadTPbeNfrDi+xMInYKlx2Cvg1BuydPSdzQs= github.com/ipfs/go-ipld-git v0.0.3 h1:/YjkjCyo5KYRpW+suby8Xh9Cm/iH9dAgGV6qyZ1dGus= github.com/ipfs/go-ipld-git v0.0.3/go.mod h1:RuvMXa9qtJpDbqngyICCU/d+cmLFXxLsbIclmD0Lcr0= github.com/ipfs/go-ipns v0.0.2 h1:oq4ErrV4hNQ2Eim257RTYRgfOSV/s8BDaf9iIl4NwFs= @@ -556,6 +559,7 @@ github.com/libp2p/go-libp2p-peerstore v0.2.0 h1:XcgJhI8WyUOCbHyRLNEX5542YNj8hnLS github.com/libp2p/go-libp2p-peerstore v0.2.0/go.mod h1:N2l3eVIeAitSg3Pi2ipSrJYnqhVnMNQZo9nkSCuAbnQ= github.com/libp2p/go-libp2p-peerstore v0.2.1 h1:u+gOfsKgu73ZkGWhvckRm03z9C+iS9TrLqpANweELGs= github.com/libp2p/go-libp2p-peerstore v0.2.1/go.mod h1:NQxhNjWxf1d4w6PihR8btWIRjwRLBr4TYKfNgrUkOPA= +github.com/libp2p/go-libp2p-peerstore v0.2.2 h1:iqc/m03jHn5doXN3+kS6JKvqQRHEltiXljQB85iVHWE= github.com/libp2p/go-libp2p-peerstore v0.2.2/go.mod h1:NQxhNjWxf1d4w6PihR8btWIRjwRLBr4TYKfNgrUkOPA= github.com/libp2p/go-libp2p-peerstore v0.2.3 h1:MofRq2l3c15vQpEygTetV+zRRrncz+ktiXW7H2EKoEQ= github.com/libp2p/go-libp2p-peerstore v0.2.3/go.mod h1:K8ljLdFn590GMttg/luh4caB/3g0vKuY01psze0upRw= diff --git a/test/sharness/t0054-dag-car-import-export-data/README.md b/test/sharness/t0054-dag-car-import-export-data/README.md new file mode 100644 index 00000000000..77679af390f --- /dev/null +++ b/test/sharness/t0054-dag-car-import-export-data/README.md @@ -0,0 +1,24 @@ +# Dataset description/sources + +- lotus_testnet_export_256_multiroot.car + - Export of the first 256 block of the testnet chain, with 3 tipset roots. Exported from Lotus by @traviperson on 2019-03-18 + + +- lotus_devnet_genesis.car + - Source: https://github.com/filecoin-project/lotus/blob/v0.2.10/build/genesis/devnet.car + +- lotus_testnet_export_128.car + - Export of the first 128 block of the testnet chain, exported from Lotus by @traviperson on 2019-03-24 + + +- lotus_devnet_genesis_shuffled_noroots.car +- lotus_testnet_export_128_shuffled_noroots.car + - versions of the above with an **empty** root array, and having all blocks shuffled + +- lotus_devnet_genesis_shuffled_nulroot.car +- lotus_testnet_export_128_shuffled_nulroot.car + - versions identical to the above, but with a single "empty-block" root each ( in order to work around go-car not following the current "roots can be empty" spec ) + +- combined_naked_roots_genesis_and_128.car + - only the roots of `lotus_devnet_genesis.car` and `lotus_testnet_export_128.car`, to to be used in combination with the root-less parts to validate "transactional" pinning + diff --git a/test/sharness/t0054-dag-car-import-export-data/test_dataset_car_v0.tar.xz b/test/sharness/t0054-dag-car-import-export-data/test_dataset_car_v0.tar.xz new file mode 100644 index 0000000000000000000000000000000000000000..34eb36dd1ca05c430c269e2df2c7179f6a2c2b48 GIT binary patch literal 379056 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%0D!~Py* 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
    ;miXYF0 z4*WRarQYZR+(!7oMS><$P^++?<)~EX&Eugfh>Wl?b%||E+IGwBlNuM{M@bs>c+8RO z(b&itnJ8tHh82PW4oBobrt*1hU(adJ5vNnAFYA~|;`*Glk?XWJccL66yc8JZBD;sX z5r)X;_Xv(7@HhPN!rB#g3v9;_@8_B81PQ~BR2?)nMYR0r%<*@$7Gz3_!&4_WTma&( z>$!J2qM!D$ug?V&W-|sUyp1rVoo0kO+2*}*jNt_U(Xs-VIMWD3#qN@TnxszGKVkth zDrqmI)gmG~+e8AX=A0(>z3AGArY6z?;9wGe zm)Ov%+VvKMup2e}xJ2htH-mvlfQwuRc{vx|Nb$xMBgCsE&Akib=L6PZ)i@i<(G81> z9&0fIHig>3N4hI$Ant*1gME9s1}KJQ_V?{)ffOlzuEEPIQs&bzkf<5s6L+uCG7DmN z_>BJY7W-!@v!l#16X%^}sTCrTS_MonyycFfUV&JdzwIM;@b9*jFT1A|(6pgAA$t2Y zJy=M#jn?$u39*l~R^e1!ExUlEQOYGTO*+$3j#vNb6~-36K}|=BF=M8fWXGHhuTr-t z5^1jWB$*tal$!gWT{7KQ1NsOo8QY8v!-AzM={!{InogBm6o7Je&fBfK4!E;_IsK0v z*fQ=w-h-ZCL={8x`;1!zPj@tL%bvqcl!4}R9{o_U#?A1d=+1_R0x4xNuH|=}>$_53 z$G454rwn}6kgw=Bn6AD8-xMWBi<5*tw}>379Tp&vZsWMQtDRfpAv);M-j3Jv<>V4v z$#U{>GvkG8iuca>#QcEus(zA~fpv;~ZGBYM$4*RIg|O7& z?Y4)Q7&}2Ap6-o)sgTCf@~k)&>0mMax+~Di3^+cND&FvngxBU&%!Cl)rda<`%W9g? z++Ub!a0UvNpY34rxBk*fl*c@{d2d~}^BToFmuz2La!<6%?1hy z1SNRDpBBGG%N|p;7Bi!q$cMzovqGK;BE;CRJu=B#2Ytq)_bE68TGgL1(%Gk^@T z_S41*KKH6LRlrObZLD#<=={;ZA(Yr>iF*w6@|kMzv}7jElA+A zq{^d*$TosIB@(RuG>YvxO5@jkf5;=H=Ow->VVvO86%7*2a(G+rOY`P_2zQE&!y*Q zAz+gW`-;rp-M0^5S;B9Gx(Rq#ur*D|2%#jjfrF~0Y~8G>h^3cDPF-5tQ&%)v2_B^; z5(akZW%tvFQL`w8-nL$i5Q4BqzRPWmGrw9X|b&h+=UjU?y$0 zOdm|FPDJH9hqz!JA`kI+52muQ>I6cQb=Ujn(9_}cni*D**7JWOmyP>dQt?!!DplQw z#OM0A2mi!{Irg)Z@ic2=Bnu8IpD&zTJI2f7h?DX+&(=KjtVQBH5QwKs=V*k0>a8bHDKHx0vau6XIfUujDh%fR=doO-ePBXy#V-> z@UB-1&;sjJOlNONqs?}$5y_;*p0Jtr z^LzLJ5GnJY3S1w2W}92@{~S!FZ@x&M3R;M^z4j0vw*gi8>3H!b)?PyUBY~s~4rVaH z>@@?8my^3>MVda9JbxYJtZ-|}Uw-$qbJh|Xi>W1LZx@d$!yWHVRDz;Te zgWr3Efqn{L1UidnR!)+k?2XhSxFBTh?}q8Ydd*rEOaP*!k6v7n$=My0)xuv+r^fi4&4nPYsQ% zfhal%-f4|KUSy8a$ZxLhVB}>g1ES>3+1H>!j}u>#Ac3sTd`6@y!!0S0ob1EI`f?j@ zm-g}6Q4qqK+-n=R@sS#1zFTyB!N}3U!|N7@`VT`7nf5}zynrs@TP=rTQ5wCCwJaXn zK}uRhlB!dJ#E9A*%tH$$0rb0;cH~m8)BdKrmDei{Tm}C_aY} zx6qE9M`aH7jQz-OqV^9AJbWvGPMc&or*~H~a&;&VE^{bz%Dk4mueOzA9oC%Axl=`g z@ZU<1MYAA9W+6g$Deq>!)k7bE{7oMn2b1Mt)&0Hajzj%PrbvSsFv(awG1jnLD)Fs! z=o;uw4?PWJT)Hx$)@Cl4|Ch{+aSRa-7Pc*JQ)7RPu10R@%a(ja zgijaFom2N5w2pWF7aX{BMB8&!sit$u3Po2a;)j!OTda!JBxuY%RoMm7PB6fN3my|O z_T%ZDvCJcBTi4I3c|uKkNc3UQZ^Y12?>NCYbx#stO4z%fXG0Gt=6!;1+5vct z1}L`P8s5i?c@G4yX=j<{Re#Dpg{9VKHVlZG-wAjz@k=d>*q40u?~^RDAG&`+dVZPK zb0*>KrWcS<+~+oT{>agvf(qO{Awn6CyBoY_sNjT+8Vh`awdHmfm?7_8aQf7|R z`)urltKp4n_G58-Q!9e6d9aOOa5yRO)un*+kWUtR_tSDdLrXxO2}ZpHur>0rFzktnYkyOHS%S!(T}G~QMMlRXE3eg! z@Sy2J9sEnC#tIm_m2add^#?Z5CU&qq@QQwDJxP60@qDMj`cjDSrH~BZG0n{BbHePD zGwzE(u8fcK`jB2V%0?Qvk@Li~5Neg-i`s#+TXN>kt`UKpZ<&ZiWDO=X*?wYT*r`&@ z8=b|@T*2Le-#PWx%>N+Bj$Bze;wxl16t-Bw;&A8x_2V@2+AdN@*?9}<58Zv74kRT@ zjJxq$irY!n%Want@vf{@tfe}Qd1gB8y6GW$BGnCQf243AiZz(;Dm}vWe*}rypv29u z3q0&Gbt+%W%k&Ikkz`37re*DgvR^HgorulH%J8LMp;WrrF49hu)prbmP(FiwU9R+h z{0;J5K8oBrVufyq-B>CVNQ=uQ%Bt*tgp2>FVgex~m;+EAiN3~&Xhut%jU<9}2Umd+ z^~3S8X}Db6J-tJB1%V4x6G>gL??|9|bZ_(olMIYfyG;fPdd;V71}D|`65SMPPRN=o zHhMcZ*zZ#>JZmX7NpWQK+O~N`z5UsxbTW%p77C?#5Z9AB;GaP7smPOy{k0oVt-u7` zS1R!O&mGYTOjI9YK1KA(=g`}(Tda)=*<#03^JUR0b{L2QE-W5`H@fji0F%WH`# z%5<1at2nPbq4m-&)+(zQ?go@yLBG9aq@p#NL)%Qu#Rc03qXzi~6~I{vs8>oi4539RTaJ+Kp)+DLTDX#57t#18r0voxG|sjBIg>&*UF@#X2_i#YDJyPK89`_~r@ z0Obo}uq~;q1X>GpG@l#Z@2nil971+Vd(y2YHyZYZAtHkprjIIK8a^;h^%lx{ zmr*-KiGs4~Y`Tu+0C!3iToH4YGw+*Eqsl_@f_84sjEyo@WuX9A>$1TyK>8d~{1(-Or4ungrJ7M(fgs|!Uh{coAh)Uf^{&B0 znfQ)ZWn7jL#~`Upw$sW4SMgXLY0Wb}AT(TSi|5_LE}IgjwoSp+OMn{?!qPr}6q>gg zR$xc>YJr^NPmQ`k{?`Bh1mxfosj-<|Anb7_tY{KeAi`#HNF4OSLyezuv5_W#5)Z12qj9NM!7SM)SIEXEmHpr9M@k z!bkeVMEa}(dVi7PuewHt!0EeO+a790GEMbpct)rKBb;hTO@6euYwm10emdUzUaawt zMNu^V)6IAg_XlguWavXFpd&YBf%1M(jO~)87H|+)@x)%D6iriG7`Pa5HaRr-MJy}k zsl3KeY7D@*?P{6k@TJTXS~Y#9{FSZ-K=@+oS6X5hHBBE9vj>QTzNs55^8lmnedq)%EhT@cQ4j}d3T zSsKO9T$Q0llhw<)Eq_W3>mH7DgLpL>Zu2SIOT6^c>Ts%nf*%(3_05rM#l%9d^WaId z>JgB^Q?Y)!KKI|W*IpQ+@;C$Ifz0s7Ov)~~JT%OMQ$$ERC@90bJurM@U99G98dL z?W>LaTT9>gSPPS^CloqD1OytDg^NU$R~*V#nF!EQpCT!C$qcvmv#lON(n_(SJt(2o zAQS&|ifD%YZ(5-~v}A$qe+K5(sFtvX#!wbY^pLy?rixjJy5E_qm!8AcTd5ZT&@_GV z0(%SuH|fi9Jn(S?4#ZL|gnnB5Lhdza3sFPd5}<;Ka{oh`?h%@+k;%a=Khyz)Y9A4mu555c5f7qp*XAOydS|NO}#r*)f?cm9EQIz zMh6u%Q)d=yW~RZs+pFi_@gJ5cHOvfeChA~}px|m{><{Cgo_8%Wrp;+@^AFd|q^*yz zEDKKJ<+9dsU?kWF9v^rWta?1()hBU1-EQuR*$wah0Qs5#bzAgvC~Eol@y|}jUIWnk zgTHkU=Ak?3v(R6%G98dPyg2>2?BJLVDjs#QGD;YHr|R7TQzH2cN{q_~vMcATe*4GH`_?F^J3tho7zttbetFD_`k+*~@lFo{(> zWKJ&0P-;iz$vtvz4Go=c6K;!>%tB%7QwI1h(2es{pY9hx<(&t7r3CSRJ6#2y!y}r; z2Nw}n23N%Huod}-Y||Dv=S@M>ueg!hyuu^#UjW)$N$1FR%R=4f|1y;#^L^mWpi88O zHr9AhF`XDjbB__QW3sCAMitK$M3zGh8KYK)@`9OP)n?m7QU?03R7C3D#EVptP8Jc; z^kuq2B%v<^WfDFe+_KoZ6P-McCmqsPcllDQ>NxV)f(ghv5sx*n^~Tdg({^8UKlvb3 zMTGsK5ITngFB-FOBBqmh^G%0j6;EDS<@shW$?jM}bOg2l^%!y{OZAxS7e9~J%%ex7 z-e>qBw>9#;IkGw4kqKd~ErHYGvILk;6eCPnNrVQTBcW0f32g=)lfniZ>q&(x&Y0{< z#B`)*=pH{qwc*N^DEro<@3PJr-IC>1cT#5(i0C3l`vOpNS z@e*UcdUl5iP|9U?^|fw+qj1D(a;N|tW#)3+X)u++TY$3)iR%~UV^Td4X)Af>3GKLZ z35?B34;kTR4hc)u*6y`&4MMki>V!$Ot>%jXOF4olw&a|_oNvaz-VF<9X{0LO!iWQE z^UMRAqxKnztzff>oNZ!%D)dvll%zvtswkg7FX}i9vgN*#$V82G>O`I^n7BDB5bz34 z`Asx^n<4~-rL_-P{*yTulmPu%L~N#-(y9rc30Uvgu5!SmnkMDbz}ZvpZD{+F0m=6< zw?)U3+YD^n|5%^KkKb^1*~#TTPqEwo)84B}aG2R@K{zC1eX}@@m$U{7tq(wMctL0M zkF^eUMgl5v3;G|IjmC!a2lbkdQqiD&1hG&hxCtM**YE*KHTXyhQj2{I<)5lSh~z>J z9dQWJFW6wrGBZvX_d!(rat@zF7~Wx+xkM?sp!#@St|0vsjobY;wTe5=7e*OC9bm(A z`mPzdi7m^SUC){AhA1E6s%p1QO#A4ySS?9KOUk$yQhLfr4OYM6q)`Y!2d9%kF`9NV6;W(S7Q5k2Q;g&y1#qd9_8#{sF_R z5@6%OQEIlN>6Y8XwT;JYuAR@v!*-9-fy4411v;&xUOqshc}FF0r$YiY=LY=%lO%KA6rR|C<=n>m9#4~y!{e*5SVF2R@8N?p#7n(uJMb40%1y-3gb4A*||zWT1HpBs8RcB#*I?>in}YvRVM=I+yH zPaoCgTzukm`+hypl6v9-<(O1M>ZNg1>{oMqXHxEy=)g>=QOip&|q)Cln1AM?+SAEbH^m&&0pTTMzo8Xz*Hegqo!ULh_| zExLsp(SJsR=^ZGec;;Fwz1Z`iWgh9l!S=;Rdb9zSG@36;)o0H|szIo2-b6}3-o#(F ztC{-i1>M7$S1zPef9~s&SjPZFg4r7x=m&drduM{I<$K$v^Xb_l6{C;hb7WERW~vd+ zIe+(JwZ34amTN7tf zs_0%O#$6b#r8mc?@2>jvV42B$^j@;`)eciUW1A2PY(wI-NJ^^6I%AK{!;Zq=%N$lj zeReP%Fn{KI(86z^$4{#xs-n+V<= z+d=URXAK8n&UmqK(nE@^`a@^09zl< zkWr&^C){q#v1QJd9YW?Jn`*%h+dPwnmM_$m)B3Tf9{CDXw+{{>!0dHkvvjSwk~xIL zfp;B3P^sE;LTq}+O|JZJg!@(->4 z%mEiONqB*b0nCAERN}Y->t>AS}nsmNm0Ihp8_JwfK z@q(BqxF!5G30nUj zG=qKiqA&cJy2Jq}M0fn^k3nZ>f)4{pe6wD`j|9UOBOVTen2DK+S?u7g*r{=nE7J@YO> zXx==Lm#@79wD?Y7kng#kZ_`vp`&{;Z-1U*FlP#g!wKYyHi0*)*NYlcX4_zaI-W1Ou zaD)c%x_rzLVZY)}{MlTT_BHalZPhv3<)$#pf8fejIfNUH0wq?SlcKRfvmKaY(%I!t#f2c3KU}mf;37IflT_gckz9v7B2_d0x2QZ#ka&+7iiW?+o*#(vNbn8gmaHp~rl=tPp@h;9DJufPRG_h%pafd6lANsbJU5fzDb^FOf>P z`On#jnhf`x;~v%d^f+>{9m#hK z8t5vrHSivwRu^a;d0A>l6FVU+0*4(Ec>VF(lIS6AMIL^AJdwd_$JzqLkZN^W9_mn^ z$-HV@LI>quh1F-V#;jd&0xq>h{X%Km*)WUedMAb#?OZbHv--U<=~$`CFAJp)4{~&r zL5f}lP%6$v!#MkWRl~_3C(}Bz-Vw^SxEyKuJEyR>jDNKQkg!dPjByLXV@Y3?Dkmej zCIc1Qsn2RcJ_{zhWMkNzVBv*k_TV%{c$(BZE#umL*5&fxo_Pr!FN*04sNu5YwU{=CmA2+pSDiTR3#FIlQm zy~-}o#kp06mL%x(&Ch31!h$#61l#jR~hwG4JBmdH6 zgmmPFo#_qg(8=6}MgcCc8vr`CC7breuumRoGS{I2a}KaxL`7=RzDM&Ff#;vCA@ks? z)%h{6k*XH#pOkqfD(dIjJ^QaT^anB>$3{D4n}Y}7XNU3>$9!o%PmaY4(<^a^aMf(w zAw$wqm7l^R^(WUt{RV)cThs73CVd6WZd`N|*Ojg^|2DD3ll!kh!HQv|Ki@sh%cAt; zgF4h1k%KsmU?zp2(NoH}`qWA@1B67ANDJx>O&DZh&M`#EWDWOwLdtgRwhb#OF)hMx z^aCUYB`SP)5ml$7;@ifwbGkkZ3)E!(I75<(AeJ09 zp#{%KU*RxF#jPLRwfPZ{)%5F?Q!DmUnX_Ut;q5QoaTEllQ^-l)Kp>gsxI`4+fGk*% z3h%YxJF$nnOOC7b+-3H(K)lRzkh>m(L5FoEM{5YQtmjL8HDW4UBtFY}l}aA(}8I+}ET)l3jZSwa|c#^hqhQ zC#vN=OgCH|U@aRtWwtJVgELrZ)2;I@M3zC*^RGa^s{c$K7F>z1J9gz92$;9*X*Qod z+ygt4riI=S%dx4$aA}3Bw32jr*B+CRyQKy2~K~LOM6J8Oipg7HR z^}3F&REhQ0v){VFGH1y=XlcdheyPYN(&dLq+z0j}gRGuFqWdloIHG#F64xh8WeUxF zk@vJ$CBtQ2mbHG0381L1-So;G69m`PRGBl*SnF;F73GF2T2bA`$Xw~enj3#Q1Gk0? zh+z!{AmB7CMEL2WQ7Ae9+&SsmW?NcfOBWYT>CM`g4||a2A!OM9BZenvQ9MJ z*?D9NEcg@3q zITgjYKdP(1L-L|sFA<9*nAb11l17G8y1#rp54#N1Dp@yf-gHyQ4^5?ryZ9HW*aqY3 zX@>Oq4G>YfPkEVFtq8h`|0EC{=EfzjJ&ihdlx=mH!qmr*Y;lV>3w1erszb=9^gMJF z8EcAUq@a7qG+H2#rAamKuN+Y6gsj_>C=y9*5%>tO(AWTF9+fMMu%hHL1s*Bn0k@U4>_U z+2TC4-hA(No(t^7liuyKbfpQr`68uAqk4t9QNi(N0D0cwkhW4M@|NMME?&_6&MxTxmKBRj@?mX^`&_uF7Z^I$AaI z|5)GuJ%Z$#P)O|fVs6tI8RPyDIkHml=;$<4T}wnGUcTNB{5XI@gt* znih9wfo`(i5Ha!>`}s#?p@ntt1g;2ghGe6t6l9M=5T26^3TDqzL|pRhY_}^nQbbIl zO-<7JT@Txl6d1WosKFS)pm|wR$_OMqOg%w#s*}RHjs&-#MTOFce=%$B= zH>%|g_@3x+XC{j#$l#Uc>UNDsZ2TFz`e|n<_tUm64cQ(21K2=lEu5+yi{Yt1xw6gn z1~E>@%Tcqsv^DK?KyDoGbWVG8xPG&n_4`t1q1bFjJ0-7A`2fZyHY#<>^C0M2*~OL< z{QkU);w{iIs^HbEF@`K(4rhuANe5&q#|BLP674UJ;yYT096v7|RFC!z!%9Sh2C7>|L==FBBmy%(cnx2)PId79?NkKO zy?OU32=U!u?B7T!bvayRFW229!(C>*HWFlF|MqZqkj?vmxZk^*?s6qHRRq^^X1-Jm z31S0xw=r!M&s>A$orz%>jV38aRN&PfQ=`)38cIK8dVgel&BOFp|i&4L9n< z8FElA8aE2Cjg42C8y%5qzy2_XiPce~&OCORp>h@W$`X?KW>+a|ZYpuGg`;(ajHmac z-1e7a7Q#SUI2coU>Ykz<`d?3ay+;x?Y=bu}&-vcgBoKn%YG6?$P)FxBtIq;bXH1MeKp=ud8PwEZFJXyu{bp9aLGDk;+dkvHHt|t8 zQ4|fQlM+o&V;iAC^bN0&>d1Hj^JW zLtPr-A@T@ASgJvOQS-gL2yze?@6qb#<1zMh_b5sPA2=UX;;!Ofb)i`R(C?Kdi`&Y6 z1zR(kXK*4k>|sruoxbAcJlCKz%3 zhrYLI)X}UV5r4OlK&k4)gk-YrEXLG%z~B6&DKq*q?4F=JFK-ER^AcuY@%8n%B%}kg z$R)p1!cX_U+np;uDcn4|82Jvk{P! zruR3OnVb>sJpL$HM6Tt*fHixw8yRzS1@se5JNNP<2^s@HuAO>WX6 z@#ByZHgzQTaHOe{ROzeL0nu~>0a@^dL5{1CUyoF3yOzNUi|j0Hxp?b6yL`isNl%Z6 zd-s0ZONMR)x_U#e$d5k9L#y9Gkz|9+%z@eQ3^v4~1D$uZ9P^=ymq9Ydt~|^1uJ!@m zlhKOeVaZkD{<$~)H_blfU;KEpLYI;FfZEg*Dm-Vw(p{)w`NF_juNho5Yb0Q{hV5B8 z1W)RBeZArzR+Szs7)83}^SH$tS%tX?@EU9T+=Ct-EkpRg(hZN$jN#A3KX%^=(L`bi z2?k0sd!xE)_#2%XtLk6e_5L)DV@mL3g>5GueihG)^Up|`dQ#9HaY{8-g>;wB=UpaZ z$y^*bbIJ4sp2?67@Iu^F&j?Mf{zj6sNnlzip78Q#Ei87;09yb!FN}kS70=s4A(vBN{`irhE8N7{d3YJg zoZMT1vXx^ZVIwssyR`&(*M=iy!7NR}ry<6=8qNnwjHY4Q@goBz3r^<(?g1ZHRdfRs zNH+Z?D4RVWd-~*>4F~{RK>A|r7g|4mHC*1p4;It2lM!N~=(#Xnm5tKOZ{75iZt3Tn ztDz0sseBe;Cxd%b!Dr`!W`P0_PoD-(i_NA0{k=)$tmTcE8 z5Werre0UjlIeOrneu~H?)cajh=VBGvtbUD_hN4O`J@2K?ZMJEM%mIen6Eecu zru)pfc)FMDnjuBIHBpR&`z?(@HwkDar z3kK1AZ7=`&-a(lDw9ehrcZ-<1*S@a^e4Xtv@_Gu?cYsOmC0F?L?o%HJIV)w8w5C6k z9}PhLo?Ba}sYX%*l3jijm6^rM6;~!z62J5mtJ801wi;nS(Z1U7nf~;AY+rkh$AD9DSSQjY$}F-sAzZaO zholEX$@1aWw(Ea-oXU~`@Bp}MZ-guB2)QB=rtvf?Rr%;&F4=1aIBcF1a9S|;Kv2LKdr%%drr5GNq*DB6V0-W3@^939DOs|#J$Fd{AwBH<3 z#(sIWyDG4BSCH_8=(Xk+xEFQHo!yoLh|rvYSG{b#+3XS2ZxEkOvg~n@Sf@j?!D<8l z2>wbXFv6@l{XzLnPk~J{&cLV$>_Rr`3uhOLYB9SGl@}5aFLEKAhHlt6UBi#M!-R%> zdVRbF;xSW1?b{OlK>HK!(kqY}z4-~vQ?%j>KH(EpxE2VSAd7ZYgkE7yKQBwp;A^LXar9jEJG6Uk> zqtsOx<7|--wJl5n?t*wBJdtIQ3S9=iT}k4l#j(oQN$+Faw?L9b zrg?wN&}{m|34zl!NbBy--5z`NZ;CmF9v9+8GXz$xk<7RI^C>G9l|q(<+_TFA5392xy+a8vsxdaCzecg`e^LS(Z_(a zD!4ScN7^4@aayDQL*ivb(j7Tx~faOn`me*G)fi_$o%J zdmcAVt-!K-wbJfsFxKc7!pFYyL*2TZ*S>@(Pr_x}HsGpyqV#BxI2g(j<3O7Rz9E=; zbckNxxJRPHoF~6OP{i0)z=06LfDoc6=m!HBXjAKe0yh{BO)=a!UEObgd=s)o8=bWc z@G42U79dn=21k55+5(8d*?x9Z!?%G*{wBQ}( zet#jAlNu!g1>UQDVQHniTCigvO6UDrha+8xR6pscN&3r#jKSO2{$X`U? zf2G}~i*|V@jJeC?uxMBUJF8ZACKso0eoiL~Hpav-9M1w?*WJ`Qwuj^R6Qf+C~=}RF-6Z7C?pCt(; zXQuPbPmGPEF;0GQfar>j$-njWRl;HG^)V?tYuVM{gxN?dJZ$ZjHD6kgSIdM@3PQ6r zXuxTNjr>z}arWA?rSO}fMzbWN)liHdrZ5wX9uUb@B?JN%D%(1kBoiIU*fxe+y&R%b z(xrAx!FYlOy{62#pncC?^O1u8Gb4y0VKeU88aOc1TomJztunY``5gj#zr9MT;A|9t zHI4Jx5QDOt`E4(va{N>89w7eTzMJWbd$Scy^)u=Z_}#+l>;IwoBMWpx*3Xri`IVfl zzwK1J2@Y>8Cr?y^KseUtboy165mt;NcWG`CKHO?ggwcCdwOWlp&%(J*g-pA{x%W2~ zOCEI2jbeNGeQ;TV{N}vg>S$jenvY)JfioFwY1t2lOK+!8M+!Yqy#D77a*=GX!;`jz zflCSAeA$Q!00&OwdF4>#R%Hg_$ zu~Hq_vFpfdL;ou)9^`_zytZ)VNg6kRIltCwUTh&3IV9q4lz;*$y@C&IjcG^;gYv6+ zd`L*|_Tf2r`ifVx29jIJjytjiNr|+aN^ot@^L4c`0gU=LQQB#J6(K2V2&~UZ2kSDx z@0`RLf=4NvJ`ws9Irz?07K);uibg-fG2j-yK~z3JzfDe3fFxGV>qfz%CmBt=Ye+Lz zJ7#{a+_zgcF>@A)J|B=FD-=bhJS`3VUbx6#f+yoxp+ z@4--a1-bJL(>(ur6J}YzFS1Tx&us^7FzytucQ8@eXF%meNNlSA{??9A4RU&#L}V-!&0^ z2SF3$zx~(r3%zDbAU)om+DLOSm0V=hiV8TTo>}Dac>KHC9qzMq9dhRPHF230YjF6d z#zcRN)i{0RTQoBxfrsgdDn`MA&)`7Sg97xT6eAR%Ui^qp2VOC1Hg~rqd+_b);;V0q3Ja3Uz;hcSkbcRtf|s)4{r`J)a_7OM7%#4(nQU;QO5V> z$F8TMaU@2+XK1g>Zg_%4?EAj67-f&S@`)XTWsm~{zaYX%-fTKod<@e%LI1Ejs=i{cd zGa`W;qfEm(wHHceOD;=aQmT5=eQCqaCz6XbJA5-lpE%K>`(OUWagV=o+3Ok>X%42A zSOb>~>bLmh_=ks8_CP{9#+7#R&9RH;SMB}`FAE4-Fgk<2Lx#$_2)QRG@gJXy;Bwkg zi};sS$kD?B=BOj68s98v_eyC?oAKflRa#7#umU%{?(@Fw|7x(P)}-^2xyGgvjoRQQ=51gZH} z8=|JDxoZ0~-T3;Ss68 zx&_C3)7TVZcX0HckFHA<8@+@nu8Ki9JQYw7GQKHI>;iH?%12?CC3bDk)3vHXFOM6` z5>C99U?rNdYr9yXjLNc^dVND+{~qNJ$h2C{%DmU>5sNS7kxH{j@mKAfv&LeFScW- z?(h~jFo&JPI%6Cry~O4BG*%xWa`}XNsxP_S6NmpJ}Za7=5KQxs|zQedWc{ak@ zcIkrlR*je7^K_Aq=FIzfdZxQo%e0ldHVb0V%iux45cKrPh>hS3*J*V{J=#?5Nr_mG zHd^CB^i<73LG}fSA7R>zB_lN^t}~atG&XpIfDegj-S=@_MBIBvy(Jvv7^HK$aj7zc zuQ;`(fgiTtkyce=n9Foe@x5V=KgGzOgn5ulue)EU0!G4dLK#J4or6E#$f?7+<*Oc# zH&7dsJtlo4OF%<>SGDK_K#2PZ(R4F7Nkq-!{)+?ongcJ_rjH2ZhO_fm7Zc*XEGF-- z{Y^BqZt0LEe$C!hs@x(>nF%@@24s^_x?AxUy(N`|-gnJ?Cu3l8UI|3R^zHgWhjIZQ z0DcN<$2fnI#KzSErFXNt%|00jP7i=Ka4IeoyIjYKhH=Qma675Im+hJ7}URlCV&N&N&(&+ZaRh4kaYDy_vbc-=>9H{q#%t8>AZ+p ze5q`!(S<}J*lqj%GRl5sB=K3Y)5%?RXu=cT);V3}0EPmo4YHy zGH7}~kN@?Xe07{1gND!OjjZ*(+4!P68D8@csR- zEZGmi67-lO;NNu(r;mJjS}K)e-L?q6>GMSksgiZ77CZPSlN$N97^I0qHoaZ=7uqLf zS}DfIi)l5=YA$!`pLw1;o5}GZoZNWq0Pk#U4dAqKCCuj8zGpmN`(?0&i44p@3h7 z$xK3cUoch=m+|rEPPS|BF;CW&)mcV7VOhOF0Z9qxNfSZjb7QtIkUUd!ZFOuCSpGd9 z@*8+Ezys1&z8ltervxRE76DMHm3_U=QJB+9thQ0ZQ3GYBVj}fC+xJ`)pWYM!MJ+J# z1t6wbtT0=jYRUT>z1bwXRYy=(D{R740ccUVwmhKDeFJdB_#H@xQ8uOvl}6)1wUr{Im;)%WlV>YS#1D0V6I&E@iLd zmc1$=vV0G}n=FL#Fg>g=KhoZgEC^;tisV9prxag4ZtVM$YQ36nvZ3REIj{QG&?}Bo za;UN-5BtogjTSmt7iefw%rIbF@BW5+&z?eoJ#6R+Ol5SqST{4zpj$aO zG=HO5uVc2kIIuNMSh3peKD!l3xH6qy5o3INlJn{O-D+Z|)H*d2W5EzpR6!B7(u6(- zElk4MnC1FgIk%c6xRjrqov{M{N!OL~Fx1AjYCmnz?V=x;C>9j}4F`LOuW8}H7zzC2 z#Ji{`Yj9o-V1~E^Rv(8W&8mSU20muE3runWK6(l~LCfBI3w(WmAh#?bFayZMKF~AI(8#`qO2!5R4ZV zU=@-9ibgHcL_;nmV|Z%qG4K;H>^fiZTokegK;qzGz}4`D0HQo7)ny%ed+>1bDHxWR z_;tQ5ntQqVP&BX5l6cfV@+p#ycg6UTK^SjsFok^02m`L7w2o?~XK9v@91t_c#j~)w zmTsu}NULV;yv6a3%B6slZPzS(OxpiWmAzAGsb2A%N6Rqu9FKJ?$2p&OW|Pz*^O-V; zENSjkEY3#d{`q7xEn!JmS2-yl&3@@(xv~ua@M)OfhcQ6XchJ z`M}c~8}brYL9>A^_D)MWSQl|k0d_0{EP*H&7J(VOX! zbO;1O3LgFrgx$Pg#p95{H8TGsF|zx*1j#9g)1mip2qE%5buOa#^Z8OYriy87tlM^s zP^!B|{8kBpH*d%F|Bcd|`}8Z+*pcl97HpKb8D`tBTQ&^kQ|vkr@Laxk#Z`H-;VtEtBE8OGW zMo2@?l4GN>3NN&h(SGdmgJth}4gvy(_v7{S<#-7oEDaD}vuS(J$psPS%hdBR^Sv75 zmoU*!9&N}Po6lL@dEqK;2&=CFiu`0~%JB`}!lcEQhanQ5!>$U0?U+^G#`9E+AzU?& z27BwWxbCI&pCGknJ-pO+dw&usB-MBOFQ&rhkn^|nC@*PGx3Nme^u4rn$0;KO4(tqbUPeJW zatc0KX%||R_8u@^r}!k*Tdi&jP_;@mE_OfRARW4?4WL^WpJC4^^%&F@q2EgJI#PiV zNg* z6cDTfu~9vEo)6~jgM(*^=n1T*@Am?mjO~hu$0US}WgRs&03fPV7ILT?z_n2~_BqX7 znW7-I&?@Xzv6+Uoc`DWo+Ot;McUunB`H|ucU&DXY5xpx#c-XQ21q%`ut;*$s?aX$u z=L2>C^ZX zMYH567rIZD$YYW?zT(U9tG!Ve8R`C+;mY7eoshS*(pCx%2$MiM=@4Euqb{N?u1u53`KGvrW@GqUUmxF0b6P z%y(AJrTgW1=$cKgZrYave}=(cR)Fhem-2i~5=}3bhDwXACRx`hswekQ=Eis==H3uJ z)GLDNh-~<}S+o(|n5#Jami4i?(vhNZYI~P==#OO-WEPq;8T zc5aRbHNeCE-95pZQ2q+6fdW{*r_4<8ku3y0t6}y~dbXG+uwVCa*xvq(SWoNoES)Oa zlIgraah?J+e7PNcMRm9c)HKsYSXR_5n96lN%GHvEF%$c}x~@rH7UbO7{{`3e9_O!; zw2|mqIjFWXmqBMeW)>Hm&tTF4g$_B4vZ+hk5MG2{bE9TN0!YYw=H#AzVRm9lV1v(m z$3Lf=iQExHy^sP3kgqU6|KaQ;wroFT=pWqIUEHvCzzp2^hp2dQyLak6R=`7>A1fhm1wlqDtu967?A7eB z@piKuGjy^--E|vY-Y+k>rpn{k9Ks{t3zY9LZu1$p;KsiEv)NLdBsCjtdB>{a-8i~O zN_D-iS8EG=cx?|bkfqo-mA8vCnG9K{%y*S@VwG?Kq`0L>A70PceM8MpEb@Xd6iSnz z-%&uOc+>l{AC~yF?v2)3pzcq}k#o~~HP;7W=lz#9m{!3DsjgUV5tDrWov8LynHv3j zOY6SaxWDQPUq2V@L9g?NB!j$!>a4{Zv?*`$_`yn8tDQ6Ec0*iE?$zX0u2+Aq(2Q8X zI3=%SB`d%H${w?+MKm=DbU(AzAQ~HTB>nKl*`Y|9S@VDV!C<5luM=epEVK7RKRGAe z)6fNDwv2iN;1`nd_#(dAQdH7n$osTsUg&9<^uVaO0VJxyeZI8KVjFjmRI!O`K9=wu z4b)-FcDgXh*_o`~u{YN?{(&5WW=vMIWoR@&{SPY8HROxy(F0=A<#Q8ANW}>0Ea1c} z(tZ)LE~zqBBHXuMLIuwsr`?W!>arHIlyn1S8!_!6w<~!-3L+>JcRr!|>5^d}y(U1%MC2oQct?}%S;b6VO?m^Fzw_{1E8eUrMsSlThC04T}ZSqQ8wSgz0O*S zO;deMgUF5w4m(BgL=QG3SH#T|m5qRtTx~Cv>x4RjRRc~L?f2=YWSpU)3m1m6WgpLw zB4sx>&d=dACs+G^FQIdei!^hoemh^`DK(y%j z&7o%(@%1B}UlWIl9$jVI|IIJY36jv6_`Q1NXFFxwRM{4IuXRtMXBaDg0)?1dOB=zV z$)veEPaB5!bHW(B5+k4>^eyrIkV}D7uy~#K5&DF0k-X|;MO+oNgxDF*L1;2ehjxW< zg5vt(J!Y1>S3>qfwB9SHq1pJt?e(biFgkPm;y24+2KB#?*-=y+KFfCjtdw7yJmwFt z`2;?vHydR)O`$dKp7ce^BDv+G9qo|R;oK=mW-I9`^&^t4;&;M@|L!wEm+S)gyFpw^ zW;V9#q&F+AB=7C0xx0U1CIG6V%|$oN(X{8o&Q%*_h@A&z$Ev%Cj!}ACaMec}Hnzs8 z?8qyL9LyIw*Q&o!In}UhkzlkdRTISe{WM6AlYY54st0vka)*H_$jO7tRPmInOkWr_ zO$+SFXoq4S$Eb;qFXu>@plUplX)kuKODV={JoiWn+#u$ z*!-oO4X1|lg`B;Pq<7Zi%fU{p$xe>k1JkB1Kty0u$}xHfHUd3wAWyoS1mjzGs_cf; zgw26Win|O68hr6$eoP9M#g&Z)sf=pG(HjILTDr1o&|DCO>#{zOoJ0I@73WWFxb~Cc zPOjqU%`Fj+?&!py$)T*@i?Y0DvljEW6&c(j>?^0ej6=YmVS`$Ct*>rug{|~%H>}qd z`5BB)HlqR7+7xj%Ed;D#g3bg@dnbb-KV|I7KqXm9r;j$PwL+ruYGl zz6@XRP>6SEMCV6j2yHVB8?OTl^xj3MivZeJKswL6$C|!T0dAS@RKWLre5yAZDEN+G zKJr+)q>2(rJJe19us^O@mKEOn8Rkqjg<>6Mo$zY%i98W!;8|y$`LO8zWhh&W=x$d- zF^sHwElRj(=^dNfi2LJc3nS$SR~rc)(1aJQbM2ALfp}@N(CmQY$7urOa%f`0J!kX} z*H!k)6h3Kb2Ak_0&Gwe-dqc^7WN^^NyK7MJr*bwKK~8rT`euU{nc+HFxnMjXAn=I_ zn%NvA%->dbgW4tr^?TL`1p;GuDci`&^F}2Vqt}boy(sPH5t8&92}O-iEvSEuPhQG0 z{F@9vlG?X{R#p5BcfsdU@5_u;YK5?9g~D0|qQDeWQcT9FW)7`|{Nezr{kNorWEIWx zP5gh|KRJuGwzly`S0$tg5gbU?-7~|+xv>B2n5{u z>nBqi)#wS?10lFn_-|Finxo^&-CEWMfTxp)<{7gzzCLZn$L5p_O#B#FT5RtEz~aedR`*H=e#P&+sZ9|`2H-hr z?PTGE-b%+5RJ(E+sLjqLIAkgW{=)QTI$UgtH*i~-{B_88!~P8(?Lhbrnz0znYXA6K zJTegMnH*L{Hx~Ec7V0su&)y_3ls;_pFsT=9%P3$+LI&6)(PEZ=gb9A%-Vr|L9-el==TuAZ1#4U9FLe=Ktc3DZ&sHqp|{j-xCPkv)OV9jm{W3zw&bp zdy-4S?)bqY%>{82))-9hg|rMC=nzz@<95mbvgU)!9aR7w+BsIFsfq35wU%e1gg4hZ z$Sc{5>}B{s%h_)pgAn4gpBb@gmm&}X|Jy1WP+m& z$a+mxA=Y>5KXljMMfZ=_Q~6#ubP?qu^P$U=EuE?-(sMyzqEGE_N!zTcZKoqqJ69Lt z@W!nXIUo&Ak(mKVAAwqR2eK6sL&0}FdYo47Y_{2TMg;OJHJBSjT%xX-(Pg-RSM}Vz z<755owlqc>QYc$>jNo!Sk~|q{8>FK>tV~5R`o;bXVZ(mbVb8FelS*6Eg)TS^fFn-? zx1Ij5)dxF4Ni<=4(|?sQXyu7tywXZNoq!wwyCBf^D+UMGc0ax;tanIKPgU7Gce;`% za{whYq8;$?vC`nFdt{0&B(_wM6`61ZmvmA|izCjhH3NuG+%;oThv<6KkT2y$H<)K{ z?is+ob{Eoo_=#|i8PYAsLYScEq;_p7o_@Po%bcZ>CR$2Z+Z%K7P(juIjO!0zd0NX8 z+^CI|^u8t)GR$x6676RZng-I9#J8TC+$z!9xo{ZJ0O@}mTpE!Icpff`pUx9s3@aG| zE*hXt&>{9;W2%d|mTvk~RfV(Ra*%+3ax5lQi>;<;A#Cs&#!^iDZ^X$q zAPL^Y!W%P-?mMEev%5;;@%8ta34FcR{@ns(1?vGQ=0hfjMd8VXFy|Vi^U7EXtHEG+ zlyFt`N#JVm8jT)vnTt;vgH!4!ZW?w)zS*|vP9Szpse0=KTTR*sd);X!GHNCdnK&X8 z^WyvfEH@GzI25DWGpS78K9EUENRiz!gj~{Wo10t51lja&4tdab?=ahV@Dwx~45-6f z&w>M7SKzCuzSVqyHqvm~e|MCwx4KH0I#5cKdxUSx-ib@5w<60O{L5ZVdhP4#;Xv0r z`vD7XNZiH(NntD9PD=Dokn)&2%KKpp5OsWpcAb5)*}Qh3Tv!r<;uZ!+q_i1le#enm zwp&s9gzQ&Q)G~QzF^EYBf`3#}u`=w|ti1+W1Bz{ffLKg%;PrgHckBa$g|+Dj@Rsz@ zc@yNAZ}vs)>Bl#jzNTC_&`_BPe4*34Ej?30qV)z725+&x68MNi;gP)3ANL(f=V! zn_D8!?p_Zuk=vV_AR;;EstE#&raNRDoV%q0!iA@tYg~b&AmS{PLg+_MfE&*Wz2~zQ zi(GHBm#=Ivb9jPAfhg;0XFc&2B;()zkNSpOAwnS|2>*%LNkhI$Pc>7PNH$Bci_p4AUY_C)0N5G*!KEBxcj_KV0ITFC$3w(rHO zU@wLM^1XgW5uR|l?oqT3sLacqv=uzUau@iWgX11|%vr0r$a+iAvz?pt&B|k`gY~`< z_~rXw6$jYj{}Ul1*J)KITJw?wc>-_^o4$Ys6e<%Wvk9oyPD3#y6N{Az#CRW$KbseP z%}5=qLs|4A4}mRwsM$aM@VK-w|E*-1emet@iBVf~8+ ztoRP|-X~OV%If9qHU3sY;KddU?mUXCkRX^)9m5|2vw9}A>>_2#2G4&-@z+(7!K7e` z{dNh*clsrKIfM5iNx9mr*2JJc;hE9#8|YYigS5t=Q6^cHXm$8S5m?aPa>73OhvB4E zsiZ!8AdY{b1RJz{I`;mU9BE?mZU>Lk7M6`PumG>c4!_eqFGhxV04vT4arW!L!Jy$T z=(q0v4b9|)!+4<=o#DI#KS3qjx+D*)8R;dZRCC@jOvdJ=sB%DXs`iYT zs`E1#tp)R(uFsx{3Pdc$P5op5dai%<^VO0whNg{>p%c!mE>&%2Nm9=cnF#U_>c2(bZQ%@>`>}_ZM-KOVo2$q!u(6gLwj%0E2ZicDtV#oG1-^ljH`Tde z2$G%d!%iw$07{=Uwu1?Y$0c7KIJC)dYqxJ&a-pFY z-=+p=>d;*Q?D;{=pXh^Gjg6zxSKtxygK#s#ap7kuc3Mel--30z`G021P+CAbi*(hd zld%@}-foYRtyb`vdA7zw%lV?5Y(990A)pp3jE(|n#t_T+McQ=0@|-wL^D@Z z*1y5(|CR+!ube(JR*O^>#2+pjKQ&eYO+`SD4#q3Wn&*@3{3(OiQ4yV>>FpXtOKeTi zLASQ4r6F-p+77*Ym}y#gRn*<0)5|vB#RF98qG?YZ+P25+k3W=R)F<6{^{*xO%sWI2Yj>HS`$J=a zEXI4qb|xklE8p|k$n--?z}nSr>#rSo1JL6UvP)oF0@sTIgPa&I2o-|EIz6~Diijj^ z&7y}OmDrYF67|T!)C{$lqjnw>cacwU9I~3t#>CW63cp#pbKIo$Z`0>eAHj!SVJ$~v zE3A8#S^HKN+9K{7+M00~uZsSHz9uwssv{wO2QqPqm!NG>YaMB&6J$|Cq$hKzFI-_l zYa-h|q>6(sxoiaa+qTggDXjKm;6jt)r& ztJek6r9*fQYt#0@lG|ChX_=zjn;-;8#Anx8((c>?nwcEOh|Fk*K5rC@v9tZp*jwz)cQKv_4YR*ikFUnBGN>53kDN5_;|uwa=oC z?;l1PD@OgxtW8Qd@$VirS&IIJX5G z*FOwA)R%`j(1gGHO7t-Y3{rlD;@$1a4WH`pW~p6~c)bmpuXdCZgq?&}o9xfib`3T-MF z;Va>m{qjPM19N4V&S}>%L0*=>wjW~f?Jng=WFZ1`>c70$K5mSpY( z&PE)q3Nc)^0^sIScPDDhwRW+uw9uv2vC667KXPwLhePqT!+=osxDI1O4 zaQDGr=7E5enztydI%CNtYv!eFq(Ibd=%>`1;I*Oshqp@r9DrPUoSz4u0AKd4o?|B= zO4F6v?f@X0mO~~539wgiq-u#BinX+zfcb<6m00{_K)C(SeON$O;bHz4reFY|6V}Et zWix>!EQ37B?-K+jgMP|*6>vX~rk$Q^*>D2QuUpc;)F>~#Vj|_&m8W1|WQnng)|fRWiCY6}Nwhl-b$2SDO2m8tE+~=pyJ^L`MK>A!x;gUT_w_E(A>I97yM$scC?)^Z$|vt7Z$%C;7~ zo2uIhoQs_5FHMb-L%{s3a=QKzoC>rqjyF{{IU7;lr%~p1*79!JqHdY``u^$Lq$|Y_ z9KxzzHNo#5nB-*H4Ex3XJCnxGN!`Z_B1+d+675aKN+`s`!MG51n?m*yw!80u@N}*< zmI5o8vW8;5D!XHJ*+Wlx)o^K;!ug|S9b~#6)xm35iMcLs=Uk@RttbM{j9YBZFvzWZ zc^AgV8q^*tbd}=}u?766w5e3Ye}ld+$Zp?}%ql_Mekzf7(-W(cUTL1Mz~+(9S}pF{ z!CO|IDLsa$NNvRhipwU5pk=mK`O79ufT+>L4!UkO%)xG+R~;3FuEF9k>)&zy{f$Ckk$c72(B}g_hPyC>tmR%#Zx%A*9X*Xa9aTVXWBU?Fn!RUpOV?bFa3b&1gLD z;lHhka>i`^C=|)oKBeow; zP}1*nHR}NXr46b5=p6LdIPNbc1W;w)aYAV^`zqw=r}Qe)n~!znO_Wy61b_}ce8?u6K~NHcmXiGXV%5J!*erIoTEg0e${{|_-uxUGaBjwHXNozAd#uoJc{TJeJ)d*z6vLoKr~y$4 z&?rP&Tx?!uT!BcCb1<7|{tMx21>VpIhd&@q#@&w@8K)c4C0{MZzoR9+C_7{jJ=u>< zP!;Hc*jKaZ<5+HBA2#&jONLtCT#j<8x2pW=S+lAJhRF z-Ts!qjYT(`N>`zszDePa--U=npUR7(1J&3e-W778O{M@0Q*6srV^Es)uR-T$iiLbL(wlY3qSym~yu!#^{_F(ca63B<|^UAImEkdId>kLX2 z+zP!ve!5ga3HNvR!Xt5o0j!juMa=t~#9~(T8k%E{qHO z@Bf$fTTE8s##z+z#5bw>?o`tTNLmk>&S8(*F0s_MIC&rc<9Q00q`UV%!*fpi@*{_@ zeds#OL@&%76D>rPQLXA(2^Lhdf1Y}e&J$UPDHoh=;XBn+N? zq%aB^-;2Qy=7t1G-?<1=DEQYlYOQPaR~sr%zP~eVbQwERI7EuCU*Q}qHYhJi$k9NM zF;Y+b%jy3{GJ^GICRwumTH_r8Qi)d|2LqkAmaqW6oq11r|BK~4jKU0#`dYd`F9dw5 z-hdU}b5M`$r&3jMc!*r_eQ*`UBR;^^Xo|zH3MX&5k!eafsR92(zGDFi z`DJyCa!x)ejW>PJ-2qH#uqk*@&5f;nNa&GuRrpL+$zNJ0QZWH(=ILXXr}!{^>tN*R z=gjj2KBq=TUvPglbH2Eb9#)0PtEH}^%VMe7@y9q3 zhFMU{Tr0M9attlR2DCB(~`JiPOP%!TG&8Z>lf$ z6EGFw#`v5{dLW=yW#acK2*akOt9s!`@RQ&|XCRd+F@%*VvLszL=sX z(18^GwIH%M!I)(%H|QDr843dhJ`W6bs;_wHJ=|0|8T#dc2tW^DLCdIy9z$$oy|fg{ z7O|XsHpSSU>n9Fozs6+*OhA3jP8CypkTf_{t9nGJx|AlQD7|^xU*IN01W$g3{LWyw zy|ofOw_aEpavdWajZ6KM^$fhwL1za+ePG?@6i;KzpE*>sj4G<)W%hXhvjlh|h zbQ!dtrEK;4_)sQ$TJLYvPWC92L3IckW$%#)U3FBJnZgj6B8l}m{IIh=_v;;Bz!~RU z8Xdzf2{OYudJ~e#;tbK-nV5t+<^~JD`DJ+5xJKZ`E%XSr)8cW_>KnH;Y+)M@fMSh* zSv4V|uySmdvE_Q}I9ue_noI3GsA~li-`h04`173LAJf;RZ7_l$ zL$;YirNs?HI@oeGl@WH*qJB{Xk!fG@MdzrLGoPIVUlO$h@w^lf|23UWJ?+kDd{H3d z$Lvz5l#8grSldI-68isP?V+;SgMefbkU?yR{h2VX0GAgQsp{yOQ+TEOGr)zDA<5diaNsdeq6gt+0poKaGga+!^}E{y*3GbICm@>xnP)-mWDZEj}eMI zzB`YLF&RVHzj_fz2!>0=86xIW^Rs1{VSNG}sh>*P=XApe;7E1>1QbwkpVtQvrinEe zlaWV!+xgFwy41m1Af^yXC`mv70mULvn6mb1OaCT#U5#yCO>+ge6ES6=(adps)WR#`g*@x_9UMRc$Tc8|y1j@vD7tAV(gPBPD<=UyM?)rg zm1`taFxdYY9rb)9&@&(x9^Q~;;(wnrzauGYQ`~kIs;o*Ig2k&CcnDqw+SP)7X;smi z|M^Zrt~O(J5Vp;YoaW9;=M{vZri|2%#o5#t>`j<~pMi4Y)9ZSeF~c58(uX)POVWUM z=OJ8&A$-m{z$%3Ra7)0qBoAtDtX*JZcV!cqRwqI#cT)RmZqckt;KS2MtnqWM`5)MY z3w1@Uo5C3lh#d_HtlEN~UWlipHuY_YI7?}G3n6Whzy%R#7R8N!9tfhvfzT&?_dfQZ z-jr-}zH*t!V!D&_K379f^fd4%6w=mixtDEpFp>xAPrA(&ESTsZ*M|>j#Uo$tSM;3d zt@QNcePIB}^TJG-OM}(r32fq7k7)0Bq3(&1F?VFeSi|Brjk(%)p(!D$Ggoe@eqaNx)s>jHr&9E=k9nmQ z-c+Gz%siXj2m%rd>j6OW2Rwbs2BJ--J!T z&qZ1j>0Y&36N^O4%E*{?)szHbF&K$E-MrqZyZ|on(!|u{9+i!;lGkMQy3I2UW<)RC z-OtWYZrmP^d6n-i2=&rmb_-KxEn5h;1M4%hO$~OjK7yAeE`MXuc_mgYGafZz!It|c zgLtHA5nl5_nH#OvM%*0WC_V7 zidd%ygb~e_r^uuUD@Fnelw2wK7Ky|lH(#OyKmgA86d0ul2h1ZGl*+x zBS+Ze@{Qwp;7_yNw~n3Ek^^_C*^EJP$w1)m4A}KXR`bC$I@7c(33E9>CcVj$kE@@! zSrpt@!Ua(~gBjFT9ewH6Fw3$|fkY15Tl#*;At1KQrXvGx=~%pXav5dRCG){A6~1P7 zTk|HgQWpqzos?c4?efghG7o6K9JU;N&lJi%wlG z$hI2mx>SiRhEE>QNz4>e?;EmghTvzB`eEKD^|HeUdGURj!aYSG&swnf*1r%C9$rO} z#XCtE@^vRdkqC+2>#j(q`{6t_?H2Lb3H5Q5CP7|EqhH-hp4Syah+48<1ApMHIGm@4 zhQL;L{mNhUsP9-mLo;0rG7fqx4kDfUFW5-$f4><40);L`fy z;v*9G5KLo8lgge3Ca>r<0X`CJz}{6lOQ4g_xnI2hkW+9Mc!rb*cMP^%sPN+D#zVf) z_(Z$?$XSN-s%+{;VG?Zl&2G+5=`*;0IeEN>bLhhWrx}?DPG0Gtgs;0 zy~dlAhkz@IjnD-#0a^#C+Y>WO!K*7aF9LaYLC%)z0!uqfV9dPu4% z#6)d6cx#plj%zGkhm8V}8n1#5(ywvtW{%R7!mN*`y>`V+KZJ#Z0d6;gN3{CW3!ChE z$mrfy=@Vv&aO!J8DyZlpE3qEAFCV<^b~HADOZv)%2_LzIh&6K}b?f(z_)7*9Gq#$~ zO9e2LXK5l%p)w+kl1>?<^38+??hZk;^kPn+r=Whucem=P`FjPT&qx|-4!V`}CA*Jc zIJV03qO=T_5bGoaLqo$n!UYVIQ27^W+u$b}_v8zQ^@_`t0|(RS?B1b*#KO5&ZRWUG z1-240aKL)ckEE%O*T_v0Y!?pr@0tneo$0ksbbenGXm3?u;IA*ns_mOML3Ba=&=%Nz zqsRj&V9;8;m_+RjlW>}z|}e~WCxR}&g7iHw+X?_CG!sL zj~3fc4WMT?$1SCXCm(h+$T|pR5;fWvG&&)GEE&1P-~r=)f5(a*xbae1Y?LC8CF|4Z z;{!?9aT`v-6}6{@A^wJ^i_y&ce@CKh(5CZszHJJ|@g(1UTm!VV+|_>S7DoGMLp(A| z_50CERE75CQZy~}<3GAdTMr=Hpgxorw&E>g>cDdz!9;6nz>S9xJK^H*+TU89rDs;9 zA;WGQ8R`{~p);#{@I>AmSh1}Ma?H7M(>*a4BU#w^lDcdM3#Da?_y6SNFZ~cl;z_eW zJ4`w9O?zjwQR&!wqKMPxy9?5wCtebgO3f(`w(~!Vo(F zlLfWNw#r2!6paRYE-Hte$s60_AFKuw;EoKyvgc=}mWeUi98liVQi+^Y2a1;AetO{N zh=zLtqXIe^c+bU@%ZNVEi{N+3RT^+Bnpp8-9k*QjEaV_$Byru{KO*xdWps4stK6cUU_S zzneL8BU0c{k`5X~CIxwPdx-okohwDaXDz{1ZnL`ZEv1q)tz4q!29b=?qlj=UUVO=X zEf`%}CDV&Dd4%~wu?hr}eflxvWpG9t@PG#3zJ^+D{Fkpu{9alg(mtJ~))kwP4ZRXU zsc@iu;8>D000b{9YV`V{2-ni~VF^ux922-*C>A8Pk|q-K2IOO$Ov3&nei28R&(9AH zqU$nbF~Z!-uY~M=wabRCUfFV7x7L~TC|M2={pAd%Qc*;9$p+?ChrF`0M5dz8ikqg_)g zIc?YdQ{c4E*1tMn7E1C5@2KLgIQ|R_(*$7)QVr!?S15BsT@2DS+4T6=Q4n{ITHHs8 zsGbbGOWyZ0dPRny3HnsHvR@Y+1qtJ^fiW?yDIcvbejzwKusKp<*|sa+!O4~4w{^!E zCcLlpf6ZKpFv~N8MxAy!bI{l@QaL>xt@gDFy~4OSjrAWk7-*Y(nDy0OZ!}S{PsDoM z5GObM^;f6AElbkrJ`_5u5b*`+)o@nw5Z!ZRDxl_N;Lq0+TZS&Te1Jc=cfqyqJU0|X z2bS8Kf+H9bVN(P2O$UlJze|J%VWLOv~hfZ7DOdrKje87iGs`kJ`*~jzA#nSvGMBGm~_rL4o zt<^ZCG?am==!l4@xlYk-uAHLrt$RzKI8FiiVr>CW?8#o310`(2%ieXjciKrX^U?Cqgo`3Q z*x`5fMs)!4R7bQoM4|wE9*R!KxjpmnzD&1q)M*$#1;Zc!hGf1-=2(c*yd}gO!sR3m zKjn=;%MYa0jgO+jS)PUB2_%iEBujOM`}_G2;psy_jJlg!J(s(dP_W}=se*2fie}Hg zM|sg#)qV78#i6_@0mvKObf_TLfim3bJ&-hd*!fb|Zg|`il_Q**6;;;*Zpo0GAAU=E;0%|#Y~(uDkaV2 z5f=5wQJh>PM?`lzoFtNC0Js*rPwZ#dq`X`}q%3PQjc7SPKy2rx&}#|whVi~ug?x=P zxo1Ea4K{|Mqm#adSP$QIHF~T%$M~E$920HEGn#@sk+~2i<53Qb5`c*tY$D)$5L(3X zmQ|ov(mmg6Bgkynm%%;GE(GX!`Wq;o_NDH2LaHzawS)kd$~OXC1gI`7Dd;G(vOjIh;$tN9;pL24(_Kl+3ty;E>e@+a=2d zuc27|Q)WeNs5mFI5?Ko|-qO|7N`x@Iu=62)uz1|P`s-e+9qrllXhLo|<`5|*xwq0F z%oKSorDKTDVcq+XmGJzCnLxOS{_0}$L+Sf)iPMTg+!CP6M5fPV?UDj{7$#F!I#Zrr zG)88o&xc!|Q7qljzi}nL#3s)cl?Q+hTpdbDkE%6^ssnP%;xgG3^K7h}-_N{=VwKg3 zR07t3v3qG@V6^E(ZNUPV}<92=4?)$Trgk#6XqUWHm%4=W2m!LE(s?`zmH)*jOmOTH=(gmXs9O zZPTNb#iK2}Two;k-E(9<{?7l0Wl4n8>^SRvo@3$ZtcCuSo(Mf$pwyPYaP%Q4G%O&e z@H1p5@77J z1Jo%MQz;g3&<3NFvM^#gjev~-ZnZivBU8=M&vdwiIDUvWe~w{2?lbg5)~ODT_$Z<# zzj^YY+*Y~hsW!%Am-K8yLYIbPi7Ig0wJr*KiVdwZZZz^(EAzBNzQd%nkK0X9cmI^8 z$z@&QMH)>vZNmTzjK8eQrQR3=t?CDCAH5dY!sbdo`sTo^I%-V^hdWJDibq?yu$uT00c+?&a=2q5f+o% zIpX1NdoSO+a~IAEJtzuV>@n67Ski1c5Rge{`e21hBR>BcumROSn5=r zzjuTa?n{?>1?n4QW;BL?b9KRATbl-NxDjfL*#;YM+_QL!!n8x!wiN?`fTD^2>eJ?; zBsIY$eF?4tRVDMv!Y6!h2<%n42;DeY28H(q6&23azCH$ES*xC{0@%La&4XPW0rLA*L`14g*Sp zGwZFtOdCLGgN6OTbwj6W_4o)Hz6i3tq+PZ>&mfv^QeLxNuo?z=kBbggC6rim0lkHw zO@vDuPFkf_+cMe#$bM1ib-GPzwlROo+5L5M(YxjoIm?iz%}s`+;B07c$V@V{9mQ=p z$8x-^>dvot!Od1B4*mi2-BpNd8xv%{TC+g7Vh;&J_)>rbdngIJ?dN|-Zf8_N7W5S% z2Q#m7wTEQz&p;s?lCaf2W@g-lSTZf%dkZ+Tf`%Vhr=~Qr7QZ$O!M{e0c*C@J4eO26 zGMz%|l@NQX;?O^+sX9*epFrf$8kA#UvY;8s+kp~ z9P*k;(jna_95iHp@1I+mkS`C*mlA%164xpE{Na0%&vcY~!@u|USX>$AM?Qx652TNy zGN{RM)prc1hVgnaF^n%=erZ;b+OMu~mt821fLRzObZV`YZ$Qb1rc%bmzEtekRnn@Z z<5H8nhd>N*!&iMf;4rYS8<3xKNztCtfxbcFTGk&aa^Ku#`MjUC8M@)kq&T;Wea<^e z>-aGl0Q@|mEyIt8*g`2#@}p^CvLwATXucbysIMNex0j#VMzx@**`l&}RodmALfP-s zhkbG!IzDavWIjrEmE$M>LX zkdS#C1E8L^r``@Q9$7_!q%14Ug$G2Zrd=9F1}hepHWk*Kj48G485$x2OYX{)$Fl{$ zn|8+gG_H2LX>HuWZ9gCPQpE(}`PD1u!+&a03-!v$P4xy?vwlYzX>LSL%Js@3Jsl;F zt(Ae%d;G+ZKm+OJHUp)63{V^M!h;&F32JkNZ3tMMIBP@Bd0~#69zLgGXg}MW+<=vR zrNvsaS(XPkRa)50l}D&1(ejg)ds>*@ci`k_3V18X)U!MKME>%{J?l3G`DF#VEmF_z zrhq;I7eu;YW8=R8K>$j9P}4BuFda%A;IZa_sI56E%gS_hTr0vU;yp9H z0L2K*Ss~J3+d~xRW8Rjzyy@29tapm}85x4F%mkPQEDMc;)Id~|ftuN-933F8Q|tHR z`B_Rk7$(Xnj1>R5koMScsNg%p3x?O>WNSx zP?0@wNGZaIRl+`72W^WN@44VeHx6t%Xq)bQeTs}K%gRmo+sn8uQh)#y_-I@C6uu`wHNo(zJ$7c!t1xSwU3TA!54WjOCRTScNHBNbSV zK&)`Cd7QjwkiMukB40;A^;E4(ZFih`*`Hjc#%xNvRti4`NC8A>!B#u3<>eCcY~4YTBf_CdS zCTn8ZVfr^~c3g=cK@JFadP{A@#{H4+%$u|Y^#%n|<}h*>fD%1W3W8X~>bbyDa6dIq z{dkfbo$OkRoQc4|S1m`^Q~->0WO3W3V9PoTZ#R$wk5ZUT`{pHmp>d+gR*gHijbkF_ zPNGrdiW2TPrwJohnJ&b1sp4$JJu#gsXU6iR;8uF@Z5~^uSnv$=_G`-aALZ5ULHm8A z5hjvlCa!gx0y;hcrwyaYl*WFsG@4O*)OH27sc0g{M)5zCe_esD=5fDr#9~jRN@o}J z%+VHdZZ+r2#;;};FDVuh4=|mSr@>gqFlKs04^ZHR#-;XV*iy~H`Lr(gWnNjp_O`F8 z%H3-*Cp|}q7_z9b^CR_cpX+WqjbB$e!(eT^`7H4ZS^QF?VS0kYUzZ4}_-BzE^)wd3 ziL=(&Ni6Sm`Z7W{{+yEoOeE@G{_MnMXT1h>S~GVmQN-?*aC7ZwdN*J(@1$W| z-UQ{?1Tx9pRC-;gBWA;q3pis9iJgNT|L*7$as#=a^i5IbC2`F!4^l+inzfcM#yqVJd$tH>1>6M9{S!;f<^7Hd z5dn|C?GifTRk`R!Nk%BCX0`K>#^0drMIN%|U>kOTP{C&nq=nHPgGA05MTJt{pXzHT z)_WNz!70pDvX}yeIx59aJRanhsBKgf7bqV$H6v>rkMFIoJ@^G4E-NFX1&ch{E=F_F`rJB7YOjtaYnwAmSPoaJ(W= zyQPpsj4JF15Z;Ki-x&P+a&%HE4q4V9kkY2n07L^W)&f5#b=E#k*!XpcK74NbBjjg-yzI7`2UNUvV3LU=wf3=ZDe+JN1&Rq<;1ktgD)}b;qQ;7q=vF%a69i zT!6Qjj0@uwWUz@ro_}Pd7*?Orf?)`WfQ~E(Y;RLX1fE~iZnJkC9p;yb8mr0>*u%eHxx9+LIwJkExNM8=17^$RAmI!HQ;PxTyUW)&d%N8yP)lZlXr zd3K?{ya*eacNcpgLk@_Bl{7b!1w27poJq$@5_D~DmnqQ2&Flk4pcRiz;S!h9oiY|~ zEF)z;?ofxjh2F8vEqUm$mI!+&(HA`z{*Kd?n+qFHng^hv{}>Y>6M!h>JM`!=zj<3; z8$a(vfeEo34+R_IPPl9k-T$QF`qn$8-4Kq;3zb8DQkDOk4+pKQGYvXR8A+=~EnIsM zDc`x&j9+$;q~(pMj}yv{s;)3A6JOn%Hm($qVz8Z0-DtCp?y&#j0dz6)T?_3(=;n;4-P#dJ0a;-Q3)bahd!EPV)b@toqm& zqnd|D?I)!^m71O7B?H7T4Y1?Ojqj1(cKxop61(TrG#P~M%d^Zcyti%Wc^Vmr!{*b` z=Y2T^f@P=d?$lQ%9S-~D8KBem1>9XW*c`@s@l&6hqNk(2J~6sz=^Ke zk6ymF%$>@gG4<$p!fPdUwGO1Q343d7{e@eQm|68qi`rRA4pg4m8F=WFLL=vKWhg6q z!Lz1q4C5pl>5r#AZdP~u4H}&A4Ix6eEOBT2+HzRiCK;Yx)$$SB{3QW%Ba zvaTg%2Sp>B!mMTVK_vqzvDS<`!Zd`RJarrnT=fmD6iQy#xM1e3gV>IJ@k(_hGVZz@ zkDN@b2^Pv~L2>l_=o38yp zFM=g-+^c1j{0YF@!MQ(Krm0G>4WDUDN2(scqwNA=PV&uBZ3D`P4UJhtSM|Z%sy71d zwA5qR7aIjt(+UN(VUZBPVBp=nuI`p+4IyGYs>6NIg(?q=nI?7kF*h8bW-~1M)PV(8 z_WVaXL0G$fttzz^uvAvi>r2a5!BxOAQTl_xm3}}>80K@7KiD}YGQ5Vz4kRHPNMwKEyUYuHT*0h^4kv)T*5|aq9qPm=*iH-~F5;P>KXuBvXh?-CP&oX1_asXW>A2`#elE%`RG0hc=4wgRK-vV`4@|j(vxM^p+1|PuIVk2%YH>uM+u|GzNU0q{5NZg<@C?2$k+bPKUjvau8tzPHZbqXA4<)Bp>}9gZ1Qv+*uzCTUr*7hd*-tu!uEFLuxBvj2U#V;JV39Us+OXrKxO+sHlX zq$UvY40$nC?1&+x@3d(kwgyqz;>2xHevbp?-)bKM0%J|`fHb12cf{GQ5ryXPBtUV zBVHvq5r<(rJ8NwHqH>TGaMTb6Vi9f0EL@SLLi-W4LxSx4$Qz&ONttb-D1yh6=c@GU z@dUJ@a!Bi7wE*e_%L6D+fE6qYn~UM6;g7Ly7$yP#!w!0)MSzd1!!1j zk>64=O#d#f!U2W|09opomDFg=x#Vuasgv zQggI%sUQ)4=&pw|biG}3Tw zr-uKjwMfMo?`@nmoLI|oles&&d0<=L7)AniNbqsHKnAe<89*U?*gRkgqNg1Ngp>D^ zmo9j3!pq&pAFZ2yFA~{V#o1cWd1TJt4w2h`Aru%qdHOmYsn8{mdx^z}sgnT_ImC$8 zi*z`VU}5Bvf08G>Ere)yDH+~Aqe$vi&S}QE^v0Xsc0^dkm?dW_)wF#B5y0qS73@&t z*Jor6-I`F6AUZDrlJeo57^*$QUm0P7_Ma(bOAudkn`7s*CEb5x zBC@{#7TB_TYN$^7&__k8Anwf@oU76ju$~#yGlE&F@Kn1%KemTrT9;8RpCnv1rTf=I z2iQl>#~H8qjLf`$FbM>@F)g>uC4NBEWA`Kc_axgo^5Py4rSPE||KIp!E=GJ}1rc;i zi#7U2OW9tBJJIm6L9MzCIuol1yUeeSdHYFcSmM5k5^mUO1_+Mu&xb#UK4^``w9Ze zH4LExf9{!wENfeWMT%_ZhvXRW@1ovj=Mi|} zU@OfJg%)y5C3Yh*fIPr-PO|H)qO)m3jqDIg<$#!Ix*d~?*X8z9%dX}uVNZ+-yE5s-U7|f9l6r^i zm;#NZ8Q}2evBPg8O&h z0TThE<ZMjO}(IFDIF5*omZ&y?yHo` z*jtFqo;rs)Y|cUcvhLg?AaFH{i5 z5R2iTUZ4k3#trNvH#|M7419nCnsoz3rNgK_of>J}HdkG&gT5^;5?p(a?0GMGT)W&| z%Ratg0qpH)x6r^I0udIGwWPk7+`{#p$-(O<3L>NvmPDju9IkS(Tzi#}`^?g!r!qXJ zLb4`DHovIQ-4{3I)SGFsUMvQHwyiIs<9Mxz;)pc_3}fRhZ`RX)AXTiJZN60iGXl@YZe>4&%Dg1SJDy3YQDrmM}^f!K(+#A?E)vT+`1(!351q~`4+PMFzg zQN$A4R0XlE>AJE*6JopuRdvuAmoF4gq-h21dYl09OmplDH?&VrrcRJDUx*jVTy!Q| zm`9N#qZhy7)!xCyV%1dg$5J2bxdh7Bux#0iERd2~dMamVYtufDXe zXGocb9z+an0HjgL$mofY-s{SZpg){nsvymM?^tveI0fMZY8lsSA53_=tH~a?ym}va zH@srLz@_-ck!{R*qFr1A-$L^XnR<==SrQ1m!tn;ym<^fUX1qk6)ZlynKR7tv^JJ~z zHW$_zj}d>7Nt}j=iI{U*)@+HU2O#15p;yItjMRKbyk)6_lRrU}64(4cnxZnSBB?Z# zSi!~zMXn^l?_sIAnWTKlhsFu&Gs?0nUDVnn2=Zo<1cE_`%MZ@c4~7fd>$k`Hv9U)^ zBQr7I=P6D;j*)p_4Cx} zH%5zxrkOhMX7Q$*w2~<^6TWJ9Jg$Jd`Txds?Q1l}0Yw3MKf0-$k&7H3#PG9dR#p14 zOh^IJFiK)XrgT72^y-#rEg#MU*}aIWnXm`qXpW(DPOvcTagpEXWL;wGlFky#l>$LX z$!a_ZTT@;j<8aV&xaem+zNlTQ&W()yOTxUAxdj$;CaW1VhdBbU>aoBw`5t26^#)me z4oDe;ki}3()fB*iV$t?3l`ivKtWGRTj&OFO__+`@{b8(2W*#VL_d8oS9Bp`31j|-b zf0NFFc8^j3lN_t@QWMnf_n%~3*#`@h>*L1=*K|D`gfCD1u4m{NIXJp}2z)azRl_$O zp*r`&UABF?{P4xhb+Ovyt9hYYu7;YWcr=YyFE?8Hv3(y^3zALeRj9KX1E*+n#M7-g ztI4M@7sSO!z<07J3K3$mV+w{?uu{Gs;UaYqXstKLoI-c-!Tn;S)lZ1Ig zN^E0pNDqN_ca#L?g_#?Frr%@j(y+tq?IzepNkvDX+6vexT9GIe(e|+3OHtxzsYStGDUH zWo7iNV*QeN6iqnpcu%S=(sdeZW~)y8&3WM2*71W zJMeJBkcjtyYd1`_9nN4svNCQt4UGkXMNXNtv?U8;dyddtw>gRU$52aBL#jdcwczni zu)h8ca5b{KW+p32LE+4tXJ}qPq~t8Dl<^2NW*D-a!K^YF5!vIMp$bl zZzjKnSNL#_*MNH9BpYA44B;^eX$&LWeOe2qDz6T!mpI?bi*`dS`P6^_uCdtdFrarG zds0%EIr3HeO+V~Ln}cpxeqF-s`13d?yg4apyvkq=ykh_A_g2dcB7Xpfl3hG>QHY$* z8X}K&R7l2X@0>o*Tg>8);4Gg-5^by+i$0k-%9Pdp=`9#L?~6^wlWmaJA>OZC_@s3) zIAV1@6f3H4r2-mMmn#w1?WJv zAG}Z1=qEQ;{x?>S13w?JO7H8u`IEmIjRm7R^_%>u94%0dRd_yvJSx?XfQn;oXGpOc z_~u1TME-1))rAlB-LaNN`!Iu`(-T%Tf*10N%C<+v_~C@FbrSg?-jYW|e$$ zYiNg|=M)iVJb&1$Nbg9;+&mmD8p0=COzCsu>`K9!dvY@OZR2&ULMj4hFzmIq#ps`_ z&hhOx5!o>gGLuN){D%{v(g~q3_B9h%%c#`7Z=m3na=mTf68G&ObU}^cAi!`}DewG(y2hWh&M*RxNobbzVtXOUPOW?9dNbWi|WX~p5x&cYgE?%mylYKVkKPCOE zInu$h5@UdURk8I57OXNy2n+55Bu;HS zq9FXP@wmeMZ&?T~yER3jbT2Vju1L;tb)0Hx=wkg{Ai^0)i}TFHmxIhfOPu)P~<`FhVgbq@pEYz?OEb&MnV?LV^j}QVYir^jo=DdE9a}* zy_}wa&29D27eh1e{vBRxn=8hUYvDP->&qkeWCN$sveOUf_T?AF3IF?Sy`eq*O{2QF zB|I+#{8?osHyAoJ4zIRkpab!U+ink=JFJ`Dt2Wt0}{YZ zLz)DXbdo?EiQVWRg@;}{51ugtfiOXs3xbJxG76Ijt>$jX>gzys&0R6g9***KIYX<~A=Z1~Z@?}M@hI}y|NSU6YU{D!+98Ndn$#Cm; zHU7yUn$hx644T%4i*9E}0l!(xWscm9d75Ql+Sx&3Br*NQw}RdSOQ9M6#J?x^ANKWd8;!D+-$YbZX> zpPPAboBJdn_cuFbG2Gy8JJW)oTMwz0&+b7>b)HhpT6EAy8%jHB<`R3vxRh=(Rijq) z#4uFix`!H>Oc#t%#bc&lU^FZwFzI3(NU-_ymy%ZH-vhf)EPqnm+1iF>Ogk<(#jH*9 z>F_!6^z&myZG`V>;?h*L!%uB)~=`4KMs=2{^l9amZuujZ<@nBB45xZq>L!JhQ^22%w{PSr8aw zHDtEA|18b2v>zCq5}Dh^cX(Zc0SrTt*Bb~Xbgs7ub8q57`4@Fs(g}~4w^7F@jP)}A z3KD4(05W%z{d3b zS)luDtEnur>O7@Zls9Ju13;4<97RbOWWpNtwH4g_<(vbm+erv(in{5o3~SLaYv(mx z=t&mbn8&P+kA(_SeG-tWLdc0}>nssCfp)65d^6bI=UHwu2@kB*pRW6HkCTr&WqxnS zG(W#nBA2HPUm>)D;w!fON$K?ofp{$FCGW|$na~B1bFXOjew7bNlc_Y9C%Yuj6oLqX zJULN1uKCmD)WD(tU^=F{DJdU3o|jV>@dqy1c-{?3(H!7&!U6YDoA$BIa84Dm?+JoX zEiZj=nI8HrP#v(lDAsaTJlK5A_a>{QSre2!a_c_Q*WFBZbFcg;34b5;s8-M8-tVIVJtR7`Hp3Mxgr zGI^Y5ZGXml`GZ$ZaNL1}Fb#vlSjrmp540^dlI76Q9kDO4g+B?mItn`&mGz+D+uz&T zA#R9a$DuqM{6y8;R)F?;G1O|EqI#u!=#Kr(eI*4DWt6H=pM^29L?o8q&O6JQ+&1Ew zAxtS27~Y?5qRc}z?K14qs3-w=f7!()pv#_<L~@H?LH(Hy?64v$H1 zkn1B%HAMyn8vka_v-#C}i!mP;lyR(8H9$$4JB-B3kJm-fbS-jczrrb#b*t(A=PDD8swlEy)93T4r z45mOj?dv!5Tcj^Iy-M)I0Q14mMC$o#d92+xJGr-gG12=Brtisnz8$dkFUOs|1?UE{ z?11esJFrhIaq@LmQ&QXYci~%D1^N3xktR=X@`mNK9{+fz*}Lwfm?G*Z3o&zyuFL>U z4U0px%r0oX(3uUKWYa^_vC#ya%@+8!eAq4)6{l8!ObWIFl9>cQ0ShMm*MjgX&yBp% zHg^|qjuJd7bKYOp4%kc;aF`>N=hm40vO_NkH)&HtYi!$Du3`t5#$#T%I~jP>dcXvo z`|?jX&w^mR9Uu72MjJeQd4BS%pEb5K+(4jd+FI!j!a1Fnk&^dExF~%q;CW3SmaApn zn+gd^WotTbzL>5E;)dAL+zUJ)QO4%f!HIv zisS`L_6@CG16=Mqv2``pYWyxy{AO_i-ZuXSO27uGy3#4i*L_-MK6|c5fXnrLuBYnj zjF_j6b?a8M@?ggUmDW{$!3@%iNA$yJa7(>YjXf?E&>h884ORRFH*zm9yg5 z5rOH>_1PLu*M8$49da;G8f6Z#U$e(&Qi$j9ISj_^CP;qoa?lFJ%8HaBic2_T5~4i7 zf;oEQzD@wmb$_eFKN#R>YE3y3_RR&9g;jK6QHq#5SXuXcK1QZaXMpX}{C26l2~yO9@M~(qAi@zZBpy z0u2)barSs&kRRk_+vbFJIbl{vTuu&-N8*8C09icV-F{CU+Cqp@a;Pb`HhCXJM#Y{x z);PuxMqTyCB|fpYR5h_6gNOsQQPYN)-QA5s{CWFCcPLUAKfG(DUPM$vx zQ2ZGy4Y#`fOt9)Ai~4<0+#X^)+u#lvmx|uPe#RWrn{BsvDrd-?0GCFsM1|-vTxw#h z-R8c@(%!W;J%e=!(2M6kWReY7N!v*~ESkq+2~ zn(knp95lKYP5^qc!i3k~f_5!@Ipy8N@3$_y1^vP@Fup9`WlSqTa3Cf zhvs-J>nJr;`;b{?IV!)=hqZo)HbcJ^3Bq1KZ5ljTfQiR9C{Tm zsk^nv@OIP{v}SG2O0Q>vHIJjh_vIiTHU;(r_x)HtDEI%rm@YQ`5GE{$n&Q5W-d+ex z5)8pd;qc@DUxA=#uu^8^6_Z#&IF#r%l{5T!T0)Ji#wa_Mu0qea!aBbi7PmZmu_kMA z)#Eimt4jc7@$<;n_qs|{?kE#5$uI(jXH*-{Dyt%`w;15!@so^s z9hJNCFVB*F-vCSkEk?O=(abVc4`u39=!!4%Uz0(RUWITL7c>4mE}_fQRy98u1WoSY zlrZgv#zLjUoNx#!U0`t$%)8Hk{_VFX8kTM;oR%I8cq(r8rUWp3ov}GtHYHq@E?xHK zQLYE%FWsW=VpGPZ?7vP47q=sCfD!@|0`oRYOX=$Lc+x8JK0C&3jQX&B#!`}TIDzCJ zPb-55BUb>1*OVFsGdqSI8~db;zB2J&*Xu=-gO!~u>V+1aJP-51ja0*buWBnN5N>{1$!Xv426`AxE>^T0~Va0zw08IApV_7%+? z5+b6j@LN>E;*ogwPNoqK3lT(bmUVrcH{$U61Io`oKp;V{yZJXYg;6kPJYq{e2msf% z;H2sVT+wbc7H$bwjAg1%HHx z9foy#z!H2yfU*WKful)QVzMEZqwc`9=>UO0Hyzb^O9UtvDtp$WPBdD?S(F@K`mEjC zIsygTE$1QP(H~7crUtJZ0!6hBERF{}PR%Sh{0Rd88(`%YjyfO&EY;U>r}SsrY#b%2 zkJi$qimC*4SJvwRPf?efAWc*4_c@C9F+)HD_jCexJ8QiGA4oOV z%7Lqa_nYc7o(yngtI)LbeJ+Jc45`^#vMG&*W>}) zC0othAG$PWe~vRY@ybeDBxTTf=vRpl1l@tVbTuALCOiRywub$XPa(6$YfR!roe_K# z27-Y{(L8sNGLAAdZ_ffv!1uj94gzf5rFYU;>*b*{F`Ak=N=-(3Trj-`UYD}$)* zXrAP0z%cdld*{5CeA29&QttL03K`mek+N5iS6hBoC-;M@CKc&VYH0|rQXshM!dm{t zYM$vrpzU2tkLpQ7&cqJX=ee#$iArZ|(v&Y%=(xo&<$Fp26EIqp`=j~xdzk5Vr;e${ywKBEKXQp zus4qJzg;d3&-!6-JMg-LA_Bng8t)!zRM2FL^QN?Ma?9E_0`_Uqs*sAm8&`F+4%ujz zq1pTAy5J^8GP{kJOb*_UHvc9E&huJyx7hIS)G4U_fWP+6>)f++xavmy^%#WaQ@kG% zH*WWRQx65V3|Xoi2{g=b&B78PLz?1y9}Sn_?1PFHCn82R+94BbZ!|acG&X%^*ouhv zjxLs|muS@q*?0>jsnx36+XFi=KWL`F`Sp%>?^l9MDkC!~OR;dZi071{#T*Luoc!Hy zhkf`%FF$9CI>fM>hNa(bRpRR)y09&0Auh#Q8sL3JMr9c`CB3Oz$r&%YChPRy-7`%#7VdM^K z)AeWf4VzS@V%T1nkRURbhO^sovk9{j0lq{qZvvQZ`28l7o;~tXpOeU>;u1H zQ3r^-c30EBx+H;ZX&u)p6J!9hyKREJpy7P&z2}#y(b0C$uETE@vSq$}nijx?CnZ9` z5i0xF03LiX%NCFXi`A>BnL|M@l?>LZop;3l+cM}}H}K8g6JlD#h(S)gc#O>ybg4X{ zd)1?x&wn=baBPM)TlpuCw#s^@(2x^{%p8ms?MKdu>fv+_Ub3g%mph{MJ=DrtbGG?~ ziuE=~eK#w0*IktyJ{~zAZGI7sZVSGt;#e{R2+fhjTjp@X*jNo3owOtxy+ZW8SFnPx zpoiO23R0xwtk6740%UVVcP}{rJf(4zljJ*7kgHPX#zy`~73RLM-^h`hTKW#F1qhbQ z?-Mmw@{~}+f`h;TC)qO*b8{q@0cS&@1E5P40`InIZSyi|DHUErv$e;@qRpQbGGaqS z<#+|>oI)0r$*?>3laesUCC^J9c%T-64#OhL;i^WVII*sGhY2bfGw>JfI&&Q*ShjHF z2SdK{RXO$O)1=r1S++;1R(^9~-7^YpnB8c*tZA`dSFujUyFGWB0w7>c@~`GD!x@$k z#O%KgzS`@E8%Ryv?!PJLV_Sg3I;J0FKdPedu0Cvz4T=+a?Zy*jBR>e<%Azx%-aNwM z+L4F7%&EDAA z)j>(!H#&Actx|>WAH^bSyZVP?s6zq*L>-$GymV=?P(3UKW4JX1@9mRZa%vy0Dl=U= z^qEWw-$Zir_;YIW>-#iICHiY%LQPpgt<46|c9K%o|Ad>ylYcdFiynhZGhmHwD%pa- zW(6)9t5q3b2tyzOAm#$@Sn%}&^LKsV zEpUuhCn32ooNTR~54V9*Q}LJ?+K+2@?I3f-ZRr$c8OnVsdDcOce=fOb z_OL`FM=p5|&E6xT=*vM}|8nu_{;bV|^(J~pHG$6JCu z;!*w;vJngqxDsr;%!=M90+gdelSQYR+M*j%W$8giF@`1~y2gb~eZ|yjs|QF^8ITjM zT%mN{*k0louYqpZ7Zk+IS7F{c;L}o~x?|73iGIdANo=yvIm!tmk14-X8|&Yk4%Joq z)Zbe18m`P@gY9;P1-*KE~hQz(J8R9OAEY0)!^mW1t7nvXPjyYggd=OngxEa)v(p zMrl@R1ut1=<1%#KC6`47D)`=@6aN1%w6}bxtE0f)RJn)ThsFJR3!0+*J<8=)YOME6 z+ZxooPCY|sbY0!ofsoY69HR#6I0 z=fG#WBd`LDv9oX3q&Wdp50?LGWfKv8F8j7Kw?8MC071NT4!$s1L;ycPz`wfnKh0UB zkY>b&;cD>RB$D95;nK>Z7@}oNW+zd2$o++2rI<*szx!Lki)2;gPx2utGvssY+NZoK zXu>Y$?lnt~Bu)4&-OZA}$iuLpZaa0A(cPvmV%39}>T6KC^2aWo&?Nhv%)-1Mr#K}?Ho^KoTw~w=J;-1OmHA>I$YWw` ztXPypKG|121xbiDVPfK(JoIGScZJjl-9kW4yx8NG%k!3t$c)1UNs8C|y%;>9$Ik59 zGx}gF?fd5W6u!aA%g-i#0XC+oX?7L`lHHz$i3r%!R^D+lvYtL68BarD;d)-2V&Cnm z#o%MzIN+Pb_@c#&y&}n2A)J=fh3CXQJjgmVPMFWQ9fxAUSh{^pBRx@Ne?mP3Fn_Cz zEHOwT5dxe)xGR0FiN9m^E|>N19u?Uaf8TIvkeWxa8#3@ZF;RJGaGN;N1Rblv&?{4P zXIhrG@2y_6?Kx6;Pi^s^5KmlC4kN6g2}y}Cvi93kd)K)h;I%)p+6(Gb`184hP6q4NbU5z`|Jzt}!w&y$j35o1L7RHk^m&EO|egSajMUcW`A zbox6RKzm4T)S{Lpgvdaw1-Cn77O3rvk&4T5pr<-)J@5|F)j8Mma%*6AFEDQhS83gE zY$Gf4d9SO}b%Qm-i(y4S>Si0C(fn5POSmDd*?N)tl3fDaISaLh!C1-V2`B!%EPSDT zJG^Vy13{7fkyLTwgKvFj_>H{bX%wY9#F)9^p}1pjig;8cItlARU=>CQX3D^#T}}0#hA;Q(%q6VyL5Nk1`m2+r7blNLsh_`0^zoDU|CxNE@*(Fe@E~& z!;j5t!t_Q#OjY3rYX)J^X4e-1OldOnVRwN?D;3pue#@SZ`zR>X+mYlOjd58Py}G}fJyNBM>`Im51UL*1aFWgf&E z#IYAVFm}P}$a&k-;;?lN&eodMB8OsQXF(5}31ZW{x;dlw%N0z)-qoasTzG&GD0i3V zBdXnp)egQ~$E@@IUr&+c0qqt#Ua*l%qJzI!_sE)^RN(i(27P8&2u>qDZMSu)vQnSi zbnz4v!pF+-9dbO)UKsgBd$G7YDE1OEgVz+*^u68FZVu=L7NyOmw=1xWx>Qn4BUJ2-))qm38v ztHpP?OaXd2x;zbtRQAa?a22%yo;Kwg{=RKjPNzMoASPO!U!c;l{mYC|<+hR8rjdz+ zYl(0xZlC)F=*Mcr78sXpPxM^eJS=8yl?CN`;Nz&1D|E>!Bgp z{4Q^q0Wmnj<0x>3d#;?{7Qnw0^ zu4t$l4sNB4Zg;<8kAO10iP4=xB!Az5#m`H*&r_*y!akE7T3pH#>r+;!u_F|@Nq=G2 z0_LIPs+3K#Cvk|%~n)*V*d^m!1GPT5$ zW_MB(=uj_V?drc(_>NyyJbmTzBcxn7(YZ)2%hyQId zh0GGaN)(0}d##l@oz|_D$;_8GdYEu^DgkZ2OHiMPz&^{?K0=29{}aqR+5+QVRj~3@ zx0a<_aXA8$&z=}GN$PYP;8E`Aa*W4%_)0jdOmcX=UcW)|*8a;<28#aq9mfjnJ>1A> zTP>&$Y~&Nc?y9+84T8PYBc%R5b&Ax;Fu0>{M{6g|;0b|F*%?FbQ0H}*S?NEYj{vkN zGtO^}+vmYPhEKg4HIvs8-@O%zNW?heB>t(@IWVp9j%8oxN&j22^F${H+$0vLW{(>KnJ=z0u(hJ-Ngd!e2=9g%%l%xF^l?;r0EEvfi)?6 zLP<{&>)%I3lCp++`7i!KqW1n5MB_Z+V{76-KbmPc(4VEJvTzydnwG#-`{Y~8C|Ij+ ziN)2ilDuG|*(%g`k40H`E#{zEw#6{LdE!1C4`2b<2o6z@<7X z4W0X? zJn{&>VA-Qf4H6ktkXX_tqMPhW z;iu6kt(Hyf4UTuQRb~^u?0NsvHYu;GH2)7h$_=jWOqC@xY zVMBT)hJAP{{LxY6n{<^B#>AkiX%W5EkJ)ul+wbhq-8**w&_Z?zPJ*5|)?vTi9|o*} zo%2%qafz%yUZFdPtQ6VVA~D>F0Q<0s`=iQy7@q?(j(f`xqg{h-&}1Yitbx;f7IK7)(w7*7(7`w3@>3uim-J#F~fKZlL~w_8W`yDhM{QpB9V2S+QRgPD9HFiH_kOR zns%GhvIx~ZtMi+k-7mV-i0C^r^V}G=EfbI80;N9um!^Qjzj|3&Q>0QFm4+zjD zPigubi!8B_=M&yvX@ddDc==8_$b&`viiMF~mzRlKJw(LiPG*uGNhgXc5-zbg4!j$HOIaT0)HJOvSOit(&+~sn@;0;c? z-lE}Rb(ni992Tl z! z8zGeigL@nAOugM=1-Qr$+o&DsMv|^E`icc(qD8~#yL~46D&}tf5Y(3?9k;E8wVx|uPLL*@b1dx-)z`L0%5owS>c*k1BCSs1!fXSmNMZ;-Rlg0 z1|Na9(PIu002aVq3_~7PXX~>-Mfj$_apEEt;)>iDu+YtLj+9R78mhs;eJW ztJqGl=szt=-z2IeR|-TiV~LoO+ah)WNtJ$_qI@!Y7Sc|KpV25`O75XjAPQwZj;5qH zI3VWytvax9$3w1zX@am0m-8rv3X7QRZQueE89$O@L{bPsRv-_LFz_I+V!?vbV?qG( z80-1Fk*oSANH4mcVAs~vZXVe$ld#y%T#)5NjSUgW_>SjKmju>^uvRbpF@mb?It}ub z48trOEY@**4cY_oZDy7ucMds59+Q!L80xIzy?azJoi)e>i+`N8M)G4A!%Y%{cwHPn z+;@(iNB)_tKsiTXkz!sR&BQPp<;ZZ!FTdK+La@DP%94+n3)v-O5KZKxcW5Pm@glfI zAw~cbVuFDm_U38c^Q4Ck{LrF|^1Up6IaKNn))c16kCLst>y+M6MMr$k_u~gFPf1d~ ze#%T*mFarOFb#0YV>VE;uJe2#7czAl_JX1~0m-PP<{#jSkDU1n+)*6+lA(WCJ?$3#+}WC~H&D zIfMM+nDH(IS^B`n$~bl`oxxA9wIC?re&PQ}4%84XnT*Er4x`l@kmUQGfg>0|9^$p+ zeS6Hdehyq4>|S$!)z6`ju&KI((+Nq|YojABo~ajO0Yc2lHEFfzBHhxp*a6?FyYfI) zjk!HNmA5EjfsHEu`n%E6I2FuMv5acDx`{kk0C_i=BYa&6r89&~E>lzFIBu^>s{fhO zq7o;}V=%1NzQhT)$Ym|vf8-jh_ACj==B6#(DHQtnp6i{>l)iUh~jE^}a)Ze-t0K_2|Rk(V#?6WBN>8^CQjR0;NY+;A1R5C?7Bi!^Nj- z0Jj&oG?l?33)LWharbTk2l(x9!2WB)($e<}w4K}!EmKdrWuGbg&fd0|iPXOabqDoc za$k!gH~BR0&t1=>u2%@-gn9;VIuYS0uFvAYzEWbOG#L6-!#Lgh#Ul zbfQ*YC~AEt&>%y6xk*eo9Le+YkL9%VykI%8A!A~$HlpjC(FpjJ|V zby&QX&txc~J3VN@t>z>+AVLIp{7S{m9a&1J7zJap29$Wq!3$YWZh&lY;!sReBGytK z&g{{81duYS%KN1}A7F9_$Uz5}j*V)UO=LInG`|8@?pKLHf*{Sbr>14TVj^ zRCQ?0i61z?Ceh)Re5;A;~2O^8jsEt@oi;(Af(s`tKbS^hPrLJ?81FZ+bprb7BCQtG|^BYfhyLdmVH3 z`6CR`YEyyJ_0ViidH>DdgbJN=RC0Mv_zbxR|1*-~?0XiL)ci%iV!S?Ek>_cgZcv}B z`sGObBa|>N7&8~}Px_;20dvfPJ`!j|cqBRVw+@--Q)BX07E0EHX4)Uki}YNXi_*!lrTkY-nQr>*V$7iG zvmfi$1(FjeH&T;mOXV)1Y!;g zou7fIFuN#5-^W@GQn;bzbN=(8#R9~fRsDEsK8L@Xcf2`-h@3LmV%tn1cD91mGHFZf z-J@nL9L1Wb!c6en2%yV(9#Qpp<;doaoSg^>huu@nLEg+@NsPxR85rphg-Va-5=zK9 z5NSyu7p#$FOjzZmz`pu~efGt%iO9h2I9IHso6~^bFe)j8hhXpo#a177BoHnXY$#A1 zYyc)SOpusObC{|m6L!+xmm zt4K2qi8hm@=jEddf@^jTB%|RM;j|S ztt_nBs}N|8wxqOS5NY12!Ok^Zve&LM82$D!-{$5Q+%h3C1?stI3Bk6$mL_91BK_6R zyZoh6-Y&;|&w?oYjQL0KtY^&-d1sT2MmXfJhI^faGL`^jow8ez9&Hl619%{F8PuAU zdr=XL?rkb%!e)gJNOr|~`rRY^r`|Ns`Fv~UUR9UAi{9XDsgL72vhR^y{nsKr1vL{O zo(xG9eGh)$tk?-GYOUo2VY_T$@dr;pV%_g7Pv|V(R!~FlMA|&|crQ9}e6ZGx0DtIp z5d__lbZnb%B}bB#TGS$GyMK}Scoy#s*6fsNMf7!;Eb5y(y-$C7^YHV2asXT<9wTTx zA=y-tR-S1!^yh9#(9IchLjyN1LrB4cMmJd9?V65<%THa_puGq5{zqEj1s%@k$*v=h z?UBnt`g;^$IMwkO|4zgM;gK`TpvPGXS7&C>L-hVOJL%x%6Aa=#%0r4D4u{qe5W1)V zr}h+IP7oOB*Lb{=i?84Wkga`G%BBuIciUf$@=ErJyXK?gp9*7q&`qLYsN_ddMsPTS z$JfuW#70g#idV1NR?0}wz^%dgnw~av%DZTh=+usL%+c0jcL6p)0muTaR6SLnBiPFg z9%nwyw+)2Jb&Z}?^??~~m7dLPVgV-GSgT}HQ{RS{o#`S!3r(<^@M&AtgS#dzaW0h& zN$(sh_Ml?MHY4|wj&-Xwbw^fD;579L4i|!tknexrReb!!w5uW+o{%2xCd?KLiy3uh zXp>C19+Q_z-;+Hl;RlpBWoYo#;hvh;zHsiu6H{uHgsZ#SXDI*~(9I7ItmGvA_3u~I z7Z~^`wkRMy+!}rRWjfPF%nCkBDZk}h<2F4;>$B{Ax@)ch^A~zSUS1|{p15tn+p&UL zE*FzTNtEdA0WKH~QElZ!4uPsVCV2DMKm9y->7^Qx949-tfwFBqXN1j_aQpTh1rzff(1SNm^&KNz1 zyDgLV<{alKEXzdplk;sSZ%4V|4n?$6Mx%AF8&S1|W11$>ia_G{Cq{X_Tsgjw2!@Bw zv)zmEZpW+~+hZ8E9e||^n%pC?`a~X03?-YJe6}FD2#2zSko`OENw5+FtbixUMtjSK z119(-O8C6ng-&V~_0Ip7%XI}XftmO?V<|j;#=KUgxH-6H{X!72KQbdeSn$e#5Ls)M zZ^YPXT&KEZ-(6`Hv7bjzcBs9+cYNtky@EiO+i4MH{Zh7~qNGHW`-Z7(J#1F+Aj9eJ zT3t+4LIU>E_~Ds4s*XpI7$iH^VHcmrv;#_PVUIiTrmTi@H=tn^GjQJ#{fO^4y}?hy zxM+<9nuOxduY3XFzzsnfrEhM@KzvUjsogSXmFl+kFdy-l)_??ng!Jhl{}+||0uAxzladD?#0X+U*Lkb+JrVOq*SE`3VDalAxwDw36(pQEr+dAnpg(d zT0H{=zPte%x}|x8CJ(Qs@+tI}(6pIWd*a%#iH+p#*lNT)-FeC1*TLWSvh_-#zr(S#58Gizl$2`0J8*k zsXz%Q5a6(=fFi~i6E6)aKR|*JFkxP>WKNsYOB`)1zuCb{7gg{_o)bN(oseh_4Jkqe z7K@@2>6TaPCIe{>R=wef1r|1rPa~=tFxk_>?18QLSOq_PdflZ0CpSR^M3ypF`wnpX z{lvZZUrJeQ!59YaYI;h`9Uj`l0&8uzeBB`D(fE>jSzPu!K;{R=9W4RgR<&Rxuf`xt z=GFZzGeeB$2f2tZ6o22;!h)(+cI>?#f)=f|2rOd|#_NLNQBhR(y}#($N7&5GrY-ON zoG&&WleZ=n@&Gfb0^L^H2v=uO)3q}PMQEV(Ws7X3ml*)$_hj5KJXmdE!93Zb=tuE| z$8oS)C5tm;t3U;j`1u~*rS(=w>~fPmV=yB}zuMT?{5R!ZvxHt$j*q5Nn^eBUu@6v> z6JX%!F}}bO$HWW42!TCwT4*I?07s!Qy{e3;N$hai#)#|BpwX>54RxmSJv!@>5N^U~ z6R}PZ=JhF38zYR=jNVRDsYgEKO22Tn@nv6#*llvp$~tQ0ZFobqzXk2s4jwm&V%IC- zS;XsX&d>{OKR=3 zFAV3{(_Wd9ps7`3*H#4$7}?2m%5IWCUh;z_c;fzE;?5`PfZBiI>=3mmVOY^4iKxAfml zvWD6yNmLU}1Uw54Ks)(8Kpk{)@taqHv^l>T`}6FA%fir>h`PqK4eEbohe38{KpaZf zTmJgGea|lJBy@T$3KLAt1rwftq&@) zD6o_FV@rOxA&Wy~@E8Z|jpYj1R(6I;dG$=oFoo~_YKL~RWhep8LV!>93#fX>zo*ZaLn;_j#rCKBkfHf%si zr$I~nn6DO4C@Xn}i$fI1z6e`|CjNI5U;b!RMMni9*kS?KcHqwfX6@YIy$1KjV|17I4KQ(>uZHQ4Y4`6yA_&?vM z1iw5G=T8^a^>nR`bVS(1>)aXwNo{BT=P)&T->!e!jaS2Mlw1@M{)+olF8?6?qb$H& zQ`tkVZKazTR#iGpY6_WxPhqud_BgSobKj<%WYCFekIKK<WFghvKdMIpz=PXUx4F027E zs&rq0>*vj>g>n3wI8}-7#wb4rmV1502(eN3mUFc#gmWV?@i%S^eFB=h@z`!kUljU$ z+GX<~22}Z4DgN9meNKA(X&4w3{29LAZ=7Vh27|RCi06V8bnn5l4>a3bSMKWlZS+2h zLIV~u#ow?sUZjLMM_ffh(5$8A)vS8pX_JUl2>xd2?v=wq)l7pw1}P_A?2@e0VHb;0 zVF~PDIcpNf2c~#K@PRxjh5gojZ`}o_Mwch!M#`LLq&isIgzY7q29(|%ZDGI>^8aW1 zCow?Z`KrqTk1S(!#>4St-@U0Fit@tB{kDZN*9&gVNG>~ z$DHAW^*j+i?Sl8*t1|H(2nx^EEeH@~>v5&_YN3kv!kK;h3Tq(-)MndyNf z4`TB#CIcfQ^THeaoWmi7DKPjbi)d&l2U0 zLpM#<9Y=(b9%y!as}=O}+E|Vk5vhcFcM>7&S8S|g(ZHKwvG@a@Qgu{OL%vkfm$1c@ z8MiCjgIgz0!a$>cwhlcmsFAxDQHon3`W%DFO-?jq3C6fE3#^uS;8xyC^d5PS(I6XEVp!PZ~{+(mR*sxOOf^&93Z_JhVl*I!Z z)thO)6^f<4*jcGARjdLHh4X9%#*^*VCoGYW zz&0gLVX#0FPfosaZI1Im%m+@NVs^2No=4DXxUAlAE>X+XNnQT*@q4<*+!_;cc2(Z_ zj+T~>al`R7T)(qN&F*AIMtbAwAAJI{59D~}YLj;EpTj_L-nyE0@ibZY87I7U%TWoR zZ{~WnWI&aa%3L!UCt!{8!W24dD8EoBpf9HsQp})m6Jbglj984|)`;}lc`MNZRe-lF z!ax$9o|aHL*!jko`L9FoH5frROOAq+wzU9rd#68{&n~K%wacgww&gYcT)jVdL4ek% zZyx_Zw=`K%wQH}fodFKBst$l(c8c_N+|!rGWd8%$)PbC~(b22uTXUKmD9Jwe4GZXS z1_K^w(G$9?tje^GVH%Dlr4;H=H<-o2_NfGV7%aO;bVs?cIj&3iU-~Vg>mI%{3zG_) z4=#%AB~aZ+x%edLn!IUEF+!1mc++CKN^?~D4mt^0-My6@XJjndGbvuJ-BjH#zK{v9 zgUc4zWKi2JcM>9P;VJM)i<#ol<9Nbqk8?A$-lazkSqghapSv~pl`H4z{x%tDl9U@! zPC61V(73Pu-57dKD81nPvxT_*?05%r(@Lu0GO}nR+7`lrsi7mjBnY%DGHTth*U-2e z)6@U0ITjla>Rf`kVH0yUHx|(g9M2l6`8~31mG6pT{hK`zlClyFS-#dFTo)M!0K!zB zhlYKsIG*92HSC!5F>C?*0D_dHu|Y0?AZAPk8N`@;j%4oaY`@8l;Sd zS5T?7Xe;xI=>PqdQF0IJA{*Ntrd>R^>M1;c23F3v@LPP5A(2xJlweJgv>0<5^=pTE zmi%!Df?#IR7y{d?So4<1|DPcq0%`~akOpxTx;(LJGeG5`HXV3sAXQ-q>M9}=^$TeR zL__L1wGRHg^kjc1y@B(jag&yoBPSs;;sYPAkgXc*w^GbssD_9JK$iIV28TN2@YefQ z6Ta$&65P=m`RnL)bT}!01f?e|J0ZfNG=qh!WLTgd2GpygnNj^TT)!##hTjv+jq!wq z>Q(gA8gkbW{ub7goBY=3#e8i#!fk2Qp(Elz5;-SG&)f+eW-=8C;CAMWOmM9Es-q^~ zLv!!>FAKM*%A2;r2>L-Vi36h$aJZzIoI+Gywt(orX?`!DLwG|&c|CAMcS^FnOxy#@ zn584GndwnhVO5p#GRgL7)e=M6)NaH#zHMzEVI9ZPEzGC=WT^E7StWOTF4g`^6=6GH z`nU}a7sYMV=I7F+H_64URPexr3!iZMYv&W!)0f@C4TK{IQJ2T~faRKbv!Oe5w58QY33mfIQP5I}iH0=Hqwcy@h;0YVkH2qrf#X={WuLX1;TE2WWH zLA`-s8OS#?xoT}mq!j3UPjE*K)i{u?R3b$`zjVLwJGIFE1tz!g^4e~o%s(+~!x{GW z$RF3VyD%-LN|uaQqj+Q&!nNOj;1vT0lHM!7=e241c{KvBv)f9-5f@Apesy|vj^GB? z?;|basoZ`Bv^%1kTP#*{FNm6@D$fQ7Sb*Cs-7GJnzan)5vN&>bpp5AiA9MZic#8^D ztm-HJN6ID5ofT z(F)9oG;t7rDcq|$$K5*ZGGjV zoGw{%mB=u?TmwLo+d=g1-m|@qoR=6UjEGMy@LECpS$)Nv4HUqygz4p#A1O_d^#pdI zXI>7u`1IY+*eFQX0-FtV-45GdGRS3|gSxD6`_2lMe!v6Asj&dO@sswi23-)xtlbCh$BzL493LT z>n1<=;#>^fy6o*3LAlhP2tMK{Qlq(;(X#ft{k>k><_o0yW)uXFXI;Dbv^R_}Zj3X) zKXYiplWlOOCVE(lH>7yw5*z0WRhjed&Fv2~Il`gKIDLJ`1Ld5nI&FGGW~Nb(zwnxF z{CH1i_`oJ8TJ?cLok|M?cuUQ@T8P@I4>y#rMjx?xHHWDkph=N~y0lHIi00p?Jq;TK zqbUY+C>7%OO$@Q7ZYoCjopun;VDB7hzgF7RRs#T@Yqu5v+fz&EG-8*{nX=-87U>*D zn6Zk&Z?aSWYWMA9_o~v8pgL(aYqCSwBUAe10sRyaY$LcU&{WD_ zmr)yP;^XHJ8)s$dGC5&d4VlfON2d)`@U_N;ST8=cXmXDo;6i4QzfA?6=BLMaL{7{iLKya1UQZvv?1z~(PiVjWQcijQ_oRJi!+;s)>-<_N2AW6!E&Ws3@gO^M{*xU^LM zIl2ye?78L_I@l-KZ0djtUS%|HJHcmy{7@r3qqKS0nG6fA=n`kg)8!MUjJf-{Q}0{R zqM_ccMIMbi8f}dTv~e;XFLH6gWn0RMZ5!I1qnrD_tNW34R4S0uM9ct@C>e^NMHOMz zc*JeyJ?l{#9KqBD+taM!AdnL&Q-x^TK#XTgbHtrBgp&^otp%pL;o`*YP~KRG7NfDR z<^)BVT)hjdbOWenHw6twaO$z8eWE?%!C%B0(*CqX_C*bWZ7iZ=Ih7ftk7|u-6)|eN zKsS)4unBlopX`+9f(V|*`znzXV!V{JGFDNbf258xE^CUl@K7Ry@VDt;TY_77*$XqQ zem^eu9&TpjMhkj~g$p`?2-RrHch_Nf5#txJcE4?VtGXd{K?nJdqdKFw>i!kPt;Zq1(Mza z^y!ux1?->TL4ax)&h{woA4hy4xKPYCq-Hw&13RNn3h;pw*6wY}#x)D}$r4#vn1Oxb zD}}Zv7*tNfak3x}#FcEAACy}P_}7vtM?`T!X*sm^yeE1*4^+bC^K4ZXjlSabrGWdN zeFu-IoU>Nn=Aq~R4lKFb>@p}&iNeIw5WMcRw}>!StfNMdVv;`L6EE?4Ejl7wl^_cy zP3u3h;skAV(x!?26_8Z%g2RMdX=`Ko4`@n>s)|=(X8EgWx1K9SkIf(r$vNl zUmE$qWyQ5UXvefNItYaI_nSLdKftgZzO}j6wft|%Y3NHtj58IYTqzNz1~pa-+LNv0 zk$ist0mZ}tO}s&X{`qPQ?BW9KFgx!sdNg(t2!LZl&DN)*b?bEw1`(J6m@3o(mG z*W*U}tC2ABSptrUl2j&KTs?Z^Jud*cE8T+XT9U%I8hs;KaIQ;slv1O@;J9pdsZc5(rU$UO2*L0p$LL--WhW z;S>h;5*1gC=7voz!Ov>*U+6PYUO=rT$VCC z>ASLErj%NF#4`pCNw8^hUo6viPi|Z8;MSoP zRf{$egvGUhgOsZ|9ARqsl)TSadClqW^3&Bpy?V>ymDPeduX^}AYFi<~{NwRz)nk(}@?~iRk_k*K{GPh(BpA|cg8vb{$}U~sJM*V6YeNRfa;q_^8c(eb z>D$9nwAN@kb|`=j!^jU4DF=)dU-pbg=a4J7lP!a}ysK2PJ&B`Syo}`)8Fh~^PFRzn z?Ob#m{vKNJ?WN&@o=aq5TLQgYrsxD86l}rYu1~Ttc-X()r}7Q-c^_L`$m()d8E4XQ zb2exnz!ph-r<=1@L6Zn6FPmG<4z*IcS6)XI^xdyg*(18j1k%7942GQQ(kgyb4~swz z2i}XKFk1hLYCx|f&;&ra&nKw$ejyK1|7$G;)5^baY!&<*BCe1s$W7SK zJrOyYJ3Y|p&=3GMj0H{1eDW{WY~36t7`!oxeUs1c@7VLwZ2yIw1gOx)tiv9ZA+h?e zrKn`jqT4K#XVBL=g z&+}1WU4dA7w(o4EhX(KGefm<6x`1!Ktx&hi9wF4Sg$q7{M%jV5^w0FnyRDY#kSS(! za;{-L{f-h`WbAWVBR686<1Kb14qp17M)l#tj(;%-Ck%LZKxglIQWX}kp)=E! z%zD4FuUvXgK{4z#NtAY8^A*SLSk%6s!CZg1Z^|lVPOK0~cn_Ca?$0rf5DK4mXLxnx zT&Ahzl$=l8*0MJYy9vPLz#2fqsiW`qbWw`Tsbp*?rIKEK;Ah;$&MCfYp%KWX(A#hI z8v*eI4#wSI%3^Pjl`_Yn`8tkX<6N5l66U_kDr%y#8U@6au-%_a8>f+UM)fs<&}A69&s)3&|K;%xgcVp&Bq2fp{s>cP1?lXY6#;2%yDt!lHeTDl{-Jy5wscL0VuG-R>e=o6HSCKRZ{<>h_@c;K6So-nDh^>)$<> zz=0ko*k&s;_pNoF(5haEAoDLcpKB$FRV7YzAZcCHBgow47z$~`Q=Bd-J8y8Lww$;w zrYijpSJk4z`)xN*D3;q|=oRGX`}W9){1RbT`V9n?MLJUa zc*y43os_{54nD1i{eX82x{wBg4jgBiiKb9i%`eVq$;?aYo4sX4d%kW!eKGrIw~O9V zYTqT|#A=vAax0^0-S_+4z4o`w5Q2Mv@Qxl(kYS6zvFSy1%2a#N=61~xPZb7W|LxW{ z;}!E37o#YI*d?oxH=$>6obX8ub_lEXk7AJrl-1hR7dTQ+*;3TyAa#c&>PbXCc*kNL zJLjQSaPLSoLzm%Yca37hqy_@v@g{_+@QL5!%Cl-%S8W9&qoE$t?01t@Dv`mk`XXA7 z*J$`+C?+fI67$yfAg=slV3V%Zf@1PP&`7MDM^P%Ohf?U-r*&y>L53E*W;{pX5O($h zcj_Z>Y0?PTr&S#tt{5wcKyKwPz2^n1abw8|IoG+@38hq@Sg z(j=uxSn4zYb!59UzQNnB=Q84_7fS9e6-R+3(0}7nV)yO38UPVl(#8%9d3$of!jMKA zwz<8Jji46KZ~lJWujd33ySMQx*6IHGoXZrDk&BMNhVrdlb(z_N0Dcy|SO%Xl6*bq8 zrcH0X&3Pmv5zBPP27d&zQCdgUCGtg?HPh=FM5s%9Z~#somZ8n;HLx_+M6DMR&rO~m zN=Qbz7qF*Fc9B5n;$F=&5_wc@;CmWFAQPkRZ#j|!yW7Ad@QdQQPZ(xSB!S;lmDb?o z$3au7xV&c+fI#jP+Gb0M>F#NF(&8UDb+;}T`64QLjnIi+S@79F#Z2qLQ8PL^APFW< zTCn}AZMqq{ycgSYb)le<-ymlqc!}OKQT}DpXsM`*4hSFj8#T*^v3*eSv@z*LejE*I!{khw9JIY)g(_ zzU{mel;a0MB*b4sA#Zh?SSNQ}U@)p*JldoEOzRJndq|+w2*l2nn04)z{y5&EIL(fk zudh~PJKgUF@C5yEOt2i#&RACec_@uJ0}(G`jE0otK{XcV*Qol{?-{A9Pzoh5m^G=y$O>% zrKdd2yUACC0<`C}fgqiJ0%RzzB%lWh_|Xp(=)Ym~myt-_1>Sj}fIVJ~5B_ic*@rS) zivWe~xOA4+jgs}$*-s>Xu`mvk-t(z-rS(F!uFqlrWCRT>dbY^EQiK!W7!q{WKmL?K4)W+MG>J)srBqny##80@sU{V+hAuZ7^vm&S5Z5+u_s=6Pn}J zB_aP6QH9{{zk#(gdDs6gqgrY0w(t!ZH@1^Cn3yG53B*0`pqrfB4^AnLSgPtoPY;NJ zU?rba#hRRSrod49wL_bJh=LKu$fzX>zt17JQUsi?x~n#1qKRS7R^+W}9L z5gqX_L?r_e00&(T#&+Heb>7v?WWg@iJlcOXHIJYz;i6DCutw7hL`3)puQ5`rFe|J}r3A3in(5CJL`89xRj+OeX}$$ilvR-MX6Kqe%8LFIRP$`FPC>ZQFm~Se?Nh0=2U47d zV96hJK-3Sa;}C$O+UBdb4=q2JBNtuzHw0)kof+!B=Z@G~QsgOfr{to*p@615<<-w4 z@XbBsI^}s`xNj_Npf9g<`2T`WeQW&r9PXu>;;i_}uWp=Tp)SQi(r_r4YVATMotyUw zJ>;C%hm;UMHjQ3Q8%y-ARJJU;Ta2_!_1wNkWh4*`=v`;d4a^0I`#2#N|B-H$Wp#?{iOpSN{2UTlrxr1 zhW-&1M6Cr7E4>PTCVLTo6Gs+K@bm33a`t)42#OBt%;;|T`Yyns>X09OJaQ_mVpi0& z|FH_2&F&51!*I>o<8nNXMc+}y#Y_u8BG@k*D7^sLu?eeAXv*mzUUIuP!rh^!X25M) z?oM0~R$kT1>-vy--23ZuR5OqHkTl>`J#X~K{C7D12e$-+Ql-2#?DFVz=TOl~G4xeQ9&2Ibi; zA)5cOO}4<0r3HXO_-1K<`$7K3Lx-lI1Cqd-JHoEYoV5Sgakt} zk$j%n37SW8CAE&dnYZsC2MzpdlQVIx8o<9y0N?ogp4qu=$m#rSdR z*Q9-RIX64li%r=%V?+31;K>c{gyKo`>p2Kp^jdfXnv75l{ypa$%z_wcR@U zh0#>XhXg`ZVE{Wo#J>V<9743juAC!KJ7NU$k_}4v3U4O1`2_ zLb`&v4ZhUz!^ux+2Bcx8Pg}nSwTHf+-r@d+ApH4|*+S%%shuWN&jD4)sD7BX;M=Qx zgTG^Xe`x=n`rGkO()iNV8e|Ky@SKK4n}U%X2lrEW9{r>8HVa@-%U;_v6itzf_GL)C4k#uk=h(a^XQ ze4C5ldldjlROk(3ak)!)7h&m7^IjN=*BonAGj2O#lI5ag-6OW8p;htwE?z70>dZ^A*0H(ddK*x?K88Sh`Yo<0VfZ1u8`LrP&Q(@@98Eq6 zUD)+8F2Ce0nQFrZRX4#H2<-$rV;i)6yjfE(E^BTjh+*-;KBh8|n?Ql!21O^bkLvM3 z=IG@tYE-tPnQseH#WN9~AJb6*0H#&fjb1KMjL8`wS<#npka-Y%Dg#2l*W(e1LHfWy znFKIDD=@MV&44GC#eh0cs2Y{Q!a$lE#?15&X|| zb16w$I0$&z!~|<-0nV1Yt13-G8WLQoAI?MVKMY)f$Ycl$l(Gy35dCY$CRXu`|CGO640evLbo2 zI4w2hW^|45vvals43+GQ>8rY;m&|EUQyorc7)41j9dn{8E1oM&^NEa>ED}EqTsb>T7 za@ZCJ(hA_D`z+vQSMY|stiW98Z!N(Q(1mch&=C>q8MNZl=!qkWMgUP+Ko+2pLWH0z z^3(h}3&{2y4e5QzB>JW(zT|GiqRAx}$8NNuz-k9^mA;SUutREiDfAjJLfXqHxX={3 z6tEtXXG}5!oI!RxC^X+dhVVm2FX zasA5iYnEY$eWav80R;>%4)7Fqfn2MIOwBJ@yz@+}kK|_*DtF<_69yu9=Hi1Gz^ZBc zBG%bC&!t;o^WyuF8)F5Ni}s7mME~D_$|}Tq(#r#@c_v%xN=<H3(Y;2)iV0!NjxkC2 z2-JYQgogfp%H2oW;b2oi7fLCa`)~ayF%WVT=&;(2wSt&v$cWIQ#WN|!`Bjxgs%I!j zxHmulN;n*pRnukz>p@hHU7a4q*qEV^h(x@SpXi-sHgpd92Kgs315+VF9`|Xp?RqJldrWdP2|F(Y*}lCB(714=s56NIlH=Cj?1!CQUVILYi|C zIE)&tFa*9X+c;ea#RG&hkgO383=T=fxQWV{(&sRUPD#Kk0@NS<0LsnBv#qmQ4+9ju z>3B=ikbWV`Q_nm6au#fIvh7rH?uqH*n1-hWe#&Wv@8J($PkDw@y;t3zfrC2gJ7meJ z&$a;~V24A{(?$prIKuT5OA~iakdG?$(VZvV}R+Ov9t#@+*z>f?eG`R~@s^HI?#^nAyy38|qPKl4};v&e2 zM4VbhD!^acPj4~t_5szKlQ`K)BD_h7t<@NNifuQ;NC+~hK#G{M3X-X>%O&{EBmC#y9 z&W<;XTJNln_w5Jn3SgL_or8&Y^YQ#biptZb*`@J(s%Oa;Y7=I12i^O7?nNC|bAKL~rrS4yD1y}GGCH~TovT;@+?wZ#l%vnj$J z;;ta5Pe#fcZ*3?^*3-4z9wWF9snGIkFPcT&J8!GAwrt@G0(8djX|M5;!(W+w(ah;(_M!0O)*@^l zv9Q5g1oBUZ&J!PDEfGy7{stO zbv%H1(AwHGDTtHh5mvZ*J$scxKW>K+rQE_7stR0BA9{=11nMbcnrRVql6mHTe#ifI zMmcWnhZ5|tzIu2qIsS}&S@;sBZ0Q@wAr2<1_g-Uk=u&2XQmt8iftW1-Er}n^6FGnvJaZiPw4oJ*^v&d`55_LDMm$>Os~k*B^h}~k~Bwl zJiZ1~yWxEWeP{O#xfgcFL3Z|o`+Z4y$-SWC1Z8Of9@7bC)2+DNZ#vxLQZ(P<)*x4W zh+soR{#ZC9VN5g^vTB3S@i$zJ(og2b9YUuY26{;4$Flg4#63Z#c5=Dx=X$}v6AMk~ zX#czToV)jKHi;s-3q>{CrW=AJc$rKSqU@j^|9uriZ=dwyHTv;ss?dV4!&Nw&jeEg# z;0r;RaT@f%vLCP0Pc1v_)(5uS=NSZLa~H(9H5;{aBz2kE;MKn5r1>L-y{fJk5kLid zctsc;lsq40x2GE<6OY5^G(@&@z$K}xwOfLYhJ1a4gGdu8MS7m&>mttOPZ?Nag<5ZU zb!wIWM-mtc(N%)W>ddC%H|OzDI{wd*?@!`^G3D?60Qw-nzOy9URMd0L5KjAlK11Mk z$iN6gq@tVZl_IX}lJ1w_jkIqtLI&`fznBOXZ~jMu<)!M zdt8K`0d$^^8J}{AMOrI2X?miJc^x+QkgGC%Ak&&4gOF?hmr3NHVX={%)x7t(mV4u| zZkTpo1j^$I2T78nV-oCPi&p^$f042M%(m~^S>^|fUa!0^XBuvk$n2{ATd|A_ddVP@ z{0J_56cx*5Oq%)6DQYsmEqOvotlLc%bXyrJWOIvU04SY=qstyO>!yJA-Wu;8o8W|~8D ze>roJpCzjbJ}%lM8Shk6i23Mn!)S%Tm=g93dDy;T4Ozp+C3ixyu7^>OcJG~h7Ru$9dnLPAuk%;LtE zUtm97tK&9;_8?f?>!so3`Q0ushIk(6<9`D*1B3;S-#xz6gh9dVBE*BsTKIwb|{ zIWEQVm=C(Oih^;fXcK4JP$jt%0x?w)4%%a>p1ILUK9m}7V%p4`qv={1HkJD5{fIdl zE&29#3dhag-KWk?W#oLfYj*~>?hQxPg@R>WoGg>bRlbDp)tEZ|scY*OM+FQO-^GAt zUo4nQ9`nITgV2%nUcRd?UVi=N2{=kZN+0e=XM#3AwOr~V6SzjinTls34_H_C=ar{2BVU|>|^M-(#~gICqX6Fft-NE0TcGqeY=MK7l# zth?@^aBK?sh*13SaDU4|rBnAzgn%7xx_a`EvzD;l3}dN0(0V6BDA!v8cgYP#S8;dU z)KQJij@o1iv7+~Rd?iUShs%PpC&F%zAi@jJ^!Y3r8(KU4eQ(h&RgYd+EIVh`vyN)y zrgXw<6_iR!n0>vLozd8!`*QS92Joxjj9*-!>KIEXDpzO7N<1vmfMeba)g|I*fBXC# zdcZ7+nv2Ex^+~T0x#ZCZ1_PNzX!Do1^Qu2k8rW?Q1@FRhR^n4j4{Ye!DWkZF)`P4^ zp2~Av9~R(2D?{)zi@v22gLL(*VzVP_Wnt~0^;b8;)rznF$4As=ttX4dZ~sVe1sm1` zvmq~3`IHJOH3?UeS<_C8_LkcG`_O&~$K`8B*<1r$Sc1x5nl^Zw=`qWRFE?76^`h;X zitrQG<3Bunk>NIwv4YwAe0nCZAZD8lK71lKG%!(LFGXm!@)e0{SMwo17~q-o3rL5? zN}W!u8YY7vusf60AO+8unPy8GXZ%h{B%#BZm3))=U#shPn7!I$AS?MNhkF~mJp3(y zL9|qadqw+$fW#`tkK4$vRX{zsC#rE9HEY+Pin=SkAAyF<0m^a5Bpi7M-6)H;ZC(iy zCK1+IMpH_2zrl?gwa@V}G1rqQqH$ZKQvy&V3jOYk8O9N`JGulfz+jg-G&cS7&`X?2 z$ocr`)VbvQ%AV4*W;ET1!o?ZxmvM7Rmol>gAhI+&#cyVjjsQbm$8mqI9C*_3_ zA%Q|Ag#P;_xs5&RdYR6l=V*=>B+>{3NkV|Ljkw}2o3(K6fTM>7lJ7*UO^$@UM?(k8NWf(1vQZ|RX+?+Icas86$`dPb}e+;`4yX_^a z3_+gnrVZ-+%TE|a2)bCkV=C}tKR=`Ktn}*u(-0T)&*{HSh^0ZylX~(;x`2|h9F40* zh@0KW>s8$R8?b59N5nV2`)G`Y83`V`O~k10Ozjy3{^Y^zlZzw=<}jfq;TI&psb~=( z{@HDVL#TvRY_GF$30`nFT{g5momzVNpdZr3t>o1X5?~uS)G`1*a?zqyZ;;9SLeixZ z-s3zRg<^x_ouZ7-r(^vu%jvny+Oc5!3#_91-YW6_B~>XhNXyZ7*AoAVp>;oE?i17d zCKE=uDb zu&)S|lIQKmgWV!C_9A5g{clTkQ~G$B}_qb_(P#7iB!P=?c|mp?A&t@J_zwzLR^>^YT}oT^^S&IY@T=< z;=v%H=rQd67ph%FhKW}_0#K?W7OeM)z_@9y08n|?}GE!OpCy$$^yLL^+?H`+DVy#CmC_P#{O$y5|8q5I@0gW?e7t>+;2zq9h;N zRZE7J8niD8pXHHc;=IAejph4-UXb^iyb3&i)-{cUKhqc{q~}`mo${Jo_QF9x@C*3( zcDl_7@zf&5Y;l6!W$B;8$yStI=R!1*Os5G0dB@~^0tkQLqL5Ebw4Lfc7e$TMT@9O# z%Z}7}$TP-vJ;nlF_NjbmBJ7znWn*ubJgJ0{YWqnzz9c{&EztnLSl+U3rpa`~c=X#dD22NDunc+z^N7b)Bm%Ammq_yTpKRHtFRHt!7=zLV9y?o=nDm)n7>6; zNI8_A3&vn{)Yve-6;QZh{bVEh%(8kWzeLc%dX{&x3`#EKFljRG-!Hz^H^jEIe^1d# ze3La}_W(DCHV(a`9iFNXeE|&5k56F9FKJ{&fRnL81}qsngH_Napf|ClkHkMe4-h^o z0EGz$F}liynvEGGK8FelqU{;DNy+?7sRK)i&Ht(CZ8zg&u{$?S=Hr@;$w*}GZQoXz zGmkSReXmoR%)l5J(jeK>$DtYqq(!3;w9>(Bw?GjrZ?Fu;3Xg|91*{{DvolW=)u7(C zy~;q-^ixwRMGkpp=8fQPNhdBLaZ0)?x++z_$eR7vj?ie&k03y$i8@+F_kTxmlK>c6ns8pY0GGH$A=)n zpGvNn$S56ntirRRId&gjbRn7m#u(uv5Lnhlu-PlNS5gzKl}>+U$?yo97s1fXthMti zLV`7>1b?gmbWY+)a(An0MT@4nJkl2RT5QP81RBHm0?Dx{&QMj(Z$EFM7LeL)-*O2CLT%@zJBaX{``RmG zNV5;Z+-CP+;#I_KM*W~7i>#l+48rgt<8cGqVy^&)r^eSfW_`iQ z=4zEJMVL~~ZYGf?iURqdG%?g!4FKqVznew?$gbh6$M|BkC}UO~+Jl_2uB}cSmrbZ2 ztHVs}bZD5r6guc5!AopWOz~lFA(OsKua7UuO7V};YHgy|n;nfnFU?a|!2o|UauUw! z?8dSCRMB=9#K03)Q-p6sA1Gc<4xyDRpSdAP(oFTp%&t}wPt9qn!Mcej|hldp- zl<^o-W8I7JVUtPhHC6>b=S-x8^M3Qm{y+X2{*TI9-rU*~LCN@Q$-52VZ46mUYhd-> zrFm&8vj*c$oe4YE2q%aM1M%Z_6_M`mt-<5KkR&@NtVdH?j?od7f}B3B|Q z{d4YJkG+u?MD`#kr>Ljyc8vUnfEf;OS5;3~if=iHZs%F;6k)2+6o={#?wcYcJI$Qt zljxKv%LGU5b3d?et6L`A%FE2!*Q{I_oir2Vr8UPcrY4(YM0qV9w|yDS^i(2=ZRz%EvqC?5#a z<0Q8|CvVFbq&UzhGTjZ6ldLzJ0zr7aFtz0j1la3pwrOd^g<=9gTlIi|VWc1@c7Wh3 zsxePj{qbyD@Qz)sz6UGx6JuI6#kQ17Udu=C1li`P7a5RpKqy%#?894)r6CXqe&Yl_ z5p%EJC7b5fT5QOwb8g%ChNam9aY=d8Q7TFgRuaE7{~X|Cp`m5YhX$@K@R1rOhH0Qx zQ%>x{m#G*>bA`E?OCD*?a}MFVUl2kNuOP4Bu1(NAUqvUWjof&6R7O*&#m-DtuBLR^ zY(bSkeetN%4*t=?d-R;6HH|o_ExU(MCv65glA$$L!4qc!`ecdoaM9LLleU?J+QR;E zfwTt}DK263X~ZQUoq(ddw{pofsyV_Z?}L*){WX5G!mh#5?OgZPcT#@fMdNoLos(mQTYkYo`Iyw~|x#A&2EYaf!9P~T1mI0N>Oye*r zsB$L+i96X@oX*DUzBX`ji*^>6cY~B(>uF}G9V*!KIV@z8FygGMyY~^=p~W-l-vhlA zwq5eZE_C^4tnjAcW3GA%YjLE9eum4cWVWJ}eND^`D(ji1eC?DGUZ9lulQ`2$3uhr= zQ$7VdK>c9kpS94z8Q#@a7|3gT)-uw*_T(IUCJ6|smf1>}`PX>@2lblOlmahCVQ>DhEcf$&+pukp60>io!9We6_ugbvHEj_Z_bl0=99#FO}c zx9pm-1ol7d3u7#IR+&LZG`qs|7&@uZWS>#Q5ZZtuKsP00&BDr!yhnEm<8fOm8OgPA zoVhD#24|>UR8Ij?eplZRjLa5hJu`m~AMEXy^0D5JBES9(5 z>D!W0xEVLwf`#(s_f-4(iH2D`y|5(Aod7`RCQw=F+H7UpYu9BSWXC@Fime9R16Mov zZBn9l;BOV*UYK)~HMbE?`;w0e90FU%HwtCaVqf&2tsdDS!4$gbn_}6$BR2IJNnEUqJ zP%ltzmZ2ktlm7X#EowR=x>zUfH&)CXJVW%)mJt%GJvy&sU8ebnm6Ws{0q1iw;FIa; z$h5RW8<@BDawk5uyMER6#e*wJb@kB*x7!#_=;FoO2Ld@E>upn z7G=%FVePz#Oj*{un6-;oX1RLKp@l#=$!`SRm&y$KwziB^6G;?(Z3H?SzIu&r#oJWx z1v)h1VBM42ysfV(5GCy@k6S=6Q@`MNL>Ovq>7vuUns4*ompaDe9#Em3-I(-T_*uC( z9B_rtV73X6_2(U0f`RBp$z-Fa2n{P6(z=nPeEwy9HfPN**Ac$7z#oBqrzGozuD;r# zQ0BcHbC8RRS_dvW!xN!PA1YWrr*_8Ua#^B3m+DI!bz+Ev z+Z*+IChn{lW=))wWU}KB77jp3zeJ2^8htaJI1J21XPKHC4v?o^V3w>MYoN%|kvmHJ z$gtSmd*)WvEmZC@xfSm#wF2Q3ym@j|21YE4I(P~D?>tf_ekKgvQ&E z8k230b{#7mQ^ZeQIS>1xiMvd0v8mDzhg%8q#mUjrX2ok;dn-m*&H*6y`JM>K)P3qcckH)d5U>D;TNqWG_FkH8bg-H zIvN&mG;W#$nnJHcC8J?j*-|{itW=}P}C z4Wo2d=Si5-sE@GDS2Y#2dYGu8f4c`cXL<9tZ9ZLG<6IBu`+-5np)x%h02_71wpXZ! zkkI2ZWPFkT&mJpw`6U7xkGy)ndLBp|N`XJ#oqAiyoL2Zuw=u5KvPw>Pg|Pp>3YmyF zDqSSMW6z1!Vtk=QfNZ3=Oq3g3TB{zzvsm3zSkurZ@}}#!@0X8c&o3?o;LT>X8(zwk zuPR*TyM;lekc9D(e}A{(gB-8_`1)RB=6#s$ggl6kzY0H^4dbN(%tHYU;t6(So|rFE zf@8@2LwT)5;=68b#%SY*4PtqlQV9cAYUlL~Kty#bt17;RFIU%%i^dQly>ybZwl`9A zaVvoMkQ7uVcv5o;;ZO#9fj&`!*|r@*ySXn&bMyOnZf zdX8tTe1sB!3TUii-;;$L8exIL`6FTPU;6_&=s(7HBEt;|SzGx41UdQ#^&S9&|J%V& zne-ywO=|=r06Jyo{eW2PVAxws3LMf9?7O}@$(7JkCsT~ZM5IJfO`^-NIq(#vE`AjQz1Z0gy;u}+ zUKPu(G_nuvIdOuDKC#vE8ZLW&%BItcjms)Z5_MiP+?k84&?2f-yNFqL6Z)Y0-Z?xt z5|r%ePQQ^$oI5DRj-%0zn&O2K$feuE>hp|bd|M)?j6IGHR$#_FgOPF1K35IB46~uc zLgD)9M+Aa^$`MHqZ@3qa4vZ{R>=2U8ozQ6^bqb(J|9s?#Uh#>n%$?}&%Q6KFHY&V? zGLi6>eO1oBb9dvr5DVQyksM}dcWG7%4*-eZ6S25NbHRkE#rCP3Z;Wfe3>Bp}HbTj| zBxW;ir4X0umEW(VjoPc{5-OL}8{ERfBL9JBwJs8&lmM`FB3T^ zVfwDjPT1=pO}Z6$(q z$F%a8=YY24(A?4(YvAm1Lg!{7v-U+l_zB$A`{uVH7(qg=cXqOo8jp-YDeHfI34YUb z8To=DSHR$}HZhT_8@}klyR8rJ85JyXAdAYMeze+5sqkQ&ag3)SJ_iC#D!2))ntKtZ zUJs_eqM6tVJQ?ck7*uwb(Kn~I@}fR)yCPx`XS?k;SY;U}6I$;C7zz9{ct{;9a)_n? zlGVg#({s#rnw9}#v^wh_%v1#gR~T4ZYw-cA)1me3gL-ma`OO8|JUX&nz2%AT5iYwN zJl(%^pQCnynLW|rAPc5>r=wA?pd{`F?CNj+-2{*p!7@>GG_dqR0|5J2cAls}Df(1c z_FDe!T4+S^J6jqo!H11~cf+Lom{E&l&bhWv>LT3IJo@%-$-2FfKQo&I_|F5(%7zjE z-By>rJ!!pCdT&)7L%E#RYZ*>DjEq%RZYW3b-_rCwr^eiTQmW!F!a6fAT6xi93he<@ zZ`RDN5#xHSK%PWkdU(K7*RWd_c=ifE?h%=KZt&JR`%NZ#bC*CzadQ8q92`L^J0BW3 z56lnC?^=J}UOLU$h-4!Bq8qGAXv9no^$gESRjj>yQ$CS>2kXJ%{1?+HOy$7pjYLgn z1xV)1TS#drBHuCdx7pzmq?L(#co7;cQ9u{Q_si@EwVJu?cKpKE%e@!`e8m0Gig(x# z|7-?lX+Gw6K3Qk*)G;1$GVIewDTh-1$juH|dPxQM>*jGL9T{SRvz{6LJPe7%BKrQ( zjB>z@o|;rfQOjj-2(k|hMNmfd0zRe)R4d=$Wf|T0I449r=VSs^lCM26zO0S#$v6s- z$u}pjfXM@TD5I)6)URBwzSvricI4M1W!u34B+c~scC5mQZZS?`(2-GcTt`DsA0{A8 zNiS}(ATS~uT+VaT)x2x@(POv%y_UWsBZeVD5^*M70|>4%(OR3=`1jMA;mvNXS*hmN zkAtu9gCmBS#!9>gVZGt3Bf(0>Q2A%Ja6Ju-5mW}fl=rvWHr~O^+06xDo zKZ<;OP81S)VEHeauB!5m^`X@eT1YWaK(*oZJ!-v|=lm_4`+pVm3L4Dy?wTG7`wmAv zw^QB+^xde&u=q_4*g3si?BxO1qrw>+*ee*nPR)_+M0)h2v#^Y0y*;YAqR*ZZ2r``# zt^@cI#%VOmg}Hl=W{n$N(sJ!hN~4Xvaknod!JjvLpNT=wT!S14ZN27+e>nUBAwu_& zdEW;2*X&MfRntX0F3SrH^i}t5tqcgv;P?%c<-X9oq(rw=tCxnpb22&tsmwi&>K>OW z5(bl}L{Y&d$ZK}w#ap-Vl$$b6jvi|(!JL7bb=|Fo?e-Ic7krP;f%+dHTtP5kL$)S9 z*1J+_s%-+?`;7TsgZQ7{0}nd(Jj2XL1=v9_r7xZ8wK=W%ct^NLhozpgTR2s=7g^pu zmsX;9>XhcN2dyX*_DYbRFrUIE&!1zUPzplBIV<8Bsb;gELh75^#$e`|lx zn$hK*lb->VsWmf!3_U41n`|%nw4(TA#2N0UvQV|}tx7^pl3tGTeU>+>01vQrQ@Tv& z02ay$BN1)C57WY8>Somyc08{*0oYh}#Wz`{uh&*@2BUq2>cNhPdzFFvwX6 z0v1@;5#A2n62`jd7rOAJ`%H!x7vX#-`Uyml5<)VwPsLFl&#z*=Y%5bI@8_*<`muGR zc}P!b_B2<*ItmOKehSD(L3AfosgM97cGEVNSeYMucCO2c07N*k_J{*`2GT75uO zb7Rp$kkJNDfPB!Xb}g{S6cTD=beLnot?|dyQg|6&Sr3(TmfycrD1TG)Ys)pbgf!d= z-#oGmPZLJ2Pvy1!6kSeUdr>amQ1}W+=G2CU>AN zmdRH)-Em5J3Gn+yCC$Gt1Dxssv@|TURW0-S4UP3W0TVZx07+VpuBXb(8jc(C<5qRU zzcIY-#>{)jZ*;Xmk|^v(>9HX#dniv563IeS+_ezd^M>t$#k0%d?u(8PYhR@i-S8At zzO8_8o`N&vhRU#wT_I+zqotSO^U&Bz{<|B$fm*BK%+D=mLP&JFqo`+ysjf74S-=hb)DIc?IB#Y#KBfvk_pl+#9?9Tx~{SG)Ft}2p~ukyQO zmdbEAs^vHDwP(wnxVVV@D;L;IfBL@AB3k8c8ldlf7J_h_)=u2@6>+>ByAk)gM~AiX zF%|)m_nQ1#n0gos&2+pl?~z5|xqKM6#zW~Mz2va#PB_sOoYE5kR>fU}j}RJjA;PRn zN~K5qYhhX@%l>l4j_*5*tAxx}Y{6joMp$&FYc$wZfV2!qa2W0L8YhG=L5BGB3<~m5 z7wPqU9s){KBeeak|L3RlUYiusYj&o{{e6I6cq)VI27l}1H3{n?MYR< z&9BjgbGV}4t7jp+8zLMdXR|aUTC($26bvpPR^ZQns9R|h`EIRWa)wtl43E#~i@D}i^`EoLOGZ?<@^a&oHWn|i*OjRv=Wl&m+fWZ5PW&ZmxA6dNTu}?yx73S} znn{B@UO%vZc66=tw-YIqm;a$)K!>-1HlLG&i#B{GeccjR`haDuU3QWao+)V3+8QRN z|9748hBLbJ@Ru>5;41syr`$nb<3vvlMQ@i3Br@^ySUpM-R_rG?k#mY#yVXo~UU8}H-&Jk~}om!)6WW|MZ)J~UzAzgiobH>jADp;bEb;t~!R z*SLuP>T&mi7vpsMuWd?A+r8L?5weQNFcEHQ>9jRRK+llgy&-NS-e|zjy6qj2vaA*0 znq%Pib}(Tha@C0zZnt!T$IPEGJ>uDLuQagA&06NM?zL8fQ=FgH#m{`X{K|fwei`F0 zffv2yo&39KiC@~9#|>?)aSNm@-m<*W>~yF@jp6r(XsqueU&kfjg4y)KYX zIC0G?yd*gEkN1&d8iAm=qd;NxQg-C;>|3*v$#$zj+c_CZdQS!3BPu}o*aWc6+CBQ( zrT=6l(pWzpflSqa;Q?HId!5?Ba~nypOS|LIjXBA^Gvt#%&IJja>O*qeI<#O2%x91Fpd8Kls4 z@;OI&x-GgduZzN8-yuRy_P?ZH-#_hqAtzRAr+=W^Df2j3Z4HX*N5J&7bjepwE3%XI z`enEcVg;&OVLB7{L7bg`jRo#&(sVsfctEErakM3=Gv0H~ycEE=7v&$y6vO|ETmHcY zUB)#!O)?vm)Gs0dz@S{8V0i~`{{3M^+I)Wls-GBH(I4>oGX~S% z_Dyavr1TY@6AOD`dPm^RZg>eW2HvfEEB)8wS1PtM^Besrk@Rj=z}B9=oQ&?;LjP^% zETI!3WJvVWBn?37L!qm;6Yj#ZYF*FN^6aERXqxB65SN-Hkpjg2l;e7tuZHpAz*FNb zm|o$I?&_7j20<=j?SLZJs6(&?rHUYDMYp`i6RMmcV7 zuk;%(PXYJb%B^QT{*z*-mh@-5Zz*Vk*TqV&Sd&kFZjnJ+-6o_uS8x+F`=a;Sq)CwI z-#tu%v2CJ&LO-(jXq6e%hsQ=dj3Z$ao@?AgY~n%1>S0>EGiw>pA({v#Lro^>#nohm zs1>VG?IP9DKjd;{O`gF@;#ctxLCPa~?FYvMN!C2jJJ27CF9p_k9(*vA5ABiY(T zJcvlr3AqIt8$`C2IGH?{2Zug+|IbM01{+U(@Vri?NU!hF>o$AW^wf@)yPmy(8pj%> zg8oxNaF{Z_l1Mmy<2)M(ISBTi5S|qT%rJaA=aUL1Nt+o%o#&Jh6qW=ERRy-hPI9Tn z<7jIA70_AksWZzA>`m4FC(}_?^*J4aWr>#>_$)744^uaf>n$zUqUlTpj!|5yUl|J0 z>VVeibyEV#<}c>g^$Ehp?*Z(f)S3*G3c#al_@|mPjTp|qruL$2LkpG5glyFrh5W?^ zU3{40P#8Frgq2cc6O!-Mh2UAzwqN@v(?^87-UhZIR`z@{kCd~+oyz6lh_}t&tzfG~ z9Z`c)<^xD=U3wmV&gDEto zzGY35OMkWK>zn~Ib1CiRuUN`E(>-maYvaBl}r zug2UPK!1Cs;wPZDz}h+58+X?E4Mp@WV8IB05yP^NiZeLP>EYS!>Kpqn(ARYj#MO$bK}!WlUYxE*3Q7-G%pt|5VBUB z+5kyOW%sWb5@fPL>-ZD%0oEi_dR%_ibjUwRQc!mcqr5Fe8zLfQdSADJXp{>%h&7*) zsFblv?XHtz_U>0aE;ScwY=Hj%L@ zOXxm#%iKs5@%kDUn+A#7&gJzo|H#3%1gpD^rk|Ms6L(lw%kex@D_`8$qdKTC#{=Ua zfp9@h&*Vl57H?YByT7(F@iR0(>~fAw1a4 z)gV;DX#VNh4vsNLZHd+s6D65BPe`4`4fc}#1IyFm&79NSx|H5epDdw2cwnE@}+=F$Y{bmm0EC94?vtruLY3$T#`f@h-sLsriR2c87`jyuDf z612oUQB|{NSrQ#o>B{%-@vK%b6C4@@@fYFF1WuxZiFb`syfGjTR60u9A-~BTR&%bH zUn74XqUkz?aM$b4MD?qT@3AN~oezf=t&P<1kiQ3C85V?0K&h~qB&&UJf7pTMD471@ zV+RhPc7YW0wbrB{;h4n3lkQB5Df34!h&jNoA zTeG%!R!>Xh$Y8b#w~=QXo@c*zk8l4LS5Cvr%H{Qc8i7EA)0;@x{=9Sj%-t|Y!EW*UaRoBQ9{(DPdm$qd*zLONx3Y^WV$v|}j_ z7Anmj4mzbJ9B&X8rD$*-3F`7+?}oDgqFZ_?#3`WABxV%5lxOM}P81_W4|(y8s5x*0 z{w+;9vS{AXWn=GQOv#FF6QAbyzF>~2$^-~Bp4!+vq4gYA$E&k1VK5}G`!2ZCt3qKS z3Kf`Iiqhdr5w=kG8){%#8l+)4oJnOWG7(#)!U69hRnjLo=)Xk#0ZXJEiC)N6`^L>7 z-XE3zW8iVsagbds-b+Y3I((LA9F1qsh3$Hrfg-J|rUkV7tM?}mw9GGjbIfAGIAMr} z6a6dc;}1^xphJyi)aD4VrDTc+%2hyu&f?o*zoSVB$>k1l{~vH)O+#qU7iH62NAvBy z#F2;&J=G|smqVM!OTXDI-+IVBWq^ZEYor}TMGBLpb(8=73M^E`Y_SKEcs>LM(I%qT zO=AEsnktXzQ0Kn>S4W6@|6qDbcTJGy1sSs&MSu$!8>JXxQgCFdBgXM}j_Uazu7g82 zcFL?R*azln#-8<`H*fYZ;|f#fgXR6#*L21+x`g6Ky8`|0`VN*ndbBrFZ6_rbqgTjnwWa{X@rcJRFeS*5dqcFxoOjUQ<;PiWCn#Pu$C>z# z*2dQ6veg&`rl=%x*hvpB;f-f}7mfanZboD&eI90)?7>c+o(J+{q>sb?@M?pJ`_X!b z8c64)C-v_gj>^Khs{^r$aWb8d7_Zxpvj8hV)W37s?*;fJpII*`AS%+jbtUPe9IGo6 zbyn#vQ#h1>$hEt}hz4~#*{sJXMQ5K!K|`UEPU$b_M!PS&%_xe5IPNNh2xci(Ys2@I z9W_W0-(_t4H7&TcO3pAphsJm62t3_h`oqpzvVux8$L>HlS?1)=`(iyS$@N_mAg!95 zjE7hS4T9Lvu=SocoV0whQYdw0YZY#jC?|0Ww6s*38cQfb^xO04eyj&zQlmWk?Muog zi& zJu0$Ijdq@m_lhIfb4fvv|MV!vxLe~!nk$Y(FYizTFB?mLdy%)TGN+Iy9N|T75FOMA z3sY%Xjrw7QVG4C@XLBhRja>dSAi9$Fcfz7W?M#5V`XykA^Sn=QW!9ImOROY{6xFeh zC>n82XZkd-xB#HbMzI=8l`dHxzR=^@kAxsrK=LYn2LDvEZzm@8C}SPOYu5^DHj}i0 z*^VfiS|w+2S|*D-+)f@Fu!SNU5$hRb(J@M6FxEszNGIQH-o9AV9@@)WFxX8_#d3}{ zsgG|~cYdPe0NR&RYG=H^KXjUa*qbCc>vjq6q&t$8HqAwP(Kp_TeX9-3xB=%g%@Bhw zRYhE?#B9u}8&ia|Y46u2iRa#tBCZFfp^wDr;9~-nQ^<7@*r-fIh9}cp2pDDAx7x2$ z!Cqr2QZCkE&c6~l61s5WU(|HLYY8h`^VL{2AGM{slkMNM3BzU%?|k6{Rz<(wWCFaA zm$X|Cl|w375Xg9;=1DEf7VIfz*-iY$H;8vEeFkjlO#nzgY9sfBeK=h~yET9Xc*P7S z^;D=G$F_BmE2jWbLazMnejMVn+h!pxx!8(=9QI!-t?6G=0$=I+^>D*pqf4e2M%e+G zpcFaVUPPHYJHUI)To;+pCNpT&cKt)@ADXc=PeOEW3AZm}K`7xo0zB$)g-M+@?sL{u z9X}mF?>}GMo%ncUdvr?)-kFZ7+26tK#9Zp%z@-r4rSes__d>c~v;@=-4txO?40&8S zQ~0Nmi7#9+X1<7r6OWtdBmXja|K@V&O?lf;1>=e*JoBHxt;m;1WtGTYbU<4 zjyK2+E=!)Auuj#K(lvfN$zbxuzXp+Zo;l5+cfeR zFjDJf5udF(+e41%Vv78LE{`v9SK(xpyKg+7ITUFY$s(}AlMk21{v+l%m(uOCR&Q*A ziuACXYf~G?rR)%K$h@>elL;#tq4|wNM_r<3_VlqUAWsb{SJmnb2veqcP}%!4YcyaRw+fjL9@NZ0Z1J2nPJO<4MH6_aJG8_Ecx&?Pq8q|(^jD?hEPlLA!ubpk zXX3)fQYJY>spsmY#wo++dQvkhDHsm8cOMpzLN0EIf$?=9m)gUVp%r%lt$r`uNEAXN z>7{p5wKW81t_a`094K-2<@bEMcye`VViIQ4$@kX*u6H$ip&Xf{4X*bGdgKGuAdJ&A z*S+I78XvSitLuERH`R?z{HR3g{$p*n{k$E~Q+D1?$90g*)c0 zRcpYpE%%L*9T^0OhJ?|`CEHZ#Zr|ushFe8DO94|Ec&5Nem>hXJulOkiYTQu4$XvgR z4Gt78i3eL;~on*HOA491wz zM#sx&0u%5~8QkG)$28+*VU=9Ch=yZJi%*&wb@rY7>M)`YD;VDUPRrRFpd344`G1EZ z`T{SMkX5)O7Dh|JP4rm+pn0B@hiLqt^NxIx-L+tXFSIs7kXTfBz-dA_W%mA$e%^u? zmjB()3Q}%onB%}OjR$@PJ3`oO6Iy{B;7HdTW9Hl>t?zqs8G<&6U}QBYEsx(W0yR$b zFfn;q+j>VCMI>tz(pG2!@}DuhyvJD*su}b*z?nK_9^vH_P@ve*gPjSPqY~nr^a7(k zyb{pDQopJy*c_q9besEkpsVIDy&u0^UxebIZ`KB5zB?Nnr^?{E2bP3Q8f~@3(}is3 z*9Re`W{ehiBF|1^I<6T6)V^<;olMSul1)4LvP~5E)ZZSbsAN;wS|~9peAE&Gt(gf? zTta>}sg}-t2=s&F%fg=pS1vu%Tg&vpXcTV z6!^yyBcbYl_;B%o=X5&%%BKQw@&QFxtZ$m+asA2ZfdUmcW}cy>_?n;3vYuZ~qlW|Q zaXL}`(hO=7va>@42YnXdEm$NIi(UuZn!vN$6kfbjShIH-o-ABkNlyHjS_0-Ac6*tU9w@&>G**M}I8T`=DeRMOL)920;n@aQSQf%0jhm*7G|Nu1oV3GVGVtlUC`oOz|)H?rTE z;GJ0lEgh?tjP?J7Mh;`insQFDN2&Kdz5?u2w(C%s=1ir0@Km`!!Dz}{g>j{+k7z(N zO~w}=z2Cx#uvx22o-qD8KTe;rJM^JKN`V`bKAf6Vf;tKgQCMLJ;alcBzl-fsAL^PnM+wg$H;bsbg%`g(A=30$qsZwyUIEocGKIb!tDu8V7$eMxZ(+|)vScOSQS#mK38{hc9Qi&SK=CSb;_wV`|a zWf4_K6iV^?(&9|U5ixN72+OVL265n;%9|J6<;_lVh5u^}$6z_4#~pD(#(oV%ceE-S z7DASNdmc>&c=%YxBXcFXPdBhzG_b;|((_*~sqcnXjQgSFg6Jm6w62Y7JmTaPr@o!q zwiYFH)Vpfx)EMy>xXMydW?;-{+j?OODwRtEis`l>`z9HlHW5WtI$bXVrSjXAfeu27 zFfjtZtE+?;IBg3tV3m*LF<$RngEbX~Ahksivf=PJ> zjfZw=fO>S2vfJazZl-uFL+u7+cZxeFz#1I*f%hW-U1ZP!W1uwUTe2+c?qJ}$5r7(4 zx?YG)({IUtMtog4igKo?8!Gf>7-Hc!gNspLu&lJ5KEq}W-WM&>Q_qG zUHU|m8zZY)38m!`Jr{BlT)n2lfhAk=es?4ajL7_QJXk^~3vKzAlfDd{Zjf>l=M|Ye z8M8Uo@dHwTS>znG-uvlfAjV6sU4tC0iUNIOUX5?q7Yuo~KNrA2Z~0)Z8W(fXnVlMP+BBxKk%7w7G-eL z2x?N5p631(%!;KW>oP*ic5l&s9q>fZ0e8%vJq@f&F?*+x5vYtB{(d2NXR_=a(b#7{ zvE}3yWMP%qSW5AY$m*e*x0ZM>c}z9QSR2W85Jrx)#Eksq^r5LPSvbrq8WpZic0Tn3 z@F~yN7M6!E^m~dEY6W(XOf5FwCB`);rGO%GI1NAnZx`SG>^gBw$Cj!`LBM+&^6DwlYp=} za5e~te`T5jK*?00L~`v2)^$53AK@QCoP{TeGrpU{y8NQgHQpqWpNP{X7UIA=YsFS{ z3)e12!1%-Re_0~mtr#e4Ajy*C!2eCvV~J5b01uq5VnP9Do_ER)-XwpD`zamgb=we; z5rF-|~@%iqO6%EU#z5;^fQ!W(gF zb|Pm&;*dYJH6oU`0cleg1o>Z`L!m#>MnJgmz=QYLxE5kP+W%^FAYB~r*kem8N@8f$ zDEZJCV%aw)%}>%n24bF=j8_jo)uh}a-^U`w!+aGOyqhQ-85iM|j$Gbc_|yDc_h@q; zcp{sg8k_vMJgqY|vXlY*JowFKU+^cPPj6toAAKzbw9b)`teo@Xmfcj3Z zNuu-*lDAn$0VvK((McRBG3XNC*93D8O3qswW}3t}=BXd-^oAu3QQy1sqbge>`Nc4j z`#C4NL~B5#Gl?nzYhbQ4LS8ovng6K-1wAyP>`{(i`p832!{r(ETE@&IiE1X4ICbP5 z)L_0AWBJe_km31d@*x$s!MpL<$y!bRaAj?rQW1)xCF)lgX3S|4CL}1lyDB#f!w#Rf z+}EC4#~v>{_dTUSGuj+HK~!iXUrxziLR-Zxqql+6*nds441T?dSvA|`PNdf?c#p|v zuTIHf8%~nxbP_HqA%C zOLXZRkiD0%#{%-lM7k*Os()I*7}T_u=D({z_d%R`OeQJC&&*KRWUC=PaS*+r-Icr& zJ^h6Q$C+L&)Suc}W}^zW=+6kNMNU0yOm))Np|&^f>jqP?BsjYHlKx>sP5trAL0Jr* zby#TCo}{v^wiuEQSNYt&7N32+;EqvWtKP3g0gqUCnvOJDx* z0$T-29ATaLNy;*qgoMHDz$!ni8$hN#*RJ2-Kw(avc>AJP?~I8^w%UFV9N=EKMsxtP zJ4-zJe^rRIHcjM2X;VSvp9zZ6Uud}XoVQ0ij^Umk@;Vy)oYckQnECvIV7XBxCS=!` zs<%J?HKC-$M2bN5kYOh&OaC+nNH0)nr2?{ zgP&jGoUxW4&@t5rfoVe`PQxzdaF*65ZOMD|E1Z>;Nu&{{;82Fa7I{y)#DS13 zCMqOK64MAZSuTiTZvt>LN&PJxg* z`8aRI{6uQushIuYZR?;u;dOmHmJufdISz6-g~>kaam`E6UjLk?gV@sWp(mvPsbVz$ z5#S5r^*h<;Xmg1sp#1_!|MHC=Q{yEDhDD1Vv@zmX%m|&Zd16&V*NeCM>!i)_3Ibe4W1~!Uk8`F{@b&}QNNf7z$M1W2y7o@ z^w!@dUzTn^KfRZNsof_Eb=w7<8IX-T^&HX-wC5qfk~W|lnVQe{q8H5RNMZuJgt*=RK-r&TM8OI!+q zSsyE4O+cf`F#!jUnYG&V4oSdFEp&x7HWMfC5MchM(R5Md*S}Xp$`s}aLJEVlN_g;v z;?XF}=||n`@5=sG_S!bZte1mf1X`#_t~#<>ef}j|O*>|E2WTY7c6mTG$}Jo-Kazcy zB3gc5kkr$)*q4?8s~eO4PB+7uQ+&gz)csfE|_JCfeEInBbK_nsrin-tk; zLKhkS<%=%sacaIrgm%*xU9Po;}v4zo*Tzd#l+|3-$ugyRiYDYvRmo{S;>QG>vW0o98RbT1h3L#NAUm}%r;!5RPghTUj9fAPx&&xX;+=koD z2bV^`PD%URr?pQq^A6th)!I%uH|73=#&FmfOt&f9&wf_MM4z{AQ}Jd?Ll6EJ`_Llt z>1C~>he1@HG|&A|=Xib6!0G%vAfPlN`qH<&SSXD3`Aie2O)0RIEo^&ecENoD*>SaLQUoV3@_wSKM$<)!}qg0g65SU-9u4&j!TOEpHa| z=r9DuplGjmz~wV6;E>k6fUN)N*e~=x{!r*mbA~3 zISl#r`@hkaQY*+=gOlv$`j#(JJ@^napU#}M%-p;*}C2y;f*pjomXK2kB3uHX(AXBo`Sz z%-4b?59G2F?W0q9q0Ja^NKyS-!(1*P?$3v>|K}&#VuyLpB(uZ}#c&E1F3M4yrSt%d zj?K(giwqRJz(57z!lF@MA{{|hyEpvc#+wh6^zs7V@}}#)pj~*J3nt9kY$*$zCZtOv z1S=vBMvxeujIHYw-g*2X0e`UHt6aE)&l1%nrx3is`6-Q^vypUZ@~BwT>rKcaBnmZF zEQ%Rb^B!jAciXo0_~IUjg!p8z804Cloh^A2bITI4gOKl(X^>O-g|G`EeduD2Tz{+_ScMSK0Y1ks;f_eW%@5NonO~(1i$aeiWo^2 zw0k-f1ybC-d{o7OjvijZg* zT|}`H(U0^_dtfG=ldNh?g2;#I;psK)jK_!I2aTlw@+AE|Der8O&#AJSe|FzuJFqvI z{=YslWrwQoLt7$%OFJjF=<)C zf|X6tJ$i*~iHz)o%&G1jLmRa&QmZjw@!YxAbsi4mOU1u-j4o4ElcyvA%Ibd7YcW7j zy*P2m;^V8APi~@724lenpCOVSc_Y+w+i6)Rtj)d;D}EKAa3Q3aO~;WGTGf9>j&V5O z36Fl*1;M=&v`W7;ymiRS{+L5Z^5msMC}VoVk@T{qK~mS_0Xb}ZmK!b)xa)AVU9;y5 z#C|l$`LY5(NmSyut|2^tnfOgw{uJ*z_Hu|3>kpNG!?w1~%8ukfbiNWTTRQWO7+}#|c zCM2YSPK)J@NgSRn&oN;slAH)L=oOYQ#J&2;eXYajVy*>iD$A_OX`8K(s2x~2pKl)) zhHB|jb;X&|JJMT-nC+eR;y(iU zWeW*}`V5*9d3s>@m1zSh#GNyGSaRk(t1ZQ#rsl?1)wTQ(g26q z%l&{iNeDM^*3PV9TFE9dZzc74a;Uw<5>Gw!id~hsZ{pg1oJyC}1La8FJPoy~5f+I4 zG#Y}JX6qbt81Ky$OzLF{|Lzf*hEPzPT%rKIjnbxHFcHqdXUTo4(}KA#IC~U4)WbAY z^IMAnh&Yevy**+P;Q=3&u%Y*z;zjHpjA7?V?q3w0wVAZ@(X9CP+%;oIwdM&}?dtCj`sXQobwm$;wNKy&e@o5xDFw|d z+JgEe-Zjq^EZHHN#fbRygO^ZIfQdBY{c}&pvC_iCv+)pG5hU) z5kw`d@#Lg^Tf2^g$e~rchW9Oyir#FDC*f>n9X~4QQm(W1W?qR$BQIQ{{h-HPiw;55eom2zsZFA@_r-Xku;{&+M@rv%;pMTlxwpPPGn+#Fq{ zTeC>01qlkL3HoCM{d8}mVcaORzR$XC7aQ<>GtfNC}ITCAsEFWS6`;rd;F4e zh*wh>)>V>x(d;Uiau9nLHP;RqlrqF72-FeaCd6Aq&5t*56r_A4XIKgj7+yx#bglEK zB}5O+yRZha%S=+ysE;Pl`jUs6^3}iN33xyq`XZ^rB8F`_e3K>z&U`cL{+@?={K23B zNfkfz`Fw@Xj0Zy&Swv;dX2N#ErdV9$-CwoW|4LuI+OBULqj{-xNA#JkkFy(#?%B?B zanNGBTgqj!O%=gdNE*k43ObzP$xC=J`xf&eAHsvcj=c0pLyex7k zW!{8Xo#XSmfsI2)K$cLvLyv(|q;b`Rx+`2ZQfM81DJpS32Dl5Md^Z@J znr&@Odk47omv)|wE>cD^7(d}Cbn!a&yA&9*iRLmhPyrk2Y4l(gB@;`^+9?Cnax!U= zVNM1=yw3yOM8ca`KreSOr|8dcm1QjLqM`S~Tr=;VxJ@syjX#}w2W(K(gRvFJ&p?$_ z&x_|I zn)Nk6a}20Ey|z2&b5O$X@0zt{muIXPGDO2_tb7#tXxh8Mq`QSoD|r7X);%vy?>Sg3 zj9w6}s8$FptJUm5^W_vPS5&*U{jHihf}ePG7=OSDn?@Xv%fnt=lkBeSjMbj=R=5yM zk~F5t)m8$i(=Jp@!B#|kBl#>AItQEa*5ZDw1 zIaM5VQg5~u#?xSxw-?gN%Xc<$@AeO`EHn1y0O7`@uAL&ML}^RHE=q%VK`Kr0jrNXp zh;WfI()|pT=wnSCRE{u+{R8!8jYX)QA_ir^16UETzY&@k_H{ZWH}pu4>%XZ*_^$Rc|4R7!y3DdcF6O)*cs-XSNC*>X=VgZZjaouDhX&s1G%NJa z2nKFUi8&s^8oPI81k(yJ7=5T?tHp$pqRnA&sX4}XrR3Ajq^{<(GN9`zjNT2uu+~)v z@YA_FN&>Qv%3PX?U$h~=+d$_299Lz3Gj7Gkg!Xp@q-6DXl4Aimr&~vvy#!2y$9v^h zfZ;)}ZPou_KB}mw;*(3-nv1TgApp?`%IYQT^PllFZ&I+^w}E3N|I}{_y{8Xco%&@z z=$l7Z_}Wu9nK#>(9Ri+&2j074hoCfI2U7-9njS?4rIw+S2mKD_YP}=ZTYrQH;G%X8 z(Pyu-zY@HSP_5L^ur!?Q&Pe0{>{6`F%b;>AyrZ( zy4P|h9YI%G{hpRFoi61Ak;{5zAi3{gGmO!Ucv(DMZVO>lz!I&m$$Ipw^&}@sRG7NA zvRK4}`9TJ@oS)`{3~(infUFYdt}UVCs?bC3bpAV!e7VI;PnHjC2ZAMv9l0Mnb;lA( zkhxq7EV|%GJgKr%CFS?!VAElQHvZ$rJz0+^_o-_dCdemVu zR4gd`rc6s4c(JNED1>Uu!HXRb3!&K4Uni#nWf$XE=~UJMk2*3pA3GCHzK=RNtz~r9 zG>7c-EgM0jjT*>)~c8KUn7ZZUtq@(S&<+oh|l-d+5g|l4ADC55IwrGP{O1Kp^{w{yVu7MCy_q%{5R&PB%Tc?e(P(Ma6|HtJW(;(4T~k7T<$^9GkQWw5P1!Ql3lhu%G}O(C;@>*pC}N2{MyVT&q0SN1-3vBEntV?!QohiS(g`V?}lv421G*y;@I|gNd4pN_?XedR_YtKTvT)FllRx9;R zvT_v71e0Xg3b?Z19!T?>9jHMwoY<*Ay_LA{avyDgF%HQ2AOTZNPSdGdYZ~C#0{DPc zc&?d*WURA4;4*@VX{FXC_w0pCd|`@w8HLhOf&+CJ5d2dB0%}5g0Od~4e(asad;{#( zv*oPts#gm_3tcObNcp;n5!4oCTwW-E_maTot)b28c~Q*@jfptYcd5d5n#`MV*IbRr zlYQ{w`fzY)T6#;TEut*!|Fy`X2_{v4Ny;{MaAP`(G~nCSqJVFHyD!L3W}yEb*13J& zGnLX<+wl?O7T;8CC449>Z^Sh{h&<|&fXTv5a zrwxYOP*xLy?(ucw6bv&qgph<-Aa!IY{iC}s%OehjyQE!^F|dRY&|)-ziO?Hwgk1lr z;y&;RpLHn6pr5^7f!Hg0R*>Jmmyc)fy3|^da5ldQq#Dh&&QlW%2kA4nUQ~_CCf2Vk zs^X9Tf#BSe2Ym7&+?jdqtW`c=mj9jwK976vKGkE3{IdaGK&36_1BeTUsJ(|C_rH%; zV5d&Bc#r5YCw$jKvC+n@5OiWiRI?V%i@Y4=Zqw7hD?`F&H{i(SD@lma96{?>+MaL? zC*iNM8{1J6e+t2Z{HQk_zukBGMd#?Oa~J5Bon)F0iqcj92aC8bXL378`7*aX!Tc?j zKGQpbPZqwp6v!kyGd+XpRWO_EfP2VMsFzjIbVF}CY4QLCS#TaZ)~+Pg%ALiXLnZ4I zL5p|y4vA>?=~fwWW%IibmMC|Xt4}(CVbL-Gz+HG7p6qMD-(1u)b>}ID=T~t5b^HSd z5-*=@eEu(S$L&|bC%!^6vq+!J#<%MH%hFVRHwvPY!YL7Fk!pg*ROhq(tLJtn8j}ZI zK<5{tmEiN!HP1 zt?+o{qEk;}Cw=4hE>Yl2kzGq{^RS{chsh}I3?J%f`C5Xwi0_Ud`VCU$-!8sdrLv#t zk$aAl4tSL`aYUu**xpy_jLo>3{WP@Dw2UTvOm!n z(7LobXCk|XE_;rvlxm3OtV~Eum!N`vrW2qpU!VLE;jX63ic$oN{b5Zzr8p5rGb%}F zOj-RR^q~TKK#7g<*{gJ<3#)GM`-1Lr$L^`r!C!~MTD6?tRIWTwZc zd1fzvsY7@t?T80n5l^72{+;B4WjX?5tmm3ox{e)ckdn<>xX0-}oZr1s2-T!gX{JJ_ zfO|7N_2y1DOBh8jLQhm}GQzH8N0P;T$8z0(+Ik?RXW|FqB=8jbW~B|_^~^_i&b$V! zBP9$6ftNXel(HfN!`+BW;zb50-ixH(5>vfjKMCA_PBV*21?R$0{cqFajeynG`Snip9f62(hIO z*1p<|(IA{H z-Zz?xT5Ncs)s7-@rR?XA4#tW-)kpJM*+s-Xv43#hPtCu!PR++YS z6(%xpz$KQuMJ~@jLL{g(5}&1+Kt~A0CA%JJKS>m08vu zukO%gU%5Vd;cOpwLD)TVHEBKZz*)*7AZQ7qNUe(6PNi)N!ks-Sv6QO?`p*~CO1x;t z5Vj_Na0coE*QsC6u~zSzj8YW_aph${f+*Av=s8o5}2Y^`1> zk)Su3$1o@k>>WZM!T3jCoaoP^rV;hh#gu2Qrb%Man0O`)#PzlF%ifw{0Xg`{$y$x3 zTD7a}A5~f_<}Gl_1kB=zBZ!yg)!=RvMDtoXl|eINui{kCJrD1S>Zl{H?|^ZzwLAPQ z!T?Wlowa$Kid^I(0xl-hpT@5ZaCk8zSJAK=&I#il!W;%KskcJ1)9Z)B1E`(GvIv)5 zhI}4fUH@>;{Z8!Fw%24l7M%b?{#aH4o>*0PXjUN7L#qS!N13ske>R=u1{uP>+5nJ_u^j>$}FWW%BO zf#~$$WR9rtLYpSDx6VidTkHp!L|c@_n>1dtfX}jJq#zrTOK{oNyhma^U`%^ntrOWS ze$H^5SKdCG+g)NfD$VY(cJ#Cr&qVl|1ft|*X>pU~=W~-p8STf!tUE`i08};PqX3-O z{yt7wW^lBZJ`@zX3_aSG?acO%^{R87BM9;o!I{?_7l1wA?qPyMc*V@)d3UJK5C>18n{b>HFVlOwCEaBfIP z&vI>5FXH~&FlON0Hvh}YK_tJ;jWt>^@~Nz@=Q>yEl6Q{+o;(u!<5zl7N?O#}Xkep( zIq!qwdrY;>@=YgCfFhAYBg(X2(FLp_eSln33awS@jT$Sp5|mcwk%rW=;82&L*zbu; zsx9T;V)oLHi3OTV_Tp0F74{93Smy%9)a4U){+SJJhLJ0ESUSxzBrm}_5^A%!2^0deLHmu27GiEd;XRA{O?Z7~?Eu9*5%<-lt3_-c7e#h@8%(+a^ zlIT<@qzmz*9coIb$$<-rx0@Mk9L(lUZ9XrLm~<0Nz0(t(L2p+&3n5Phl=A*YLR8h0 zmbZ#z78R5s!b3GlOEXFt6@)<0*YXw)EGme9$UD{{Cb1vF5Avoy#Pd7!l^Zu^#Sv5_ zm=_Vpmy13vTlIKgxReSpnUb3b6}|zX%f9)*mez`rZ(K(&0{_#e6`9A{m6@|d4RcF|4vaU2hEh+h4ny^E26mVs0` zt{!mp5O^7g3}rfFU)6xl5lNL$++%Z$Yk%QTl+@{>uSJILVNOp}BH`>(rq7C{S(;rg zsE2=->Om5R)`TVtf-_8j0cpAwDja@!f&`fsj}60${h+J4=*c&+rGo8 zK64~4BF&cr*E1kTwQGLx{ixg#qaOs9zx8Kp0ur{E-@h3%FS@nND>Zx!-nf~_4J;!M z=&JT`=Zln#&Unka*O8u)!!stHg4b8?*FX>~(WvuHKis1+mU;qhApB62#j$7_DV1kZ zlIvd(1fudW<_iZxO90!*6cUC0 zmm`7k4vlNI$vIG+ectEv!sbgo%&i?a@faq88%K^P8VuhP$LcnoE?)6S)&r{Mr>RtPC`B#-Xt<6ajRA_W~%GZ>WLW z{B-8@*CKcm+f5gVc2*#D(iwgG>fNri={aa z+w5}s&zDDQ;S`g@`@my_>SHxOOESlsO@7z;qJJ+mq&XOcs7nkx?cX;O-Pd;5-B4WX zZcAFjnwqizSbNTp_}3!7cK@S*`KDtF*2Tlr^i>zEAHwUo7uhq5k)BGJi!ZKoz+2pK z1t&wa;^H9IVzm4qc1`6nN!;{=i9vlJVm*I!YJ?SjyCRdVAZnx<1BtiSVt0h}>O#2v z1|Y5RH~WNIHSVI?#DkbhAqvr`MMB)gQ9lV0ZiFuOEk)Kmy^hd0#WQ(*u{qSGgGOKr z?RQC#y4j(ArFoMHH{Xv?u#=d$a7ijbHN)Vh0Wfoug(X=~Dl2;Q=6#1@ap&dZ#2pA{ zmh>+^R!4Kx&W#vJ{@@ViI%^8>$74<8e*Fc_l}SJ_UQ_)s!ETLCUi$SBMN|BXO(Udnui-B5h-2)1>#lZSt~-rx6F0SI&P zh=4*f*~QwT?;kClWRd&D4w&;Im}Zpnk#JsHSI&%WM>`X=C!AVKuC)VGR?EsNNbA2k z(KbTvtZ~8p#pkwe6PgI7-11E-!c0#9@y}%0%|;q%VmJBEO6|4GAuk6>)yjMCu~3_W zj%gC0r6i}|HD_Z5I5ayQ)!+t=!~3_N$c?{jp@E7T(dXNA| z1T4TN<`9`N)XySVL27FLbl$C2!)k7UPt)gFXM^83_0QBnAQdx#ya-@w;=k;_UIqF< zoU_aVP15)s#)VO@$R^@tEVr3okLvotk81WlE)yu9VybfA&*lYz?FfjdVW^s9_WP85z4L7rlCCoLJ^q;M187-lx5eXmK8Y!Su zmc77T4=(b}+r@|k&_zn??G7Gx<(cQo)LOKT;OP)^O}UOB78+U1cnEKK>mQY`J4#>a z(LYPAt;=Ot6Dn+H6}S45;*+#it{h2QRLj|O>i2JtrLzaJtvpf^bH>A>%?83q2Dkyu zdt|O#H(M-Bldcp`w}q6(oxPZI8_Scq58lIihC~FHmiq)>@d$eR;!oOE6JO8sN;ZO= zlkr4d+<mdA&+5afJxi=?NJWuq1ht%xc~7KYs!0VW8oRi$ffzF=_WTCOi= zwqG(m2V{QbBW>$=2qEmXUB8ZPEB?0ch&P}6#cndftGMhm#bqB6ECXS<1(U;ML7B>s39+3-zD)t1C)0E5kCl0`GN zF+}SB?QKIm!F_+JxXa^kJ2o&#DTdHqBUst|3kD+5`$s5OMzEnAyy>w4^T8&-5F$O7 z8ocN}05x(slVRXU7AHl0*VN=lj0-0zpbr%MHSI9OtUXt3a_{?C97DpmnL0fC0|@(F zx_SG4col^HZ)YY@Ksf1+MZG0v4JmWz9|rP_%EDvDl(^;irMr!mcd6+z1wa1RYSZIq zVHS}-{#uSgTBV-JItAny7TW6&89gJ!+@6%|zmQhAv%D3z5-h8&E#cvreDWfVYj?6E?gzC^qJPJ*fkEy@+q=W8RnLhs4>zB24vOlfyF=# zlzK}v2V|tC`oWEB=udsVgefzn#Q`zZOK(09&f(*W3&^++`R)PGd=;$0KSBfBm2gS~ z5$;g-(f3{lC}bU45s_VSqW(IA);y%ODZCY0j!-klUr|vUO@m6zh!Wa%nsC3=?8FJf z|Aht!cf|fjwo=}vvl>lrANBZKeCnBEI}HylTikIA_QGra0c^G(L5iT1Nx)HnLt_;uxQtd^=X2E+et3<3#sTAZ;-iFxJu z02yKl%BHvJh@?>NOc%xh>*LJ2q>yk+UN=4n0<`B|pwR7YPjy16a1G(n=LZ>p7U}62 zW;YzW_NfMYqMh7qKYM(sD7cNp(qyk8?*l;QF;D5Mn4F~%-uNV_+3-!6dGKY!mZshWU$tHq``Z1jd@O30r&oujqW`rBU{O1Y_D0- zL`U}_ms8p6{?K3fe5shr`3pNDk(1~AyQ0K8Lqdk5;=aT*OE?lL4?-S1BDhOrpqOLs zahwzzqjQsR28Wqi-f26MwPWgHGHs|M8}qfGuihzF{~U9(v#RbK4|AR;x}JhUamShQ zU?O2?yLh#M`Ss4jI-$ydDDiyn2}5tZe!Q#>v_?KGtT^e{Cog(`E70XQnrrkMEssF} zc&}x;rp=-^Y#=!Xl=l?faMF={;KtldhJ1QMUCzGhRX|hKoYt1?+Sf8OEfg&;Q?88c zzc{RIYSId>;0505n;=q?=c_EER}^3lYEh)ge}}%YL!K zPlmjQ`j;}X^ns-CTpjS?KvLb(0kcKjvT( zOLW-nny&oC?*=&+Q&v@#=CH5OAa8*CG{Ugai9Zzxk^Q8wUTSiqzVH}6imd;9Jy>TA z(WeGJrPhdFb^crHr=yY;hztWuJ&LyXtgVp;uUAh2XLme7soF3d^MQ?7h)D*Ay z0tv82=#wBY8wD6I^7;{4l9(22io^i|Z@N8DHA+aAVwa4R(TyZ?H!}U1?9c8*2XJ0B zIes3N0-SwA&Sd>eBFcKIN9##E?4mkSjuo`ZMJFl=iV^uDbIWPT{pRHUpYBdbe+6ZT z7fI7Cb~P%kAbyG!+wx=~eJ#M1pIx=8P;}s+JoZ1`7+?Y$H~_!1^Pk=2v-)2nwe1G* zQ)^NrZ51yzdbhD=FW23RvN#z9 z1u5!$5LY!8$3?ypk_@Y?=0V!_1o{u5WMO%+Ce{}NC2Vy=6F7VaVnne&3rU1+j!W zH~heF+G_%+9;^)3xvMfMN<8tmt_v_r+BR7kqq+jmBFkHCMSEHA-@f(pEw8yj_Q*bv zceUH#Dv8<3r;C1f?(y4B{&Aa5SqRps7NlQ?Y#{-2E320k0iz7IAvQcBz$A|2$!RV+ zxZD;X;TAnq;g}IYAp>80G<5AU6i)n(h{V!-8f$@3JtGM+w+@sJ=tR_6J+i3?tWv@n zOrEWy4ejK>_O5J#6S29N^>w+{^t;Y#U)&LtqPV0nQGI|pZH)Rn14Bjm7r9vW(VaX5 zX)Rikpeq0YkB=o8IG}PkJ3&PAre696C-OueLg_<9`#3nwlZj)&K;GiE6xy6UkqdCq ze+m~AoazNam9P|Zt|c7E=dHemx?}p|wl-?G5PN@yX2l8ennU$P8N}zkopF zO5zYk_})QMZJl(^ZTU!7l_sIB@C)*KDL6k;H}?`~%_$2CifHoxH&v3BloCRUHV1Ew!ZW^_&7`kO;7S)Uuc$oFeIrQ+S zpr~xJ&}Zq)0~3!jJr_VZ?bOpI1X0ngNb4q|DSS(rnJq4e>|rA;w{LM%*S$=$EirL* zpQA%KnLmx%frt7#1XP}Ij~n5ZaEs^q=*hp%;aj#S0Q8V2T)!sXfib2pUv$pIrsjC5 zEo0F$cYLV%QE8?;BOa?JRD&$gbh{EZs9li}m+2Qbbd}R}#ZwK|W0a>#3Y$IUcL)mr zBI%|~TYo@gxZ+NAKRc9`X8$WB>gCNAPEN=-ZT=^dR$_eCUwF~z(5%AX^PlBYodwfY z5V}ml&9d1;sY?8-m)}m<9CiYP+H{FJ9A?{RABA9BhFm#aNlmp`EW0WY?<=dm6^Rjm zrUWZ?zAX25j$wu;Z}S|}?EG2bIEpp<+m-oAjO#!+rwmfcJ1^})=jt}v;78>UP$)-* z)I8jMmH!l02Q%44BTeChAlUuO(_wP{Ddcm^wKj_tmClik*z9%h0X=D7G3>g@RB7tV&?+mN!)f z=omNXNH7T$Z7xv`1D~uX%c@B~RPVPG#{EmV8f zfe%VEgf7d`SwfkamUkc)(HE>k;GK%(?pMc&(N zl!cCVsQ@V0@PHj6EL^veWGrD=zWeIoy`m2@|HlFg!U*DuD5G!qmx6WAa@p(n2O_B#v+ zDUr#nGo?v>D2n##`)M<(XUV-V&N!W*QP6n&IvOI-{vEg^I$dRV;oM5<9SJ*Rw}S>t z@2?z^rHE&LdhlemF~}t|IJgztYO$d)`MSA+D>x>)I`L$5)hStu>U@%csLgOn&)NJ8 z%F2v66HH*Mh;*XX6~*C z?6^hpo5{*m;ogu38XVBx)xDMELMn=ExCB31g zwr=RfCUK%F|x;sV7 zqEEAgUd(vW6(*$fYShWHN{5oV=%YF#5TOi2ij*~ZW5U20AeJ>It{Ph;P@ScM%U)f0 zz!L{>KS#G1_QQ2_d?;;)=+IEg*Aog3;w&N@-y>qbHmo38d$!4Y4o3}V7I(n+=CVNY zT@EC=(MjXGBMvU8Yp!bwUC7<)^zXtH>DOps2RJY_@?`}s&-Ag4dCw9no%zHpt=XXo4Ys&LIk&f*o6d;hgB6$Hwyd-tJ`QL zESkb~;`@d;HWn@N#JG7@EvN?YbDf#c#|nIT0TlX@zr;SFA_-8JQ-_w zlA;=@dO6X{Yk`BCx-I}b|E`Wv|Md^bT;C)$%uk~<*P5mXGT{{O{kU6=`%}y)? z8&ALc-bb4=g(GzX>!#qppLK(8aK2W1JA%NV@W+hcLGiJ?tM$!yva59HZ9aIOdEK>j zk6c+MzV1De>p*D`*;wDmlh&DsRr#!EdLbQF-JwIUqiAYhK7cb!lu@i!^vm~+hC{L-xh9+`)=PTKwO z9Xjn`2BF&B7NnoGszlW&6~DmDB|pn_P|lXp0Y#Ut#h_2=N|P%=kIL=!I_1r5M1HcW zQUvbRQj-*umimM^l?cA!I`I9h9(00qOIm7)GBWc|QIu{Hh9F!1)1m5AzXr-OaCDxX z29j>(k);vh4n2{MW&?!0#7&+6lStgMl)(dYm5@_f+&;_>!I$`syinI(pc}Z1^>3TLhTf<6)GGRqM+nfk2O) zQy4Qgun*hf*V?mj%er#xMW0>uRQB|yNdn7YO19WvkNloKu=4m~&s0^0u5F9D7LwWV zyHgE^e3GqVkUoO-6R!xWW+!Y3(OxuCZT_o_qNY=@xsCwRIyKZVk~HJW!v*Q|$2{FEG=|Ra{nhxnDwDD| z3`uS6mT6gy4PY(ilC~0I^@GS%`xDvrHZC4;&;`oI;hPsH%Z#qP0{BkkS9l`S)yi6s5L&ss0SXBHVVPm1;PgSgeuC<6k|yTaU)#=V-4 z);H9HYO`V};pEJ*EfxD12)GQbOB%3N!vvxK0Bk+L?BIA%HZr^iRFrry z?o$*#f~is$2Zhc;TSZ86XdnJl)y1KMfk8yheXYEw`0x=qE#HVUR4c)9PpvDJ^kd%2 zaYOw+x*rAH;X4|XSAB9w_X)!zT;~Pv?aY3CX7uOH0~pb?d;bLkIWqZ`{)^zRudw`2 z6wvP{P$h1oSRoC~<}YTAR^99*YJQ7?(EkN{J(GB_LXST?`Pj201R7kSdl|+kZ$>OH zpPsU1MQ10OIv+XFOu3+pb=lKPkwo!zBVE2K*{5LUM)+OJ{6OjmVVPExqBF!H@)#6S zgNEfk^Al22ums<8{4Q?4zx*uo2o#oho0^MMUr+^ zEkdoiL-3rP|Bo7QbyA$1@fQz`tu@jc*Sh-8TH}b;k~$q^{O=Fv6ww>ss4YTx%*Di= zL-eBMs~m%IWjsYN|Nh%$H)pGszOptwdMHa^$)cdYBsdSIO|402d6V^SkqRY7$~bVT zNk^5po{0rPt6)*9u-*%XX~+|X49%xskM@Gp@3|S+=zN*<$Z*t7)M!FvrSvFngFY}Z z-Tt{M*%uf^BVqEocA=j#iOD3%b!T_>$Ut7?iaS`j3rh^ zirF?Ww2!k=K0+;(s>fa7v?H1SmeWCRg3Cj%FpU~oX_RZI2{Ep>Ic^4nSSKOp@fEGvXP^`uzo)hQFqAGf;Sgp3h0)G|KS->UzU}I?Fr!BOtE|;_xzs5E(Quuw#u@}U z$GN(&Tnut2&nl;9T>}ndIn`s<)0kW4;k_0G>>v!t%1Xi4L|QV98lf6dw(hJ;2Zg@ea-CUAl-8>{%6mt8yntKSr!d8$6pfMLRX!Z)=0ib$7r%cKqmG7 z+pW%oPE`FHgmHmnJHtz~J>>Zy^PBfs$&~p3ktS;k22Kio@BZ~h`;;J5T|gl7-9EG! zKpQB3;l#jYr`*I+tc)q#n-w3M1A6RD!TB*=%xY_DV-Wh9VaHBV;p(CB%Mu#BGf*;| zi>_!@Ho=MJc}LkGcUMdUfS|@NQT{$~|911|RAeD%7=RnXm@I`c(+mdjtLv9ocgL?K z<7O{gS{jXpe-GP)Ok>1@E0}Tbh&YkWCTM;e9vOGTe;ZP;{Qi8N_JwQ%JpX7!WViO^|l?n_3o{n1vU#vUv@9uf%5l%3j^1P z(C~q>bcBVHk80)oqHay$QHBgiFm-TCqs|G#-(oqsv^f4Iv04_%Y%z$gwWsnicgu@@Y0b&_i%h|3Ih9{^+zf;$~We>|zQEMT1Lx?)R8 zfrzuG*g4Ezzgpe>x9igqW>T}Z8BvzH{On@%kI#CvFpYu+ZipP=mfjWs8Ido{*An52 zqD{SEpqSN~J4Ay~C#!2pbpK)Sz;I*pT+WgVicA15L1!Oh7!l|^!1_g+bGad;18&h% z`L^l#gJxkJx)>pJ`yi!Zuk*r~`%3S(s8*PLa z&gCrJo(vKJw0%|cXt6l3Hj)f-@1IALEH^5!7`PC^(9HFUgU1{SvO9;Uv9qTEG17qfNd_>AWMCB$?KkOQ zI$_@O%OjVDAv;SLX!2u96gNaB4`T@5u7XLavPb&jJEV4-ce+DwZ6!-tuEu+?GNpiY ze1D^YI3u~AB}+QoS({o0WNREK;LpEB47g}sC1q_efiaJ&aPYjfid<`S`sDkX*nWFI zx5UiG?qqmx7CTJ0XqeCV<6F0n7D#ycyyt62{|-tTXU>BFZ&*C+9N#dDo+zE3Y0U46 zXp|`jUxYLqLoILUc(d+FDmk?IiPpJ4Zm6kMbbdVrqd>JCw$EN{1u{if-{THg!Z+y* zGN!h=d{%Gm6?Aw~fZik#a_>%vHc6iy8Jh|Xm%R`9>4}f7vbjS{Wf~%vme{DeRzo}d z{UM(qF*Cnm8J{oZrwjlNQ>;pnWSPe@Gu?#GLFH?XLg3wY05#cUKFV^{;xWL(U4o!6$6)16!V{*}CK!iO0 zMjmnO9;7yWGo1ZNsUOFPA(=M*T(rFfiX(<^Rk6vF$Tl5K6&|4{TH12IZ^j*vbYdr< zBxuhDs*l%il(3V6oTVw{O%9sw|ymsq0kZv}Dfun_Dg) zmOf^szY4Z=#k>}dn0|#%F?i*EpWmvxR&Ctod{E)>eRP(NWAxWm&yM?SKL1=SdDNii z0f|-?Y%_Y!GqKL2TI&-LWp3*ALzkTP!QPt42&Uso*+|)CmkkQW8BGe~>h^Ej8d^Xv z`~iOV|F3$xff>!Bgqof&{)4#SpYzL$13h3$Sj$u9V+by#-wr#jYReV1EZrTuG#F(gZ@IZs9FmuK}@Fx~1(S z`mFw)seK(|N)!$CCeIIXWrEH>Pu{>))1yhc`S1#?;)dNv~qyqp=! z#gv!79_AQJh0wh5E2(ef64yLLuvS}1+=2JeV{O`;#hRUrQO5J#2bOhu&hl+H*KpLr z&^E0QN#%ZXKMV1IT<~xV$dD^25-1bp^yiNe+pN|kG6?MM2tJxfRi1D3~PGRWjA0#Y( z1q{-l8k`^p4|0xr-btu-Uzay9o!rNeL>@J z7Io>InL*nenL}##^k)iF?-sjk#OT+ek`Wn1O7}HL_#`gRIK6JG;WSRiUg&XK*_y5W zj;F{zF>)$4U7#6{HwhOOA3I=iK|G#Z@z<5SW1sr=t>Ea-9B16Sj!3aLL+L&bmxBI6 z$k4zAqjCmMkrTm_c3kMWTxJO(BfqzDnB)sV$pQd*%bvZ3T#!&JU%NiVIO`=ZHG00#-%N2yYS(eK z4cn`oP8fe!WA3ndKzSq;2txd4+K)Az_*Hqry=QnlO2u-h}#>HT|1^#BRaNVBHL77B5VcEz#u(?MC zE;C?@iM=rULyv;kCHxeyu9D2QFj@KOi`&aXlB7O*ABz=1MTxmlCZ&i+oRBLeS*=7d z3=D~;EO_8pgz7ZINpH75LoV>N`oW?CFfK-}Zy_X*$4OLGsSf(q^0LVnf{-9 z!7-Yta;c-&0ztsP;!3cLU*9J0DSoX_LgnPUA!&G0cN?3>GYrU{YfO^DUiV2wnlroA z4nHr-b8;vZW-{NGm{hX8Kom#Az^bt0P1ZJ*p~PUdt|&qWuRVqOt}}rm&nyr2&Az(t zSY2((Qdha8ahMhrWmWf>xwEAcRt}572yVMH1GhJP83`(|T3$5&C#N}05rplTx#3{6 zD*CZbl^#gUZa)m)C`4!~EuhkOZ?&emV7)ZM?K45oTOmV&+rVy=;!xk?cJMU`c-OSg zP5;-#ywKABKMb#B|73gu+Ki5reEe9YnqbHdx#lE}xe8Cc0F@HM{h2SadT#BXTTw;A ztkwUN!nlULYpt#fYEr=r8b_pb)$6sbS$;0jZMxA58Sp6Jmtx2UID#-a{vEukKln>Z z>!Uu$Na?C{ws$d)=kbyK92s<^l}dpUz?k zWB&@&PdR}OAl32WIJBqvZXvS-;TX&E7Y`iZYmBY)qhbP*>0<)7nSE2FkRU+_Y}6jZ-Bj_}&c541_pYJ-{=r z8M#9KO1yZfJUo3V;?`a4ct>f0p`Y6e^G>oc<6U4V*iK!{)CH0#CQ_&lqODrW-jdu& z$0dm?Ul*pSL#SRIR|0zJSin45U2H!mW_zweC9Dhw96k&(c+jN7{vCThBVkvn5i{{l z?TJs4@0?jD{}skOhBdv<-^uVPMbNzij`$Uh{+_|l^vq=c@Q&c%l!e`YqSkFf8P^zb zu6yvhxw=8CX8R#DEtAPH4h1|Txxtffv6@9Wnf_i53I*;d7Fd~}*yj2PklT*~%P!hDj{c-++K0+u#nzX==$2BW+ zliI8dNloSIAqPLvH*^l=~Y-gH&OdXiS_+P762&;du-foC;t{wSMdAMcMcWMht z^_p_uak}q3t%dqKN&Q%$;G!J(k1+&N!;$p+k1@FS&HJ``arv+SD;9l~STd@K8T-Xg ziM}2h2PG+tvq;3XSZsj#Pu4%fdm#0Bv+ z`)kvaEvv=%JF5$9u{u?vHw+=YH={b}TG)~jaxzbW)^jL1B>X@XrrwTt zVm~9MBcT6z^k$|qyK*NjQcN9@$%|y@^*zO8{f?nm80sWuo)N`UhXd%#Q!FmEWz&aVx_6wea|OJNC#_2!Csyza*KW`Q$zPDaEng zBrd6zXC-#}XGZyuYc90wRB-6&$X3kIwM)+#qV{U4hEK2L6=X%-3DP<}2|t8Ioeh8` z{#G}3y(GzRA^?&1KqdM?!Kpk@bs|~2uVPb=cc~}Y)cm|_SyF>xE|LeueSd(S_^a8y zdO0d#u$SFd`q1&-^{YoeoIdgogF0QxYVWoqE8foqNQf?Tq_YD}=)sIP->RA?=rPLA zB2g?C>avuYN5fqllyu^I6} zf}TSEfg<4mXFgas19N}VyH)$97gYrLcvna@2f|R#o>|v^Tuv51l&YC#2?IFF)v{d< zcvMe+l3_l>DwuaEUS#uFabCf^5~wIDTqsQScqhkV8cOT9utj~V`E;H=h2?-ae^>5) zj37?gR81a9cHS}k^L9CMl#M-lgG}4Mp}3m)J=v3W2hwmsa&z)poW(2$(uz1JD|chX z6}2%gM3xqRVWe~OL+TfvZzy^|ZTw|-;XV@qi~pcW2$?HLse0X!<*k`%6G2D=s?Y~z zaop%IGaG#ZOeeKW#Sz*Dq#;AHfe(3}6iYWi~s$7FkEd9MhbB(p!eZ&o)a5>V!Xl3-G5ng5PG~ zX;p2H25ky?IHmc=)KtBV@Fa>;7&g?{oEPDwtsgig9oPW_s>#!D^Q^0ldy*oRtjD3; zh|=h}8U`ML;9TEl^KpDZvazb1!LB%Al=`pao}$)HO!vjTW{`g3-GO0Gk#-QC%cd2V z@8hlS9NMm&`qe0+vF9GgjaeJQK&qB{d9nJlL-iK`)qxb~Waa^J#CCGRc;w)NWF{2BHfkCEAX@EOll&z#&r((s2jIl!_D{(pOJS;4y$KZTxw+IJKugg$ccw6%KAa zWbM)wB`>@)CO{oR!b_QL7%lyie^ir$iElJ06;4s&f930?Nj;HCUB=N$4OOy#)N0_b z{`ev+dIVb-Pf`BH`Ob1fN6NK9>6zc+<2k84v^j($VtVUU7btWUK{ZEcekYs(a!%h1 zi(TOOh{!>?wA#)Yk3W5q^d;Mlg}40<_X!~vB=GMQdu3Co+cO;|F;+i*YgyaqD-aJd z{L5DjXnJm1bN;`1mRvLJ)KuvqUZlcmY09vT?mQ+V)!(VpCs`8Xva@jR6vA80o(j%F zUv!zk4zT~f%y3=&(yxpJoZH0E^99PKe3|s z+|~;1la-1=fpE6VH^(&bO!ptzGaheo%r}Q{*@q+J-{()h24t98w)Kurh)1#$4j#2# z6xkELCVT<)C?PHt3Clr*B18%u>@gI_xs9|5HA~bW{gD}Eck~fB=e&`o%vvfSxc>-RYH2qRqTOdPRp04{9$V;t} z-7)WI)qWOqWWLo5G)KYwo8PbKHTv8Z;mjpJTUZoPP!ouv4zp?e;Yonzz~egwh6s*( z1p;#&1Gt3}K9WK&*{)JUOzxbqeZUZ<;rvURL*&LQft0OVFFgWGrw`ws(!RS2C&Pq1 zYY`u_vGpXxrWz!Hr7Jh{LX>=jXA^lY-Bh$B9x%_uFHfVAOK@do{CTm&i_&0zJw<){ z;P+VLwMXOb3V1zdnF8V{kR_)7)3kBgxf%X(M+dtsY|+8TKwkoO>^tcstD7cATY9n^ zq$6GQeD@MiiZ_0HpD>b%NV=RwfIKI*Gv0;IHMNWuaNNRQZv6$!CahY(fWm%oN^NuI zVN@y|E#*oUI92!uO|X;K+38ZPH+7QSna#ATXCSh@$aNQaB-E$sYB4ExfCqzq6D?0- zRM+vvIs*-A*mY8M)J9h@FTy;*z*R%GYpJaZ71QyyEuM??-A2ja#L+bLhvDov!l2>a z&9;TS9q)vx-bwJ$f<9+u&g;G-yr}RkSjN}@OYv2T@ZfVtvsAZQ(L}ou7eK$(I7)66 zeKsJ~G44@3Ddj9JWzzOrs=gjboYLdwUBLN2OL+b0oI=qY z%b@*XmE&Bma@-lRscHCky6(CX6AsD2%T$6CjpR+(DhH#~PLV*Y38%VkeOMQW?mL3p zOJM=e^Ls5yBX;_i01as{#nGC}#4QAxoh>GWO!*EkWJ2@D!2Xu|U-5y0-m3FftT+^cX z`(|Xf-LA(zvp_CRlcH*i94|0ZSfH-~|5W(QgTJ-taFrH8GmQRv3~k+NKSwNxPnpTsKMJivHN=48>p-AR*_TC9 zTfF88A-%%p7#MFuT)1}$b_eCWojekmV$mo>adoy{5#8y^H9jd<(yz8&(_X;`;vgwL zUUdd$fT)2~l~M855kW)a7Kp{I_fB5&PK+bm;Ayv86#=SSrqhG7WGgus?!(k9C-#D~ zN$b-8HP_l9W)KR#XfSPxc1=eX_*Up`arf0o%LV6*=lC%gFUqXgn9>@yJlyiHqClq^ zxzX$g9i^{_%j(|6_M-vFHKt@@!xx^s?uFq!+F#WYPC`ZOpfjkBgF~oQ4~sH_w2^Rk z4`nw{o>tv^`e4lzi%t;F!wpLzynn**3jdb}eb7p1mxjAegdZ*7)sKadWM&su^fW_SpLU0xq5+N!p~mi+AEH}D1UHs8S=SO2B+#tJ6j7s9 zij{pLY#PFcOK_jvA8W zziGTXbA9S`1Oy!%l17Ogk6qd8cGclpNM(b9N9FUf7b|ou?SAi#q+uXhDudM@^G@D1 z!kxxuz83m%mPmDZBw!+2DW~J875#pAsqeibyaA15tvc4gGJVn?rlLbdl8?g(VAuuu zWVx>mnAo)Y5hJ#HGHKk#aGObyRpIdlMs^(tCBd{Op(!$Xzb@}NxeR#$nATNaAd`hI z6h;DH|5OD+E1krt>aG(VRv-_SAo(7&`jqq=)oLp2lADLY9jdV;iLe7L|7#1#0u!H3 zr)co*+^PoX!n_#Cy?>vY&L%en|ddfsFnEH zumXhcvc}~sJYy=p+v94@%E380stmpGb)*7B=Mo5o(7ftDaC%V?s9i!Hxzl$bC{6D) zKBX8cXw_BMCZ=kp70UG*#F-<38AE6jTCKhD#2(PGNDfr_IhjP)9=}Hbsn5n-!3|WYc@lIZlMm zC1!0s8~Qs7c6CSK&2&mN)Kg!%Od}|^IOv1_-`gtf0oXFidsmd=Rmx-JqP;sSV;7a|44UghP_VBJZGStWBisAZ@ z>>$9*j`WJN6sGE{neFJ{Y2DZB-)L^rqQS==d`!)gScvdtS zk$>X$IcpC6$jpT(xRBN#_HEQ+tE=n&xk99wZUjU@v>Em{Y&GxT8HYH8p6P=i8)NvA z?Ag^;9G3_JU5er_-eB7-XOwR2_m004a^(EH#nqD?+HY?X^Z8e+&Bp!|EB8oR11Sm( z&>$p2Ppl$u-ALWAAQrdtOYaIDGIgkm+;~FH(Jf;tv(b&p!`SVo;!z-K)4M3X1zpHn z-i~PGDoV3Rw;*);r%uWe6#0akvv_#Iv{T5&#C!#o$DHvIvDL?19>Oz@^5OdxNrQUW zv-#&_D|WSBDJn0!+q&G{+gAcQjO8^05e;Z~hyPF6=;hX3TT^52g1uZc#2XTPsC`RP zOi=c(r8E51g1NzlnE7QuGeryAFB>O4RG&scGy|j2U=^DY6fJC3mLTc~`MCtx6hDjr zClF%TvmgIMFd(s$*jx#Ns@nUBE@K-mnaHj5wEXyQRRVbo z1bYfJigp#jX|%m}gOVAyRUV`$v8PI^Z|2&cC&$6^AAK}^i2Hyq zjG^-IR8TrT+cAyW2#5GWM3TJ$1(t12=YlW;{(xL22nI%5zMRfZb$u0OK4Nfa12$GZ z9Ng+{s-C(xQ+@NXyH=A-#;r&^MPzTF1X&cplDY>6ITg5 zrJRU`a%vHo4A6P0F!QeVa#9QG)Kp;8gG_7bf&7fOMfL|AX!C-Lb^j;V>cByAaC&^A zj4RpuG;rDCk2}05*pdah$ERTbOI<*QdQDF1b^_-D!zA2jaB6sl<|Lq(c*yRs#+w@^AZrL!c zM;thmZlWK_ter^1V~+>AH8gtNRloIcuSix-(lziB_IsL*+W$)l#W5fehF3;t};imrC^W{>)qkg4-J)Iq? zA?KLp=1Ar)mq?*^yLF6=jWTW_1&Q%b5dnB)cF+Q8kDYB2*Hpt&7Iyp^;}#8r%#JYX zDXM}JwA-W7MeA$|=2$SeNeCeiB|A&_kJyhRI_+&OmZCmNHod_~t`q-1VkL4i1?iuL zeO*pQ@3LF(X32Ak`)-P5d8ruly!SDr@?mr0_OmF?3zDy5uq~i+pP|m$OgUfP#ld72 zA@vxcyRTqLF8$0?8}~&I`I5aD0Wuu_)%9z+;YR*eaG;aG1#YDc$2n!AkiAGk$II=1 zAXCNV#G5t!WZS~HkpAM(*V;hfq38s}HF+RYWq6yn_0T|(*GJ6;kSrpzR!~3gx3sVB z@tX>6@Q!y!b@u{+q<+WP-Q%j13&)G|F-Wm>ObI}_!t7(GizRz>D(cZZNsS|~|0xFl zTJ-5qKJA0P&Vrdjm?6nOLFd(Y!MKZwozZaIJ!h(>tF`=ypwP4{Z0?f=9y8nRuR{s7 z>SUZi7Rr;kOIvBnQiKfzv`w|ePlBr3o=!ARJi^B9y0AUeLit%JKf#E03GSpg?$0%P zJ4`VhrO9>rz&<%j{MucBE&#!4X|ltvFJncqCAFYig!VH%BSd1N6tP}`0iEk!mN}#o zNHR%Z$2_jMg*UYU1Pyq0PFit+8Iyl16S%^S5<1w-AiDn1QO3_#_LI6J@?J95(VGl@ zVg9OMB`G;s`3_k)tjq~o03;J`3o=;1=kEII;niLRnk~x+kCtw_+F~v$bXPZQVt%o6 z6lktd(W$Gu_J{kSR3u9vdUCCF3RF);tGErFKDeHv+n0CzI$G5?(Y6T)X-81~V z3v6%C{c9C!#Ix*O+zskF&xy&_3#&Vp7Nl5TkHNC#{7oJ261+P_%d9%$ zeJ!HvsZ@pxjl5_@iTET4-rj~W^!h45FNIjjm{#Et?Y%H=hsI3Shz`iSSf;v9KT;1H zSodR0I=Ccq3`fit{%Q}&)b{w+V0Y3^ejBdQJU~d0SH^h&o|#dgUA{O{^A%N)*!&(L zuTR#1EYpp%{FX+(|IALerxMoZ66X~Tqio`NyX}Je@v8EM-F(gw z_xZu8Tk4|3BK|l{ ztu@)Qx72efAz}meI?P4SUw`X$5UyNx2d++!kL9Q&X*0S@w5Vsq-R1Ms2oi$6@WjfxsKqSKYLHV~B$-xp zD=stvW?3k~mFqtgJl|@ELEJ}gMB!Z5(3Ag zdV9fb$)F4`kq!t!Z2|6LPn02&-++jen08)W%nlR=k_z2R5=($Tzn3o6EI{k==XIox zfc|jb!BgyVkYQvU%udcsv>{fM-lW};R=GwgqboXsS>wn((8$Gfrhg0T{gIQO79>$K zif3oo-s_aGU*~oIP&^PY%6NgeM4AH#1Rr5j;|%iUEYNeI+u~vSMCn<^ld#$ZF8O(O z;&Ga%)v@%$yZMzsycT|>Te} zMBBh9QDLAo3`NW^8^-T#X6OfQvOq1>XYHEHF>0C6wmAzIRg91Dinxjj=OArv6)_=LCPil1o|M z7_~g={KFeWC}92f+VXY@t_7sM3#jHZfoz~6er%)lf3)L1reYeWi>wyaR{hXe8S!ZJ zk>kq=gLfMaahR})@@(h~%MdA_dGNG7*KE=3RjdH8D=zlOVd_rP1LDC(vQrsiI>DmX zY&b&kjgM8e?ije)KQFHLGoR;Fl%;Ih#ut_b$tD>W?032XI*qdT1z3jCSkm5@`-ftS ztD3e@jRe?JB4L~M?@4>Ehm6mkI2gL@{|qYpNQ1y`nukIdpI~bjB6{*~n`nvLaDDevz!#ri+qz=m{N_n!?e; zbg_W}qlvGl2(k!H;{3S9i;~1cs%_ukc84MOK0R$~a_uJcpVwCc2`wQ7wFRV>6s}MQ z^^StQ!#1*8!orMZ>d(TH9*DYp5@Ja&yN3@6(fW+DqLoekMJqg|8`HAXKi{1vpo?{y z9`0I;EI0K~@L?K$(1(288~u&x`|sOjJD7zB=30sDM!XJVqvGCiyeptNE^7bQ=E9Vi z3$#vxc#j>>C--m-lgxJEx0`abpz9^e+kG;=;t9ti(e!v)gcpGy!A?f2!n=%@XbVBM zL(hoRd2FT{Gi(boVC>RkP5|o6_tTODcQE&m2cDFH;^n32{EZp0lrdrS!f4%O_0C%P!s28mxVitg%?;xqJ$p)Ar?i{Akh6LS-GgN`amW zk3Uz!@j5s$jk#||xY1tZ4E>X@eBPq*MN4#MlGWF4hdm@qtH_JA=-kWzToqBK^qN9i zI3({ZCeJ@ka5ux(=>&(^(VwN>%W_!`&M@6Y7Z2LlB>1mR)KR_wW z6a8&=Gwy&CKZ}ZNw4CD9>ztp^y8uLB8m7$8c1N^==Ha@>>U@!i$So}|=B|@k0y|kQ zsW%jUtRB}DxNJo!rs&Z^1*S`Fv{afuaXRf1sr@Z@PYJNfF6e4+*lKZ3cYf+amCm6g zL}A196^3x0lY^)$@sliAdVm*%d`sFm>SxOn(@D1zGFw~zb|iN-lGRyS>`tOcc1nlyNt%W6rwGycDsz~;T!HU?+XqqhV?7z zg>5+@CQ#1L{F|;Yh=Pcbc!lYMe;UPfm(k*_VM-wbAM1feE8|BUls2(6Vw~<=#a5Lv z5RzaFrj;Q&07jX63l~DUKmnBMwjER*UBFw{TS=XJlct75+qEPu1Mj%T9I1$I<0tT` zPhF&6$S=`p_D;Rbgh{t$g00{x|3uZl)2}ZA{*B9`4qrp$&;xteI_5{eXt?73oLNHc z^XCu!w3g$LBw$}!*e6P}TNBQcQX9=|(xs9AWOOM4M^X$Iy2iH(tZ6@E7Rhv!O((G{79A#wvdm=5L8O+C(U2J$WX ze5D`{z3uH??RBCdS;0UO6C{ z{)Jv?ebXq?MVF`V=NcTr&ix+nVvEsUPj_d$+TMNs>JOGn8o7s}iu*weLT@}(_sE%G zho^6akQXhv!r2S$Jw*CWCL=)Gvp{uSO?q_KAt@`v2RkIOqeaJB%Kuz$SNkai)2O&| z4zx`atQ~ShkzBf~&p%mHgP4!(H8u?;kqjnx82X};6>+0VvZ?3Q#Nk&s9gRll?4*3$ zBCD%`0LF?|D;zueTezyMHsOORC3e2qRC?ECexOj;D6^9eYzE?M7#F@x zuCA+|&&|tGRS&HzO-1W?s8PcRaGe6!4FWMNjLo6d4$4q9&ls5DZ z0Bc*|Ve8D5t$o@dVxD#`O7qsqucCO5cZvaN^;}}wd&aLL- zE6PPsuOvqz%CVP<_qP~`A@A11uxE$&VX_K85R^X&Zp%1%2b^-&WD|$JC`GcnJ5FaG zc8i&mwpfZmi{rNVs?jm%V5X+{DA)DkD*zbxDX@hd?m9&9Zbqg&v%+cP5`4MOUorjW ziiBAM0G*7V!1)t(K?IuRL4ygflgdBclmXZ+fF8XSuv9xF71f!r)z=%A+YsS$lS^cU zP(&k~)c^;BS`sf;*}JXn&$08rBdU8&HxJ#4{#M+74{U(gk$3v)kz}SjfWMY@84j3p*4Z;+>(ynSgMpdsJY>0yCpZ<8daEV)DexAPD~)tMSIIL!$kjQE*u@3!RUfA zR&XXI#*u)h{9MYp51c2~wV0=nUC8TNa?-(Du0VJvQCcos3LoW2c&J-$J#$u$2^ewp z%~BlqVEm_1SZ@Lepv&l#EP7=%5Y0Y6iFp!Kec3$^mUbva_nZYi)QXX5E@B=$pT3>K zsMUkqj8>snGu&D;h=CY6=_ zvCII%jQ}-p+Q4f64YiwuPvQ8Qc7pdoUIzfSQN!{?NuDt*B!SQ8MwP|Zb)Akp8ay3g zQW%M%|~f zJ(&UpV}7^8sb8E~hb}z0yf(PzYQHW-4YSLF;*raINZs(9yO&Ml=ZCVUsX?&}JQ-XW zebi>erA6zYx_+IvqMj@B5JT`Y0W{Qv4(r|$aeDiD zaG_8I)$;{sPL{ZhvS@zdhLAbCtl?UT?!U@Ahzh+lq1gs*!&RINx!>%@vfkV)<+V2a z>xbT}=5A86o1V?QG7b+!Ma_#>jrWt{4Ouf^GvOmjNk{&FK@(Q87DlFefIKqDE--Fk zshova1*i{f5#l$9Pf`fR!C=j@j*@~D zOQIDw9?>LeR_Sce?Mia9*q!{6b`NEU2Tg4HMtOPtH}h@JY2-Us-x>y zi+^B}NO$fp4r9eO&OJ?z{_&%roB0Te&(f(Yv&z~tQ9N={n|*fLQ5Cjf{*;B6&D3UO3|A>C{&YhsPydcnhP!gp-pd7OC09F=TK?$=6S{gqzv#P!eMtAMS%NXd%Cm? zT|y#DKiXaBBgBQwId~ETR6nl^jOkl=FsNwK!Kovki$;^Bh4;I=5~{;nQJ}k7CI^DUytH;+aUAIRfRh9=GCr!oL)xSuinDz zqH1eltC#OX@M4@YKbf!?=9Kon(tJ=iTAJ$4@1yhPqw|jA$9qB@e#lM9CK&4GE=E84 zS)p=nFIShQrMt+$UL02KzPdV1y1oht78!!rrOSPRbQXY($h&NKU7)+(Bi86s$57*i z{3rUQzDv0WgJ_P1s-(aYxz+OBJ`J-aIdo;qO!s+fYzBJ}pdD z)pp95RaZnuU?i(y$NG?`6%<>-kG`tHenpwEp`oSupk@L9Qb0=7PU;)q+)H{ysE-{N z!ZGXPzLLrXAppgp*1HhbQWc&EN#sS)Q^P%=4vSJ%8?d=to)u1y)VIE820fPm&$+wN z^W7Xp=?>T^7F z+g-p4Uw*l*Q6O1yYMPpms#dk?^BllDKhfaH(8ZyU|Kd}n)ANf7`UT417# z1py2M;5LavJ|F(S;ZutF9V7j3K~8V{A!VxRPv;{iq{0T5!6yvwaBl3L=(Z@gJi0VF zJ?#-_gAIj3$Yed+I~Wt;j{inWKl`1xkbE6f5XcqZG(sP2=rhD#sPbsw2G%GZ|C(d! zzq<74m@Qzu0fspX=cw1gk5i9Y4B|r({`q94yd_OqH<^}XN4pk}Yg?%F;KSN`t<@vk zvW#|C=HiqzB%N>v@kc8)wgVLyTy9VCG$L+) z;PP|$E;0F3GKuMEPAEnoCB}Rn?pB;$fSCRAbtTnXlo0EjFW%(=ZML+56DP1X-9Q81 z275C?IASvlN?s^IVJLocDjrcVf7B;fb1I{cTsE-6ay(Zf6-~g{o$ts~EB$u7^zd)b zl%0tSL#FYh1Q4p{Wqs%_W?v6v^pNt@EUgqcN_8+HOY$8?$ZonK7wP70{*Z=;@w*XT zFfK=y@Z<`V-~GEnTZ(Z5yFO!md&Lwa>zDpWxQGP#@hOPQiUa09h>1%b&@0zA%(;&q zkcP^z4iP3Y1EtnAZUBhQWeu%phStDugPN}V=F=j^zlBYo1S_aB(t0N1oUr&sjd;jk zYCL#IJT}aLsNS1tOk(Nj3ic|8ZiztL7z#LF>&l*yd$C*@3K&P-f!Xi6YVOwN)zx3t zpCU59gO)M~_ecoSo5JlH^Wr=u6Ros15{9~62znPY5`2f~yr+SO~ zMn*>op|uJ6)EP?C#!azbAE56Q-?Y&{wFHIF!#_r8VXKjn9U8Nmt}~?bxcW_ga+tsQ)ny?T`W8(t@I?1=XktG7ShDdAHzO-0z`N@x?P0EiK^~ zkL80T0ua@G@nCQ%*nn%)VkvA+e@da_t;tEPVil&|`wtenV>Tmi!*0HdUXtz5{H`&_ z2MJvf8qYwP^gH6t#;ik8>@|o-*KDzXO^h;wkQw3h3dSR{`ujhScC@gvAU19__1pd) z%tGg4XlGF0%B$l5Kl_O!gZ4og5J9TSm;0!h0(XH9ql?saUtmuVY1nd?Y$1@68Q`&C zDT+#7mr?Hz9`AXNw8Zr`?ujoYc_`o1;`G>{1;Hv@jMNz~DdtE=2O&3@R#I6+M&ylb zP`RlBK7Ru2bZ%w?xK|FA+pOa4jnU$s>0T zPeN^1w>FLi#ZrFDX+EQ1JXQtay_sRBGRks7@%p-UUZ*>SRTn3!csi3Q{#|J-Z_opy zO-!OZR^WH*(JB7glmIv7DOB-esdgGGD1@E02xr-82neTM^nGVe&@}FUb&txy3u6t( zUaWWNt!+8N8J7{LT0y4x>Vu2;tfNoShP35$Y|pDhBBI$$ta?8l2U(oYU-&|Xffd74 zxh5kMW&FJwS5SOz85F~DIZ+?O2^4$78iqxk;C^{gMilB_5*9 z&99h$5E8)5Ba;7N+9a#8V2EgzUJj=I;LP|xxOz=K+m8jRL5pH=s$OVQQ0}NK8k#B^ z6XsrgQ`>Eu7&Wd``=*u>n*L<#TlA!v$;)Il2`w%i?38kY%gJwveZorGT+}fMW)Al` zlb&>4BPZ8rvBgRVg%x?8nT$cAF(b-ZY&>?mT@pr9ojd-B0F3qr>YsWzHpB<&iFxopvd1=5z}vm!h_MAqeEGoQHeRPbd_YFWf&7S-v#>u8^jDA+j< zb+tk@1K&c!uTbQiEg%$Ics#R74zFC&XP~*`4fbHxPJOL+PbHE%76*-tmpGMBN==C` zEmzqYx8AEa4Omhl?H;Zvza~;EycO>!ypG0d0Sm$5;j}bIWp0GpBU5g-9~t*qOnu%H z_jD8>Tc?~;a5;IoB10G-25%iPj8skYu6mCMjG#SK5ymdu=JikYqDBu$2p!}M68#g? zrW1{4WgZg#r76-$Zx-ZHx~0uZ(t4gk#z{VJCvu86D}Xg%QBEcs{!`3p3sSeU@Vz43 zuKisxJa3LkL0`f$)E-as-??y*OvXQW3%PJO%()3oWo z$`?Enj$0JwZTCu0Al8k@tJySvg26^skuQSCy7Ec0>pj#1oNP0FZqvZ~)#t^${0(9& z+2A5J8Z(CEJJI)k@ed%k+M;szopIN5UuivW>pPddcWoas$eKL)kV)O>e49 zPE$)SGeZOw4uIbhY;I$n&@T5_k94Q}*rWA|GlW+VsMmP*xgFEdaW@-+g(%|sE5}uq ztj|Pn=(cW|Ue+zU^uTv4T%HK7W$}NmwTeAnyQ;l+{k8MSQXtshg^BP!YL~NwA=O40 z%a=lVeJ)`+Wtp;{?l?LIY}qL25bh-0BW!5n!D^^Q(3mN5_rbuiJ|%f}{=DNXX2p;B z-Aa*%nX4imoyn&sui4Qk``JOszFJIq_&{W4ilMo)dMp}YK1in`&#dXWo}(%zPj#?O zqdwvjFPILPHI%DEOOulDZ~vz$hEL9Y%^IPft<$5%6G+=hj?Q&h_z6A8Xa?slH)?yk zw>CqD0MCc*TJ8>$Jz{^coPT2Px25mC+33saE#61rW!m; z5?Ux|*OVIwzHK}J4kWxyo~DK!qL-b#r>iSyLi^;5U2E)&`Hqowhhed$+&{kTy_KYc zFznh4fwiPs%3xyKV&F3m)({8^ChKaKVnjN7zprj-=|&vbI<1oy*&BPH_RyuQ3S*-O zew9T$KM@L%Hl(>)(-P}GMOP4zZfTHo%a1)My<}|XauI)52x+LVIi>V)9t*?T-mZ-2 zrp8d#0&0*)&x=W#zjhT1-zN!2Lru>cHEr};+3Nym*)p7YI>tV}0eq}CnO$I2_I3o@ z;+IygMTr|xzm~E<1;H#za?799-%lIB-HzE-Jro=(3nghpgkj`8pKDpjQp(BQd*f%) ziZlQW|gC$@-rT3Yx3rLM!^dV3c;QQdh8Gy0A-C_Djb zxH=p2MHOvvjqFlX0`agi|A5ZEKs* z0gq$1&pq0@p~K6kzBtP{ zIFcP`yE0F!E%PnJ`E!{cN;l~(SEa3DdTqe_`{`Bwr$qV|J;}+C*Yy~?;rd)d*{!>8m#9j{Pl(spd6pqS59``Ey+c`ioxlsi5l~?KPgNZZRzA1 zFespLMdN%I!*Y+&lk;alb`-QMRz)sS7$kA6!pgsTHDKRjsXyJ9Q^U!;D3328Osb*b zk8hY2k(_$5b0&~j;n{og`3x^NVSte!o4z(bb&3iSi3P067) zhZX&$@jInhfZVR!s7v|3*&%vX!v2V*Ul~emAI73VJv*2vl8q+y_%MP0r|j)i(WB!L1|%y z27JDCOmdmFldczmb0=??PejV3%iobz*oz02;;CYr%slOaV2)v4rg?;)a^-}?mt#(H zwNDOtw6iI%@=6*Tx+)u+8@vHXa*yt)Hs>4CN5$-I;fW))^ZP5%U_+&EhNFU#A5J9 z5$B#hQ{jsqbPisdJESo;bN?{Nv&1(&`kuzz<(B*qU%*a+y}eVg;M?oP=T(#(Vg=Tz zKcGRP8q<9T`4Ncx`Jsuuulbd~myhM(>nSEdBOL33qG1RBlpz0*&31uu^-*lF%k|*< zKnUqwPjyOgaur-(%L+V@!jy~BL0BkWFxd_UjM7mhQ&yYTXNxn&T$U0-KnqE;qy9MiNFniD(CD?0bxoMkv=Sh6($#=!4Py!Yo#c^XwM2A~dI?2IY*<8p`Gd zk)cV4W1K~XLElnmP7#eXQNF-!eRV48@w|j*(eynJKd}n-HJyg31C1^UA1$EtmuD4)ksKS1pDxOA5kmP(z#ajm5^L0 zabpQaD9NnKysm|g9C{-e6grK#{{Mu<%9@-cIdc6XPaz=32NjkFGjSR3F_3dj8NGwB z>bWih9&CJK+5Dra4LD=~8Yjl`&7dp$n1u2~5)1QfFVs`yARs$)h%2SFKSbv=Gx z2wwWMnT@>gB_7>)%Ys_DzEX_NW)7q_8V@#yM;_{OO{A2C%05{*DW2yUzOGa;w9^=N zO)9yn?jFihYn^LL`UC;v((S>kCFQD99TJ`|BUNa2B|XM(v)_27l%Fzob(L|Y(+W%0 zarf;{3=v&?cZ?78P^a|EWoPoM0nlpIvvSWeiEn>#Ydi&>N&oNx5=-J3w6i5}cEq<( zCsJJo`UE!CNa`-F+$U`eoBDcMwY9C#6vb1seFC#Urd-eAdH`vm$y#2wQ& zWTc2fX1DIS5m|osE3K@6J-L3VzR}3}_DGbO4LuXRPw9IB%~H8ltm~y;o9dJT-?116 z_=`fuRImR^WeJ05t%VF2K2mPua-O9vO;ENDUVV*uA|4$^&JCwnT+(Ysw2WfU*gmUi z4lELUj`Siipkm@TObe|vFn~gY2*Ce{Ukv2JwKg|fe};qaz<>tE@P`{Wv~d?#$vKx@ zqcr@Lc$tgT7^$zKReXIb54G+cDQ{q2$nt<=RsaqL%}d_$CP({ScMsP`Bo|b!>}!u zRv%7Of6G4V^W6pspGrEcI^U^pA==EpU>fD{1-q7U)Ywvt|4uv}?X-BxDKUU@M+uGR zd}UwmCLt^xP>|87SanqvCU?u&Y||?yX3%8=NO#LEiLkPs053jpCj|NVh@6*=8woKPo0QQPmiX6b@}zc z`AZ_)v%$Gp(TLs~FDRe+{+X8SVmiLb{U1#e2#JySWK%R#y%#eRnXPRIu>0?U64ZaF zfbn2fbND*0rB*|R!9)nLSlHYX??iIu5Ml`!ff9C!4{Y!7k<^pdvrg<Rd}uE%4p@b!}B&^}T{C zHl@3d`_ALK5%tGYy*(2eg7HHmV13ByU;iJw{ZO|BVXh6@sr^+dmAeOZc2CBFtmA4X znnXJS+B6UC>gYyg!sYHQyaHjr?U@R}naS_Y$TC zs}u0@55X8LVF8hl8?!%EDI{6B2iT0fJC0CV!rJ=9mnAIR&XR6>16h( zM;ER7ZWT%PX1XzHG)8wj{7m}sH-{wz62lx@TPkjk@{Hid>9+*2uf+g;{(dj+`Hz&G zh%h$7oY%7Aixm8z!2ZnT1>wYu(%`@P^~5FZ`+0v~=3<<3~dd(c0G(Ue`Au`8)4 z&4WR=3cF#jw-(@Xwy0Tz&4HJ`iXxvyh0ZsGWu;Ui7>9Dt`M|yt&scdLE9B!mG0QN0 z1zp{G@CV1M{1HMq1Bo~UR1cGf$Y1uY$7sd*ClSJUF~{&XNj#Kwv>Y%Y# zn!59XOKO>+^s2+zyBgo>d+&H+Jk1jaDw1kLVwqk#u55ZqXpLPbu)5OQYl zx9cDHnW72@RZSyoQRPMk1gUh~d^I~)gCDb}?PJ^V$3)Pv7{s4B2!_jeO7njbd~o#2 z4OsgCT=F*q)S0(a5kP5B*fFxK>nfR%RpIUij!iu{aP3}ABN zSnU*+S01LALIF6)2as-lrdC=Z$!m1j0E5Zg0_D`|u_3+(C)cj<{towl0X6dVDL0ak zVBf#qx**q_1cQji^adTfC%gxapHwbZmCwBsEyQCCQB>|9;C_ix-1Xyvj1kdE)jojC zqrps9o0Thux>Hz+ucrtP(Z4ZnK071RBZAIW2rpU2WnT}1v$O0~;^px4u> z(}gcBu4tv!VU@!(-Y2A#{-VJAoNQJAdRQRr*{*QU)kB%kJ?bB)PtswagL&MAhJl$> z0`9QH6$6NxUNKfAt1#2^@j-1d;KeYY^7(6X19p0@<&A4yoVPcr^k;4gM6N$Qf{hgm zWM_^34GD*F#%2)Jj+#_z&ExxE5%}1QbWFoB9fi8nXCKg-xB|hNk52Z_FRp9wF;Wj3 zc3Mtc9FnJ!E3Lue@DvHVa8ZXF^<8ZO7qJQw$~xx;pjW)`Sx7SR<|l4cfKq0QMTQ^s z_e$FP@6(+hR49MM+dAm-0VTm|Ssc;J%BIhqC^#>OrOnPoIeGWDMk~_)1|OD-Iyduo z{eRqPp8h3xV?#!h$`jhCJ~Gx?q`*5G2;ch-i<%fEVZCD8H6vgU#ygF{gzk@;^JOcL zS?e@YYbe_z9KqSfaim{d&?YMKbDtIl$>8;ift@73JY{W32MmRiEfAp+ZT&&Pw^rdoh4M7)T;Sdn`S+ zwmAbD^q?VNc=e^TjF#d;Cf?5+DDcS71ubWE5IOaml{PtG#T!a88l|4I?MM%%D*M;} zD(mo_M;lSoo(KTX>*zr~-@f4yQVV3l!im_k%}WDe9S#1N?p`2*?)B`m;%w}vj^ne> z;?fFZ<1cqnh6awG>UL{E^7wRqvQx5^ojLEpm4ewTs2MCl89Dn3Yw7hIb0+QwnuTT$ z)GQ~jd-xcB;TfYD=vT;4nMftTL2a40e6#MvHWf)8ECn6Y0MDz9Mp$>b=4+I6|T$t5Em>=VE|INKqQu#=L(;l8*d1%>0dC|nyAmgLK%J7)E zYO-!oU1DbM_#IH4$RZ9~F%$$U`pSvjajYcvG+ou&_lIY0^qp({@gXuU$G9KTYMwUc zF)be;fY#*E^gS*KCLx*nf-%*#eMxdVWA-sqvmSQ=@xScM{^{xpO8-yG=9>pM^|JQ!gOPV-Igo1@|hX9Gu&GfewB@9R>D$xt(lIZ|g7eGO=(<{sX377bD3^`RrlqYD{fv>lZfFGVC zQNxLtC~{G~%ng>?F~%SYfmzux8A4GQ!9smPUg@laX`wpD=??6G|7LhoWWqu$rpmM9 zxO*G`p-DCP_I*X=#9*=?hm?XqK^g1d?V5Ky(0NW511RVR4FGML_H5=UuG8 zz&MdhP~9vCXY|9epY?q)Os1J=mZX93qn3$)+C@9JWBf3^y~oC%J-cY--LGX<9y5nE zo4&w^EYlTjsa3~R9*75=ZvL@x)6kRF-ta2*mAaW0Yk`o6iJc(i9lkfsN{>BsN!U1+ zGi|2zFTU$g^KR%zHRCffu~sZHY{{t7X5d;jNuu&P8cH;;Y3dd@{lS}v0N0uFaL zvu;RyRyD`}O>MtM^K?PAZW=FK^o|pK#dPrX_qlF)ZwjCfG!!NP7yu=QUs{KXcL71w z5YV3qqLdMo?j?K1_d<$Trcbr~M-9wz0^^IXP8YPPLBPzeJ20}@xi|*u-As`Z%S&1q zi|W!$6x!n}IF(uz&IAd>EFK_vG2|AC?;fn~_yiOZ>&F_g)uwTb#vWKiE(dr`h;@fP z>G?_dtRO16T$|&SzVLb$93^CIPE&d>Ceag=aj1*`eFSX_4|v|d5j-Uq=if4-37Poj z`$X0WW4#HZZG`sOGCa)7DJBgP#sSpoqoQ?zU155qm?_{VIj;tVgP{@PcmV6qfnhew~-T z0tAZ=KzaPGr-LJeM?U(jaP-MU@b(NqEkUFiB7J~f(tuFYW|4uo$ZKvHvgmK@ z2vTW#ZZIJ8e~fRGJ|K-0UC4e>TET%SWj0UVrM};cJd1L168ftW9HWGKQ*tJ6LNf9`Wtuj%g)gk1g|gF%;4 z=KGP#gW5!U{fiWC*OMYFVBPDH^e(zBA&2gNGZi{S`@&0q8N!q`6F!k0c=d4o7!!6$ zITN@$`Z6i|Xef4Jz}CvGw#!$5Kg}HgU9lqae(&B)q!_E1YG-%6^cJfYO{!9DL5A=^ zUaEz)GUQaE?Um&kC;&&-c~D;PZM1vGHuO*WGCSj)8(zb%qQfW4??>@Uy zPLfOwC%;yU2-2M0xY%QW-e5)~pWdxNgX^1sXFnybQwnp*M6!nRp|ds&F`_U|%;Sif zuPx~XB294MV_Awh4HC<|p@ZdCM#TRH79Rso+B_NnNSmO`MmOk7MkDwoG?DVA|1~fz z)B2Run=St6_PB49YIZ{9cZGy#FK_I>jQSG@)(Z4lGx|JBK z4d#v)*rjer(Kj7qN<5&yc|=`5_$;aTei2+@QbhW&_$lr+8@xr0bF(gczJP>*>bitW>q?EuI&fy5Xc25pLr z%J4g>+;HvY-y`vA4gOr0f)4ZxQm$oom{AMKn>av*!EUC73^b8iUi8vAR7)BZ+v@DB zv=Qsa=}CB_;x@-x!X9#CFOmbsTah>kaU13Vgy%HBEm1yuPbrXP2uH#LDPzM)BK|Z4yCi{(-zU6(URg76J^sS7fxbrD--o@YpMyLh*c|N zJgM<#?vDUPUpVfTe#*yS?-+}Z3#@D}GVPvG$6&lEcPp;=7IgD4*VV@g^4p98ereN` zQ|*U~)jnv9t_ie+;d^16>>LV3NfsoE2Tp{e_6)_UK;ebet&GjUv%9;%=?GpWLi-LT zo67-HDGXB6B6*n5WUQZj>e{i~kU~ z=g@?1_N860kcW-shc;lg-E9&bMM4nRs^ztOiybGcJTSKQPD{2t;Dq7JftZD^-I|yW z3T?S#=wc;`EdvM$?nlVpa87O!r$m+t9y67)T1f*FE5ZR%eIw5?z9?RA0ee1ft7W63 zv&#-qX8eaE?M`T>3fM(9L!&@v@;4XCJJ4!Ld58(OF?^!#akWvqdD53$4Kw7oJ)7qu zc=GEJ!9Fq`%+LURHR!r#6ou{)z;lmf zCn@f#qlYd}fde-+xjN2+Zyw5^cg8)vRuTZDc_85OEzTFYwI?|jzbZDTlqiX&XG2#? z_a6d^F^7W0su`dCqZcD^E%iAO+D>dz^~E?PANW$qzX-AFd)^aekPkty0E-3(PGkyKJO1FBgkUPBcZI^j0uiQQvr}dPk^3>5 z(6PSx=T_UTRD{?lpAMe6#fhJU)nqsnJACDzv0F6H_^{PU3pUnWcy6h#l+;j_R*DLV zA8FCAiWHfq;p9n&43)=)QR(*lQY$JglOSN!T| zfq?^pbjq&+8VwPc^ecaVu0pcybGd2i;2>rxeSKSD&%P@XWdQi4aCx>M-t@vEmV3E>~}L9%p3LoW-FF zb6-juLpj;dx29$c0U$ylzl*(To|f-}?9LE25!#dw<7s{%GcGLE1ZhZVWCu)uGJbSO zhE+?$*qm9a(K?GY?`5dvXbnJ%drAc`>pU?-8Iw_U&<2mcLbq&|g)z8WQDt3NQ{(&w zykb7)y@74eCwjqn``=wCMo!`9zfG@%dJwuPYpH$BHrfRfElQN2gn^jsTU~(ueU0ztDrL(4u|u>rTbgbrb9UqCpH)zt>-Aqv&y|*RRaS zv!GEOChby#c*T~a02xR~1DF>_-1V2&_&F+}=^VB*PaY763CT6|fDy5msFhtMMAQ;z z@lbtIvyDtU1ICK^wBb%CW9LC*%Y8UL2wyY3S3Cp~Jnjl~Fb~D@N6ipkS}7F=CCdcY z?dz#V;0T>&czMGEq33P$)}&fS`p03;rls#ow}8?c#$#$OaLHFGzsn+6e|}_)c`ub@ zp2dg;q_rj~uDQrm_xJ4h4R2va=58=9Q^r$|r`fn(_-olik#AC9O5pA2UyLjpm!@*@ zRMFvzpqndF!KbasmE$N;Z|3WR-i+T-yN&u&2AG7oSw#WMtmjmVq?j0P2y|rAO&pZX zoEFWUx9kR8XMh)H1$@<9hO1h9`wdeV*mfaY0ihUewISd-ZPrQ4MD^{DH-9|74;}ynmrWO$pVj29{`aozxD_Z zO5+iZdW>~FsYCdwzJcW{&%#O#8q-9Los{CLjyqY7pPVcP*N?g;{YoR$uePP^9C4WNE5D!ojlO_6%1MXZ7=O84fn#s)pGaX;P32G;nQR|Cg_?#zX|LA)#Z>m`& zfyE=Er~8K#r!FN{I;A5p{6*f5gtKkV^p-!ndXn}11B8;>mOBZq%F}e`tzte z9QpJj@=c6FR7a#M&q$zbGEy<-R^|D`^f;D3G~*z2f^L2u?<+6GLD`z;K%oesr!i3J z%%?j9Q8Gi=%?Eb2uKs-D;?f4K#jCy%o3Akw*0XF&KE74uCcZ;V=+M)b^H~N5$wB7qwlDfj-A&!#kC* z#lt%)p-I2Ui8F;g!NfkWh)1`j!S$@XLU&?Oq;8vqynQeJ*+|-ps=!RE5@y&uT7EY< z8cb-0oSL4hCqjO-PzR4B;jiy&OmSDGiU}1Dp``Q7KAssOd0yMd;;x;I9x4bm1!?Tv zdB?#R`CijTg(J_Z7`=x;KSs-{#Oe}ziPgb!Q;S|1tBp#db z{bTD@t;R)_D*c-s^_+IqQmqTT%~kgoQg%AINhvK?i;`M5r2Cr(C!MFrp7B<}al{;e z1xzq$5|qEFE24Qy{hDAp%GS4hfo<`kN^TLY8qIOF8R=O$2d!mJJ=2h1Er9^4MpxdA zcquptX2f$l3`0)0)lyim@|HzSSWES(c8{NoczG? z;fhZMV%IfbuK!$@T9I18a&b|+eD*gaeQYbqfP{5CC<)(8m2>ZOlPK55FhuH;kigRL zi2onpqfi9Pt5n@%bg6x4WgHijN5hxoj#169^LYHZ4C<32 zM%!H!61zFW)HnD;Me!lDH$btnp^hq7UL{Y;tFHh4Gpc4HGRyb24#~(Bz*d|V$^+)o zwfg)l^@4uLx{A}B{m4`>GDzdmL&x7G>)CC^9Djes#Y~=RlI101;+cIa+Wv3{lQ;f^ za@7Ua-f5l*?RM5^9t{CjHJrYsR8`9@WrI=~ZZ~q5iO8&IMoR^%e%XaLs>BJK;6Hh+H!|07|uqUAu=NO`j@#h}4|#v4YICqA;_yg#3H$TF zUSZU_yM69+&hR8OqI&rN7wy0@%3s2AiyxQ#Jr`r4Qxx72R$@#q3>jet0ajV%r0uwk7<)&zDn>$kp^d2=Hd#9M~ z1;qE|?+!MQ?3Xi1E-;#Mj^vh|`(Z9WL(nhF%@rd;!*c;hQZ0S}lcbjj+8S*C1ugmk zf+(({O{wOM#JGVO(PG9D5Y^)6_*p#^8**tV9f(g)*l36~+Gd$yu z``F-7b7}wJ`X==wl7f)b|Jj61!2QVA|G%5`T(amEfhXu0d<`3O9MTr|u`JKGp2`9X znMtq?^u1E7!wmFBSs-QG8CqA)b>Ux~Vby&NYQeWH!;=zcsd5H#Tr!04dTQKRkHxQcQiZR`6^>lK zDMs)p;**x(PfE_iN&Na_G@JMT;9c1!L{3>QYoEJdwF(MDsmxvEX}&GL2Pw)o(h(zP zG}KMwS=its=IO1?O<2q-c1C!EBl1Ym<-;rgMKTkecBxY`n^uK1MIh_{(PFi~ox{+G zEY-RW-BvT=TW`lAf+z>Smg&yr|IA93Eg!^07Y!!Tf=kc_yzf9ob3_`Lr^MGp8`}5g zh*7Um30M&M?xeuB3Sl$_gXo2d4T}iOfq(_Fffv0md-6_%X_TDI7{TvE!sr;&mkJ+) z`ql44+f(yClTWSp%Zl_LG8jP?zKd77aRZw5zI;E&VR!*g!)tXTz_$;G{^MoRt3g!v zlrE*J9E5t;e!Hq13rR4iprx$Mdq9%{0ayw~R8@6aDV^S(s3t0~$zOgaM<0Hj4XZ8Q z&3AI7N5E=r^ub&L;ipKYzFQlrJDgL^Twl|9L!A_ZT#coZerU69JqB>AWLU8bSak3=v(K-VQSR$;6EmZ8FG4%$!SvA*tpJ< zTNqW(iP>>E0)Q8-mN4Zv(ug8kbj=MLKGSXMB;EBUIfFr(!uG{!QPcuO1VL&aE&TfS zgU)RDvdeA>E3MUJW2F+KPp8x8X)^=E{mG{vrx|+_X}P%t!rlanU7i)wcI<7Kn{{)*MHqYC!I?lwGsrrIyjvKz9V{%~2z@I%e>BG+N#_v)5()jpzgaeMm;nIsWNt zS?pB0!<}a}a@sZ7aRC|XPEPr`Mwss;wBww8lf|J&CerKzY47f#Yoxi15qEX4@Qg#{ zqq`Xspj+ovN#QU&UoE2#|K%o0^`MJ5sqg*(;{QMvP$q6fkRVU*?^!Q+^cTlkV-q5EAI_zH@v+V+)zgGHoKPY)A4mLNKa z27T~`vd=t}WCZo#ElNQ<@Np5DTCGwe-GSkLhkJssox6(W6gV&;_d5wBhlc}+Gu zddVNm*g$&YJ=;S*`>}qXr{C@UP)1pid%{H_rlpP#gg{E|9bsU8IXJt43l~{-Lnx#F zksNyaE*nZ5FWohw=9it6?l6aX8Nk_EUOWQqw`0j=!o`5^q>nPtpMJV%&!#~Aa_EDQ zkVOyO0#=Kx+7gmj4o$ZgkNL<_#)_rx0$ukvYAgT zJkN_iv#{x?`zSh4ye9Y;aWs!0_g*Y)dJ4~`} z_nE4dLy5GWS>avobUNkv{hI6QGulK{?jfRA2 zC6|2FlX_|ZIY7q0y*DY#4l!WXd4Ua|>?_%D=J~N*@;H2$GzYa^OA9R#bz7JVs%~Ep zXu02$5WkZ#eOb2SP;8vEOaG!BF_*c-CI>O5Rd%gZV_;xO0}4w-qF6VdQ7HA^hlwP! z1w~xAG;8>QedfF$&=(XHs4|gA9b{8b&2vcbBONlQ_Ri)3sK}aXC<V!z{+1#>zhuGKih(;)a0BGZ}KR#T~Az@ zc?wUK;nweC)kCeE&5~JCS3rf~ut=ybC=%wXQ0+dlZ z8AiwOa*L1TKKkutFR*V1p6N)>}$ONixZZNzG zZtq^}`M`cxcSDH7Qs;hvT0LN6jkX~$_!!Gc-$^~x5j!tSp%CO9f{lk%F z^KzBbWiD4zgALhkPA{CD)e{{CJzYplQq@{iZ(H0eX1Wx4!qfre+BpLkLh@5W$K44s z<#Mit@>Nv;(A@Flh0BVdn&}oT!)ej}hObmg!QlAt;ZC*v{<-QZIK1ewI7=#T-OQJa zr1(11GK(CDVa0zIOt`#Z=q(VLdN;p->7!{hBb2pVbubHQ;yda48DuYhSNQv3RQEsO zHsZj^{|_7_-6H*5>Jfi$3TSmD)cvP3%`jxc9APAE3|Uux(tUs^CMZc}_dmV`6b!Cw z)CY4C4>*_wp&RTCvh85iT>T8vaPx?-%Q~o9!`44KNuM6jemWYJ$J18AMh?~`mmQHh zkhE7Wr@toafq15S(^STjjCQyH_VvdRDd^>>7a_{38u0#hs0wkE6JY(27B2T>miK>_3lx>6)C&+J83;xm0ei?C!K$d2kaHfmWMQ$*soLuv1 z6gyzgY#f}UqwB<+@-HIXhd;wzR{|)vhp}vPS};d_eISd=WQSUXI@4i9Iey z;k8-3x;0n|D>qAm{5Aly76tgbTFwH+eH2;noLU}*MU%1Q z0cCj${_Q-k;nTXQn=_DeeCdDO-sPdk@JCVYCuma%=3v!o4U;kp@x3oe)t!M9?BMyU&-1`9Z zh>jvzL=aY8CW2%ybtd*V7Pqj3dkvHOo)HkW3MWet4C%{aBPI zN85^+Y3m;jRHU$428YC8uSd7lymJLv*ojRwucw`hHI5RDdQ&0#-- z{S$9_t}vO)#c=22Mb;|&@RPAnYO}jO;pKgfdzUf+2NJ3w>1k~r`FHUWBmnhJ5@Afk zUGDSofw(b1k+D#X{Zb-Z;1=9Fz zXi^p0LPkE33&iLj^VLa2J`vp>DDh7DkOiNA^7X}}eNZCbV2J`1-A&H!9V<=j-Z}zH zVCFNb^)Z*qx2$!4f#XE$Gkg%OLZN`v5rqf0h=M1NJm^07G7H@}e>@ja11$H-IriDJMpBizQnOzAiM?3Hnk~$+ zGNvL10zmU>wqvJoUl|*aH^eVYM_SsK7nq0?fzGT5F zpuK$UELu%G`4+rFU6KHpz>4j6&<8z6Yq^0AfF5-!5%w{KJ|$*kgWqnKQj`0Q{Szaw z+tBH~-UgOLbGFVV;rqQRkmhBe9CY{(xYP@u$i`$PD*h9Q7o{&14QQLOpgCObk3K`+ z<*)|uxo~OJHN)i29+E=XMQEosyRU{Odt3g8wd-u$f)Z%N9_@qC2b(k^yar3fFPE^t z=uQx#4}pa)#C@PJQiDj%3c1A{uBu|uQ#8$Cu7;%Uw)X+!m5r}ro^_bYt+9_<34EDIW?>isMa_chYO=m9dp6t*oD+nO1P#B{G;+0NoE{>_vUXK-f}L&Y|*@K_?VcM^$D%?we? z5)5d*^J|A*=85FaAVE09PS=Q^TVSZrA)Q z*v<~{jYSS+oJ;&Ow_-<2_eOkxXrJpcffXq zM6gWr)W`Xn4n$4MI)@R%Dl6D5KYJLr0m1D18n}Vx5NkhX;$37U8}#j+vF#}}<2*e4 z)`u%v;^|f=>0CQ;*ksj$;Y0|-{rMgGtVu9l?04bjcGswbd1FDG+W-l zFXy`smb&{f(ko3HaOj8VQ9losf1$k1)AnOJrmpxos5W<&fFg#%e3u7q%6Heo^c497 zB}>_}&;7}CIKgd)OmO75rE-8B*qB7_lv;z4`4jf7_Z3U5goQV1JSxma6r$d+(JH;n zr0uA>(NkFkXmX$ogqref=7->Kmo{RrKE{8#n9G*Eor(u>^2!N%_hxQc}OjVNDuB zC8|-$WbQcJC|@H;`FzWW`(V?j4Sj-en^?}nffPp8l-A?7ay2c_^@*LXORk(F)ZOVe zFD~ZzF8RXN8b9$*C#b^976)fTEY)5}5b;-yFojRQ8^f{#l<^^k-$K7=WF3N`6Gw&1 zac;38vL}n%zPk2-90hQ^)4&!nUoLquMLt)_i>~eVo$pz4&U7gBG5En*A^Sb4UwXDL9mh@w4S+pi| zzOMF*K{#sr2Kr(l#SkR@AazLN@N7ely&hY_%bwY*) z^iV4O_KsPsf~p?1pUKt|h@q$ZV+=C)nLu3oHX-a{W6=9BnibYIU%ixhCly=2)T91? z8)Yq3EN6d@udsOuyI_W0F^5^aTgl)=kj#sTl0OdS-=W)3wZm!W%y4u%z3}qp11wmU zLN<~K4p^U~M*Rn@R)WI^=?F0sy%Y;+m<^b9MTY$R9G!?6A~ z&fZz_3;-_y8D%d+65-$7e8Toxqy~qV`nCCUkN4C^v+q^Lw29M*Ja`$ZO{6-z>V-iJ zmlj@)RB&AlQ=U_Itc!+F@>BuNOe|-*yyd$!GoZ|8R-;r?GB#_QO(1s3r!HJ(#mSS* z=SK7`WceATlSP50HqxitZJ<5UKV?Ub6ldY;(HzbmAUTmQqCWARkp|~OuK|PK&(5=R z<>FbZHdK!bpkmO2!R!}|$}~J=!GIeFcC45uY<&Jh^Pj2u)8`S@!29={G;c#-S&1ALvydNuo5RO=uz{My?-eDF5 z=ZkJd`hzRHrN&ugN|Vn%_M6^b#{a$&hNKT_L~=Hazt7PotX8IPXw^?61sZ|NapN3s z>(|L!p|un-2$I8vI!jnGf;^F34qpkXh8G&C0BjK(DcZP!d;R(YNd)dGSVaYji&}Q{Y{=;eq*e70s&uW4T&1wPqeSOvd0kM5#iN$?mgLpj z_VR}{NTegNURtcr$szqjeXV&Zb`hULWRcOy0T?e_>@}u(i1<5(A@Kk7%qy*cOxX=H zR6wm;>0iy7x7PRNta`lMT)pPR(n3STAk(=}2Xac6-d#LLm0mH;jM|S+CKa|M0=?d0 z_(Q@htK`O49_&bs>b^TDU(@{ja))}O%$0rEFMlOhSei&iP*ln zH_9~6Xmf_6e0@S5{>{L4{gUx?05012F5%4*Hk>-|#W*`whkk+sjtq)fITj{(rem*^ zprkz!JwudWdr0+ae?B~hH)QPGmpGLORNNOW9KCTV`|Q=wXooK;>Os2WluDi@g*>h# z1gJ_ar3K$H%J4n}G>fe*2e(?a)0$q`W)g3Wn@Wdhtf75(%F>+Mu}SQvffh1sCLCr+ zC48}CuZ`95MkQOTr^m)PVc1-H=5-4}tJyY-n`6Zh${}EYO4+th{K|Rkmz!C#r}f~$ zkyz+dAw1aUQ#Zo~B!Nh^ASJSFbY)6NKipy(mhFY`3`N`KZ-AO6lw$(uAv6WIjEK&v zH`Bdj8%7^(X`bt=zH=77K~Y8pL#-shD2`Yn@ff@MA+TSfo0S)Nx!;K@uN{}8Z@ejX z`aTsC1p*F&fz9SjqFW`_r!xKcAA!nTFHS++*T&w6a(mpz6*S^^hp*3;P_`GU;ajV{ zFBa&$NC0m&cmHFvD=lx*e!?w*f~I!;)pmJkpls+5-0!(yFTy=hO(bD_of%8NM8ejI zUT58YJ{z#SV6^WkQVi0}+-vh8r>?0|?@->j5y6r;a+GwuBFtkZsb-tF2-q<5WUM_L>t-^efoIYUPj08)wa;=@kcgy#UgHMYkFQ zHw<(FEHh#)o=u6VBZ zNLvh-_oG60`x+8tMD^t_UFKd~O6SQ+hw--aY3}9@h*Rep&y$J%FWcOyB}PQH8a6Ss zlCKX$6P9?}cf^_{2?d~F+9Yjy@}71PICz1%tABwum<^T?()!XpL+!+LhQ)ESdhB_W zDa78hxcFZN0?_q*BAs-QsuQ#n>J+Fs$-;TkaoBU$Ozqg(mwphqV-1C8E0pzwZ%~^~ z`*x$d#w%S5+_ZMDVO%`PiNcD}=Yqbf31R5&U zb#4P)Q+;DYIkYhgzyH7va$-l3KVGV1jhLyQQFPfbj;QTZ^6)(~;I^6O&dxoK%}^y1 z;v%1GT*O=(N_@mPf5vIKF=kOjyhhV*HNH=O)pWKR@k9fkozAUQv^yq`J5}x%#o>o^ zElZ6TdcD)e>>qL5QM}Elw4a0yjRGGT&DWOh>(gWPcMrM&{Jd{Gm$td%X@W|%Su@vZ z^t`h4Rl!MrKl#2Bv84G8I%F#(>SIJem09C`yYaE;$vAg2EG}o4XqiYn+KJW@hhjJb z)$`Omq0{iX^B1g4Z|guFvGOfsLC1wZ@)K9&)P%!9yxoIj2iVt6C(z9}ir&2w$EhR+ zz5HX}zSj|(>PReEw~r_K@zv#FB_JBnXh0n%42vFI82T`NTfjSirg8V8eoDruxV(hA zA`swkmYTi&ydS@=U5?uxd#T#BUc68vfJ?>5%b6{BiqQMFT~`CiXC`EBoI{$n&Y%(3 zm_F%i_Iv&A1!mN=h+fMAY5VdC0xs84t!aivh6PvP(M$cDX3yrlL$IGnNGu(NdYMvQ z5v53uTPd|Ds>vaSf2+M)z+#!e?TaK-82Zi)b4cJNPota@fGmC+#>lWHUe>1gRVP%T zJX!+d3_ljJ44cROXk^8K@D?K&?pNia<9)1C!R}yk zWl*@9t?4Z4)GqDxmW|d}FlFu(vJJY&3x|)3KwdQ_V#EEY3yWLjQ+NaBp%smtCqs zJoR4a`8KBK#JH`gOwnNz*G-9Un+R)pL)M;F)8%9$nrcI-2WtWm1|0>lbA%6 zam)}5*q)8bH+o&aO0UEvZgwu}WPy%J?2%;asEvhk9)Yr0>9&WBDy^I0z*(HB7T|il zA=T|9_8Mxjh(vSQxQgdBfCpKATq8iDJnf&Gt`YK-ffPH+B)ve>+A})eqM1=&1o%}t zH_=Kx8ii@r{h&u+q7Vuv4>{^L>8yl__xIs$8~;&a7uYjpR3z8%B7(EDq$>AtD#i$S zkyj4I@YH0nWK-Xju68z%RuewJX!-=tWn*1vAo{P=?jwRU z>%tmzvoKG}owstUa%aMkJ+$g@IG^pM`~!P(09g`!zw#FucvIa4Mzi02DYb1#?{aXN z-VrW7oM2N2lFY~}s6I6-uTL(V>aaT3l{(mmWZUYH4Tn5e2$BaLn@42;jny%I+`5;u zd?5@vWR;+DPOiyx1xXnVjJz7}o3n-6f~R|(Xl{vv5s)dIKzrR@mz7R3=>K$|5OG>d zatdu{#k0C|uaSRV%N`uf{n&RodzfZ=U_Yq8dwe^}8|mD(k^ZJ;4?Gw$>O@h$yK5SpLev{p9AvwTH|eUx&+GJiv%=5_@h`{}I7u@x zRBO|!3CcBZk>Bf@WKv(I?{em|jR5Ucy zmWj%6-UjCgfbZlR)Z@&p_w{&V572^WLo0Fmz)}k1j=`Mdou>RaR_kxT`H_9&QGiYz zcHF8wTEH8AvDN9lPg;{kW4MxNR+p-jYsLtAs=08|28m0QRmxJtk=Eg~KGcGULJ)!h zto_jmMElMk49cLSM*tR)JO=U=3{jOQ-9WZRgcU(QAeXo|X7`)3pmLtL^Am$W`|#1S z%s6O}IUtf3V?|&$0>(PBYHvDSiRJd~7#I*|)^Xg#n^fNFe+^0=x6dB^78`Unp_--Y zf0=(P`eg!Z$`kT}SR1>BqKo~zoeM-2|Nf=C-|I{k`>ArJZz(K1-}7ZEd;+j~x|>iF ze(WH5`Ix=Z(gosK#kD{@4d=erNDk}1fNUasqctsRm5C=FaI)0#pz`bWDzk5%7Ucco zufN!?oxyzSlA?<$P^BpS*oF|udbbIMCcPN%!!*~lHKGD zLaeL`?mb%6tVWb>)|R}-IPy#<@m#g-#d$I+N(=F&{qVon*brQX zP6l|nzv^W+Q%=UnIT2ZO7e3wD#o?9Nzl0oL^e~wTlL9Bn#sq;h4b6GNVC6B`HE%IS z^u)9LaLp5v5wNtRQ=m$5@dzq?FE1)z9wGQX15>774Upy9#8yM_iUl~e(IyUIL+Cql z^5`w(>Zc+m1!8;opMKoNiKoUH$LbqRe=6ClwL=g+dHBAJTTxxXi}R+veQ*kKwcM4q zWBP4pi{$Gk2#6V1n;&;ZGscu|cV&;I8?@>D1J>Sha1RC35G$aFmh}zR2&e5B+(&Gx zCK8SS60qU}({a+k->uADu$**B&3LL?IiBG;S~Bm?O5?!rkz8|tC_q%*yha94eiCp} zmB^<$7nKDzaT*ltNXo;po7aQaa@dO&qY`_X>+T?t`1xB}rhT;yi?%t*42Q))LuK9O zYl5r8bi#7E~nf|fCvp{#QL`XI<9&;8J_YSMqt<#jh0Vkn)jZiP~@_F zCAz+JVBjr@g{|ftw4^*hO#|%MCRw&L8>*x|NL4`n>vaJNeArUFF`G ztpKmw&?#fPY(mQN3ui!5j8SOaxr2+6NW?x*% z$FbmO$w794E+;R0y*>}5sG}}!#k(bbxRUN|h zc1LWdYF)*rxj)A}3TtoQ?m)yS^k+gM6ZGIuarV~Sr!U4WQfq`xbvD$!7E^fHooLJ& z(`F@zt()#cuqMbM>3v?YJp7Ssa=A^rgO~a6(_U5Tk0z{vxuJ_qX=&)^u1fICN=N!u zd_56H$M1Q2tjesd2Y9SW8o7sV3GYL#>LoY%$L$Fe9aHau#ku|9C4R4twZPQx-{_Y1 z54c=}kifYN2VznNO7?ggYpx5Be6S^@tRP537Xz0RU2WK5TX1nglWWvl=vbIg(9RhI zB5}Os#JAp^@WEcFp9k}dvr|jsDfQH+`6s3e41jKxMTUik-138Ny}Q7lV^~IoHL7Ik za52d{(}|snjkFM8nR>-g1&^6UodB(!HuK0*?NGKjA;!WtmK9P|^oa}j1Z?K*q8X8U z0^tI0o%lc7Oi@F*O{nGJDHFEw&FV*c-vUcI|7Uu(ntq`Mhi8fT@ADC*x^{jhvkv9e zl)7w32UTYs{;EhQ+6V?L2lm=K9A+g#N``T_w9KE$&D!Z~40^edGP(?qY?3+xL2H(r2G0N#-nCoYYsIHvzgRIm2PKNK{YZC z%V7Q@Y{HVOgz!pSWlZW1txD+w)-5n}6TB6B+*0{0JM`tmJEe0v?bvp^>L(alAF+U& zgzU9IaR4`d{K+MDEqW&$+Z>~F4HjK~U&IsXkYmLY{*bhFpdsjqRMmDhB0*soYY#y~>s`reFw%}9*+vAw{-G+rnc5fb|dzcptBZGi@5 zEmi#D+(QSBwLYIn^DC5^v|RN``Z0)y3LzsC`y3JsJU2biy9E$MBi+y*c`cwR8V1>r zD!r(>FFKp6+BO$6t4woNPoa<`>U0*?g=8k&TcEG^6&u&#n^P?A`=o-&=XxEX|gGtif4y2&8-`Y{?288^bD;_ABH*UO3$?rM1U zGK-OH3@_~*xbaQdE}vkUf%;x1Dny0f4Y1BK(J=NP;E%c52+zP-K1-&R<)oj43|&&~ zK*ni{Wrtx_)~C4_pGlI;7dMc49h^`l8sL)jUXz_N)hV&B%E*3}JJP0^3kC?V6?{pO z5BvLjGyRcLfATwFk4RgUnRdbBm@1XDSp9x;I;-=8 z>A#SMqSGCIW4AnjcgfOP7={T`rWAB9wbe3e-;ygj-RdcM=1sEpT3Ru-qgeWOmASmT z8{K2iYrK35(nd(V%V@kKXQh<^{0szZ43)m(vb2FN^hPl414$ks?gbLH3a)$);k%I( zfSv+LbU>WPA!l>e3?0%v+WEQc6}$YVA6YsXH};_)R(_c@TY=<{_^|jqd$`vIu4MwP zlxc<9@-&vfoOqq)DzrvgXGndRmk&7G&iIz1+WTYM+HszIIL!qUAaU2RBD(a~IEN%F z4DLjl4sPSV_?a*6opu8zw}`abA$5}?&W_}w+Q|L?ih|GmB@OQhET!!#9Lwl4iD0F! zNKDjXwM}BdUcn&zhXz6B(s~xW29yLjn!q0ZSzq&qTk*wjLJoaCYH`R8>O(MBR=;r*q>#N0-BXbF73w@5Yd!FuHN-H5%gg~1_7~f)S%epB<2=tnX5kF^^ zI+#Z_)xJMr7|%kLm!*jiSsZ9S=v#^A2!JjA0oOI;3a(IT;A$tUw+h~&c%~8X;IBSN zEDfE3t*v3ALBMw-K1u@bpdgq6TXdiUY=n2zm|DEpPdYH}RCRv_4}?@8Ys~!|=o{FF zMR`^Wr6nB-l#){XRwUnu0aknOtTjnnO`2VOs*`=7t>3>Bv_5DnH0<|CLgZC6Mq&$C zm|fBf2FcdV1!uxqo`4@C0^Nh~Sn$MgPG}-5SDSo>-RimRzzcgEN2zm&N2bKH_^tqf zU3oSdAf79qsU48#Sx+oxu}z4)RA^(;*bfzoklkA+ z{m6^H0^ZdLLx$TXwsT^2&(3cnLIXOnx`xugE`dR_>yc4>q$8*^W~;vpJW-E<8kdJK z0*ifMSm^mjS2hN3e|gCDvjQR`9ldx&5jLX}+kLGomhISb-JQEm_TX>qjRC)e+}9=z zEp2HmZ(QdY*K1}JlJ1~OV77vGa`91mER2j(%?9Fa&T$ErK!yNGlE29~Erqz0kl*>I z>d6M-e5z3ZpZyY2CrF0{7u=!nz;D`VI z+~y<>PrerkAAZ=}$!KC~@pb;je*GM{_<++ci5#M4=zYk&%>T$w9~t0%8YYdC|2y_^ zTv2^=W_m{+cuX%j7{3wSq*MZu89d_fq%X30u#g2bKT{qW@E?$gja7cO0*q^ljBJG~ zkBitLpf^Y@0`)*K<{u8Bw{Py7FdOR0P&-B8-1tu5{qPhBESi|@S`G97!{4v#;E;tMw^G@Dx~UgQD8gQT2e0oQNz}6V3Fw=Q#<9H~(^eCYX!wSeO8k zKVZ1G2(`@dUY2>m&xq(>4h8MP{=TjUXtOG-OsY7mpVjb%`|U*`%7H%j{V^vtf@;^f zUdNZ7I9>5sR3Heb=1kxYctm6LE=RhS^MZ4f$=0g7`+JZp+)D!R3+}MOk zRJsZ`$XgynaZMEjBM5HlHrK$~q6w%2?fPd-L{K7?-b4%C$=4X{n0hH?q}rc8?5%w7y#n;8UG zw{xK{4=X+&MX9}|t%2^!BhprQ;-ASSek9iU^}N!lXg_-a4PCob-v}pvIl3v)LP-pj zlfzCwK=qMAp|pS};???bpQ(1wet9YwX@FQ;pte|Yq^QtT%83a~u}%4M;w2E`og4!L z`cZ1S5a%hqQ}y*ao7g-SA{RqQgS{e2thy zkN@CgiV?ypb&6tAXb(}yqF9FTrBBeEt5`_qDFv}fPm;U1r&BZccH@8#XTK-Rr*s4k z&w5U}B}pUxOP=&}zDYc8A!70>50iq;L;b}dJ=Zdn+)t@JGAeh7%Fsx(@`Gnn7yZ-XizY4%fZG?{^`?jN zXe+h0YkZoN3(c_0Dj9m!5*4BN^FKRMG^3#Hj|;x?WZ30+rx~A-A&Qxv=3xaKXQJT3 z_Gr%5*^XrT&Z>%Rr$~6?E9xo>w~8n|&N8o7(kI~42R_hqZ)~d3Tn$3IP;sOf@(~0yg@qzjb8_ZiY;SQUz$DF3) zoiB&YQMy1<@jtd89k&G@(o9jdc&%;L$Q4>SMbpS;-Gce?*=)rh0r#Nk{{gHvrVouU1+rKR(t}VOC(j)-TNXZe$CfVO@7h)@vGE5l3@ zA#K1md9_%Zbv~3G7PQ;<2*tDUU^q#J+v`|=$jSK$<*Vi-TX1|l;CMHPCzi8sArWY% za#LOlED}@`=6@c^yeoxzcScK?r|(wFINq)SjH>ot)iRD!f>Ioa{isnsbxsjWr8?WC zT<}NSO#x5(>ILz35KZwXEA9Qgn$bWTzU?nsWs0{}Ax5~1 zz~`Xiojh>IiuC~P!Kz^T)mExgktB*)`WQ}t`DSzLPUhanAf7l93BjPTL%~_wCn)61 zjFB}9dBCcYL_Yk@5v1>ABt0E2sv?R`&-vh5;(2#@h%Tb?w|yqE9_5y;>%*+`2{7)YfK&6vAP^ zoK?0GQ24U_J*!!JmbTQ}lflX(oaD%4_;X2|G>zfy($}Y z)Qvs~L&VaSssCbjfBHhtA_ejPmVdNFPvhlPftn8NJxf0>z4yonOKdYA`{U9ZWXYrs zLcyN#+KXB|PF|H$AP_E6S8zd`4eN+tb(I~}i1g{?2sw*ONmrRiLy>ygiu^^sS;!aD33SiVnME)?d$!k^@okI1%cyp zFhTQd({Up?FUyFHLz-vO)FDrIjiZ1_ZPcbbmQn%rCtjUMnFx7WXzAW*MQ@^f+L3Aw zml0GSsmY^GtJIbR;GV69Yj*ll4vKj5`%4~=mGdzO5}@bVcP)x0KURjF0a<%Ye54f< zMj5j%c5G$NuaV(7q*iY3Q=`cJD9x?>EkUU~K-Drrw4XUsDf~6$gjm~FbZAuP*zGc^ zAvKLkdJ)&F@snV6lKAer(>5f|K3W_#N}+&QEudLy2Kuo|Sf7knT`OFi(FmG%PD#6e z)n>K|kVdi}nsX7CMD$ABusxg|AsHO}z`sk}>5~J5vv~~tE8HJFJF3}2tkxL)r1?7z zLj3PE?q((z2iDsx^G|UH4U!L&m}}aPs8! z-;4kzMc~4KQ-BVywxj86pMiYdR84#Ick*Fgr0nr_Ww?fnUT=Y}Dgfv2@|O?i(CFIe z=&D!1_R5+Gh&Aa#Fc0y$o4BQj5ZAyY~U^NlkQz$zxEHy*1U?g|CH#JgB}&miiU$oCxP1;yLn1=g9i~=Qo9zY+YpcOnG{u|hsXwy|mT7x}wu{fb0f#c&4n=I&KMx7Vevs%f1(5tG= z>+Io?3fMIl^jk6Ut*O3hO={TkQbOaJCiM5@PTzF}kMLTqC(@NE@=^^Xv`wZ^6j`Y=4m0WUNZk0G>M2s`QX6Ah@ist6Ged0$X0njPT zhhSgaC@ma(zx!pW(Yzv)DuUJaO`!0n(HUl~B?2H#`sV07sdet@)__XZB_~Zvj|a=V zHzoy;Zi%zb+2EZ`zl6f9J|&kV|Edilxwg2Pl!thkS7AiCKA4X7|B~8r2K@EOKw&V+ zT+!(>@Z+hhfup`snL0QH4_E5m=#!GMH~L)?0kPU-Q>wXh39JAIl;G^mf*tjYh@Qz6 z9oivUoR!9Ud48)CyxI^ib?=*z`b;cvCJvhgo+Jh zgs=|}WxCW1Qn`}YvM19*$9FU_$0>f)2JYo|_a-iodUtC`D^08oZWEB|T*@zi(u+N-nJ=-L{Dim|b5Aqfn>Uu491_n(%jab|rG#kr5gZn+Ao`Eu zAglS>C(kX`n8?DEM;YI^sDd9`)fh1b6GZ!e`V>B6ma0bMj95;PGR%nFR{N>2YVLq1 z`p+@o8Spe+;dp)5r&j0Ffh1WH)+Sx64y_UZ<{i$biMM{R8knOxovj5$FGkmvJR#8m zhB&uRfEE*0b+R~@fMLTgRpMc@PE&R<&lPXU&5Y!dru|6t=aY)P^_%!q$}O;7HfjVD zycDKz$(5YSF_!8>3PDfGfh62a46I3)aYc~* zlR?~LYZzvg|9M|KxjsP(2D9oIUHvFD%44xnD*wMwopMr-7Km?^DqL+W8dZ}~dAj#K zr@SnW7i4&Vo^0PEodnE31oY&w{ou5u<^O->n_fIq-BoQu10?cxMMnsp6ZQ@3pvQ)y z)>mGrcZGO_%gDJ6HGlFdf4k&a-6q9aN_R3$x$EDqFRAgxt&nYbfju{>vw&2@NJ#B~ zuFxh*m7c6mv~rrWTE$39-kot=#T623UdDq-(5;Ec7|I}5ygXR-fkEf=c%2?ImM`=Z z-FtD9d+q|&!~L37>`V=+3xX`%3iF|$hAtD%O=d4*v+VJ2T?krk^9R%TDS5qT%xZ&6 zVRjoF*du41yVp4no z4SySG?q1sHqH*HA4^4)GMVOd?F&{xfgUd9XsLlTgR^Yhe7GApQN0V@&n;)E^wIr!# zhpt3*tZi~b15PGaGwZj{&yqR*=OA(N4+#a8c!N627JucJ-nP<~Nl3(~Ew(l$m+Q3J zh^cad5Nd~Q?5{gmX@~U2jCt2uFXL9gX>y@W$|{i%X!!6g$$U@cjF^!-9ShmaQHwDt zXKLGsJA#;EOnnoNQDycTvA*;IMz^bIB8?)I(c4_gg<1;43 zxbcdB^|fFe*!=<){wg|pJ2VSEOJ0oA4TgaeBd1R%llb7=L$W3)+>vZT#<^#>F(MG4 z@jUwlX=7_zWO52-tXo}=)v9O_O+Ko_y<3!|Pi67pnbx$bYxgG8Q~=Lz`OH2nBk>1d z59{1=G?O*|oPN(6be1cO5bJ@6*}#vKw+iDP^#CTpPQO%HI6CY}q zhQ>2?|21vB-_`sj>x7?(0z1WFvkm-P?Ei9t2C7(xbYDWXYyvC)EKPy~yUW`HfZI`; z&DNlU7A$E?7o1>trSQAC2&BNFB42(Svve38qv_0iSl(Wgf8n7?G-CB=T^FpJQr3AR zy*aSB4DV!Vk2^jS6Gh9yqJTSPZb752qJy`ao$ZE|S;J~X>hJdlQWheF^%FNC*CN5MUB%WJ8DlruOj?dH2MPC=i`dvuk6~|$_FnZE0idQ`Rw_YgC}w1Qt{@@$LRJ3bKAo#azlHiO zxSG*@h5}0}_%@XunnN0Z7Aelbd`}^k;yN2ye zUIO^RivE4&3preb)!*Ps19Nzyw{J|94`FC${6-B;zf;BkF^{$*(+5D%m1HD~FG8Pa z?*;|vGP{(i(}%-xKbLaqK1mCs%rsv%SM8iH_>(q-)3ozr z?^`P~E<#u-!!`glgiFxE>239`xRWWC{Gee&|z!2T5ra38*~{uqAd3vFw+Jc6MhQ9e9Un9s1gTr@z9}&faN09@^@fN(8l)j& zU4nd}sc=P%Pq+6a!6T#Jm5Mpoq<{rD53C|qlv3?b$@0|&3jyZ_SKoJLFIga6m5`Niz;4DHfyDKL_vhueXh zMzbnj@$!3m35ldxr8m}8y&3)E=#8e>(8bHFK8@@b=KDg442lf{LP}sQt^!Is+C?LRvoVl-!iBeoq;hhIEmp_g z4At5!sw`s}^ywype6rxM<+BMCr{;rCa5a0Pf7HOx=r5Tmof{KIi(MYzm*|x|V1aHHq0*mXhWd6e$m<-H+AC%o_ggEXz zpNp)gMBymE!_#aAAa?V8Im9m(=9dY}Cpy2AjAeO_b00CHQ4lxu!0>iBA(PIEO$^J~ z#t~yv5*;dKDN@q2$T9GAcW;6d4p*CAD){ zQx)1ba!ARSA>hZCRoB?@bq|33SwfFyy#XpM*R)#82Fb*n`Z2^TN>WdqJNjHCZGt=< zGpXL?B<(TcA%&>tJzdqKt&Nx>O`i{}o^Z}S&N*nk||x2q+k-w5q% zv&Vo0hhIaC1#c}>KRnm_)oSnw?LzLuSTFddOZA6=r+9y_6B-+&_`fJJ84#abpUlELDNdw;wKLQBtOoFk%B_;%pD8L%d0u z@kz47(GzJ5&GR~2K$UoRb_gIizP^FF0F!oP@k|JxO~b9z3EWg@=AwNFvbi-zj|7* zR{uOYT!pS;TFdZR0Sjm04x@zQa;w;lluyX(L;08qbdjh5`39w;i{z90_OQ(F0&(J= z9$~=n2{!v8Ad=naZN1zK(O{7A?=W>bc;Uska}O+AVCf+yjt2%wKY8RWYv8dAxcRu| z7FH&Kz5n;GK^R`V;vmNuAKAkgfTs{ThOMmL82VO_9gp&rPDyqJ?_`5dm8DDMcTn!Y z$XMnIBc&L9XFa!#)2d&G1W9*@%wz((sbRZzr&^smg;b&T)DXeEMVXTr-;gg=V1*09 z$lzT0>Niyr8OabL+ji~DIF5C4xpy_B$KR5xx<=wXVA{bxsP9l;uFkRp>UP?g`be#Z zjH$TGub83c#l+e%kl&ZF*XGGuU9z`;m$@ZG%KI5PInO(}28@g@r{5Z+0nj4s9Y;=9 zQ)gEIFKgv~jh;RKc)3(-WLxm{Op?D#RgIO{r0p5y^`pk=i6X|??Cw(fj-bS80(qv6V~Jrgh_U7Z!$|+q+QaA7Iu3su^jgnIQisN2Vcc8a))Z)f(po zjD6|+$^Eo0>}rUcD3Sd;DKn4 ze>bpoD6I2V-x)mabrUJ;7{L(1L@3iC`tR9)L@cl6i*43_GxS}q4z8u|#O?3;E816M z-qQ?;kAwEG6Vk;l+vP`{8<(`D8NzmBuQt~%$92rn0M@D*Ah(9@cs67?X$X4#Sm>+i zazFqbXEjIh3>1g~F!mKQc^^Z?7j{ZynFB&Wk#*xAF|Xy(hb51QY8~p;eaSI4Bn^sQ ze9a(Kk3EC7`PZM5^Tt#=>0I_S`7|vtoC!0T&=03%22}%iRN2SEE2&|ypY{{Fa=z8+ zXv7)+ZxrPh;@es7DZU}S&s?(mag*hlTUTPq4t8PMzb(_{td#6*7krgQ>ibDE|XcS)KSqu zk0IbHfIja_qAl>gVe;*mr*&*L+Z%7aBi8OU*wd>+cZC?5za_4>baoJpH?h_p2JxN* z*{A)x$mC<92D%ur&z3s&1xpRQq*_N3*VspEGo7+|qKtz6lcln>)9yFDL!)}C713e` zytdm-36chlEU+et>#dc~OV<$fXaGAv#J~2cZtPf5D`1%h^p^1d1QhT#AG7InuJ$<4fujX6vX=--Q!OJmx4j>O9heRzSOJ(&gxVBhzH>?K(2sV0{ z-{Pxcp5eT6(6eDFT9C0=Cz{J$0ZJk$CI4FO?}oc{*$3J%UC~sI=ud>3thPz^zCAKS zS!jotf!>&d;DE-YyU=T-i_5e|z67jxpK@)JO|Dk79{vz=9)YxT+}JHum-;||5Oqwy z^4NV7Fl02+aDL}Js&+dS^%}P$D<92cx1({q6aZS51JkW@m z18ii7s+$pofTt4xjXxx|?^*xPg|F^Wg`_!mX_FE&UVorTdj9mlN2aa*(!hULi*&K^PBSH%3PlZ4H#xEb)9w5r6^Vg*`fFrRS@(MRRnlKhRp>rkdag%Isy zergN2}1 zQ*jwYeC*JQhRj1`r9)U`(0jPwCsi8KJ{ZSYxV9iuBwajJ+s1Qv2y>o)H!Sdduko1valOnNeLR92eEl z@y%Fek}9zVXzr&qbNhMp;)TmwnSd@;MQZECONcvwc2{ zDx#~YyNne{2wzYc(M)t4t(K&T2+ez*FUKcnseT7akz{=4l=wjhErITcZ|C=mEPAHl zLVyfS6tjT1i|V{wND>n!=OUX-|6ulrbnL?BK^*b*mJOD(RTz9%yR{%Yx@0#0vE++o ze_0^f=k=1b6$k6(zq*$9!HPy{B7>=r-Y-jj%cEuJ3qSM#DpN;(5@AW)I|$@s1Z<4H z9rSMcdbO$r84f5yCGEriFs84#v)>3RQ7UgtdWdmRgzsnqXe*9wPm22o(@fy3N6E?8 zqO_+|N(ek*FDic~W@V6miRKy|OMOz{Bvxa5t89D7o`D)rEHj#YT-+_Mh9hAvLeSS{ zG)vkc3R2NCy3wNcDKu4myz{W)r}YnX<|R~fC0vn@4;@so)d;Jj2Eh;qX}9wAkU)oi zZOWx*Y4FPq(PjHW&SD2$3;#%>HG?JxYtp%M!Qb0WHlV=igiLPG6;OSyM_IvRw!wNCKM_Bk z^?WFc@~Kk|uda%X(feI$-QN8@O)hb zW64sM9(`YAQhsHf-7E(CNI)Ys9Nv{B;*_4xE{~NP3B2!_Kck=aB9nyZ$z}kn z)B#MhR{K+&tEodM@h>&{i6Y;zXdEDcuzK|1OvL3?tyEW za9P(EA6x{>3u&Au12TvH!zD@`&2G}*STo-Lb6*8fQ+9d=mW8&hCtlrDiek%)G#;jl z&K)TYY(PAEbI(z<3e~!Bi{IYeC=0A=!9sT zeg=k(r%?-+3t^0-3o#Zc-;4PObR$EPCy|?!^2en~C7`KNwbFQF+7B=}yx%P8I#lU7uzgU+Kl5SZ(0G;h@a;#}0$`2t>o_*7tJQ3=<_ zkLMCLq`plevg-JIqlRX}s*qf9KdcVIhxhobxc*O;RbQpd>(3LT2xCs@CQcK^N4V!A z)oN|-!pdmpakXMKi-2l^3vai|pVr>+>PikR;F*elBF%O|>#3GBPqGzYrCplIn=vL& z2|p_3###!WQ&D2DZYfF+78nMtLEj1FSjd1Ox4dSCbI_{rqVj{*QaV zn%j~X(A%iek0(XP6+DRH3 zVZ3}#b-cVLFXIF5a)Au9gxX2!hkD4-yJYq0HZ&lU*;bF`IdJ7wC%l`1d4DYoMnNdy zUw*wBXQ_79o1K;u<7o)JvLXrpyZoh91?}dQLaw8Q+oT?L%N zch_?YAL}q3d9-`!3~Zs6Qp=)6C6BrHJ6z3solj2@4!8%H9Ym8_M92cuqXcP(gPyEq z!=mVV+JU??uAq;=g{uA!hECi8IrI7ND_nmP6F z0~;@C;|p_Ma4;KCj=ndJzxbsX9f}O*6kHO{D}ZSZsG8{1?G+fLjXXjLk;c#Fmsb=^ z^ei&6yy8nbp`bT{H~*&e!BIqR!ON+CJHDUSS?7!i z#K>hlL-k-)q5bXLZ=xG~sFm)e@qU59nj>`=$XACT*+)idYA;G8pZ5zZbHcTV+dj@E zZg1o;9ZUW&4J0Wx1p^N`o?BxspTGuzYgA|G0{ON|U&|k#ii~Q1OVna^{u_ z$1FKU(Xq`1GxjDyU^t5Z7$s<+sG7|@?&$&0vM8uJW;p<}gh4f79MohjxH#223End? zd31geVP8Fh(-$9S(F0My>UB)1v@`8U3u6o}E?eX)VN%FGSuBg-#p6{8TY89dfNQE1 zNhAK7wOXT<`ASV&keWs5-(pLQ6jq;zd{j}RWb=RYh|CnBMTOT2+ntYZsAR!5FAi~g zjn9r~VeydDD=ZEq`+@=*TXVytEM6jE@(dH!p~5ZA zDwFL;_O-M7eWZ6iE5$IjOWe|2Iv*P5tS)1QHn~8MQc(0`>jfjoIRhA~HP9?mdy;VA zHTcvGCg|ND`ikFf|M^RMhc}Oq$TIuc`fIjxDXOK6Qs8}@ZW&m#1wYHCun!=Hh||!J zvMB%{iB+(?wha7(tQq0kZ%UjQEk%xs=#5Tee~vr+@zTRNaMcqbLJkZjQt@+GBbxnn z(A%z?p!xIZg7BrBeBvMVcZV`xj(46N6A$k&Gu^K$Y+}+R++wam0B14zI-2dmZJ#-~ zQ|R_oAlD|Ly+zTbFR$9u;{JKG6|^r9JGI_9m;tKXEjCRw)JUG;#e9UIiog94B~{}% zK-+1Peq1zd2URsv?mm%?!@;>E>Z=gP81dBjw^%_gul{=hG}#^Ge!{dXLgeIkQl(yE zmue--C@D^BpdZE$7=qEa%%aXtttly>xGtpuB4a%9*bPP0<<;Qi``cfY6zkiozA^i% zYT+BM%4<3KdCBjgSj(%Otq8op`sSR2_kO+8#9xO5ah2&~J)cWY81r9L2)8=}U{IJv z3Ert{O7rR#;4HZhlQ=z#@S`w;a^j0Sc>$f>3Xj&;)0OknRQ|q%6SB5jA89azUqPnb znn=d~J8y43I5M!yQ4jIyrWMWR0_yawSIiB2?SYQV4@3Qjc7@VH+x`-F6JmsyENuqs zBwAK8&T=DZO3N!VE}K;KY@T1q;CoCiG-WvwAsm{XVESuHH`Mgtmr1Gpoc=t6MHKz> zes7|c>Tav82hI|#5y%5aTB^`dC=P^!`czp`&{6dYE_{pMJjmZ{t;HM=X zbc*{&d! zkvPR<=>pWKyMwD!wdDO#fWn#L^`6pQS~-J@078vf&63Qt<~JcHv?pljCfSx0h_spmFsP@frA2GzvMC1lWflbP81eTL7e(lDYlgp z2e7Pk@meu>-xAX_w=gzva^SD0DJuCpQ5a||;I~*2EkQ4o_BrM;wfpDc4A+l~ZXd<+ z>{@@0vqa!?V=V3qe_W?1>iz>lLS$?OLV>?n(kBD=LJ==1E|g4YDF}a03iH8yijC$2 z@*36-Obo!tNd70@5$L5U{Oq2wJPo^?M}mOU_HSw;L1KP9-C^^)%(6(?8MD5Z*fr5= zVSlyr?iO*b#AT@xjAU{+!vvtAkhUL6&VSSv3h4=Y

    *E%0;c5IUTNlCw>Z4|7Iwu~*@3s` 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 literal 0 HcmV?d00001 diff --git a/test/sharness/t0054-dag-car-import-export.sh b/test/sharness/t0054-dag-car-import-export.sh index d40dd666fe3..2a92309f25a 100755 --- a/test/sharness/t0054-dag-car-import-export.sh +++ b/test/sharness/t0054-dag-car-import-export.sh @@ -4,22 +4,171 @@ test_description="Test car file import/export functionality" . lib/test-lib.sh +export -f ipfsi +set -o pipefail + +tar -C ../t0054-dag-car-import-export-data/ --strip-components=1 -Jxf ../t0054-dag-car-import-export-data/test_dataset_car_v0.tar.xz + +reset_blockstore() { + node=$1 + ipfsi $1 pin ls --quiet --type=recursive | ipfsi $1 pin rm &>/dev/null + ipfsi $1 repo gc &>/dev/null + + test_expect_success "pinlist empty" ' + test -z "$( ipfsi $1 pin ls )" + ' + test_expect_success "nothing left to gc" ' + test -z "$( ipfsi $1 repo gc )" + ' +} + +# hammer with concurrent gc to ensure nothing clashes +do_import() { + node=$1; shift + + bash -c "while [[ -e spin.gc ]]; do ipfsi $node repo gc >>gc_out 2>&1; done" & gc1_pid=$! + bash -c "while [[ -e spin.gc ]]; do ipfsi $node repo gc >>gc_out 2>&1; done" & gc2_pid=$! + + ipfsi $node dag import "$@" + + rm spin.gc + wait $gc1_pid + wait $gc2_pid +} + +run_online_imp_exp_tests() { + + reset_blockstore 0 + reset_blockstore 1 + + echo -e "Pinned root\tbafkqaaa\tsuccess (root specified in .car header without available data)" > basic_import_expected + echo -e "Pinned root\tbafy2bzaceaxm23epjsmh75yvzcecsrbavlmkcxnva66bkdebdcnyw3bjrc74u\tsuccess" >> basic_import_expected + echo -e "Pinned root\tbafy2bzaced4ueelaegfs5fqu4tzsh6ywbbpfk3cxppupmxfdhbpbhzawfw5oy\tsuccess" >> basic_import_expected + + touch spin.gc + test_expect_success "basic import" ' + do_import 0 \ + ../t0054-dag-car-import-export-data/combined_naked_roots_genesis_and_128.car \ + ../t0054-dag-car-import-export-data/lotus_testnet_export_128_shuffled_nulroot.car \ + ../t0054-dag-car-import-export-data/lotus_devnet_genesis_shuffled_nulroot.car \ + | sort > basic_import_actual + ' + + # FIXME - the fact we reliably fail this is indicative of some sort of race... + test_expect_failure "concurrent GC did not manage to find anything" ' + ! [[ -s gc_out ]] + ' + test_expect_success "basic import output as expected" ' + test_cmp basic_import_expected basic_import_actual + ' + + reset_blockstore 0 + reset_blockstore 1 + + mkfifo pipe_testnet + mkfifo pipe_devnet + + # test that ipfs correctly opens both pipes and deleting them doesn't interfere with cleanup + bash -c ' + sleep 1 + cat ../t0054-dag-car-import-export-data/lotus_testnet_export_128_shuffled_nulroot.car > pipe_testnet & cat1_pid=$! + cat ../t0054-dag-car-import-export-data/lotus_devnet_genesis_shuffled_nulroot.car > pipe_devnet & cat2_pid=$! + + rm pipe_testnet pipe_devnet + + # extra safety valve to kill the cat processes in case something goes wrong + bash -c "sleep 60; kill $cat1_pid $cat2_pid 2>/dev/null" & + ' & + + touch spin.gc + test_expect_success "fifo import" ' + do_import 0 \ + pipe_testnet \ + pipe_devnet \ + ../t0054-dag-car-import-export-data/combined_naked_roots_genesis_and_128.car \ + | sort > basic_fifo_import_actual + ' + # FIXME - the fact we reliably fail this is indicative of some sort of race... + test_expect_failure "concurrent GC did not manage to grab anything" ' + ! [[ -s gc_out ]] + ' + + test_expect_success "fifo-import output as expected" ' + test_cmp basic_import_expected basic_fifo_import_actual + ' + + test_expect_success "fifos no longer present" ' + ! [[ -e pipe_testnet ]] && ! [[ -e pipe_devnet ]] + ' +} + + +test_expect_success "set up testbed" ' + iptb testbed create -type localipfs -count 2 -force -init +' +startup_cluster 2 + +run_online_imp_exp_tests + +test_expect_success "shut down nodes" ' + iptb stop && iptb_wait_stop +' + + +# We want to just init the repo, without using a daemon for stuff below test_init_ipfs -echo "Error: merkledag: not found (currently offline, perhaps retry after attaching to the network)" > offline_fetch_error_expected +test_expect_success "basic offline export of 'getting started' dag works" ' + ipfs dag export QmS4ustL54uo8FzR9455qaxZwuMiUhyvMcX9Ba8nUH4uVv >/dev/null +' + +echo "Error: merkledag: not found (currently offline, perhaps retry after attaching to the network)" > offline_fetch_error_expected test_expect_success "basic offline export of nonexistent cid" ' - ! ipfs dag export QmYwAPJXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 2> offline_fetch_error_actual + ! ipfs dag export QmYwAPJXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 2> offline_fetch_error_actual >/dev/null ' - test_expect_success "correct error" ' test_cmp offline_fetch_error_expected offline_fetch_error_actual ' -test_expect_success "basic offline export of 'getting started' dag" ' - ipfs dag export QmS4ustL54uo8FzR9455qaxZwuMiUhyvMcX9Ba8nUH4uVv >/dev/null + +cat >multiroot_import_expected < multiroot_import_actual +' +test_expect_success "multiroot import expected output" ' + test_cmp multiroot_import_expected multiroot_import_actual +' + + +test_expect_success "pin-less import works" ' + ipfs dag import --enc=json --pin-roots=false \ + ../t0054-dag-car-import-export-data/lotus_devnet_genesis.car \ + ../t0054-dag-car-import-export-data/lotus_testnet_export_128.car \ + > no-pin_import_actual +' +test_expect_success "expected silence on --pin-roots=false" ' + ! [[ -s no-pin_import_actual ]] ' + +cat >naked_root_import_expected < naked_root_import_actual +' +test_expect_success "naked root import expected output" ' + test_cmp naked_root_import_expected naked_root_import_actual +' + + test_done From fbe40883e6cd7aa7e8bc890fd54f541ce896803b Mon Sep 17 00:00:00 2001 From: Peter Rabbitson Date: Wed, 8 Apr 2020 23:26:19 +0200 Subject: [PATCH 578/671] Remove PresentInImport tracking as per conversation --- core/commands/dag/dag.go | 26 ++++++-------------- test/sharness/t0054-dag-car-import-export.sh | 20 +++++++-------- 2 files changed, 17 insertions(+), 29 deletions(-) diff --git a/core/commands/dag/dag.go b/core/commands/dag/dag.go index 34ea70917a5..88f6ebadc9d 100644 --- a/core/commands/dag/dag.go +++ b/core/commands/dag/dag.go @@ -73,9 +73,8 @@ type CarImportOutput struct { Root RootMeta } type RootMeta struct { - Cid cid.Cid - PresentInImport bool - PinErrorMsg string + Cid cid.Cid + PinErrorMsg string } var DagPutCmd = &cmds.Command{ @@ -274,7 +273,7 @@ var DagResolveCmd = &cmds.Command{ } type importResult struct { - roots map[cid.Cid]bool + roots map[cid.Cid]struct{} err error } @@ -361,7 +360,7 @@ Maximum supported CAR version: 1 if doPinRoots { var failedPins int - for c, seen := range roots { + for c := range roots { // We need to re-retrieve a block, convert it to ipld, and feed it // to the Pinning interface, sigh... @@ -379,7 +378,7 @@ Maximum supported CAR version: 1 // // if err := api.Pin().Add(req.Context, rp, options.Pin.Recursive(true)); err != nil { - ret := RootMeta{Cid: c, PresentInImport: seen} + ret := RootMeta{Cid: c} if block, err := node.Blockstore.Get(c); err != nil { ret.PinErrorMsg = err.Error() @@ -430,10 +429,6 @@ Maximum supported CAR version: 1 event.Root.PinErrorMsg = "success" } - if !event.Root.PresentInImport { - event.Root.PinErrorMsg += " (root specified in .car header without available data)" - } - _, err = fmt.Fprintf( w, "Pinned root\t%s\t%s\n", @@ -452,7 +447,7 @@ func importWorker(req *cmds.Request, re cmds.ResponseEmitter, api iface.CoreAPI, // similar to pinner.Pin/pinner.Flush batch := ipld.NewBatch(req.Context, api.Dag()) - roots := make(map[cid.Cid]bool) + roots := make(map[cid.Cid]struct{}) it := req.Files.Entries() for it.Next() { @@ -483,9 +478,7 @@ func importWorker(req *cmds.Request, re cmds.ResponseEmitter, api iface.CoreAPI, } for _, c := range car.Header.Roots { - if _, exists := roots[c]; !exists { - roots[c] = false - } + roots[c] = struct{}{} } for { @@ -505,11 +498,6 @@ func importWorker(req *cmds.Request, re cmds.ResponseEmitter, api iface.CoreAPI, if err := batch.Add(req.Context, nd); err != nil { return err } - - // encountered something known to be a root, for the first time - if seen, exists := roots[nd.Cid()]; exists && !seen { - roots[nd.Cid()] = true - } } return nil diff --git a/test/sharness/t0054-dag-car-import-export.sh b/test/sharness/t0054-dag-car-import-export.sh index 2a92309f25a..4bd37f19cea 100755 --- a/test/sharness/t0054-dag-car-import-export.sh +++ b/test/sharness/t0054-dag-car-import-export.sh @@ -42,7 +42,7 @@ run_online_imp_exp_tests() { reset_blockstore 0 reset_blockstore 1 - echo -e "Pinned root\tbafkqaaa\tsuccess (root specified in .car header without available data)" > basic_import_expected + echo -e "Pinned root\tbafkqaaa\tsuccess" > basic_import_expected echo -e "Pinned root\tbafy2bzaceaxm23epjsmh75yvzcecsrbavlmkcxnva66bkdebdcnyw3bjrc74u\tsuccess" >> basic_import_expected echo -e "Pinned root\tbafy2bzaced4ueelaegfs5fqu4tzsh6ywbbpfk3cxppupmxfdhbpbhzawfw5oy\tsuccess" >> basic_import_expected @@ -55,8 +55,8 @@ run_online_imp_exp_tests() { | sort > basic_import_actual ' - # FIXME - the fact we reliably fail this is indicative of some sort of race... - test_expect_failure "concurrent GC did not manage to find anything" ' + # FIXME - positive-test the lack of output when https://github.com/ipfs/go-ipfs/issues/7121 is addressed + test_expect_failure "concurrent GC did not manage to grab anything and remained silent" ' ! [[ -s gc_out ]] ' test_expect_success "basic import output as expected" ' @@ -89,8 +89,8 @@ run_online_imp_exp_tests() { ../t0054-dag-car-import-export-data/combined_naked_roots_genesis_and_128.car \ | sort > basic_fifo_import_actual ' - # FIXME - the fact we reliably fail this is indicative of some sort of race... - test_expect_failure "concurrent GC did not manage to grab anything" ' + # FIXME - positive-test the lack of output when https://github.com/ipfs/go-ipfs/issues/7121 is addressed + test_expect_failure "concurrent GC did not manage to grab anything and remained silent" ' ! [[ -s gc_out ]] ' @@ -135,9 +135,9 @@ test_expect_success "correct error" ' cat >multiroot_import_expected < multiroot_import_actual @@ -159,8 +159,8 @@ test_expect_success "expected silence on --pin-roots=false" ' cat >naked_root_import_expected < Date: Wed, 8 Apr 2020 23:29:45 +0200 Subject: [PATCH 579/671] Harden test - no -z in busybox --- test/sharness/t0054-dag-car-import-export.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/sharness/t0054-dag-car-import-export.sh b/test/sharness/t0054-dag-car-import-export.sh index 4bd37f19cea..1f6016236e2 100755 --- a/test/sharness/t0054-dag-car-import-export.sh +++ b/test/sharness/t0054-dag-car-import-export.sh @@ -16,10 +16,10 @@ reset_blockstore() { ipfsi $1 repo gc &>/dev/null test_expect_success "pinlist empty" ' - test -z "$( ipfsi $1 pin ls )" + [ "$( ipfsi $1 pin ls )" = "" ] ' test_expect_success "nothing left to gc" ' - test -z "$( ipfsi $1 repo gc )" + [ "$( ipfsi $1 repo gc )" = "" ] ' } @@ -33,8 +33,8 @@ do_import() { ipfsi $node dag import "$@" rm spin.gc - wait $gc1_pid - wait $gc2_pid + sleep 3 + kill $gc1_pid $gc2_pid } run_online_imp_exp_tests() { From a903e23ab9917cf7ca9f6d74faf8e64451d66611 Mon Sep 17 00:00:00 2001 From: Peter Rabbitson Date: Wed, 8 Apr 2020 23:39:39 +0200 Subject: [PATCH 580/671] We are running under set -e :picard-facepalm: --- test/sharness/t0054-dag-car-import-export.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/sharness/t0054-dag-car-import-export.sh b/test/sharness/t0054-dag-car-import-export.sh index 1f6016236e2..33652b2aa6f 100755 --- a/test/sharness/t0054-dag-car-import-export.sh +++ b/test/sharness/t0054-dag-car-import-export.sh @@ -32,9 +32,9 @@ do_import() { ipfsi $node dag import "$@" - rm spin.gc + rm -f spin.gc || true sleep 3 - kill $gc1_pid $gc2_pid + kill $gc1_pid $gc2_pid || true } run_online_imp_exp_tests() { From 791156e734c5f135e4d8f22b37526012747f515a Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 8 Apr 2020 20:10:32 -0700 Subject: [PATCH 581/671] chore(dep): update quic and kad-dht * QUIC: update to a new protocol version * DHT: add some extra checks --- go.mod | 6 +-- go.sum | 144 +++++++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 128 insertions(+), 22 deletions(-) diff --git a/go.mod b/go.mod index a6d52b0cfab..747c0c74674 100644 --- a/go.mod +++ b/go.mod @@ -66,14 +66,14 @@ require ( github.com/libp2p/go-libp2p-core v0.5.1 github.com/libp2p/go-libp2p-discovery v0.3.0 github.com/libp2p/go-libp2p-http v0.1.5 - github.com/libp2p/go-libp2p-kad-dht v0.6.1 + github.com/libp2p/go-libp2p-kad-dht v0.6.2 github.com/libp2p/go-libp2p-kbucket v0.3.3 github.com/libp2p/go-libp2p-loggables v0.1.0 github.com/libp2p/go-libp2p-mplex v0.2.3 github.com/libp2p/go-libp2p-peerstore v0.2.3 github.com/libp2p/go-libp2p-pubsub v0.2.6 github.com/libp2p/go-libp2p-pubsub-router v0.2.1 - github.com/libp2p/go-libp2p-quic-transport v0.2.4-0.20200228032821-6d8b0e775c52 + github.com/libp2p/go-libp2p-quic-transport v0.3.3 github.com/libp2p/go-libp2p-record v0.1.2 github.com/libp2p/go-libp2p-routing-helpers v0.2.0 github.com/libp2p/go-libp2p-secio v0.2.2 @@ -101,7 +101,7 @@ require ( github.com/whyrusleeping/tar-utils v0.0.0-20180509141711-8c6c8ba81d5c go.uber.org/fx v1.11.0 golang.org/x/crypto v0.0.0-20200406173513-056763e48d71 - golang.org/x/sys v0.0.0-20200406155108-e3b113bbe6a4 + golang.org/x/sys v0.0.0-20200408040146-ea54a3c99b9b gopkg.in/cheggaaa/pb.v1 v1.0.28 ) diff --git a/go.sum b/go.sum index 7d836da7f6d..554336f8e71 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,14 @@ bazil.org/fuse v0.0.0-20200117225306-7b5117fecadc h1:utDghgcjE8u+EBjHOgYT+dJPcnDF05KqWMBcjuJy510= bazil.org/fuse v0.0.0-20200117225306-7b5117fecadc/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo= +dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= +dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= +dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= +dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= +git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIoKjsnZuH8vjyaysT/ses3EvZeaV/1UkF2M= @@ -21,6 +29,7 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -28,6 +37,7 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= github.com/bren2010/proquint v0.0.0-20160323162903-38337c27106d h1:QgeLLoPD3kRVmeu/1al9iIpIANMi9O1zXFm8BnYGCJg= github.com/bren2010/proquint v0.0.0-20160323162903-38337c27106d/go.mod h1:Jbj8eKecMNwf0KFI75skSUZqMB4UCRcndUScVBTWyUI= github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= @@ -46,6 +56,7 @@ github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVa github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= @@ -61,6 +72,8 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee github.com/coreos/go-semver v0.2.1-0.20180108230905-e214231b295a/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d h1:t5Wuyh53qYyg9eqn4BbnlIT+vmhyww0TatL+zT3uWgI= +github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.0.0 h1:XJIw/+VlJ+87J+doOxznsAWIdmWuViOVhkQamW5YV28= github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= @@ -95,14 +108,20 @@ github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5/go.mod h1:Jp github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fd/go-nat v1.0.0/go.mod h1:BTBu/CKvMmOMUPkKVef1pngt2WFH/lg7E6yQnulfp6E= +github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= +github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-bindata/go-bindata/v3 v3.1.3 h1:F0nVttLC3ws0ojc7p60veTurcOm//D4QBODNM7EGrCI= github.com/go-bindata/go-bindata/v3 v3.1.3/go.mod h1:1/zrpXsLD8YDIbhZRqXzm1Ghc7NhEvIN9+Z6R5/xH4I= github.com/go-check/check v0.0.0-20180628173108-788fd7840127 h1:0gkP6mzaMqkmpcJYCFOLkIBwI7xFExG03bbkOkCvUPI= github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= +github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= @@ -118,9 +137,12 @@ github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.4.0 h1:Rd1kQnQu0Hq3qvJppYSG0HtP+f5LPPUiDswTLiEegLg= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -128,6 +150,7 @@ github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -135,12 +158,18 @@ github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gopacket v1.1.17 h1:rMrlX2ZY2UbvT+sdz3+6J+pp2z+msCq9MxTU6ymxbBY= github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= +github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c h1:7lF+Vz0LqiRidnzC1Oq86fpX1q/iEv2KJdrCtttYjT4= github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= @@ -149,6 +178,8 @@ github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvK github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU= github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= github.com/gxed/pubsub v0.0.0-20180201040156-26ebdf44f824/go.mod h1:OiEWyHgK+CWrmOlVquHaIK1vhpUJydC9m0Je6mhaiNE= @@ -387,11 +418,13 @@ github.com/jbenet/goprocess v0.1.3 h1:YKyIEECS/XvcfHtBzxtjBBbWK+MbvA6dG8ASiqwvr1 github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0o= github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= +github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= @@ -413,6 +446,7 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/libp2p/go-addr-util v0.0.1 h1:TpTQm9cXVRVSKsYbgQ7GKc3KbbHVTnbostgGaDEP+88= @@ -515,8 +549,8 @@ github.com/libp2p/go-libp2p-interface-connmgr v0.0.1/go.mod h1:GarlRLH0LdeWcLnYM 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.6.1 h1:ijPmjn6arIzxaIsX9MsnA3yfm3QgS4fNlWxd7cgYeZ4= -github.com/libp2p/go-libp2p-kad-dht v0.6.1/go.mod h1:tQM3dloie3MUDj2Cam13H4Lwq/piSxY+HLQshOOrngg= +github.com/libp2p/go-libp2p-kad-dht v0.6.2 h1:ZKXN7iqjIGC3+z4MKoBoyOGq6zvJ294J/tAA7LfihV0= +github.com/libp2p/go-libp2p-kad-dht v0.6.2/go.mod h1:LzZi6RR6NrgfFboyk03I5Yzg1Rr4eoQictDXpKpI45c= github.com/libp2p/go-libp2p-kbucket v0.3.3 h1:V2Zwv6QnCK6Who0iiJW2eUKwdlTYGJ2HnLViaolDOcs= github.com/libp2p/go-libp2p-kbucket v0.3.3/go.mod h1:IWFdYRBOYzaLEHnvrfzEkr+UcuveCXIoeO8QeFZSI6A= github.com/libp2p/go-libp2p-loggables v0.0.1/go.mod h1:lDipDlBNYbpyqyPX/KcoO+eq0sJYEVR2JgOexcivchg= @@ -573,8 +607,8 @@ github.com/libp2p/go-libp2p-pubsub v0.2.6 h1:ypZaukCFrtD8cNeeb9nnWG4MD2Y1T0p22aQ github.com/libp2p/go-libp2p-pubsub v0.2.6/go.mod h1:5jEp7R3ItQ0pgcEMrPZYE9DQTg/H3CTc7Mu1j2G4Y5o= github.com/libp2p/go-libp2p-pubsub-router v0.2.1 h1:F5JYaHQuuMKVbSgLsH2POQwT1rloWpc7fUCOq6PBjyE= github.com/libp2p/go-libp2p-pubsub-router v0.2.1/go.mod h1:cl46APmxgKgzgpCGFb8Ns7++cqnJ29CxESXCQATp55k= -github.com/libp2p/go-libp2p-quic-transport v0.2.4-0.20200228032821-6d8b0e775c52 h1:2rpnIL9nXtYVX17Z4mjZYghCRcuU41bdVcBHeEEOoHA= -github.com/libp2p/go-libp2p-quic-transport v0.2.4-0.20200228032821-6d8b0e775c52/go.mod h1:X6hcn1DQ72RXa/LSWTSoWyCc30beTpHdjoiEkI5Ls20= +github.com/libp2p/go-libp2p-quic-transport v0.3.3 h1:A920y1nion8PkGKsEnMiho+3OHpXUqfy35YnPfta4aI= +github.com/libp2p/go-libp2p-quic-transport v0.3.3/go.mod h1:DqzycUAZfeuritygmSOh3kPrs/Cqvc0V1uGkoCEGUXI= github.com/libp2p/go-libp2p-record v0.0.1/go.mod h1:grzqg263Rug/sRex85QrDOLntdFAymLDLm7lxMgU79Q= github.com/libp2p/go-libp2p-record v0.1.0/go.mod h1:ujNc8iuE5dlKWVy6wuL6dd58t0n7xI4hAIl8pE6wu5Q= github.com/libp2p/go-libp2p-record v0.1.2 h1:M50VKzWnmUrk/M5/Dz99qO9Xh4vs8ijsK+7HkJvRP+0= @@ -704,16 +738,16 @@ github.com/libp2p/go-yamux v1.3.3 h1:mWuzZRCAeTBFdynLlsYgA/EIeMOLr8XY04wa52NRhsE github.com/libp2p/go-yamux v1.3.3/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= github.com/libp2p/go-yamux v1.3.5 h1:ibuz4naPAully0pN6J/kmUARiqLpnDQIzI/8GCOrljg= github.com/libp2p/go-yamux v1.3.5/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= -github.com/lucas-clemente/quic-go v0.14.4 h1:LdXgELrB93kvTqbZyEf+mcsGvmyE+EHsLFz1dqbR5PI= -github.com/lucas-clemente/quic-go v0.14.4/go.mod h1:Vn3/Fb0/77b02SGhQk36KzOUmXgVpFfizUfW5WMaqyU= +github.com/lucas-clemente/quic-go v0.15.3 h1:i6n4Jr7673z9TlurAjc87+GlE/BN10++r9XZIPS9j6I= +github.com/lucas-clemente/quic-go v0.15.3/go.mod h1:oj40DjNLuNugvtXWg4PwaYgv7tAbzAabrT57CC69EhI= +github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329 h1:2gxZ0XQIU/5z3Z3bUBu+FXuk2pFbkN6tcwi/pjyaDic= github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/marten-seemann/chacha20 v0.2.0 h1:f40vqzzx+3GdOmzQoItkLX5WLvHgPgyYqFFIO5Gh4hQ= -github.com/marten-seemann/chacha20 v0.2.0/go.mod h1:HSdjFau7GzYRj+ahFNwsO3ouVJr1HFkWoEwNDb4TMtE= +github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/marten-seemann/qpack v0.1.0/go.mod h1:LFt1NU/Ptjip0C2CPkhimBz5CGE3WGDAUWqna+CNTrI= -github.com/marten-seemann/qtls v0.4.1 h1:YlT8QP3WCCvvok7MGEZkMldXbyqgr8oFg5/n8Gtbkks= -github.com/marten-seemann/qtls v0.4.1/go.mod h1:pxVXcHHw1pNIt8Qo0pwSYQEoZ8yYOOPXTCZLQQunvRc= +github.com/marten-seemann/qtls v0.9.0 h1:8Zguhc72eS+DH5EAb0BpAPIy3HDXYcihQi4xoDZOnjQ= +github.com/marten-seemann/qtls v0.9.0/go.mod h1:T1MmAdDPyISzxlK6kjRr0pcZFBVd1OZbBb/j3cvzHhk= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= @@ -732,6 +766,7 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0j github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= +github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= github.com/miekg/dns v1.1.4/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.12 h1:WMhc1ik4LNkTg8U9l3hI1LvxKmIL+f1+WV/SZtCbDDA= github.com/miekg/dns v1.1.12/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= @@ -817,21 +852,26 @@ github.com/multiformats/go-varint v0.0.2/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXS github.com/multiformats/go-varint v0.0.5 h1:XVZwSo04Cs3j/jS0uAEPpT3JY6DzMcVLLoWOSnCxOjg= github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= +github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU= github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.9.0 h1:R1uwffexN6Pr340GtYRIdZmAiN4J+iw6WG4wog1DUXg= github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= @@ -843,6 +883,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 h1:2m16U/rLwVaRdz7ANkHtHTodP3zTP3N451MADg64x5k= github.com/polydawn/refmt v0.0.0-20190408063855-01bf1e26dd14/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= +github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= @@ -853,10 +894,12 @@ github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1 h1:KOMtN28tlbam3/7ZKEYKHhKoJZYYj3gMH4uc62x7X7U= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= +github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= @@ -866,6 +909,29 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= +github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= +github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= +github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= +github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= +github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw= +github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI= +github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU= +github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag= +github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg= +github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw= +github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y= +github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= +github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q= +github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ= +github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I= +github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0= +github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ= +github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk= +github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4= +github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= @@ -878,6 +944,8 @@ github.com/smartystreets/goconvey v0.0.0-20190710185942-9d28bd7c0945 h1:N8Bg45zp github.com/smartystreets/goconvey v0.0.0-20190710185942-9d28bd7c0945/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smola/gocompat v0.2.0 h1:6b1oIMlUXIpz//VKEDzPVBK8KG7beVwmHIUEBIs/Pns= github.com/smola/gocompat v0.2.0/go.mod h1:1B0MlxbmoZNo3h8guHp8HztB3BSYR5itql9qtVc0ypY= +github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= +github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= @@ -902,15 +970,14 @@ github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= +github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e h1:T5PdfK/M1xyrHwynxMIVMWLS7f/qHwfslZphxtGnw7s= github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e/go.mod h1:XDKHRm5ThF8YJjx001LtgelzsoaEcvnA7lVWz9EeX3g= github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c h1:u6SKchux2yDvFQnDHS3lPnIRmfVJ5Sxy3ao2SIdysLQ= github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0= -github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= -github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k= -github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= +github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= +github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= github.com/wangjia184/sortedset v0.0.0-20160527075905-f5d03557ba30/go.mod h1:YkocrP2K2tcw938x9gCOmT5G5eCD6jsTz0SZuyAqwIE= github.com/warpfork/go-wish v0.0.0-20180510122957-5ad1f5abf436/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= github.com/warpfork/go-wish v0.0.0-20190328234359-8b3e70f8e830 h1:8kxMKmKzXXL4Ru1nyhvdms/JjWt+3YLpvRb/bAjO/y0= @@ -949,6 +1016,7 @@ github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee/go.mod h1: github.com/whyrusleeping/yamux v1.1.5/go.mod h1:E8LnQQ8HKx5KD29HZFUwM1PxCOdPRzGwur1mcYhXcD8= github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.1 h1:8dP3SGL7MPB94crU3bEPplMPe83FI4EouesJUeFHv50= @@ -983,15 +1051,19 @@ go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.14.1 h1:nYDKopTbvAPq/NrUVZwT15y2lpROBiLLyoRTbXOYWOo= go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= +go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= go4.org v0.0.0-20200104003542-c7e774b10ea0 h1:M6XsnQeLwG+rHQ+/rrGh3puBI3WZEy9TBWmf2H+enQA= go4.org v0.0.0-20200104003542-c7e774b10ea0/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= +golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -999,7 +1071,6 @@ golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -1008,6 +1079,7 @@ golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200406173513-056763e48d71 h1:DOmugCavvUtnUD114C1Wh+UgTgQZ4pMLzXxi1pSt+/Y= golang.org/x/crypto v0.0.0-20200406173513-056763e48d71/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -1022,12 +1094,16 @@ golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190228165749-92fc7df08ae7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= @@ -1040,6 +1116,10 @@ golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1051,6 +1131,7 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1058,6 +1139,7 @@ golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190302025703-b6889370fb10/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1065,11 +1147,9 @@ golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190524122548-abf6ff778158/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190524152521-dbbf3f1254d4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190526052359-791d8a0f4d09/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190610200419-93c9922d18ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1079,13 +1159,19 @@ golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200406155108-e3b113bbe6a4 h1:c1Sgqkh8v6ZxafNGG64r8C8UisIW2TKMJN8P86tKjr0= -golang.org/x/sys v0.0.0-20200406155108-e3b113bbe6a4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200408040146-ea54a3c99b9b h1:h03Ur1RlPrGTjua4koYdpGl8W0eYo8p1uI9w7RPlkdk= +golang.org/x/sys v0.0.0-20200408040146-ea54a3c99b9b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181130052023-1c3d964395ce/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1093,6 +1179,7 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384 h1:TFlARGu6Czu1z7q93HTxcP1P+/ZFC/IKythI5RzrnRg= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1110,12 +1197,23 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbO golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= +google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= @@ -1129,6 +1227,7 @@ gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qS gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVYcSwSjGebuDL6176A1XskgbtNl64NSg+n8= gopkg.in/src-d/go-log.v1 v1.0.1/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= @@ -1139,6 +1238,13 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5 h1:ymVxjfMaHvXD8RqPRmzHHsB3VvucivSkIAvJFDI5O3c= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= +sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= From 9a98158bed7cb2f8206ad4aef7f9d37f929c4a9b Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Fri, 13 Mar 2020 16:45:54 -0700 Subject: [PATCH 582/671] test(sharness): test address filtering tests #6995 --- test/sharness/t0142-testfilter.sh | 61 +++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100755 test/sharness/t0142-testfilter.sh diff --git a/test/sharness/t0142-testfilter.sh b/test/sharness/t0142-testfilter.sh new file mode 100755 index 00000000000..0b46e2c9556 --- /dev/null +++ b/test/sharness/t0142-testfilter.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash +# +# Copyright (c) 2020 Protocol Labs +# MIT/Apache-2.0 Licensed; see the LICENSE file in this repository. +# + +test_description="Test swarm filters are effective" + +AF="/ip4/127.0.0.0/ipcidr/24" + +. lib/test-lib.sh + +NUM_NODES=3 + +test_expect_success "set up testbed" ' + iptb testbed create -type localipfs -count $NUM_NODES -force -init +' + +test_expect_success 'filter 127.0.0.0/24 on node 1' ' + ipfsi 1 config --json Swarm.AddrFilters "[\"$AF\"]" +' + +for i in $(seq 0 $(( NUM_NODES - 1 ))); do + test_expect_success 'enable quic for node $i' ' + echo "$i" + ipfsi $i config --json Experimental.QUIC true + ' + + test_expect_success "change IP for node $i" ' + ipfsi $i config --json "Addresses.Swarm" \ + "[\"/ip4/127.0.$i.1/tcp/0\",\"/ip4/127.0.$i.1/udp/0/quic\",\"/ip4/127.0.$i.1/tcp/0/ws\"]" + ' +done + +test_expect_success 'start cluster' ' + iptb start --wait +' + +test_expect_success 'connecting 1 to 0 fails' ' + test_must_fail iptb connect 1 0 +' + +test_expect_success 'connecting 0 to 1 fails' ' + test_must_fail iptb connect 1 0 +' + +test_expect_success 'connecting 2 to 0 succeeds' ' + iptb connect 2 0 +' + +test_expect_success 'connecting 1 to 0 with dns addrs fails' ' + ipfsi 0 id -f "" | sed "s|^/ip4/127.0.0.1/|/dns4/localhost/|" > addrs && + test_must_fail ipfsi 1 swarm connect $(cat addrs) +' + + +test_expect_success 'stopping cluster' ' + iptb stop +' + +test_done From 8a002250dc0b21f213fea07a8329d8b05ab5ed13 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Thu, 9 Apr 2020 13:17:49 -0700 Subject: [PATCH 583/671] feat: introduce the dual WAN/LAN DHT And only join the WAN DHT if we're publicly reachable. --- core/node/libp2p/routingopt.go | 7 +++---- go.mod | 4 ++-- go.sum | 8 ++++---- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/core/node/libp2p/routingopt.go b/core/node/libp2p/routingopt.go index d7f4f7a18a0..b673290015a 100644 --- a/core/node/libp2p/routingopt.go +++ b/core/node/libp2p/routingopt.go @@ -8,6 +8,7 @@ import ( host "github.com/libp2p/go-libp2p-core/host" routing "github.com/libp2p/go-libp2p-core/routing" dht "github.com/libp2p/go-libp2p-kad-dht" + dual "github.com/libp2p/go-libp2p-kad-dht/dual" record "github.com/libp2p/go-libp2p-record" ) @@ -15,7 +16,7 @@ type RoutingOption func(context.Context, host.Host, datastore.Batching, record.V func constructDHTRouting(mode dht.ModeOpt) func(ctx context.Context, host host.Host, dstore datastore.Batching, validator record.Validator) (routing.Routing, error) { return func(ctx context.Context, host host.Host, dstore datastore.Batching, validator record.Validator) (routing.Routing, error) { - return dht.New( + return dual.New( ctx, host, dht.Concurrency(10), dht.Mode(mode), @@ -26,9 +27,7 @@ func constructDHTRouting(mode dht.ModeOpt) func(ctx context.Context, host host.H } var ( - // FIXME: Set this to dht.ModeAuto once we resolve - // https://github.com/libp2p/go-libp2p-kad-dht/issues/564 - DHTOption RoutingOption = constructDHTRouting(dht.ModeServer) + DHTOption RoutingOption = constructDHTRouting(dht.ModeAuto) DHTClientOption = constructDHTRouting(dht.ModeClient) DHTServerOption = constructDHTRouting(dht.ModeServer) NilRouterOption = nilrouting.ConstructNilRouting diff --git a/go.mod b/go.mod index 747c0c74674..03a9d869635 100644 --- a/go.mod +++ b/go.mod @@ -66,8 +66,8 @@ require ( github.com/libp2p/go-libp2p-core v0.5.1 github.com/libp2p/go-libp2p-discovery v0.3.0 github.com/libp2p/go-libp2p-http v0.1.5 - github.com/libp2p/go-libp2p-kad-dht v0.6.2 - github.com/libp2p/go-libp2p-kbucket v0.3.3 + github.com/libp2p/go-libp2p-kad-dht v0.7.2 + github.com/libp2p/go-libp2p-kbucket v0.4.1 github.com/libp2p/go-libp2p-loggables v0.1.0 github.com/libp2p/go-libp2p-mplex v0.2.3 github.com/libp2p/go-libp2p-peerstore v0.2.3 diff --git a/go.sum b/go.sum index 554336f8e71..5fbf8220550 100644 --- a/go.sum +++ b/go.sum @@ -549,10 +549,10 @@ github.com/libp2p/go-libp2p-interface-connmgr v0.0.1/go.mod h1:GarlRLH0LdeWcLnYM 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.6.2 h1:ZKXN7iqjIGC3+z4MKoBoyOGq6zvJ294J/tAA7LfihV0= -github.com/libp2p/go-libp2p-kad-dht v0.6.2/go.mod h1:LzZi6RR6NrgfFboyk03I5Yzg1Rr4eoQictDXpKpI45c= -github.com/libp2p/go-libp2p-kbucket v0.3.3 h1:V2Zwv6QnCK6Who0iiJW2eUKwdlTYGJ2HnLViaolDOcs= -github.com/libp2p/go-libp2p-kbucket v0.3.3/go.mod h1:IWFdYRBOYzaLEHnvrfzEkr+UcuveCXIoeO8QeFZSI6A= +github.com/libp2p/go-libp2p-kad-dht v0.7.2 h1:pmjjvk0q3wAQVLWWcFaYb0Ha+QXpa7NlzeXkKvhGYXU= +github.com/libp2p/go-libp2p-kad-dht v0.7.2/go.mod h1:+XvZEgO0gOAd9liN1wjdewxIdcdtWLJXG8U8ou2oo/A= +github.com/libp2p/go-libp2p-kbucket v0.4.1 h1:6FyzbQuGLPzbMv3HiD232zqscIz5iB8ppJwb380+OGI= +github.com/libp2p/go-libp2p-kbucket v0.4.1/go.mod h1:7sCeZx2GkNK1S6lQnGUW5JYZCFPnXzAZCCBBS70lytY= github.com/libp2p/go-libp2p-loggables v0.0.1/go.mod h1:lDipDlBNYbpyqyPX/KcoO+eq0sJYEVR2JgOexcivchg= github.com/libp2p/go-libp2p-loggables v0.1.0 h1:h3w8QFfCt2UJl/0/NW4K829HX/0S4KD31PQ7m8UXXO8= github.com/libp2p/go-libp2p-loggables v0.1.0/go.mod h1:EyumB2Y6PrYjr55Q3/tiJ/o3xoDasoRYM7nOzEpoa90= From bb08f7fe5643b9b832f06d952bbb1615d75d8ebd Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Thu, 19 Mar 2020 18:38:36 -0700 Subject: [PATCH 584/671] assign public IP addresses for tests that need them --- core/coreapi/test/api_test.go | 2 +- core/mock/mock.go | 23 +++++++++++++++++++++++ namesys/republisher/repub_test.go | 5 +---- test/integration/three_legged_cat_test.go | 16 +++------------- 4 files changed, 28 insertions(+), 18 deletions(-) diff --git a/core/coreapi/test/api_test.go b/core/coreapi/test/api_test.go index f13d7ad3aa3..f3e3903bc28 100644 --- a/core/coreapi/test/api_test.go +++ b/core/coreapi/test/api_test.go @@ -65,7 +65,7 @@ func (NodeProvider) MakeAPISwarm(ctx context.Context, fullIdentity bool, n int) } c := config.Config{} - c.Addresses.Swarm = []string{fmt.Sprintf("/ip4/127.0.%d.1/tcp/4001", i)} + c.Addresses.Swarm = []string{fmt.Sprintf("/ip4/18.0.%d.1/tcp/4001", i)} c.Identity = ident c.Experimental.FilestoreEnabled = true diff --git a/core/mock/mock.go b/core/mock/mock.go index 2867de1112a..673a54b8698 100644 --- a/core/mock/mock.go +++ b/core/mock/mock.go @@ -2,6 +2,8 @@ package coremock import ( "context" + "fmt" + "io/ioutil" libp2p2 "github.com/ipfs/go-ipfs/core/node/libp2p" @@ -75,3 +77,24 @@ func MockCmdsCtx() (commands.Context, error) { }, }, nil } + +func MockPublicNode(ctx context.Context, mn mocknet.Mocknet) (*core.IpfsNode, error) { + ds := syncds.MutexWrap(datastore.NewMapDatastore()) + cfg, err := config.Init(ioutil.Discard, 2048) + if err != nil { + return nil, err + } + count := len(mn.Peers()) + cfg.Addresses.Swarm = []string{ + fmt.Sprintf("/ip4/18.0.%d.%d/tcp/4001", count>>16, count&0xFF), + } + cfg.Datastore = config.Datastore{} + return core.NewNode(ctx, &core.BuildCfg{ + Online: true, + Repo: &repo.Mock{ + C: *cfg, + D: ds, + }, + Host: MockHostOption(mn), + }) +} diff --git a/namesys/republisher/repub_test.go b/namesys/republisher/repub_test.go index 5fedc3907a2..fd946501eb3 100644 --- a/namesys/republisher/repub_test.go +++ b/namesys/republisher/repub_test.go @@ -29,10 +29,7 @@ func TestRepublish(t *testing.T) { var nodes []*core.IpfsNode for i := 0; i < 10; i++ { - nd, err := core.NewNode(ctx, &core.BuildCfg{ - Online: true, - Host: mock.MockHostOption(mn), - }) + nd, err := mock.MockPublicNode(ctx, mn) if err != nil { t.Fatal(err) } diff --git a/test/integration/three_legged_cat_test.go b/test/integration/three_legged_cat_test.go index ab9b857c59f..eb82d00083a 100644 --- a/test/integration/three_legged_cat_test.go +++ b/test/integration/three_legged_cat_test.go @@ -9,7 +9,6 @@ import ( "testing" "time" - core "github.com/ipfs/go-ipfs/core" bootstrap2 "github.com/ipfs/go-ipfs/core/bootstrap" "github.com/ipfs/go-ipfs/core/coreapi" mock "github.com/ipfs/go-ipfs/core/mock" @@ -76,28 +75,19 @@ func RunThreeLeggedCat(data []byte, conf testutil.LatencyConfig) error { Bandwidth: math.MaxInt32, }) - bootstrap, err := core.NewNode(ctx, &core.BuildCfg{ - Online: true, - Host: mock.MockHostOption(mn), - }) + bootstrap, err := mock.MockPublicNode(ctx, mn) if err != nil { return err } defer bootstrap.Close() - adder, err := core.NewNode(ctx, &core.BuildCfg{ - Online: true, - Host: mock.MockHostOption(mn), - }) + adder, err := mock.MockPublicNode(ctx, mn) if err != nil { return err } defer adder.Close() - catter, err := core.NewNode(ctx, &core.BuildCfg{ - Online: true, - Host: mock.MockHostOption(mn), - }) + catter, err := mock.MockPublicNode(ctx, mn) if err != nil { return err } From 924e8704a0606613158c361262378141d70be985 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Thu, 9 Apr 2020 21:42:15 -0700 Subject: [PATCH 585/671] chore: update flatfs fixes #7115 --- go.mod | 2 +- go.sum | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 747c0c74674..eb478fdffc2 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( github.com/ipfs/go-datastore v0.4.4 github.com/ipfs/go-detect-race v0.0.1 github.com/ipfs/go-ds-badger v0.2.4 - github.com/ipfs/go-ds-flatfs v0.4.1 + github.com/ipfs/go-ds-flatfs v0.4.2 github.com/ipfs/go-ds-leveldb v0.4.2 github.com/ipfs/go-ds-measure v0.1.0 github.com/ipfs/go-filestore v0.0.3 diff --git a/go.sum b/go.sum index 554336f8e71..4417b7618ec 100644 --- a/go.sum +++ b/go.sum @@ -29,6 +29,8 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alexbrainman/goissue34681 v0.0.0-20191006012335-3fc7a47baff5 h1:iW0a5ljuFxkLGPNem5Ui+KBjFJzKg4Fv2fnxe4dvzpM= +github.com/alexbrainman/goissue34681 v0.0.0-20191006012335-3fc7a47baff5/go.mod h1:Y2QMoi1vgtOIfc+6DhrMOGkLoGzqSV2rKp4Sm+opsyA= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -261,8 +263,8 @@ github.com/ipfs/go-ds-badger v0.2.3 h1:J27YvAcpuA5IvZUbeBxOcQgqnYHUPxoygc6Qxxkod github.com/ipfs/go-ds-badger v0.2.3/go.mod h1:pEYw0rgg3FIrywKKnL+Snr+w/LjJZVMTBRn4FS6UHUk= github.com/ipfs/go-ds-badger v0.2.4 h1:UPGB0y7luFHk+mY/tUZrif/272M8o+hFsW+avLUeWrM= github.com/ipfs/go-ds-badger v0.2.4/go.mod h1:pEYw0rgg3FIrywKKnL+Snr+w/LjJZVMTBRn4FS6UHUk= -github.com/ipfs/go-ds-flatfs v0.4.1 h1:l43jeAUALOKRvoMMJ4rOddxUzcOACUjnd1u4AfKqeZo= -github.com/ipfs/go-ds-flatfs v0.4.1/go.mod h1:5fR0eUTIrFWJqa4zACd3mKUNm26wM/jVbVDo39/WRRo= +github.com/ipfs/go-ds-flatfs v0.4.2 h1:v8VwVkmO+XN7YlrDgpuHl/0bGgu3qD44MKhIlbcfcFY= +github.com/ipfs/go-ds-flatfs v0.4.2/go.mod h1:KiZoBq31WFUR5LmDKPUHhsc0XZgjho+R/AzEPQpaN4U= github.com/ipfs/go-ds-leveldb v0.0.1/go.mod h1:feO8V3kubwsEF22n0YRQCffeb79OOYIykR4L04tMOYc= github.com/ipfs/go-ds-leveldb v0.1.0 h1:OsCuIIh1LMTk4WIQ1UJH7e3j01qlOP+KWVhNS6lBDZY= github.com/ipfs/go-ds-leveldb v0.1.0/go.mod h1:hqAW8y4bwX5LWcCtku2rFNX3vjDZCy5LZCg+cSZvYb8= From e55c688fca457c40d95bbe4c9c7d407bdda34219 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Thu, 9 Apr 2020 21:40:22 -0700 Subject: [PATCH 586/671] fix: run tests in "dht server" mode Otherwise, we'd need to wait a delay on start for nodes to start becoming servers. --- core/coreapi/test/api_test.go | 8 +++++--- core/mock/mock.go | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/core/coreapi/test/api_test.go b/core/coreapi/test/api_test.go index f3e3903bc28..153a8c7cf31 100644 --- a/core/coreapi/test/api_test.go +++ b/core/coreapi/test/api_test.go @@ -13,6 +13,7 @@ import ( "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" @@ -78,9 +79,10 @@ func (NodeProvider) MakeAPISwarm(ctx context.Context, fullIdentity bool, n int) } node, err := core.NewNode(ctx, &core.BuildCfg{ - Repo: r, - Host: mock.MockHostOption(mn), - Online: fullIdentity, + Routing: libp2p.DHTServerOption, + Repo: r, + Host: mock.MockHostOption(mn), + Online: fullIdentity, ExtraOpts: map[string]bool{ "pubsub": true, }, diff --git a/core/mock/mock.go b/core/mock/mock.go index 673a54b8698..ed123dff7c0 100644 --- a/core/mock/mock.go +++ b/core/mock/mock.go @@ -90,7 +90,8 @@ func MockPublicNode(ctx context.Context, mn mocknet.Mocknet) (*core.IpfsNode, er } cfg.Datastore = config.Datastore{} return core.NewNode(ctx, &core.BuildCfg{ - Online: true, + Online: true, + Routing: libp2p2.DHTServerOption, Repo: &repo.Mock{ C: *cfg, D: ds, From 4319c12692064f4cc97e5b59c1e05d0f721d7a69 Mon Sep 17 00:00:00 2001 From: Peter Rabbitson Date: Fri, 10 Apr 2020 14:45:48 +0200 Subject: [PATCH 587/671] Fixup all original test issues --- test/sharness/t0054-dag-car-import-export.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/sharness/t0054-dag-car-import-export.sh b/test/sharness/t0054-dag-car-import-export.sh index 33652b2aa6f..d4a3693a8db 100755 --- a/test/sharness/t0054-dag-car-import-export.sh +++ b/test/sharness/t0054-dag-car-import-export.sh @@ -12,14 +12,15 @@ tar -C ../t0054-dag-car-import-export-data/ --strip-components=1 -Jxf ../t0054-d reset_blockstore() { node=$1 - ipfsi $1 pin ls --quiet --type=recursive | ipfsi $1 pin rm &>/dev/null - ipfsi $1 repo gc &>/dev/null + + ipfsi $node pin ls --quiet --type=recursive | ipfsi $node pin rm &>/dev/null + ipfsi $node repo gc &>/dev/null test_expect_success "pinlist empty" ' - [ "$( ipfsi $1 pin ls )" = "" ] + [[ -z "$( ipfsi $node pin ls )" ]] ' test_expect_success "nothing left to gc" ' - [ "$( ipfsi $1 repo gc )" = "" ] + [[ -z "$( ipfsi $node repo gc )" ]] ' } @@ -57,7 +58,7 @@ run_online_imp_exp_tests() { # FIXME - positive-test the lack of output when https://github.com/ipfs/go-ipfs/issues/7121 is addressed test_expect_failure "concurrent GC did not manage to grab anything and remained silent" ' - ! [[ -s gc_out ]] + test_cmp /dev/null gc_out ' test_expect_success "basic import output as expected" ' test_cmp basic_import_expected basic_import_actual @@ -91,7 +92,7 @@ run_online_imp_exp_tests() { ' # FIXME - positive-test the lack of output when https://github.com/ipfs/go-ipfs/issues/7121 is addressed test_expect_failure "concurrent GC did not manage to grab anything and remained silent" ' - ! [[ -s gc_out ]] + test_cmp /dev/null gc_out ' test_expect_success "fifo-import output as expected" ' @@ -154,7 +155,7 @@ test_expect_success "pin-less import works" ' > no-pin_import_actual ' test_expect_success "expected silence on --pin-roots=false" ' - ! [[ -s no-pin_import_actual ]] + test_cmp /dev/null no-pin_import_actual ' @@ -170,5 +171,4 @@ test_expect_success "naked root import expected output" ' test_cmp naked_root_import_expected naked_root_import_actual ' - test_done From edc27793fb746b4a1c1a9f5e475838b2509bce27 Mon Sep 17 00:00:00 2001 From: Peter Rabbitson Date: Fri, 10 Apr 2020 14:46:17 +0200 Subject: [PATCH 588/671] Extra cross-iptb-network testcases --- test/sharness/t0054-dag-car-import-export.sh | 56 +++++++++++++++----- 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/test/sharness/t0054-dag-car-import-export.sh b/test/sharness/t0054-dag-car-import-export.sh index d4a3693a8db..e6e63217822 100755 --- a/test/sharness/t0054-dag-car-import-export.sh +++ b/test/sharness/t0054-dag-car-import-export.sh @@ -9,6 +9,7 @@ export -f ipfsi set -o pipefail tar -C ../t0054-dag-car-import-export-data/ --strip-components=1 -Jxf ../t0054-dag-car-import-export-data/test_dataset_car_v0.tar.xz +tab=$'\t' reset_blockstore() { node=$1 @@ -43,9 +44,17 @@ run_online_imp_exp_tests() { reset_blockstore 0 reset_blockstore 1 - echo -e "Pinned root\tbafkqaaa\tsuccess" > basic_import_expected - echo -e "Pinned root\tbafy2bzaceaxm23epjsmh75yvzcecsrbavlmkcxnva66bkdebdcnyw3bjrc74u\tsuccess" >> basic_import_expected - echo -e "Pinned root\tbafy2bzaced4ueelaegfs5fqu4tzsh6ywbbpfk3cxppupmxfdhbpbhzawfw5oy\tsuccess" >> basic_import_expected + cat > basic_import_expected <naked_root_import_json_expected < reexported_testnet_128.car + ' + test_expect_success "export of shuffled testnet export identical to canonical original" ' + test_cmp reexported_testnet_128.car ../t0054-dag-car-import-export-data/lotus_testnet_export_128.car + ' + + test_expect_success "basic fetch+export 2" ' + ipfsi 1 dag export bafy2bzaceaxm23epjsmh75yvzcecsrbavlmkcxnva66bkdebdcnyw3bjrc74u > reexported_devnet_genesis.car + ' + test_expect_success "export of shuffled devnet export identical to canonical original" ' + test_cmp reexported_devnet_genesis.car ../t0054-dag-car-import-export-data/lotus_devnet_genesis.car + ' + + test_expect_success "pinlist on node1 still empty" ' + [[ -z "$( ipfsi 1 pin ls )" ]] + ' + + test_expect_success "import/pin naked roots only, relying on local blockstore having all the data" ' + ipfsi 1 dag import --enc=json ../t0054-dag-car-import-export-data/combined_naked_roots_genesis_and_128.car \ + | sort > naked_import_result_json_actual + ' + + test_expect_success "naked import output as expected" ' + test_cmp naked_root_import_json_expected naked_import_result_json_actual + ' + reset_blockstore 0 reset_blockstore 1 @@ -135,16 +171,16 @@ test_expect_success "correct error" ' ' -cat >multiroot_import_expected <multiroot_import_json_expected < multiroot_import_actual + ipfs dag import --enc=json ../t0054-dag-car-import-export-data/lotus_testnet_export_256_multiroot.car | sort > multiroot_import_json_actual ' test_expect_success "multiroot import expected output" ' - test_cmp multiroot_import_expected multiroot_import_actual + test_cmp multiroot_import_json_expected multiroot_import_json_actual ' @@ -159,16 +195,12 @@ test_expect_success "expected silence on --pin-roots=false" ' ' -cat >naked_root_import_expected < naked_root_import_actual + | sort > naked_root_import_json_actual ' test_expect_success "naked root import expected output" ' - test_cmp naked_root_import_expected naked_root_import_actual + test_cmp naked_root_import_json_expected naked_root_import_json_actual ' test_done From 768c287f9b47730e97b59881bfe72b007f8c948f Mon Sep 17 00:00:00 2001 From: Peter Rabbitson Date: Fri, 10 Apr 2020 15:47:41 +0200 Subject: [PATCH 589/671] Extra potential deadlock debugging --- test/sharness/t0054-dag-car-import-export.sh | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/test/sharness/t0054-dag-car-import-export.sh b/test/sharness/t0054-dag-car-import-export.sh index e6e63217822..ecb989870a3 100755 --- a/test/sharness/t0054-dag-car-import-export.sh +++ b/test/sharness/t0054-dag-car-import-export.sh @@ -29,14 +29,13 @@ reset_blockstore() { do_import() { node=$1; shift - bash -c "while [[ -e spin.gc ]]; do ipfsi $node repo gc >>gc_out 2>&1; done" & gc1_pid=$! - bash -c "while [[ -e spin.gc ]]; do ipfsi $node repo gc >>gc_out 2>&1; done" & gc2_pid=$! + touch spin.gc + timeout -s QUIT 15 bash -c "while [[ -e spin.gc ]]; do ipfsi $node repo gc &>>gc_out; done" & gc1_pid=$! + timeout -s QUIT 15 bash -c "while [[ -e spin.gc ]]; do ipfsi $node repo gc &>>gc_out; done" & gc2_pid=$! - ipfsi $node dag import "$@" + timeout -s QUIT 10 bash -c "ipfsi $node dag import $* 2>&1" rm -f spin.gc || true - sleep 3 - kill $gc1_pid $gc2_pid || true } run_online_imp_exp_tests() { @@ -56,7 +55,6 @@ EOE EOE - touch spin.gc test_expect_success "basic import" ' do_import 0 \ ../t0054-dag-car-import-export-data/combined_naked_roots_genesis_and_128.car \ @@ -118,7 +116,6 @@ EOE bash -c "sleep 60; kill $cat1_pid $cat2_pid 2>/dev/null" & ' & - touch spin.gc test_expect_success "fifo import" ' do_import 0 \ pipe_testnet \ From 8679954f9bb560259fbda2cd42a42f957c07e2a2 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Fri, 10 Apr 2020 16:41:12 -0700 Subject: [PATCH 590/671] chore: update flatfs And remove retry logic. This was flatfs specific and we've moved the logic down into flatfs itself. This update: * Retries in more cases when we run out of file descriptors. * Ensures we don't leak temporary files on batch put. --- core/node/storage.go | 22 +--------------------- go.mod | 2 +- go.sum | 4 ++-- 3 files changed, 4 insertions(+), 24 deletions(-) diff --git a/core/node/storage.go b/core/node/storage.go index f1d9495fe53..92d475339f9 100644 --- a/core/node/storage.go +++ b/core/node/storage.go @@ -1,12 +1,7 @@ package node import ( - "os" - "syscall" - "time" - "github.com/ipfs/go-datastore" - "github.com/ipfs/go-datastore/retrystore" blockstore "github.com/ipfs/go-ipfs-blockstore" config "github.com/ipfs/go-ipfs-config" "go.uber.org/fx" @@ -18,15 +13,6 @@ import ( "github.com/ipfs/go-ipfs/thirdparty/verifbs" ) -func isTooManyFDError(err error) bool { - perr, ok := err.(*os.PathError) - if ok && perr.Err == syscall.EMFILE { - return true - } - - return false -} - // RepoConfig loads configuration from the repo func RepoConfig(repo repo.Repo) (*config.Config, error) { return repo.Config() @@ -43,14 +29,8 @@ type BaseBlocks blockstore.Blockstore // BaseBlockstoreCtor creates cached blockstore backed by the provided datastore func BaseBlockstoreCtor(cacheOpts blockstore.CacheOpts, nilRepo bool, hashOnRead bool) func(mctx helpers.MetricsCtx, repo repo.Repo, lc fx.Lifecycle) (bs BaseBlocks, err error) { return func(mctx helpers.MetricsCtx, repo repo.Repo, lc fx.Lifecycle) (bs BaseBlocks, err error) { - rds := &retrystore.Datastore{ - Batching: repo.Datastore(), - Delay: time.Millisecond * 200, - Retries: 6, - TempErrFunc: isTooManyFDError, - } // hash security - bs = blockstore.NewBlockstore(rds) + bs = blockstore.NewBlockstore(repo.Datastore()) bs = &verifbs.VerifBS{Blockstore: bs} if !nilRepo { diff --git a/go.mod b/go.mod index eb478fdffc2..f2639af85ec 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( github.com/ipfs/go-datastore v0.4.4 github.com/ipfs/go-detect-race v0.0.1 github.com/ipfs/go-ds-badger v0.2.4 - github.com/ipfs/go-ds-flatfs v0.4.2 + github.com/ipfs/go-ds-flatfs v0.4.3 github.com/ipfs/go-ds-leveldb v0.4.2 github.com/ipfs/go-ds-measure v0.1.0 github.com/ipfs/go-filestore v0.0.3 diff --git a/go.sum b/go.sum index 4417b7618ec..3653d33cdb1 100644 --- a/go.sum +++ b/go.sum @@ -263,8 +263,8 @@ github.com/ipfs/go-ds-badger v0.2.3 h1:J27YvAcpuA5IvZUbeBxOcQgqnYHUPxoygc6Qxxkod github.com/ipfs/go-ds-badger v0.2.3/go.mod h1:pEYw0rgg3FIrywKKnL+Snr+w/LjJZVMTBRn4FS6UHUk= github.com/ipfs/go-ds-badger v0.2.4 h1:UPGB0y7luFHk+mY/tUZrif/272M8o+hFsW+avLUeWrM= github.com/ipfs/go-ds-badger v0.2.4/go.mod h1:pEYw0rgg3FIrywKKnL+Snr+w/LjJZVMTBRn4FS6UHUk= -github.com/ipfs/go-ds-flatfs v0.4.2 h1:v8VwVkmO+XN7YlrDgpuHl/0bGgu3qD44MKhIlbcfcFY= -github.com/ipfs/go-ds-flatfs v0.4.2/go.mod h1:KiZoBq31WFUR5LmDKPUHhsc0XZgjho+R/AzEPQpaN4U= +github.com/ipfs/go-ds-flatfs v0.4.3 h1:7M8/xpLkJhFJYaLumo2RRgt/cOehetutGW5zigTa5qY= +github.com/ipfs/go-ds-flatfs v0.4.3/go.mod h1:e4TesLyZoA8k1gV/yCuBTnt2PJtypn4XUlB5n8KQMZY= github.com/ipfs/go-ds-leveldb v0.0.1/go.mod h1:feO8V3kubwsEF22n0YRQCffeb79OOYIykR4L04tMOYc= github.com/ipfs/go-ds-leveldb v0.1.0 h1:OsCuIIh1LMTk4WIQ1UJH7e3j01qlOP+KWVhNS6lBDZY= github.com/ipfs/go-ds-leveldb v0.1.0/go.mod h1:hqAW8y4bwX5LWcCtku2rFNX3vjDZCy5LZCg+cSZvYb8= From fdd0ebac18d602b1109a9c5e98da2f570a441fe7 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Fri, 10 Apr 2020 17:37:01 -0700 Subject: [PATCH 591/671] chore: update bitswap Hopefully fixes the message queue bloat issue. --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f2639af85ec..05c98db75da 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/gogo/protobuf v1.3.1 github.com/hashicorp/go-multierror v1.1.0 github.com/hashicorp/golang-lru v0.5.4 - github.com/ipfs/go-bitswap v0.2.8 + github.com/ipfs/go-bitswap v0.2.9 github.com/ipfs/go-block-format v0.0.2 github.com/ipfs/go-blockservice v0.1.3 github.com/ipfs/go-cid v0.0.5 diff --git a/go.sum b/go.sum index 3653d33cdb1..dcb7619d1de 100644 --- a/go.sum +++ b/go.sum @@ -214,8 +214,8 @@ github.com/ipfs/go-bitswap v0.1.0/go.mod h1:FFJEf18E9izuCqUtHxbWEvq+reg7o4CW5wSA 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.8 h1:5tQrbyyRS3DkzvcM5n+bVjdSAHLgvH7D+1LopndhUII= -github.com/ipfs/go-bitswap v0.2.8/go.mod h1:2Yjog0GMdH8+AsxkE0DI9D2mANaUTxbVVav0pPoZoug= +github.com/ipfs/go-bitswap v0.2.9 h1:23xzQ5kWx9F3Q4PrBS9nbPwMsxdWHXeD9nZX1/ozTlI= +github.com/ipfs/go-bitswap v0.2.9/go.mod h1:2Yjog0GMdH8+AsxkE0DI9D2mANaUTxbVVav0pPoZoug= github.com/ipfs/go-block-format v0.0.1/go.mod h1:DK/YYcsSUIVAFNwo/KZCdIIbpN0ROH/baNLgayt4pFc= github.com/ipfs/go-block-format v0.0.2 h1:qPDvcP19izTjU8rgo6p7gTXZlkMkF5bz5G3fqIsSCPE= github.com/ipfs/go-block-format v0.0.2/go.mod h1:AWR46JfpcObNfg3ok2JHDUfdiHRgWhJgCQF+KIgOPJY= From cb5863c038a98e1d2556a91100c7af5cb54f27b9 Mon Sep 17 00:00:00 2001 From: Peter Rabbitson Date: Mon, 13 Apr 2020 19:28:14 +0200 Subject: [PATCH 592/671] Temporarily disable gc-race test I am going to rig a more robust version and run it locally to crash Disabling in master in order to validate the pipe reading itself works correctly and reliably --- test/sharness/t0054-dag-car-import-export.sh | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/test/sharness/t0054-dag-car-import-export.sh b/test/sharness/t0054-dag-car-import-export.sh index ecb989870a3..706f8b582cb 100755 --- a/test/sharness/t0054-dag-car-import-export.sh +++ b/test/sharness/t0054-dag-car-import-export.sh @@ -29,11 +29,14 @@ reset_blockstore() { do_import() { node=$1; shift - touch spin.gc - timeout -s QUIT 15 bash -c "while [[ -e spin.gc ]]; do ipfsi $node repo gc &>>gc_out; done" & gc1_pid=$! - timeout -s QUIT 15 bash -c "while [[ -e spin.gc ]]; do ipfsi $node repo gc &>>gc_out; done" & gc2_pid=$! + # for tests below expecting this to be non -z + echo "FIXME: BELOW TEST DISABLED FOR THE TIME BEING" > gc_out - timeout -s QUIT 10 bash -c "ipfsi $node dag import $* 2>&1" + #touch spin.gc + #timeout -s QUIT 30 bash -c "while [[ -e spin.gc ]]; do ipfsi $node repo gc &>>gc_out; done" & gc1_pid=$! + #timeout -s QUIT 25 bash -c "while [[ -e spin.gc ]]; do ipfsi $node repo gc &>>gc_out; done" & gc2_pid=$! + + timeout -s QUIT 20 bash -c "ipfsi $node dag import $* 2>&1" rm -f spin.gc || true } From b64d17b9241ee0024522bbb4d6a450131b00f443 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 13 Apr 2020 15:58:12 -0700 Subject: [PATCH 593/671] properly expose dual dht --- core/commands/dht.go | 7 ++++++- core/core.go | 4 ++-- core/node/libp2p/routing.go | 11 ++++++----- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/core/commands/dht.go b/core/commands/dht.go index fa5debdc0e0..6e140dfac13 100644 --- a/core/commands/dht.go +++ b/core/commands/dht.go @@ -76,7 +76,12 @@ var queryDhtCmd = &cmds.Command{ ctx, cancel := context.WithCancel(req.Context) ctx, events := routing.RegisterForQueryEvents(ctx) - closestPeers, err := nd.DHT.GetClosestPeers(ctx, string(id)) + dht := nd.DHT.WAN + if !nd.DHT.WANActive() { + dht = nd.DHT.LAN + } + + closestPeers, err := dht.GetClosestPeers(ctx, string(id)) if err != nil { cancel() return err diff --git a/core/core.go b/core/core.go index d3c3a5ae5e1..6cdf4d921a4 100644 --- a/core/core.go +++ b/core/core.go @@ -33,7 +33,7 @@ import ( peer "github.com/libp2p/go-libp2p-core/peer" pstore "github.com/libp2p/go-libp2p-core/peerstore" routing "github.com/libp2p/go-libp2p-core/routing" - dht "github.com/libp2p/go-libp2p-kad-dht" + ddht "github.com/libp2p/go-libp2p-kad-dht/dual" pubsub "github.com/libp2p/go-libp2p-pubsub" psrouter "github.com/libp2p/go-libp2p-pubsub-router" record "github.com/libp2p/go-libp2p-record" @@ -92,7 +92,7 @@ type IpfsNode struct { PubSub *pubsub.PubSub `optional:"true"` PSRouter *psrouter.PubsubValueStore `optional:"true"` - DHT *dht.IpfsDHT `optional:"true"` + DHT *ddht.DHT `optional:"true"` P2P *p2p.P2P `optional:"true"` Process goprocess.Process diff --git a/core/node/libp2p/routing.go b/core/node/libp2p/routing.go index cc32ce4b3ca..14b8fa40c10 100644 --- a/core/node/libp2p/routing.go +++ b/core/node/libp2p/routing.go @@ -5,16 +5,17 @@ import ( "sort" "time" + "github.com/ipfs/go-ipfs/core/node/helpers" + host "github.com/libp2p/go-libp2p-core/host" routing "github.com/libp2p/go-libp2p-core/routing" - dht "github.com/libp2p/go-libp2p-kad-dht" + ddht "github.com/libp2p/go-libp2p-kad-dht/dual" "github.com/libp2p/go-libp2p-pubsub" namesys "github.com/libp2p/go-libp2p-pubsub-router" record "github.com/libp2p/go-libp2p-record" routinghelpers "github.com/libp2p/go-libp2p-routing-helpers" - "go.uber.org/fx" - "github.com/ipfs/go-ipfs/core/node/helpers" + "go.uber.org/fx" ) type BaseIpfsRouting routing.Routing @@ -31,8 +32,8 @@ type p2pRouterOut struct { Router Router `group:"routers"` } -func BaseRouting(lc fx.Lifecycle, in BaseIpfsRouting) (out p2pRouterOut, dr *dht.IpfsDHT) { - if dht, ok := in.(*dht.IpfsDHT); ok { +func BaseRouting(lc fx.Lifecycle, in BaseIpfsRouting) (out p2pRouterOut, dr *ddht.DHT) { + if dht, ok := in.(*ddht.DHT); ok { dr = dht lc.Append(fx.Hook{ From d0d508b2e1ec7e6a51ca78f6d10ee0c7b560efea Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 13 Apr 2020 17:42:03 -0700 Subject: [PATCH 594/671] fix: fix 'dht query' command to actually return the closest peers Then improve the tests such that they actually work. --- core/commands/dht.go | 34 ++++++++++++++++++---------------- test/sharness/t0170-dht.sh | 28 ++++++++++++++++++---------- 2 files changed, 36 insertions(+), 26 deletions(-) diff --git a/core/commands/dht.go b/core/commands/dht.go index 6e140dfac13..aeaa7712b80 100644 --- a/core/commands/dht.go +++ b/core/commands/dht.go @@ -81,19 +81,23 @@ var queryDhtCmd = &cmds.Command{ dht = nd.DHT.LAN } - closestPeers, err := dht.GetClosestPeers(ctx, string(id)) - if err != nil { - cancel() - return err - } - + errCh := make(chan error, 1) go func() { + defer close(errCh) defer cancel() - for p := range closestPeers { - routing.PublishQueryEvent(ctx, &routing.QueryEvent{ - ID: p, - Type: routing.FinalPeer, - }) + closestPeers, err := dht.GetClosestPeers(ctx, string(id)) + if closestPeers != nil { + for p := range closestPeers { + routing.PublishQueryEvent(ctx, &routing.QueryEvent{ + ID: p, + Type: routing.FinalPeer, + }) + } + } + + if err != nil { + errCh <- err + return } }() @@ -103,15 +107,13 @@ var queryDhtCmd = &cmds.Command{ } } - return nil + return <-errCh }, Encoders: cmds.EncoderMap{ cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *routing.QueryEvent) error { pfm := pfuncMap{ - routing.PeerResponse: func(obj *routing.QueryEvent, out io.Writer, verbose bool) error { - for _, p := range obj.Responses { - fmt.Fprintf(out, "%s\n", p.ID.Pretty()) - } + routing.FinalPeer: func(obj *routing.QueryEvent, out io.Writer, verbose bool) error { + fmt.Fprintf(out, "%s\n", obj.ID) return nil }, } diff --git a/test/sharness/t0170-dht.sh b/test/sharness/t0170-dht.sh index 1e35a3a0b42..e76b8586089 100755 --- a/test/sharness/t0170-dht.sh +++ b/test/sharness/t0170-dht.sh @@ -76,16 +76,24 @@ test_dht() { # ipfs dht query - ## We query 3 different keys, to statisically lower the chance that the queryer - ## turns out to be the closest to what a key hashes to. - # TODO: flaky. tracked by https://github.com/ipfs/go-ipfs/issues/2620 - test_expect_success 'query' ' - ipfsi 3 dht query "$(echo banana | ipfsi 3 add -q)" >actual && - ipfsi 3 dht query "$(echo apple | ipfsi 3 add -q)" >>actual && - ipfsi 3 dht query "$(echo pear | ipfsi 3 add -q)" >>actual && - PEERS=$(wc -l actual | cut -d '"'"' '"'"' -f 1) && - [ -s actual ] || - test_might_fail test_fsh cat actual + # + # We test all nodes. 4 nodes should see the same peer ID, one node (the + # closest) should see a different one. + + for i in $(test_seq 0 4); do + test_expect_success "query from $i" ' + ipfsi "$i" dht query "$HASH" | head -1 >closest-$i + ' + done + + test_expect_success "collecting results" ' + cat closest-* | sort | uniq -c | sed -e "s/ *\([0-9]\+\) .*/\1/g" | sort -g > actual && + echo 1 > expected && + echo 4 >> expected + ' + + test_expect_success "checking results" ' + test_cmp actual expected ' test_expect_success 'stop iptb' ' From c12c184ca499d1059e684e010217c83b30752d65 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 13 Apr 2020 18:22:04 -0700 Subject: [PATCH 595/671] fix: invalidate cache on failed publish If we fail to publish, _invalidate_ our cache. The publish may have partially succeeded. --- namesys/cache.go | 7 +++++++ namesys/namesys.go | 3 +++ test/sharness/t0160-resolve.sh | 19 +++++++++++++------ 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/namesys/cache.go b/namesys/cache.go index a0029829d33..b2b1f43a8d8 100644 --- a/namesys/cache.go +++ b/namesys/cache.go @@ -49,6 +49,13 @@ func (ns *mpns) cacheSet(name string, val path.Path, ttl time.Duration) { }) } +func (ns *mpns) cacheInvalidate(name string) { + if ns.cache == nil { + return + } + ns.cache.Remove(name) +} + type cacheEntry struct { val path.Path eol time.Time diff --git a/namesys/namesys.go b/namesys/namesys.go index a486b83b8a3..0f076ea64e9 100644 --- a/namesys/namesys.go +++ b/namesys/namesys.go @@ -218,6 +218,9 @@ func (ns *mpns) PublishWithEOL(ctx context.Context, name ci.PrivKey, value path. return err } if err := ns.ipnsPublisher.PublishWithEOL(ctx, name, value, eol); err != nil { + // Invalidate the cache. Publishing may _partially_ succeed but + // still return an error. + ns.cacheInvalidate(peer.Encode(id)) return err } ttl := DefaultResolverCacheTTL diff --git a/test/sharness/t0160-resolve.sh b/test/sharness/t0160-resolve.sh index 62a6f5b3bfa..1524ed8d28e 100755 --- a/test/sharness/t0160-resolve.sh +++ b/test/sharness/t0160-resolve.sh @@ -153,17 +153,24 @@ test_resolve_cmd_fail() { test_resolve "/ipld/$dag_hash/i/j" "/ipld/$dag_hash/i/j" test_resolve "/ipld/$dag_hash/i" "/ipld/$dag_hash/i" + # At the moment, publishing _fails_ because we fail to put to the DHT. + # However, resolving succeeds because we resolve the record we put to our own + # node. + # + # We should find a nice way to truly support offline publishing. But this + # behavior isn't terrible. + test_resolve_setup_name_fail "self" "/ipfs/$a_hash" - test_resolve_fail "/ipns/$self_hash" "/ipfs/$a_hash" - test_resolve_fail "/ipns/$self_hash/b" "/ipfs/$b_hash" - test_resolve_fail "/ipns/$self_hash/b/c" "/ipfs/$c_hash" + test_resolve "/ipns/$self_hash" "/ipfs/$a_hash" + test_resolve "/ipns/$self_hash/b" "/ipfs/$b_hash" + test_resolve "/ipns/$self_hash/b/c" "/ipfs/$c_hash" test_resolve_setup_name_fail "self" "/ipfs/$b_hash" - test_resolve_fail "/ipns/$self_hash" "/ipfs/$b_hash" - test_resolve_fail "/ipns/$self_hash/c" "/ipfs/$c_hash" + test_resolve "/ipns/$self_hash" "/ipfs/$b_hash" + test_resolve "/ipns/$self_hash/c" "/ipfs/$c_hash" test_resolve_setup_name_fail "self" "/ipfs/$c_hash" - test_resolve_fail "/ipns/$self_hash" "/ipfs/$c_hash" + test_resolve "/ipns/$self_hash" "/ipfs/$c_hash" } # should work offline From e1f78e79299081b3330f65aa52ed5f27e4e847b7 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 13 Apr 2020 19:51:22 -0700 Subject: [PATCH 596/671] chore: update deps --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index cbca9b42014..fada361b479 100644 --- a/go.mod +++ b/go.mod @@ -66,12 +66,12 @@ require ( github.com/libp2p/go-libp2p-core v0.5.1 github.com/libp2p/go-libp2p-discovery v0.3.0 github.com/libp2p/go-libp2p-http v0.1.5 - github.com/libp2p/go-libp2p-kad-dht v0.7.2 + github.com/libp2p/go-libp2p-kad-dht v0.7.3 github.com/libp2p/go-libp2p-kbucket v0.4.1 github.com/libp2p/go-libp2p-loggables v0.1.0 github.com/libp2p/go-libp2p-mplex v0.2.3 github.com/libp2p/go-libp2p-peerstore v0.2.3 - github.com/libp2p/go-libp2p-pubsub v0.2.6 + github.com/libp2p/go-libp2p-pubsub v0.2.7 github.com/libp2p/go-libp2p-pubsub-router v0.2.1 github.com/libp2p/go-libp2p-quic-transport v0.3.3 github.com/libp2p/go-libp2p-record v0.1.2 diff --git a/go.sum b/go.sum index 2e2cfaff7d9..0b8f29abeea 100644 --- a/go.sum +++ b/go.sum @@ -551,8 +551,8 @@ github.com/libp2p/go-libp2p-interface-connmgr v0.0.1/go.mod h1:GarlRLH0LdeWcLnYM 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.7.2 h1:pmjjvk0q3wAQVLWWcFaYb0Ha+QXpa7NlzeXkKvhGYXU= -github.com/libp2p/go-libp2p-kad-dht v0.7.2/go.mod h1:+XvZEgO0gOAd9liN1wjdewxIdcdtWLJXG8U8ou2oo/A= +github.com/libp2p/go-libp2p-kad-dht v0.7.3 h1:veitKCfUhquYdPOSXoohm8gLymK+R0w7SmVHPBmF58k= +github.com/libp2p/go-libp2p-kad-dht v0.7.3/go.mod h1:+XvZEgO0gOAd9liN1wjdewxIdcdtWLJXG8U8ou2oo/A= github.com/libp2p/go-libp2p-kbucket v0.4.1 h1:6FyzbQuGLPzbMv3HiD232zqscIz5iB8ppJwb380+OGI= github.com/libp2p/go-libp2p-kbucket v0.4.1/go.mod h1:7sCeZx2GkNK1S6lQnGUW5JYZCFPnXzAZCCBBS70lytY= github.com/libp2p/go-libp2p-loggables v0.0.1/go.mod h1:lDipDlBNYbpyqyPX/KcoO+eq0sJYEVR2JgOexcivchg= @@ -605,8 +605,8 @@ github.com/libp2p/go-libp2p-protocol v0.0.1/go.mod h1:Af9n4PiruirSDjHycM1QuiMi/1 github.com/libp2p/go-libp2p-protocol v0.1.0/go.mod h1:KQPHpAabB57XQxGrXCNvbL6UEXfQqUgC/1adR2Xtflk= github.com/libp2p/go-libp2p-pubsub v0.2.5 h1:tPKbkjAUI0xLGN3KKTKKy9TQEviVfrP++zJgH5Muke4= github.com/libp2p/go-libp2p-pubsub v0.2.5/go.mod h1:9Q2RRq8ofXkoewORcyVlgUFDKLKw7BuYSlJVWRcVk3Y= -github.com/libp2p/go-libp2p-pubsub v0.2.6 h1:ypZaukCFrtD8cNeeb9nnWG4MD2Y1T0p22aQ+f7FKJig= -github.com/libp2p/go-libp2p-pubsub v0.2.6/go.mod h1:5jEp7R3ItQ0pgcEMrPZYE9DQTg/H3CTc7Mu1j2G4Y5o= +github.com/libp2p/go-libp2p-pubsub v0.2.7 h1:PBuK5+NfWsoaoEaAUZ7YQPETQh8UqBi8CbMJ1CZ5sNI= +github.com/libp2p/go-libp2p-pubsub v0.2.7/go.mod h1:R4R0kH/6p2vu8O9xsue0HNSjEuXMEPBgg4h3nVDI15o= github.com/libp2p/go-libp2p-pubsub-router v0.2.1 h1:F5JYaHQuuMKVbSgLsH2POQwT1rloWpc7fUCOq6PBjyE= github.com/libp2p/go-libp2p-pubsub-router v0.2.1/go.mod h1:cl46APmxgKgzgpCGFb8Ns7++cqnJ29CxESXCQATp55k= github.com/libp2p/go-libp2p-quic-transport v0.3.3 h1:A920y1nion8PkGKsEnMiho+3OHpXUqfy35YnPfta4aI= From 5772ac7a5f5b44a0806c2dcd76893aba22d614a6 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 13 Apr 2020 21:42:27 -0700 Subject: [PATCH 597/671] test(sharness): improve CAR tests to remove some potential races * Instead of ensuring that we GC nothing, verify that the repo validates. * Avoid a race between removing the fifos and trying to read from them. * Avoid all 'bash -c' invocations. Instead, make liberal use of subshells and wait. Hopefully fixes #7123. --- test/sharness/t0054-dag-car-import-export.sh | 67 +++++++++----------- 1 file changed, 29 insertions(+), 38 deletions(-) diff --git a/test/sharness/t0054-dag-car-import-export.sh b/test/sharness/t0054-dag-car-import-export.sh index 706f8b582cb..51151dd87ad 100755 --- a/test/sharness/t0054-dag-car-import-export.sh +++ b/test/sharness/t0054-dag-car-import-export.sh @@ -14,8 +14,8 @@ tab=$'\t' reset_blockstore() { node=$1 - ipfsi $node pin ls --quiet --type=recursive | ipfsi $node pin rm &>/dev/null - ipfsi $node repo gc &>/dev/null + ipfsi "$node" pin ls --quiet --type=recursive | ipfsi "$node" pin rm &>/dev/null + ipfsi "$node" repo gc &>/dev/null test_expect_success "pinlist empty" ' [[ -z "$( ipfsi $node pin ls )" ]] @@ -27,18 +27,20 @@ reset_blockstore() { # hammer with concurrent gc to ensure nothing clashes do_import() { - node=$1; shift + node="$1"; shift + ( + touch spin.gc - # for tests below expecting this to be non -z - echo "FIXME: BELOW TEST DISABLED FOR THE TIME BEING" > gc_out + while [[ -e spin.gc ]]; do ipfsi "$node" repo gc &>/dev/null; done & + while [[ -e spin.gc ]]; do ipfsi "$node" repo gc &>/dev/null; done & - #touch spin.gc - #timeout -s QUIT 30 bash -c "while [[ -e spin.gc ]]; do ipfsi $node repo gc &>>gc_out; done" & gc1_pid=$! - #timeout -s QUIT 25 bash -c "while [[ -e spin.gc ]]; do ipfsi $node repo gc &>>gc_out; done" & gc2_pid=$! + ipfsi "$node" dag import "$@" 2>&1 && ipfsi "$node" repo verify &>/dev/null + result=$? - timeout -s QUIT 20 bash -c "ipfsi $node dag import $* 2>&1" - - rm -f spin.gc || true + rm -f spin.gc &>/dev/null + wait + exit $result + ) } run_online_imp_exp_tests() { @@ -66,10 +68,6 @@ EOE | sort > basic_import_actual ' - # FIXME - positive-test the lack of output when https://github.com/ipfs/go-ipfs/issues/7121 is addressed - test_expect_failure "concurrent GC did not manage to grab anything and remained silent" ' - test_cmp /dev/null gc_out - ' test_expect_success "basic import output as expected" ' test_cmp basic_import_expected basic_import_actual ' @@ -107,37 +105,30 @@ EOE mkfifo pipe_testnet mkfifo pipe_devnet - # test that ipfs correctly opens both pipes and deleting them doesn't interfere with cleanup - bash -c ' - sleep 1 - cat ../t0054-dag-car-import-export-data/lotus_testnet_export_128_shuffled_nulroot.car > pipe_testnet & cat1_pid=$! - cat ../t0054-dag-car-import-export-data/lotus_devnet_genesis_shuffled_nulroot.car > pipe_devnet & cat2_pid=$! - - rm pipe_testnet pipe_devnet + test_expect_success "fifo import" ' + ( + cat ../t0054-dag-car-import-export-data/lotus_testnet_export_128_shuffled_nulroot.car > pipe_testnet & + cat ../t0054-dag-car-import-export-data/lotus_devnet_genesis_shuffled_nulroot.car > pipe_devnet & - # extra safety valve to kill the cat processes in case something goes wrong - bash -c "sleep 60; kill $cat1_pid $cat2_pid 2>/dev/null" & - ' & + do_import 0 \ + pipe_testnet \ + pipe_devnet \ + ../t0054-dag-car-import-export-data/combined_naked_roots_genesis_and_128.car \ + | sort > basic_fifo_import_actual + result=$? - test_expect_success "fifo import" ' - do_import 0 \ - pipe_testnet \ - pipe_devnet \ - ../t0054-dag-car-import-export-data/combined_naked_roots_genesis_and_128.car \ - | sort > basic_fifo_import_actual + wait + exit "$result" + ) ' - # FIXME - positive-test the lack of output when https://github.com/ipfs/go-ipfs/issues/7121 is addressed - test_expect_failure "concurrent GC did not manage to grab anything and remained silent" ' - test_cmp /dev/null gc_out + + test_expect_success "remove fifos" ' + rm pipe_testnet pipe_devnet ' test_expect_success "fifo-import output as expected" ' test_cmp basic_import_expected basic_fifo_import_actual ' - - test_expect_success "fifos no longer present" ' - ! [[ -e pipe_testnet ]] && ! [[ -e pipe_devnet ]] - ' } From 90b7b53a4024e6b367d36282ccb0251cfe0e780b Mon Sep 17 00:00:00 2001 From: Roman Khafizianov Date: Tue, 14 Apr 2020 13:24:49 +0300 Subject: [PATCH 598/671] fix the typo in the serveHTTPApi It looks like the incorrect address passed into the logger in case of error --- cmd/ipfs/daemon.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/ipfs/daemon.go b/cmd/ipfs/daemon.go index 26761fa4266..54c46337c08 100644 --- a/cmd/ipfs/daemon.go +++ b/cmd/ipfs/daemon.go @@ -473,7 +473,7 @@ func serveHTTPApi(req *cmds.Request, cctx *oldcmds.Context) (<-chan error, error for _, addr := range apiAddrs { apiMaddr, err := ma.NewMultiaddr(addr) if err != nil { - return nil, fmt.Errorf("serveHTTPApi: invalid API address: %q (err: %s)", apiAddr, err) + return nil, fmt.Errorf("serveHTTPApi: invalid API address: %q (err: %s)", addr, err) } if listenerAddrs[string(apiMaddr.Bytes())] { continue From 81ed4a14309cd83c2349e4596f17788c003626b5 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Tue, 14 Apr 2020 15:10:10 +0100 Subject: [PATCH 599/671] docs: fix link to version.go --- docs/RELEASE_ISSUE_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/RELEASE_ISSUE_TEMPLATE.md b/docs/RELEASE_ISSUE_TEMPLATE.md index 736b0dee9ea..7cdfcfd3433 100644 --- a/docs/RELEASE_ISSUE_TEMPLATE.md +++ b/docs/RELEASE_ISSUE_TEMPLATE.md @@ -79,7 +79,7 @@ Checklist: - [ ] IRC - [ ] **Stage 4 - Release** - [ ] Final preparation - - [ ] Verify that version string in [`repo/version.go`](https://github.com/ipfs/go-ipfs/tree/master/repo/version.go) has been updated + - [ ] Verify that version string in [`version.go`](https://github.com/ipfs/go-ipfs/tree/master/version.go) has been updated - [ ] tag commit with vX.Y.Z - [ ] update release branch to point to release commit (`git merge vX.Y.Z`). - [ ] Release published From 7d397ac219f57bc1e74d7808dc17f228104e3bd6 Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Tue, 14 Apr 2020 17:51:25 +0200 Subject: [PATCH 600/671] feat: webui v2.7.4 (supersedes v2.7.3) License: MIT Signed-off-by: Marcin Rataj --- core/corehttp/webui.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/corehttp/webui.go b/core/corehttp/webui.go index 4a31f719a94..5e9839a6dcb 100644 --- a/core/corehttp/webui.go +++ b/core/corehttp/webui.go @@ -1,7 +1,7 @@ package corehttp // TODO: move to IPNS -const WebUIPath = "/ipfs/bafybeihpkhgv3jfnyx5qcexded7agjpwbgvtc3o6lnk6n3cs37fh4xx4fe" +const WebUIPath = "/ipfs/bafybeigxqbvc6qxk2wkdyzpkh7mr7zh5pxbvpjb6a6mxdtpwhlqaf4qj5a" // this is a list of all past webUI paths. var WebUIPaths = []string{ From 9a9841074ff92597be9a2bb5fc3587f35af9905f Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Tue, 14 Apr 2020 16:41:13 -0700 Subject: [PATCH 601/671] chore: update bitswap Remove some allocation hotspots --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index fada361b479..426a224ee69 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/gogo/protobuf v1.3.1 github.com/hashicorp/go-multierror v1.1.0 github.com/hashicorp/golang-lru v0.5.4 - github.com/ipfs/go-bitswap v0.2.9 + github.com/ipfs/go-bitswap v0.2.10 github.com/ipfs/go-block-format v0.0.2 github.com/ipfs/go-blockservice v0.1.3 github.com/ipfs/go-cid v0.0.5 diff --git a/go.sum b/go.sum index 0b8f29abeea..07d44c20bd2 100644 --- a/go.sum +++ b/go.sum @@ -214,8 +214,8 @@ github.com/ipfs/go-bitswap v0.1.0/go.mod h1:FFJEf18E9izuCqUtHxbWEvq+reg7o4CW5wSA 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.9 h1:23xzQ5kWx9F3Q4PrBS9nbPwMsxdWHXeD9nZX1/ozTlI= -github.com/ipfs/go-bitswap v0.2.9/go.mod h1:2Yjog0GMdH8+AsxkE0DI9D2mANaUTxbVVav0pPoZoug= +github.com/ipfs/go-bitswap v0.2.10 h1:jO16YYZ7ZT0Utf61hM/pENcptl8BfxX29z4HtKNPJkA= +github.com/ipfs/go-bitswap v0.2.10/go.mod h1:2Yjog0GMdH8+AsxkE0DI9D2mANaUTxbVVav0pPoZoug= github.com/ipfs/go-block-format v0.0.1/go.mod h1:DK/YYcsSUIVAFNwo/KZCdIIbpN0ROH/baNLgayt4pFc= github.com/ipfs/go-block-format v0.0.2 h1:qPDvcP19izTjU8rgo6p7gTXZlkMkF5bz5G3fqIsSCPE= github.com/ipfs/go-block-format v0.0.2/go.mod h1:AWR46JfpcObNfg3ok2JHDUfdiHRgWhJgCQF+KIgOPJY= From 1f23fc000c01605d51ddaaf01ff7402a330e8f9c Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Tue, 14 Apr 2020 20:40:45 -0700 Subject: [PATCH 602/671] feat: add autonat config options 1. Enable AutoNATService on _all_ nodes by default. If it's an issue, we can disable it in RC3 but this will give us the best testing results. 2. Expose options to configure AutoNAT rate limiting. --- core/node/groups.go | 21 ++++++++++++++- core/node/libp2p/nat.go | 22 +++++++++++++++- docs/config.md | 47 +++++++++++++++++++++++++++++++--- go.mod | 4 +-- go.sum | 8 ++++-- test/sharness/t0185-autonat.sh | 10 +++++++- 6 files changed, 101 insertions(+), 11 deletions(-) diff --git a/core/node/groups.go b/core/node/groups.go index 5b5c8476abe..f94d97634b1 100644 --- a/core/node/groups.go +++ b/core/node/groups.go @@ -90,6 +90,25 @@ func LibP2P(bcfg *BuildCfg, cfg *config.Config) fx.Option { } } + autonat := fx.Options() + + switch cfg.AutoNAT.ServiceMode { + default: + panic("BUG: unhandled autonat service mode") + case config.AutoNATServiceDisabled: + case config.AutoNATServiceUnset: + // TODO + // + // We're enabling the AutoNAT service by default on _all_ nodes + // for the moment. + // + // We should consider disabling it by default if the dht is set + // to dhtclient. + fallthrough + case config.AutoNATServiceEnabled: + autonat = fx.Provide(libp2p.AutoNATService(cfg.AutoNAT.Throttle)) + } + // Gather all the options opts := fx.Options( @@ -110,9 +129,9 @@ func LibP2P(bcfg *BuildCfg, cfg *config.Config) fx.Option { maybeProvide(libp2p.BandwidthCounter, !cfg.Swarm.DisableBandwidthMetrics), maybeProvide(libp2p.NatPortMap, !cfg.Swarm.DisableNatPortMap), - maybeProvide(libp2p.AutoNATService, cfg.Swarm.EnableAutoNATService), maybeProvide(libp2p.AutoRelay, cfg.Swarm.EnableAutoRelay), maybeProvide(libp2p.QUIC, cfg.Experimental.QUIC), + autonat, connmgr, ps, disc, diff --git a/core/node/libp2p/nat.go b/core/node/libp2p/nat.go index 28ce03203c2..9fe74d91cb3 100644 --- a/core/node/libp2p/nat.go +++ b/core/node/libp2p/nat.go @@ -1,8 +1,28 @@ package libp2p import ( + "time" + + "github.com/ipfs/go-ipfs-config" "github.com/libp2p/go-libp2p" ) var NatPortMap = simpleOpt(libp2p.NATPortMap()) -var AutoNATService = simpleOpt(libp2p.EnableNATService()) + +func AutoNATService(throttle *config.AutoNATThrottleConfig) func() Libp2pOpts { + return func() (opts Libp2pOpts) { + opts.Opts = append(opts.Opts, libp2p.EnableNATService()) + if throttle != nil { + global := throttle.GlobalLimit + peer := throttle.PeerLimit + interval := time.Duration(throttle.Interval) + if interval == 0 { + interval = time.Minute + } + opts.Opts = append(opts.Opts, + libp2p.AutoNATServiceRateLimit(global, peer, interval), + ) + } + return opts + } +} diff --git a/docs/config.md b/docs/config.md index 03b64ef45f1..371e0c44396 100644 --- a/docs/config.md +++ b/docs/config.md @@ -192,6 +192,47 @@ Example: Default: `null` +## `AutoNAT` + +Contains the configuration options for the AutoNAT service. The AutoNAT service +helps other nodes on the network determine if they're publicly reachable from +the rest of the internet. + +### `AutoNAT.ServiceMode` + +When unset (default), the AutoNAT service defaults to _enabled_. Otherwise, this +field can take one of two values: + +* "enabled" - Enable the service (unless the node determines that it, itself, + isn't reachable by the public internet). +* "disabled" - Disable the service. + +Additional modes may be added in the future. + +### `AutoNAT.Throttle` + +When set, this option configure's the AutoNAT services throttling behavior. By +default, go-ipfs will rate-limit the number of NAT checks performed for other +nodes to 30 per minute, and 3 per peer. + +### `AutoNAT.Throttle.GlobalLimit` + +Configures how many AutoNAT requests to service per `AutoNAT.Throttle.Interval`. + +Default: 30 + +### `AutoNAT.Throttle.PeerLimit` + +Configures how many AutoNAT requests per-peer to service per `AutoNAT.Throttle.Interval`. + +Default: 3 + +### `AutoNAT.Throttle.Interval` + +Configures the interval for the above limits. + +Default: 1 Minute + ## `Bootstrap` Bootstrap is an array of multiaddrs of trusted nodes to connect to in order to @@ -700,11 +741,9 @@ DHT and override its public address(es) with relay addresses. ### `Swarm.EnableAutoNATService` -Enables the AutoNAT service for this node. +**REMOVED** -The service allows peers to discover their NAT situation by requesting dial -backs to their public addresses. This should only be enabled on publicly -reachable nodes. +Please use [`AutoNAT.ServiceMode`][]. ### `Swarm.ConnMgr` diff --git a/go.mod b/go.mod index 426a224ee69..684a563afaa 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,7 @@ require ( github.com/ipfs/go-ipfs-blockstore v0.1.4 github.com/ipfs/go-ipfs-chunker v0.0.5 github.com/ipfs/go-ipfs-cmds v0.2.2 - github.com/ipfs/go-ipfs-config v0.4.0 + github.com/ipfs/go-ipfs-config v0.5.2 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 @@ -60,7 +60,7 @@ require ( github.com/jbenet/go-temp-err-catcher v0.1.0 github.com/jbenet/goprocess v0.1.4 github.com/libp2p/go-eventbus v0.1.0 - github.com/libp2p/go-libp2p v0.7.4 + github.com/libp2p/go-libp2p v0.8.0 github.com/libp2p/go-libp2p-circuit v0.2.1 github.com/libp2p/go-libp2p-connmgr v0.2.1 github.com/libp2p/go-libp2p-core v0.5.1 diff --git a/go.sum b/go.sum index 07d44c20bd2..40e8b33c9ee 100644 --- a/go.sum +++ b/go.sum @@ -293,8 +293,8 @@ github.com/ipfs/go-ipfs-chunker v0.0.5 h1:ojCf7HV/m+uS2vhUGWcogIIxiO5ubl5O57Q7Na github.com/ipfs/go-ipfs-chunker v0.0.5/go.mod h1:jhgdF8vxRHycr00k13FM8Y0E+6BoalYeobXmUyTreP8= github.com/ipfs/go-ipfs-cmds v0.2.2 h1:F2pro/Q3ifRUsdxEKIS8cg8lO4R6WiwAyERiaG8I9no= github.com/ipfs/go-ipfs-cmds v0.2.2/go.mod h1:kqlUrp6m2ceoaJe40cXpADCi5aS6NKRn0NIeuLp5CeM= -github.com/ipfs/go-ipfs-config v0.4.0 h1:MOXdj8EYQG55v1y+5e1QcctDKPEGobdwnXaDVa0/cc0= -github.com/ipfs/go-ipfs-config v0.4.0/go.mod h1:nSLCFtlaL+2rbl3F+9D4gQZQbT1LjRKx7TJg/IHz6oM= +github.com/ipfs/go-ipfs-config v0.5.2 h1:SPWiMNo7IOW0k+meO3PIprggp/PbZGUiO57L7HQ/sOY= +github.com/ipfs/go-ipfs-config v0.5.2/go.mod h1:nSLCFtlaL+2rbl3F+9D4gQZQbT1LjRKx7TJg/IHz6oM= github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= github.com/ipfs/go-ipfs-delay v0.0.1 h1:r/UXYyRcddO6thwOnhiznIAiSvxMECGgtv35Xs1IeRQ= github.com/ipfs/go-ipfs-delay v0.0.1/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= @@ -484,6 +484,8 @@ github.com/libp2p/go-libp2p v0.7.0 h1:qWmciout2lJclKfRlxqdepsQB7JihcbRhgcRcssP4r github.com/libp2p/go-libp2p v0.7.0/go.mod h1:hZJf8txWeCduQRDC/WSqBGMxaTHCOYHt2xSU1ivxn0k= github.com/libp2p/go-libp2p v0.7.4 h1:xVj1oSlN0C+FlxqiLuHC8WruMvq24xxfeVxmNhTG0r0= github.com/libp2p/go-libp2p v0.7.4/go.mod h1:oXsBlTLF1q7pxr+9w6lqzS1ILpyHsaBPniVO7zIHGMw= +github.com/libp2p/go-libp2p v0.8.0 h1:8t8kAJM+o4rR91bfwbgbtykbdqPJv819+CTSPkXDT1A= +github.com/libp2p/go-libp2p v0.8.0/go.mod h1:QRNH9pwdbEBpx5DTJYg+qxcVaDMAz3Ee/qDKwXujH5o= 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 h1:aCWAu43Ri4nU0ZPO7NyLzUvvfqd0nE3dX0R/ZGYVgOU= @@ -494,6 +496,8 @@ github.com/libp2p/go-libp2p-autonat v0.2.0 h1:Kok+0M/4jiz6TTmxtBqAa5tLyHb/U+G/7o github.com/libp2p/go-libp2p-autonat v0.2.0/go.mod h1:DX+9teU4pEEoZUqR1PiMlqliONQdNbfzE1C718tcViI= github.com/libp2p/go-libp2p-autonat v0.2.1 h1:T0CRQhrvTBKfBSYw6Xo2K3ixtNpAnRCraxof3AAfgQA= github.com/libp2p/go-libp2p-autonat v0.2.1/go.mod h1:MWtAhV5Ko1l6QBsHQNSuM6b1sRkXrpk0/LqCr+vCVxI= +github.com/libp2p/go-libp2p-autonat v0.2.2 h1:4dlgcEEugTFWSvdG2UIFxhnOMpX76QaZSRAtXmYB8n4= +github.com/libp2p/go-libp2p-autonat v0.2.2/go.mod h1:HsM62HkqZmHR2k1xgX34WuWDzk/nBwNHoeyyT4IWV6A= github.com/libp2p/go-libp2p-blankhost v0.0.1/go.mod h1:Ibpbw/7cPPYwFb7PACIWdvxxv0t0XCCI10t7czjAjTc= github.com/libp2p/go-libp2p-blankhost v0.1.1/go.mod h1:pf2fvdLJPsC1FsVrNP3DUUvMzUts2dsLLBEpo1vW1ro= github.com/libp2p/go-libp2p-blankhost v0.1.3/go.mod h1:KML1//wiKR8vuuJO0y3LUd1uLv+tlkGTAr3jC0S5cLg= diff --git a/test/sharness/t0185-autonat.sh b/test/sharness/t0185-autonat.sh index 88ae053e217..9cde1ad5cbd 100755 --- a/test/sharness/t0185-autonat.sh +++ b/test/sharness/t0185-autonat.sh @@ -11,7 +11,15 @@ test_description="Test autonat" test_init_ipfs test_expect_success "enable autonat" ' - ipfs config --json Swarm.EnableAutoNATService true + ipfs config AutoNAT.ServiceMode enabled +' + +test_launch_ipfs_daemon + +test_kill_ipfs_daemon + +test_expect_success "enable autonat" ' + ipfs config AutoNAT.ServiceMode disabled ' test_launch_ipfs_daemon From d63761bc9f67b0f9e71e668782bbe83bdbe59f64 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Tue, 14 Apr 2020 21:19:57 -0700 Subject: [PATCH 603/671] release: go-ipfs 0.5.0-rc2 --- version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.go b/version.go index 0bf72334c72..415ab7c03ac 100644 --- a/version.go +++ b/version.go @@ -4,7 +4,7 @@ package ipfs var CurrentCommit string // CurrentVersionNumber is the current application's version literal -const CurrentVersionNumber = "0.5.0-rc1" +const CurrentVersionNumber = "0.5.0-rc2" const ApiVersion = "/go-ipfs/" + CurrentVersionNumber + "/" From 635a5c798eb3d2b3468fbd7004f93865b1527eae Mon Sep 17 00:00:00 2001 From: Will Scott Date: Mon, 13 Apr 2020 17:10:01 -0700 Subject: [PATCH 604/671] integration test for the dual dht --- test/integration/wan_lan_dht_test.go | 223 +++++++++++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 test/integration/wan_lan_dht_test.go diff --git a/test/integration/wan_lan_dht_test.go b/test/integration/wan_lan_dht_test.go new file mode 100644 index 00000000000..7950a1254e5 --- /dev/null +++ b/test/integration/wan_lan_dht_test.go @@ -0,0 +1,223 @@ +package integrationtest + +import ( + "context" + "encoding/binary" + "fmt" + "math" + "math/rand" + "net" + "testing" + "time" + + "github.com/ipfs/go-cid" + "github.com/ipfs/go-ipfs/core" + "github.com/ipfs/go-ipfs/core/bootstrap" + mock "github.com/ipfs/go-ipfs/core/mock" + + corenet "github.com/libp2p/go-libp2p-core/network" + peer "github.com/libp2p/go-libp2p-core/peer" + "github.com/libp2p/go-libp2p-core/peerstore" + testutil "github.com/libp2p/go-libp2p-testing/net" + mocknet "github.com/libp2p/go-libp2p/p2p/net/mock" + + ma "github.com/multiformats/go-multiaddr" +) + +func TestDHTConnectivityFast(t *testing.T) { + conf := testutil.LatencyConfig{ + NetworkLatency: 0, + RoutingLatency: 0, + BlockstoreLatency: 0, + } + if err := RunDHTConnectivity(conf, 5); err != nil { + t.Fatal(err) + } +} + +func TestDHTConnectivitySlowNetwork(t *testing.T) { + SkipUnlessEpic(t) + conf := testutil.LatencyConfig{NetworkLatency: 400 * time.Millisecond} + if err := RunDHTConnectivity(conf, 5); err != nil { + t.Fatal(err) + } +} + +func TestDHTConnectivitySlowRouting(t *testing.T) { + SkipUnlessEpic(t) + conf := testutil.LatencyConfig{RoutingLatency: 400 * time.Millisecond} + if err := RunDHTConnectivity(conf, 5); err != nil { + t.Fatal(err) + } +} + +var wanPrefix = net.ParseIP("100::") +var lanPrefix = net.ParseIP("fe80::") + +func makeAddr(n uint32, wan bool) ma.Multiaddr { + var ip net.IP + if wan { + ip = append(net.IP{}, wanPrefix...) + } else { + ip = append(net.IP{}, lanPrefix...) + } + + binary.LittleEndian.PutUint32(ip[4:], n) + addr, _ := ma.NewMultiaddr(fmt.Sprintf("/ip6/%s/tcp/4242", ip)) + return addr +} + +func RunDHTConnectivity(conf testutil.LatencyConfig, numPeers int) error { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // create network + mn := mocknet.New(ctx) + mn.SetLinkDefaults(mocknet.LinkOptions{ + Latency: conf.NetworkLatency, + Bandwidth: math.MaxInt32, + }) + + testPeer, err := core.NewNode(ctx, &core.BuildCfg{ + Online: true, + Host: mock.MockHostOption(mn), + }) + if err != nil { + return err + } + defer testPeer.Close() + + wanPeers := []*core.IpfsNode{} + lanPeers := []*core.IpfsNode{} + + for i := 0; i < numPeers; i++ { + wanPeer, err := core.NewNode(ctx, &core.BuildCfg{ + Online: true, + Host: mock.MockHostOption(mn), + }) + if err != nil { + return err + } + defer wanPeer.Close() + wanAddr := makeAddr(uint32(i), true) + wanPeer.Peerstore.AddAddr(wanPeer.Identity, wanAddr, peerstore.PermanentAddrTTL) + for _, p := range wanPeers { + mn.ConnectPeers(p.Identity, wanPeer.Identity) + } + wanPeers = append(wanPeers, wanPeer) + + lanPeer, err := core.NewNode(ctx, &core.BuildCfg{ + Online: true, + Host: mock.MockHostOption(mn), + }) + if err != nil { + return err + } + defer lanPeer.Close() + lanAddr := makeAddr(uint32(i), false) + lanPeer.Peerstore.AddAddr(lanPeer.Identity, lanAddr, peerstore.PermanentAddrTTL) + for _, p := range lanPeers { + mn.ConnectPeers(p.Identity, lanPeer.Identity) + } + lanPeers = append(lanPeers, lanPeer) + } + + // The test peer is connected to one lan peer. + _, err = mn.ConnectPeers(testPeer.Identity, lanPeers[0].Identity) + if err != nil { + return err + } + + err, done := <-testPeer.DHT.RefreshRoutingTable() + if err != nil || !done { + if !done { + err = fmt.Errorf("expected refresh routing table to close") + } + return err + } + + // choose a lan peer and validate lan DHT is functioning. + i := rand.Intn(len(lanPeers)) + if testPeer.PeerHost.Network().Connectedness(lanPeers[i].Identity) == corenet.Connected { + testPeer.PeerHost.Network().ClosePeer(lanPeers[i].Identity) + testPeer.PeerHost.Peerstore().ClearAddrs(lanPeers[i].Identity) + } + // That peer will provide a new CID, and we'll validate the test node can find it. + provideCid := cid.NewCidV1(cid.Raw, []byte("Lan Provide Record")) + provideCtx, cancel := context.WithTimeout(ctx, time.Second) + defer cancel() + if err := lanPeers[i].DHT.Provide(provideCtx, provideCid, true); err != nil { + return err + } + provs, err := testPeer.DHT.FindProviders(provideCtx, provideCid) + if err != nil { + return err + } + if len(provs) != 1 { + return fmt.Errorf("Expected one provider, got %d", len(provs)) + } + if provs[0].ID != lanPeers[i].Identity { + return fmt.Errorf("Unexpected lan peer provided record") + } + + // Now, bootstrap from a wan peer. + bis := wanPeers[0].Peerstore.PeerInfo(wanPeers[0].PeerHost.ID()) + bcfg := bootstrap.BootstrapConfigWithPeers([]peer.AddrInfo{bis}) + if err := testPeer.Bootstrap(bcfg); err != nil { + return err + } + + err, done = <-testPeer.DHT.RefreshRoutingTable() + if err != nil || !done { + if !done { + err = fmt.Errorf("expected refresh routing table to close") + } + return err + } + + // choose a wan peer and validate wan DHT is functioning. + i = rand.Intn(len(wanPeers)) + if testPeer.PeerHost.Network().Connectedness(wanPeers[i].Identity) == corenet.Connected { + testPeer.PeerHost.Network().ClosePeer(wanPeers[i].Identity) + testPeer.PeerHost.Peerstore().ClearAddrs(wanPeers[i].Identity) + } + // That peer will provide a new CID, and we'll validate the test node can find it. + wanCid := cid.NewCidV1(cid.Raw, []byte("Wan Provide Record")) + wanProvideCtx, cancel := context.WithTimeout(ctx, time.Second) + defer cancel() + if err := wanPeers[i].DHT.Provide(wanProvideCtx, wanCid, true); err != nil { + return err + } + provs, err = testPeer.DHT.FindProviders(wanProvideCtx, wanCid) + if err != nil { + return err + } + if len(provs) != 1 { + return fmt.Errorf("Expected one provider, got %d", len(provs)) + } + if provs[0].ID != wanPeers[i].Identity { + return fmt.Errorf("Unexpected lan peer provided record") + } + + // Finally, re-share the lan provided cid from a wan peer and expect a merged result. + i = rand.Intn(len(wanPeers)) + if testPeer.PeerHost.Network().Connectedness(wanPeers[i].Identity) == corenet.Connected { + testPeer.PeerHost.Network().ClosePeer(wanPeers[i].Identity) + testPeer.PeerHost.Peerstore().ClearAddrs(wanPeers[i].Identity) + } + + provideCtx, cancel = context.WithTimeout(ctx, time.Second) + defer cancel() + if err := wanPeers[i].DHT.Provide(provideCtx, provideCid, true); err != nil { + return err + } + provs, err = testPeer.DHT.FindProviders(provideCtx, provideCid) + if err != nil { + return err + } + if len(provs) != 2 { + return fmt.Errorf("Expected two providers, got %d", len(provs)) + } + + return nil +} From 02cf54dec679cf723fb6a48ef32e9f1b70c23296 Mon Sep 17 00:00:00 2001 From: Will Scott Date: Tue, 14 Apr 2020 08:15:19 -0700 Subject: [PATCH 605/671] rebase on dual DHT --- test/integration/wan_lan_dht_test.go | 58 ++++++++++++++++++---------- 1 file changed, 37 insertions(+), 21 deletions(-) diff --git a/test/integration/wan_lan_dht_test.go b/test/integration/wan_lan_dht_test.go index 7950a1254e5..e66c78d0f75 100644 --- a/test/integration/wan_lan_dht_test.go +++ b/test/integration/wan_lan_dht_test.go @@ -102,6 +102,7 @@ func RunDHTConnectivity(conf testutil.LatencyConfig, numPeers int) error { wanAddr := makeAddr(uint32(i), true) wanPeer.Peerstore.AddAddr(wanPeer.Identity, wanAddr, peerstore.PermanentAddrTTL) for _, p := range wanPeers { + mn.LinkPeers(p.Identity, wanPeer.Identity) mn.ConnectPeers(p.Identity, wanPeer.Identity) } wanPeers = append(wanPeers, wanPeer) @@ -117,18 +118,30 @@ func RunDHTConnectivity(conf testutil.LatencyConfig, numPeers int) error { lanAddr := makeAddr(uint32(i), false) lanPeer.Peerstore.AddAddr(lanPeer.Identity, lanAddr, peerstore.PermanentAddrTTL) for _, p := range lanPeers { + mn.LinkPeers(p.Identity, lanPeer.Identity) mn.ConnectPeers(p.Identity, lanPeer.Identity) } lanPeers = append(lanPeers, lanPeer) } + // Add interfaces / addresses to test peer. + wanAddr := makeAddr(0, true) + testPeer.Peerstore.AddAddr(testPeer.Identity, wanAddr, peerstore.PermanentAddrTTL) + lanAddr := makeAddr(0, false) + testPeer.Peerstore.AddAddr(testPeer.Identity, lanAddr, peerstore.PermanentAddrTTL) + // The test peer is connected to one lan peer. + for _, p := range lanPeers { + if _, err := mn.LinkPeers(testPeer.Identity, p.Identity); err != nil { + return err + } + } _, err = mn.ConnectPeers(testPeer.Identity, lanPeers[0].Identity) if err != nil { return err } - err, done := <-testPeer.DHT.RefreshRoutingTable() + err, done := <-testPeer.DHT.LAN.RefreshRoutingTable() if err != nil || !done { if !done { err = fmt.Errorf("expected refresh routing table to close") @@ -149,25 +162,28 @@ func RunDHTConnectivity(conf testutil.LatencyConfig, numPeers int) error { if err := lanPeers[i].DHT.Provide(provideCtx, provideCid, true); err != nil { return err } - provs, err := testPeer.DHT.FindProviders(provideCtx, provideCid) - if err != nil { - return err + provChan := testPeer.DHT.FindProvidersAsync(provideCtx, provideCid, 0) + prov, ok := <-provChan + if !ok || prov.ID == "" { + return fmt.Errorf("Expected provider. stream closed early") } - if len(provs) != 1 { - return fmt.Errorf("Expected one provider, got %d", len(provs)) - } - if provs[0].ID != lanPeers[i].Identity { + if prov.ID != lanPeers[i].Identity { return fmt.Errorf("Unexpected lan peer provided record") } // Now, bootstrap from a wan peer. + for _, p := range wanPeers { + if _, err := mn.LinkPeers(testPeer.Identity, p.Identity); err != nil { + return err + } + } bis := wanPeers[0].Peerstore.PeerInfo(wanPeers[0].PeerHost.ID()) bcfg := bootstrap.BootstrapConfigWithPeers([]peer.AddrInfo{bis}) if err := testPeer.Bootstrap(bcfg); err != nil { return err } - err, done = <-testPeer.DHT.RefreshRoutingTable() + err, done = <-testPeer.DHT.WAN.RefreshRoutingTable() if err != nil || !done { if !done { err = fmt.Errorf("expected refresh routing table to close") @@ -188,14 +204,12 @@ func RunDHTConnectivity(conf testutil.LatencyConfig, numPeers int) error { if err := wanPeers[i].DHT.Provide(wanProvideCtx, wanCid, true); err != nil { return err } - provs, err = testPeer.DHT.FindProviders(wanProvideCtx, wanCid) - if err != nil { - return err + provChan = testPeer.DHT.FindProvidersAsync(wanProvideCtx, wanCid, 0) + prov, ok = <-provChan + if !ok || prov.ID == "" { + return fmt.Errorf("Expected one provider, closed early") } - if len(provs) != 1 { - return fmt.Errorf("Expected one provider, got %d", len(provs)) - } - if provs[0].ID != wanPeers[i].Identity { + if prov.ID != wanPeers[i].Identity { return fmt.Errorf("Unexpected lan peer provided record") } @@ -211,12 +225,14 @@ func RunDHTConnectivity(conf testutil.LatencyConfig, numPeers int) error { if err := wanPeers[i].DHT.Provide(provideCtx, provideCid, true); err != nil { return err } - provs, err = testPeer.DHT.FindProviders(provideCtx, provideCid) - if err != nil { - return err + provChan = testPeer.DHT.FindProvidersAsync(provideCtx, provideCid, 0) + prov, ok = <-provChan + if !ok { + return fmt.Errorf("Expected two providers, got 0") } - if len(provs) != 2 { - return fmt.Errorf("Expected two providers, got %d", len(provs)) + prov, ok = <-provChan + if !ok { + return fmt.Errorf("Expected two providers, got 1") } return nil From 94de6055702618c9b1b5f790965e18d72fd75434 Mon Sep 17 00:00:00 2001 From: Will Scott Date: Tue, 14 Apr 2020 12:26:02 -0700 Subject: [PATCH 606/671] startup bootstrap --- test/integration/wan_lan_dht_test.go | 51 ++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 11 deletions(-) diff --git a/test/integration/wan_lan_dht_test.go b/test/integration/wan_lan_dht_test.go index e66c78d0f75..7d32aaffd35 100644 --- a/test/integration/wan_lan_dht_test.go +++ b/test/integration/wan_lan_dht_test.go @@ -7,6 +7,7 @@ import ( "math" "math/rand" "net" + "os" "testing" "time" @@ -18,6 +19,7 @@ import ( corenet "github.com/libp2p/go-libp2p-core/network" peer "github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/peerstore" + kbucket "github.com/libp2p/go-libp2p-kbucket" testutil "github.com/libp2p/go-libp2p-testing/net" mocknet "github.com/libp2p/go-libp2p/p2p/net/mock" @@ -90,6 +92,8 @@ func RunDHTConnectivity(conf testutil.LatencyConfig, numPeers int) error { wanPeers := []*core.IpfsNode{} lanPeers := []*core.IpfsNode{} + connectionContext, connCtxCancel := context.WithTimeout(ctx, 15*time.Second) + defer connCtxCancel() for i := 0; i < numPeers; i++ { wanPeer, err := core.NewNode(ctx, &core.BuildCfg{ Online: true, @@ -103,7 +107,7 @@ func RunDHTConnectivity(conf testutil.LatencyConfig, numPeers int) error { wanPeer.Peerstore.AddAddr(wanPeer.Identity, wanAddr, peerstore.PermanentAddrTTL) for _, p := range wanPeers { mn.LinkPeers(p.Identity, wanPeer.Identity) - mn.ConnectPeers(p.Identity, wanPeer.Identity) + wanPeer.PeerHost.Connect(connectionContext, p.Peerstore.PeerInfo(p.Identity)) } wanPeers = append(wanPeers, wanPeer) @@ -119,10 +123,11 @@ func RunDHTConnectivity(conf testutil.LatencyConfig, numPeers int) error { lanPeer.Peerstore.AddAddr(lanPeer.Identity, lanAddr, peerstore.PermanentAddrTTL) for _, p := range lanPeers { mn.LinkPeers(p.Identity, lanPeer.Identity) - mn.ConnectPeers(p.Identity, lanPeer.Identity) + lanPeer.PeerHost.Connect(connectionContext, p.Peerstore.PeerInfo(p.Identity)) } lanPeers = append(lanPeers, lanPeer) } + connCtxCancel() // Add interfaces / addresses to test peer. wanAddr := makeAddr(0, true) @@ -136,24 +141,48 @@ func RunDHTConnectivity(conf testutil.LatencyConfig, numPeers int) error { return err } } - _, err = mn.ConnectPeers(testPeer.Identity, lanPeers[0].Identity) + err = testPeer.PeerHost.Connect(ctx, lanPeers[0].Peerstore.PeerInfo(lanPeers[0].Identity)) if err != nil { return err } - err, done := <-testPeer.DHT.LAN.RefreshRoutingTable() - if err != nil || !done { - if !done { - err = fmt.Errorf("expected refresh routing table to close") + startupCtx, startupCancel := context.WithTimeout(ctx, time.Second*15) + testPeer.DHT.Bootstrap(startupCtx) +StartupWait: + for { + select { + case err, done := <-testPeer.DHT.LAN.RefreshRoutingTable(): + if err.Error() == kbucket.ErrLookupFailure.Error() || + testPeer.DHT.LAN.RoutingTable() == nil || + testPeer.DHT.LAN.RoutingTable().Size() == 0 { + time.Sleep(100 * time.Millisecond) + continue + } + if err != nil || !done { + if !done { + err = fmt.Errorf("expected refresh routing table to close") + } + fmt.Fprintf(os.Stderr, "how odd. that was lookupfailure.\n") + startupCancel() + return err + } + break StartupWait + case <-startupCtx.Done(): + startupCancel() + return fmt.Errorf("expected faster dht bootstrap") } - return err } + startupCancel() + fmt.Fprintf(os.Stderr, "finding provider\n") // choose a lan peer and validate lan DHT is functioning. i := rand.Intn(len(lanPeers)) if testPeer.PeerHost.Network().Connectedness(lanPeers[i].Identity) == corenet.Connected { - testPeer.PeerHost.Network().ClosePeer(lanPeers[i].Identity) - testPeer.PeerHost.Peerstore().ClearAddrs(lanPeers[i].Identity) + i = (i + 1) % len(lanPeers) + if testPeer.PeerHost.Network().Connectedness(lanPeers[i].Identity) == corenet.Connected { + testPeer.PeerHost.Network().ClosePeer(lanPeers[i].Identity) + testPeer.PeerHost.Peerstore().ClearAddrs(lanPeers[i].Identity) + } } // That peer will provide a new CID, and we'll validate the test node can find it. provideCid := cid.NewCidV1(cid.Raw, []byte("Lan Provide Record")) @@ -183,7 +212,7 @@ func RunDHTConnectivity(conf testutil.LatencyConfig, numPeers int) error { return err } - err, done = <-testPeer.DHT.WAN.RefreshRoutingTable() + err, done := <-testPeer.DHT.WAN.RefreshRoutingTable() if err != nil || !done { if !done { err = fmt.Errorf("expected refresh routing table to close") From b61d9639f6cc5b1f0c316929694243a82d6095ab Mon Sep 17 00:00:00 2001 From: Will Scott Date: Tue, 14 Apr 2020 13:03:33 -0700 Subject: [PATCH 607/671] better address generation --- test/integration/wan_lan_dht_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/wan_lan_dht_test.go b/test/integration/wan_lan_dht_test.go index 7d32aaffd35..0bfcb081e50 100644 --- a/test/integration/wan_lan_dht_test.go +++ b/test/integration/wan_lan_dht_test.go @@ -64,7 +64,7 @@ func makeAddr(n uint32, wan bool) ma.Multiaddr { ip = append(net.IP{}, lanPrefix...) } - binary.LittleEndian.PutUint32(ip[4:], n) + binary.LittleEndian.PutUint32(ip[12:], n) addr, _ := ma.NewMultiaddr(fmt.Sprintf("/ip6/%s/tcp/4242", ip)) return addr } From 5079cfa6241ef7d314fea1c2ef5af8fb5a5cd659 Mon Sep 17 00:00:00 2001 From: Will Scott Date: Tue, 14 Apr 2020 14:29:08 -0700 Subject: [PATCH 608/671] minor cleanup / progress --- test/integration/wan_lan_dht_test.go | 67 ++++++++++++++++------------ 1 file changed, 38 insertions(+), 29 deletions(-) diff --git a/test/integration/wan_lan_dht_test.go b/test/integration/wan_lan_dht_test.go index 0bfcb081e50..2ecee82b23b 100644 --- a/test/integration/wan_lan_dht_test.go +++ b/test/integration/wan_lan_dht_test.go @@ -13,13 +13,10 @@ import ( "github.com/ipfs/go-cid" "github.com/ipfs/go-ipfs/core" - "github.com/ipfs/go-ipfs/core/bootstrap" mock "github.com/ipfs/go-ipfs/core/mock" corenet "github.com/libp2p/go-libp2p-core/network" - peer "github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/peerstore" - kbucket "github.com/libp2p/go-libp2p-kbucket" testutil "github.com/libp2p/go-libp2p-testing/net" mocknet "github.com/libp2p/go-libp2p/p2p/net/mock" @@ -146,26 +143,20 @@ func RunDHTConnectivity(conf testutil.LatencyConfig, numPeers int) error { return err } - startupCtx, startupCancel := context.WithTimeout(ctx, time.Second*15) - testPeer.DHT.Bootstrap(startupCtx) + startupCtx, startupCancel := context.WithTimeout(ctx, time.Second*60) StartupWait: for { select { - case err, done := <-testPeer.DHT.LAN.RefreshRoutingTable(): - if err.Error() == kbucket.ErrLookupFailure.Error() || - testPeer.DHT.LAN.RoutingTable() == nil || - testPeer.DHT.LAN.RoutingTable().Size() == 0 { + case err := <-testPeer.DHT.LAN.RefreshRoutingTable(): + if err != nil { + fmt.Printf("Error refreshing routing table: %v\n", err) + } + if testPeer.DHT.LAN.RoutingTable() == nil || + testPeer.DHT.LAN.RoutingTable().Size() == 0 || + err != nil { time.Sleep(100 * time.Millisecond) continue } - if err != nil || !done { - if !done { - err = fmt.Errorf("expected refresh routing table to close") - } - fmt.Fprintf(os.Stderr, "how odd. that was lookupfailure.\n") - startupCancel() - return err - } break StartupWait case <-startupCtx.Done(): startupCancel() @@ -174,7 +165,6 @@ StartupWait: } startupCancel() - fmt.Fprintf(os.Stderr, "finding provider\n") // choose a lan peer and validate lan DHT is functioning. i := rand.Intn(len(lanPeers)) if testPeer.PeerHost.Network().Connectedness(lanPeers[i].Identity) == corenet.Connected { @@ -200,32 +190,51 @@ StartupWait: return fmt.Errorf("Unexpected lan peer provided record") } - // Now, bootstrap from a wan peer. + fmt.Fprintf(os.Stderr, "moving on to WAN.\n") + // Now, connect with a wan peer. for _, p := range wanPeers { if _, err := mn.LinkPeers(testPeer.Identity, p.Identity); err != nil { return err } } - bis := wanPeers[0].Peerstore.PeerInfo(wanPeers[0].PeerHost.ID()) - bcfg := bootstrap.BootstrapConfigWithPeers([]peer.AddrInfo{bis}) - if err := testPeer.Bootstrap(bcfg); err != nil { + + err = testPeer.PeerHost.Connect(ctx, wanPeers[0].Peerstore.PeerInfo(wanPeers[0].Identity)) + if err != nil { return err } - err, done := <-testPeer.DHT.WAN.RefreshRoutingTable() - if err != nil || !done { - if !done { - err = fmt.Errorf("expected refresh routing table to close") + startupCtx, startupCancel = context.WithTimeout(ctx, time.Second*60*5) +WanStartupWait: + for { + select { + case err := <-testPeer.DHT.WAN.RefreshRoutingTable(): + //if err != nil { + // fmt.Printf("Error refreshing routing table: %v\n", err) + //} + if testPeer.DHT.WAN.RoutingTable() == nil || + testPeer.DHT.WAN.RoutingTable().Size() == 0 || + err != nil { + time.Sleep(100 * time.Millisecond) + continue + } + break WanStartupWait + case <-startupCtx.Done(): + startupCancel() + return fmt.Errorf("expected faster wan dht bootstrap") } - return err } + startupCancel() // choose a wan peer and validate wan DHT is functioning. i = rand.Intn(len(wanPeers)) if testPeer.PeerHost.Network().Connectedness(wanPeers[i].Identity) == corenet.Connected { - testPeer.PeerHost.Network().ClosePeer(wanPeers[i].Identity) - testPeer.PeerHost.Peerstore().ClearAddrs(wanPeers[i].Identity) + i = (i + 1) % len(wanPeers) + if testPeer.PeerHost.Network().Connectedness(wanPeers[i].Identity) == corenet.Connected { + testPeer.PeerHost.Network().ClosePeer(wanPeers[i].Identity) + testPeer.PeerHost.Peerstore().ClearAddrs(wanPeers[i].Identity) + } } + // That peer will provide a new CID, and we'll validate the test node can find it. wanCid := cid.NewCidV1(cid.Raw, []byte("Wan Provide Record")) wanProvideCtx, cancel := context.WithTimeout(ctx, time.Second) From 971cbf747ae3d85d2e9ec9f291e6907807c49822 Mon Sep 17 00:00:00 2001 From: Will Scott Date: Tue, 14 Apr 2020 16:01:25 -0700 Subject: [PATCH 609/671] test passes --- test/integration/wan_lan_dht_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/integration/wan_lan_dht_test.go b/test/integration/wan_lan_dht_test.go index 2ecee82b23b..17714e6c579 100644 --- a/test/integration/wan_lan_dht_test.go +++ b/test/integration/wan_lan_dht_test.go @@ -7,13 +7,13 @@ import ( "math" "math/rand" "net" - "os" "testing" "time" "github.com/ipfs/go-cid" "github.com/ipfs/go-ipfs/core" mock "github.com/ipfs/go-ipfs/core/mock" + libp2p2 "github.com/ipfs/go-ipfs/core/node/libp2p" corenet "github.com/libp2p/go-libp2p-core/network" "github.com/libp2p/go-libp2p-core/peerstore" @@ -93,8 +93,9 @@ func RunDHTConnectivity(conf testutil.LatencyConfig, numPeers int) error { defer connCtxCancel() for i := 0; i < numPeers; i++ { wanPeer, err := core.NewNode(ctx, &core.BuildCfg{ - Online: true, - Host: mock.MockHostOption(mn), + Online: true, + Routing: libp2p2.DHTServerOption, + Host: mock.MockHostOption(mn), }) if err != nil { return err @@ -190,7 +191,6 @@ StartupWait: return fmt.Errorf("Unexpected lan peer provided record") } - fmt.Fprintf(os.Stderr, "moving on to WAN.\n") // Now, connect with a wan peer. for _, p := range wanPeers { if _, err := mn.LinkPeers(testPeer.Identity, p.Identity); err != nil { @@ -203,7 +203,7 @@ StartupWait: return err } - startupCtx, startupCancel = context.WithTimeout(ctx, time.Second*60*5) + startupCtx, startupCancel = context.WithTimeout(ctx, time.Second*60) WanStartupWait: for { select { From e5a41875bae7215c902435f35af50d0984c1add9 Mon Sep 17 00:00:00 2001 From: Will Scott Date: Tue, 14 Apr 2020 16:05:29 -0700 Subject: [PATCH 610/671] lint --- test/integration/wan_lan_dht_test.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/integration/wan_lan_dht_test.go b/test/integration/wan_lan_dht_test.go index 17714e6c579..77c6f129bc0 100644 --- a/test/integration/wan_lan_dht_test.go +++ b/test/integration/wan_lan_dht_test.go @@ -104,8 +104,8 @@ func RunDHTConnectivity(conf testutil.LatencyConfig, numPeers int) error { wanAddr := makeAddr(uint32(i), true) wanPeer.Peerstore.AddAddr(wanPeer.Identity, wanAddr, peerstore.PermanentAddrTTL) for _, p := range wanPeers { - mn.LinkPeers(p.Identity, wanPeer.Identity) - wanPeer.PeerHost.Connect(connectionContext, p.Peerstore.PeerInfo(p.Identity)) + _, _ = mn.LinkPeers(p.Identity, wanPeer.Identity) + _ = wanPeer.PeerHost.Connect(connectionContext, p.Peerstore.PeerInfo(p.Identity)) } wanPeers = append(wanPeers, wanPeer) @@ -120,8 +120,8 @@ func RunDHTConnectivity(conf testutil.LatencyConfig, numPeers int) error { lanAddr := makeAddr(uint32(i), false) lanPeer.Peerstore.AddAddr(lanPeer.Identity, lanAddr, peerstore.PermanentAddrTTL) for _, p := range lanPeers { - mn.LinkPeers(p.Identity, lanPeer.Identity) - lanPeer.PeerHost.Connect(connectionContext, p.Peerstore.PeerInfo(p.Identity)) + _, _ = mn.LinkPeers(p.Identity, lanPeer.Identity) + _ = lanPeer.PeerHost.Connect(connectionContext, p.Peerstore.PeerInfo(p.Identity)) } lanPeers = append(lanPeers, lanPeer) } @@ -171,7 +171,7 @@ StartupWait: if testPeer.PeerHost.Network().Connectedness(lanPeers[i].Identity) == corenet.Connected { i = (i + 1) % len(lanPeers) if testPeer.PeerHost.Network().Connectedness(lanPeers[i].Identity) == corenet.Connected { - testPeer.PeerHost.Network().ClosePeer(lanPeers[i].Identity) + _ = testPeer.PeerHost.Network().ClosePeer(lanPeers[i].Identity) testPeer.PeerHost.Peerstore().ClearAddrs(lanPeers[i].Identity) } } @@ -230,7 +230,7 @@ WanStartupWait: if testPeer.PeerHost.Network().Connectedness(wanPeers[i].Identity) == corenet.Connected { i = (i + 1) % len(wanPeers) if testPeer.PeerHost.Network().Connectedness(wanPeers[i].Identity) == corenet.Connected { - testPeer.PeerHost.Network().ClosePeer(wanPeers[i].Identity) + _ = testPeer.PeerHost.Network().ClosePeer(wanPeers[i].Identity) testPeer.PeerHost.Peerstore().ClearAddrs(wanPeers[i].Identity) } } @@ -254,7 +254,7 @@ WanStartupWait: // Finally, re-share the lan provided cid from a wan peer and expect a merged result. i = rand.Intn(len(wanPeers)) if testPeer.PeerHost.Network().Connectedness(wanPeers[i].Identity) == corenet.Connected { - testPeer.PeerHost.Network().ClosePeer(wanPeers[i].Identity) + _ = testPeer.PeerHost.Network().ClosePeer(wanPeers[i].Identity) testPeer.PeerHost.Peerstore().ClearAddrs(wanPeers[i].Identity) } From 8290ec11c376d8246a7e592eb4e6472479833077 Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Wed, 15 Apr 2020 13:42:29 +0200 Subject: [PATCH 611/671] fix: subdomain redirect for dir CIDs Closes #7164 License: MIT Signed-off-by: Marcin Rataj --- core/corehttp/gateway_handler.go | 10 ++++++++++ test/sharness/t0114-gateway-subdomains.sh | 12 +++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/core/corehttp/gateway_handler.go b/core/corehttp/gateway_handler.go index d26f21d54a2..8c7cea1346e 100644 --- a/core/corehttp/gateway_handler.go +++ b/core/corehttp/gateway_handler.go @@ -342,6 +342,16 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request BackLink: backLink, Hash: hash, } + + // See statusResponseWriter.WriteHeader + // and https://github.com/ipfs/go-ipfs/issues/7164 + // Note: this needs to occur before listingTemplate.Execute otherwise we get + // superfluous response.WriteHeader call from prometheus/client_golang + if w.Header().Get("Location") != "" { + w.WriteHeader(http.StatusMovedPermanently) + return + } + err = listingTemplate.Execute(w, tplData) if err != nil { internalWebError(w, err) diff --git a/test/sharness/t0114-gateway-subdomains.sh b/test/sharness/t0114-gateway-subdomains.sh index d079f56e6c7..426ed2e92e2 100755 --- a/test/sharness/t0114-gateway-subdomains.sh +++ b/test/sharness/t0114-gateway-subdomains.sh @@ -145,7 +145,7 @@ test_localhost_gateway_response_should_contain \ # payload directly, but redirect to URL with proper origin isolation test_localhost_gateway_response_should_contain \ - "request for localhost/ipfs/{CIDv1} returns status code HTTP 301" \ + "request for localhost/ipfs/{CIDv1} returns HTTP 301 Moved Permanently" \ "http://localhost:$GWAY_PORT/ipfs/$CIDv1" \ "301 Moved Permanently" @@ -154,6 +154,16 @@ test_localhost_gateway_response_should_contain \ "http://localhost:$GWAY_PORT/ipfs/$CIDv1" \ "Location: http://$CIDv1.ipfs.localhost:$GWAY_PORT/" +test_localhost_gateway_response_should_contain \ + "request for localhost/ipfs/{DIR_CID} returns HTTP 301 Moved Permanently" \ + "http://localhost:$GWAY_PORT/ipfs/$DIR_CID" \ + "301 Moved Permanently" + +test_localhost_gateway_response_should_contain \ + "request for localhost/ipfs/{DIR_CID} returns Location HTTP header for subdomain redirect in browsers" \ + "http://localhost:$GWAY_PORT/ipfs/$DIR_CID/" \ + "Location: http://$DIR_CID.ipfs.localhost:$GWAY_PORT/" + # Responses to the root domain of subdomain gateway hostname should Clear-Site-Data # https://github.com/ipfs/go-ipfs/issues/6975#issuecomment-597472477 test_localhost_gateway_response_should_contain \ From 66643e0c9d7efbb1bdc25116b74a2f90c7754af3 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 15 Apr 2020 15:53:59 -0700 Subject: [PATCH 612/671] chore: update the DHT Reduces allocations --- go.mod | 4 ++-- go.sum | 10 ++++------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index 684a563afaa..7e3286705d0 100644 --- a/go.mod +++ b/go.mod @@ -66,7 +66,7 @@ require ( github.com/libp2p/go-libp2p-core v0.5.1 github.com/libp2p/go-libp2p-discovery v0.3.0 github.com/libp2p/go-libp2p-http v0.1.5 - github.com/libp2p/go-libp2p-kad-dht v0.7.3 + github.com/libp2p/go-libp2p-kad-dht v0.7.4 github.com/libp2p/go-libp2p-kbucket v0.4.1 github.com/libp2p/go-libp2p-loggables v0.1.0 github.com/libp2p/go-libp2p-mplex v0.2.3 @@ -75,7 +75,7 @@ require ( github.com/libp2p/go-libp2p-pubsub-router v0.2.1 github.com/libp2p/go-libp2p-quic-transport v0.3.3 github.com/libp2p/go-libp2p-record v0.1.2 - github.com/libp2p/go-libp2p-routing-helpers v0.2.0 + github.com/libp2p/go-libp2p-routing-helpers v0.2.1 github.com/libp2p/go-libp2p-secio v0.2.2 github.com/libp2p/go-libp2p-swarm v0.2.3 github.com/libp2p/go-libp2p-testing v0.1.1 diff --git a/go.sum b/go.sum index 40e8b33c9ee..a05b2569b13 100644 --- a/go.sum +++ b/go.sum @@ -187,8 +187,6 @@ github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmv github.com/gxed/pubsub v0.0.0-20180201040156-26ebdf44f824/go.mod h1:OiEWyHgK+CWrmOlVquHaIK1vhpUJydC9m0Je6mhaiNE= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI= github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -555,8 +553,8 @@ github.com/libp2p/go-libp2p-interface-connmgr v0.0.1/go.mod h1:GarlRLH0LdeWcLnYM 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.7.3 h1:veitKCfUhquYdPOSXoohm8gLymK+R0w7SmVHPBmF58k= -github.com/libp2p/go-libp2p-kad-dht v0.7.3/go.mod h1:+XvZEgO0gOAd9liN1wjdewxIdcdtWLJXG8U8ou2oo/A= +github.com/libp2p/go-libp2p-kad-dht v0.7.4 h1:VfEPT//zG1ePIi0kvfO7FERSntttPfspT1750kwMErc= +github.com/libp2p/go-libp2p-kad-dht v0.7.4/go.mod h1:hcER9ypTCtFTumizViAYdTx65NMKtVshfMYI8jAsdQ0= github.com/libp2p/go-libp2p-kbucket v0.4.1 h1:6FyzbQuGLPzbMv3HiD232zqscIz5iB8ppJwb380+OGI= github.com/libp2p/go-libp2p-kbucket v0.4.1/go.mod h1:7sCeZx2GkNK1S6lQnGUW5JYZCFPnXzAZCCBBS70lytY= github.com/libp2p/go-libp2p-loggables v0.0.1/go.mod h1:lDipDlBNYbpyqyPX/KcoO+eq0sJYEVR2JgOexcivchg= @@ -620,8 +618,8 @@ github.com/libp2p/go-libp2p-record v0.1.0/go.mod h1:ujNc8iuE5dlKWVy6wuL6dd58t0n7 github.com/libp2p/go-libp2p-record v0.1.2 h1:M50VKzWnmUrk/M5/Dz99qO9Xh4vs8ijsK+7HkJvRP+0= github.com/libp2p/go-libp2p-record v0.1.2/go.mod h1:pal0eNcT5nqZaTV7UGhqeGqxFgGdsU/9W//C8dqjQDk= github.com/libp2p/go-libp2p-routing v0.0.1/go.mod h1:N51q3yTr4Zdr7V8Jt2JIktVU+3xBBylx1MZeVA6t1Ys= -github.com/libp2p/go-libp2p-routing-helpers v0.2.0 h1:+QKTsx2Bg0q3oueQ9CopTwKN5NsnF+qEC+sbkSVXnsU= -github.com/libp2p/go-libp2p-routing-helpers v0.2.0/go.mod h1:Db+7LRSPImkV9fOKsNWVW5IXyy9XDse92lUtO3O+jlo= +github.com/libp2p/go-libp2p-routing-helpers v0.2.1 h1:tV5fxxkl1cEEFXIv9yl5OGbLjEwngtq1qf5G/beLRvQ= +github.com/libp2p/go-libp2p-routing-helpers v0.2.1/go.mod h1:rTLUHlGDZbXHANJAWP2xW7ruPNJLj41/GnCBiR+qgjU= github.com/libp2p/go-libp2p-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= From ac122ba4fd85e4671291aa5b7bdc272a2f64f0f7 Mon Sep 17 00:00:00 2001 From: Marten Seemann Date: Fri, 17 Apr 2020 16:16:13 +0700 Subject: [PATCH 613/671] update go-libp2p-quic-transport to v0.3.4 --- go.mod | 2 +- go.sum | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 7e3286705d0..66ee96ef042 100644 --- a/go.mod +++ b/go.mod @@ -73,7 +73,7 @@ require ( github.com/libp2p/go-libp2p-peerstore v0.2.3 github.com/libp2p/go-libp2p-pubsub v0.2.7 github.com/libp2p/go-libp2p-pubsub-router v0.2.1 - github.com/libp2p/go-libp2p-quic-transport v0.3.3 + github.com/libp2p/go-libp2p-quic-transport v0.3.4 github.com/libp2p/go-libp2p-record v0.1.2 github.com/libp2p/go-libp2p-routing-helpers v0.2.1 github.com/libp2p/go-libp2p-secio v0.2.2 diff --git a/go.sum b/go.sum index a05b2569b13..42d373a42d5 100644 --- a/go.sum +++ b/go.sum @@ -611,8 +611,8 @@ github.com/libp2p/go-libp2p-pubsub v0.2.7 h1:PBuK5+NfWsoaoEaAUZ7YQPETQh8UqBi8CbM github.com/libp2p/go-libp2p-pubsub v0.2.7/go.mod h1:R4R0kH/6p2vu8O9xsue0HNSjEuXMEPBgg4h3nVDI15o= github.com/libp2p/go-libp2p-pubsub-router v0.2.1 h1:F5JYaHQuuMKVbSgLsH2POQwT1rloWpc7fUCOq6PBjyE= github.com/libp2p/go-libp2p-pubsub-router v0.2.1/go.mod h1:cl46APmxgKgzgpCGFb8Ns7++cqnJ29CxESXCQATp55k= -github.com/libp2p/go-libp2p-quic-transport v0.3.3 h1:A920y1nion8PkGKsEnMiho+3OHpXUqfy35YnPfta4aI= -github.com/libp2p/go-libp2p-quic-transport v0.3.3/go.mod h1:DqzycUAZfeuritygmSOh3kPrs/Cqvc0V1uGkoCEGUXI= +github.com/libp2p/go-libp2p-quic-transport v0.3.4 h1:kgbG++mMaAcBesW889QreDL5Qg0lGO+jbcX6uYBgFfw= +github.com/libp2p/go-libp2p-quic-transport v0.3.4/go.mod h1:29Bqo+L5/F8lLlhFLSPJwc48uRf4SzzE/vh4U2Lc/GU= github.com/libp2p/go-libp2p-record v0.0.1/go.mod h1:grzqg263Rug/sRex85QrDOLntdFAymLDLm7lxMgU79Q= github.com/libp2p/go-libp2p-record v0.1.0/go.mod h1:ujNc8iuE5dlKWVy6wuL6dd58t0n7xI4hAIl8pE6wu5Q= github.com/libp2p/go-libp2p-record v0.1.2 h1:M50VKzWnmUrk/M5/Dz99qO9Xh4vs8ijsK+7HkJvRP+0= @@ -742,8 +742,8 @@ github.com/libp2p/go-yamux v1.3.3 h1:mWuzZRCAeTBFdynLlsYgA/EIeMOLr8XY04wa52NRhsE github.com/libp2p/go-yamux v1.3.3/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= github.com/libp2p/go-yamux v1.3.5 h1:ibuz4naPAully0pN6J/kmUARiqLpnDQIzI/8GCOrljg= github.com/libp2p/go-yamux v1.3.5/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= -github.com/lucas-clemente/quic-go v0.15.3 h1:i6n4Jr7673z9TlurAjc87+GlE/BN10++r9XZIPS9j6I= -github.com/lucas-clemente/quic-go v0.15.3/go.mod h1:oj40DjNLuNugvtXWg4PwaYgv7tAbzAabrT57CC69EhI= +github.com/lucas-clemente/quic-go v0.15.4 h1:2dK8LiQz0xMJd//Jeev0EkdoGNwv48AVW0yoIj99Waw= +github.com/lucas-clemente/quic-go v0.15.4/go.mod h1:oj40DjNLuNugvtXWg4PwaYgv7tAbzAabrT57CC69EhI= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329 h1:2gxZ0XQIU/5z3Z3bUBu+FXuk2pFbkN6tcwi/pjyaDic= From 135c4519973fdb05e354770c9fe220349272a768 Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Fri, 17 Apr 2020 20:10:21 +0100 Subject: [PATCH 614/671] feat: webui 2.7.5 --- core/corehttp/webui.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/corehttp/webui.go b/core/corehttp/webui.go index 5e9839a6dcb..02f2da73ad9 100644 --- a/core/corehttp/webui.go +++ b/core/corehttp/webui.go @@ -1,7 +1,7 @@ package corehttp // TODO: move to IPNS -const WebUIPath = "/ipfs/bafybeigxqbvc6qxk2wkdyzpkh7mr7zh5pxbvpjb6a6mxdtpwhlqaf4qj5a" +const WebUIPath = "/ipfs/bafybeidatpz2hli6fgu3zul5woi27ujesdf5o5a7bu622qj6ugharciwjq" // this is a list of all past webUI paths. var WebUIPaths = []string{ From d354ccdb608ce876fd28cc1e2922144faefad385 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Fri, 17 Apr 2020 12:54:49 -0700 Subject: [PATCH 615/671] chore: update deps --- go.mod | 9 +++++---- go.sum | 17 +++++++++++------ 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/go.mod b/go.mod index 66ee96ef042..767cc74a4cd 100644 --- a/go.mod +++ b/go.mod @@ -60,7 +60,7 @@ require ( github.com/jbenet/go-temp-err-catcher v0.1.0 github.com/jbenet/goprocess v0.1.4 github.com/libp2p/go-eventbus v0.1.0 - github.com/libp2p/go-libp2p v0.8.0 + github.com/libp2p/go-libp2p v0.8.1 github.com/libp2p/go-libp2p-circuit v0.2.1 github.com/libp2p/go-libp2p-connmgr v0.2.1 github.com/libp2p/go-libp2p-core v0.5.1 @@ -99,9 +99,10 @@ require ( github.com/whyrusleeping/go-sysinfo v0.0.0-20190219211824-4a357d4b90b1 github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 github.com/whyrusleeping/tar-utils v0.0.0-20180509141711-8c6c8ba81d5c - go.uber.org/fx v1.11.0 - golang.org/x/crypto v0.0.0-20200406173513-056763e48d71 - golang.org/x/sys v0.0.0-20200408040146-ea54a3c99b9b + go.uber.org/fx v1.12.0 + golang.org/x/crypto v0.0.0-20200414173820-0848c9571904 + golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e // indirect + golang.org/x/sys v0.0.0-20200413165638-669c56c373c4 gopkg.in/cheggaaa/pb.v1 v1.0.28 ) diff --git a/go.sum b/go.sum index 42d373a42d5..86cf4c3b255 100644 --- a/go.sum +++ b/go.sum @@ -484,6 +484,8 @@ github.com/libp2p/go-libp2p v0.7.4 h1:xVj1oSlN0C+FlxqiLuHC8WruMvq24xxfeVxmNhTG0r github.com/libp2p/go-libp2p v0.7.4/go.mod h1:oXsBlTLF1q7pxr+9w6lqzS1ILpyHsaBPniVO7zIHGMw= github.com/libp2p/go-libp2p v0.8.0 h1:8t8kAJM+o4rR91bfwbgbtykbdqPJv819+CTSPkXDT1A= github.com/libp2p/go-libp2p v0.8.0/go.mod h1:QRNH9pwdbEBpx5DTJYg+qxcVaDMAz3Ee/qDKwXujH5o= +github.com/libp2p/go-libp2p v0.8.1 h1:6AK178W4GmfGxV+L51bd54/fSWEjNR+S0DO0odk/CwI= +github.com/libp2p/go-libp2p v0.8.1/go.mod h1:QRNH9pwdbEBpx5DTJYg+qxcVaDMAz3Ee/qDKwXujH5o= 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 h1:aCWAu43Ri4nU0ZPO7NyLzUvvfqd0nE3dX0R/ZGYVgOU= @@ -1037,8 +1039,8 @@ go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/dig v1.9.0 h1:pJTDXKEhRqBI8W7rU7kwT5EgyRZuSMVSFcZolOvKK9U= go.uber.org/dig v1.9.0/go.mod h1:X34SnWGr8Fyla9zQNO2GSO2D+TIuqB14OS8JhYocIyw= -go.uber.org/fx v1.11.0 h1:WTxcE9VicMCGSB//JfMtpD9XP500wJx6w8lYEcsdPQk= -go.uber.org/fx v1.11.0/go.mod h1:egT3Kyg1JFYQkvKLZ3EsykxkNrZxgXS+gKoKo7abERY= +go.uber.org/fx v1.12.0 h1:+1+3Cz9M0dFMPy9SW9XUIUHye8bnPUm7q7DroNGWYG4= +go.uber.org/fx v1.12.0/go.mod h1:egT3Kyg1JFYQkvKLZ3EsykxkNrZxgXS+gKoKo7abERY= go.uber.org/goleak v0.10.0 h1:G3eWbSNIskeRqtsN/1uI5B+eP73y3JUuBsv9AZjehb4= go.uber.org/goleak v0.10.0/go.mod h1:VCZuO8V8mFPlL0F5J5GK1rtHV3DrFcQ1R8ryq7FK0aI= go.uber.org/goleak v1.0.0 h1:qsup4IcBdlmsnGfqyLl4Ntn3C2XCCuKAE7DwHpScyUo= @@ -1080,8 +1082,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d h1:1ZiEyfaQIg3Qh0EoqpwAakHVhecoE5wlSg5GjnafJGw= golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200406173513-056763e48d71 h1:DOmugCavvUtnUD114C1Wh+UgTgQZ4pMLzXxi1pSt+/Y= -golang.org/x/crypto v0.0.0-20200406173513-056763e48d71/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200414173820-0848c9571904 h1:bXoxMPcSLOq08zI3/c5dEBT6lE4eh+jOh886GHrn6V8= +golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1119,6 +1121,8 @@ golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 h1:Ao/3l156eZf2AW5wK8a7/smto golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1163,8 +1167,9 @@ golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200408040146-ea54a3c99b9b h1:h03Ur1RlPrGTjua4koYdpGl8W0eYo8p1uI9w7RPlkdk= -golang.org/x/sys v0.0.0-20200408040146-ea54a3c99b9b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200413165638-669c56c373c4 h1:opSr2sbRXk5X5/givKrrKj9HXxFpW2sdCiP8MJSKLQY= +golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From ee741fece16fc2744fc64dbc10a6fada496d5d22 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Fri, 17 Apr 2020 12:54:49 -0700 Subject: [PATCH 616/671] chore: update flatfs Another attempt to fix #7115. --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 767cc74a4cd..0d8df6d37fe 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( github.com/ipfs/go-datastore v0.4.4 github.com/ipfs/go-detect-race v0.0.1 github.com/ipfs/go-ds-badger v0.2.4 - github.com/ipfs/go-ds-flatfs v0.4.3 + github.com/ipfs/go-ds-flatfs v0.4.4 github.com/ipfs/go-ds-leveldb v0.4.2 github.com/ipfs/go-ds-measure v0.1.0 github.com/ipfs/go-filestore v0.0.3 diff --git a/go.sum b/go.sum index 86cf4c3b255..3850e24f1f0 100644 --- a/go.sum +++ b/go.sum @@ -261,8 +261,8 @@ github.com/ipfs/go-ds-badger v0.2.3 h1:J27YvAcpuA5IvZUbeBxOcQgqnYHUPxoygc6Qxxkod github.com/ipfs/go-ds-badger v0.2.3/go.mod h1:pEYw0rgg3FIrywKKnL+Snr+w/LjJZVMTBRn4FS6UHUk= github.com/ipfs/go-ds-badger v0.2.4 h1:UPGB0y7luFHk+mY/tUZrif/272M8o+hFsW+avLUeWrM= github.com/ipfs/go-ds-badger v0.2.4/go.mod h1:pEYw0rgg3FIrywKKnL+Snr+w/LjJZVMTBRn4FS6UHUk= -github.com/ipfs/go-ds-flatfs v0.4.3 h1:7M8/xpLkJhFJYaLumo2RRgt/cOehetutGW5zigTa5qY= -github.com/ipfs/go-ds-flatfs v0.4.3/go.mod h1:e4TesLyZoA8k1gV/yCuBTnt2PJtypn4XUlB5n8KQMZY= +github.com/ipfs/go-ds-flatfs v0.4.4 h1:DmGZ4qOYQLNgu8Mltuz1DtUHpm+BjWMcVN3F3H3VJzQ= +github.com/ipfs/go-ds-flatfs v0.4.4/go.mod h1:e4TesLyZoA8k1gV/yCuBTnt2PJtypn4XUlB5n8KQMZY= github.com/ipfs/go-ds-leveldb v0.0.1/go.mod h1:feO8V3kubwsEF22n0YRQCffeb79OOYIykR4L04tMOYc= github.com/ipfs/go-ds-leveldb v0.1.0 h1:OsCuIIh1LMTk4WIQ1UJH7e3j01qlOP+KWVhNS6lBDZY= github.com/ipfs/go-ds-leveldb v0.1.0/go.mod h1:hqAW8y4bwX5LWcCtku2rFNX3vjDZCy5LZCg+cSZvYb8= From d1b5bbe8e12bd677c05e3b6504f637b357afd4a4 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Fri, 17 Apr 2020 15:47:55 -0700 Subject: [PATCH 617/671] chore: update template labels for label rename --- .github/ISSUE_TEMPLATE/bug-report.md | 2 +- .github/ISSUE_TEMPLATE/doc.md | 2 +- .github/ISSUE_TEMPLATE/enhancement.md | 2 +- .github/ISSUE_TEMPLATE/feature.md | 2 +- .github/ISSUE_TEMPLATE/question.md | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md index 8e24a4e128c..adbc0c64d95 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.md +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -1,7 +1,7 @@ --- name: 'Bug Report' about: 'Report a bug in go-ipfs.' -labels: bug +labels: kind/bug --- #### Version information: diff --git a/.github/ISSUE_TEMPLATE/doc.md b/.github/ISSUE_TEMPLATE/doc.md index 5a0d1982180..ec264a6be19 100644 --- a/.github/ISSUE_TEMPLATE/doc.md +++ b/.github/ISSUE_TEMPLATE/doc.md @@ -1,7 +1,7 @@ --- name: 'Documentation Issue' about: 'Report missing/erroneous documentation, propose new documentation, report broken links, etc.' -labels: documentation +labels: topic/docs-ipfs --- #### Location diff --git a/.github/ISSUE_TEMPLATE/enhancement.md b/.github/ISSUE_TEMPLATE/enhancement.md index 4d2233d35f2..c05dd5fb32f 100644 --- a/.github/ISSUE_TEMPLATE/enhancement.md +++ b/.github/ISSUE_TEMPLATE/enhancement.md @@ -1,7 +1,7 @@ --- name: 'Enhancement' about: 'Suggest an improvement to an existing go-ipfs feature.' -labels: enhancement +labels: kind/enhancement --- #### Location diff --git a/.github/ISSUE_TEMPLATE/enhancement.md b/.github/ISSUE_TEMPLATE/enhancement.md index c05dd5fb32f..8c1c31c0d9d 100644 --- a/.github/ISSUE_TEMPLATE/enhancement.md +++ b/.github/ISSUE_TEMPLATE/enhancement.md @@ -5,7 +5,7 @@ labels: kind/enhancement --- diff --git a/.github/ISSUE_TEMPLATE/feature.md b/.github/ISSUE_TEMPLATE/feature.md index cb5801f5c4d..0cd141dc706 100644 --- a/.github/ISSUE_TEMPLATE/feature.md +++ b/.github/ISSUE_TEMPLATE/feature.md @@ -1,11 +1,11 @@ --- name: 'Feature' about: 'Suggest a new feature in go-ipfs.' -labels: kind/feature +labels: kind/feature, need/triage ---

    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