├── .gitignore ├── LICENSE ├── README.md ├── ctx_mutex.go ├── dht_net.go ├── dhtmock.go ├── go.mod ├── go.sum ├── lookup.go ├── main.go └── pb ├── Makefile ├── dht.pb.go ├── dht.proto ├── message.go └── message_test.go /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, built with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | # Dependency directories (remove the comment below to include it) 15 | # vendor/ 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Adin Schmahmann 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dht-graph 2 | A simple libp2p DHT crawler 3 | 4 | Crawls the `/ipfs/kad/1.0.0` and `/ipfs/kad/2.0.0` DHTs and dumps the resulting routing tables into a GraphViz compatible dot file. 5 | 6 | Run with `dht-graph -o outputFile`, if no output file is specified it will default to `rt.dot`. 7 | -------------------------------------------------------------------------------- /ctx_mutex.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | type ctxMutex chan struct{} 8 | 9 | func newCtxMutex() ctxMutex { 10 | return make(ctxMutex, 1) 11 | } 12 | 13 | func (m ctxMutex) Lock(ctx context.Context) error { 14 | select { 15 | case m <- struct{}{}: 16 | return nil 17 | case <-ctx.Done(): 18 | return ctx.Err() 19 | } 20 | } 21 | 22 | func (m ctxMutex) Unlock() { 23 | select { 24 | case <-m: 25 | default: 26 | panic("not locked") 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /dht_net.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "context" 6 | "fmt" 7 | "io" 8 | "sync" 9 | "time" 10 | 11 | "github.com/libp2p/go-libp2p-core/helpers" 12 | "github.com/libp2p/go-libp2p-core/network" 13 | "github.com/libp2p/go-libp2p-core/peer" 14 | 15 | "github.com/libp2p/go-libp2p-kad-dht/metrics" 16 | pb "github.com/libp2p/go-libp2p-kad-dht/pb" 17 | 18 | ggio "github.com/gogo/protobuf/io" 19 | 20 | "github.com/libp2p/go-msgio" 21 | "go.opencensus.io/tag" 22 | ) 23 | 24 | var dhtReadMessageTimeout = 10 * time.Second 25 | var dhtStreamIdleTimeout = 1 * time.Minute 26 | 27 | // ErrReadTimeout is an error that occurs when no message is read within the timeout period. 28 | var ErrReadTimeout = fmt.Errorf("timed out reading response") 29 | 30 | // The Protobuf writer performs multiple small writes when writing a message. 31 | // We need to buffer those writes, to make sure that we're not sending a new 32 | // packet for every single write. 33 | type bufferedDelimitedWriter struct { 34 | *bufio.Writer 35 | ggio.WriteCloser 36 | } 37 | 38 | var writerPool = sync.Pool{ 39 | New: func() interface{} { 40 | w := bufio.NewWriter(nil) 41 | return &bufferedDelimitedWriter{ 42 | Writer: w, 43 | WriteCloser: ggio.NewDelimitedWriter(w), 44 | } 45 | }, 46 | } 47 | 48 | func writeMsg(w io.Writer, mes *pb.Message) error { 49 | bw := writerPool.Get().(*bufferedDelimitedWriter) 50 | bw.Reset(w) 51 | err := bw.WriteMsg(mes) 52 | if err == nil { 53 | err = bw.Flush() 54 | } 55 | bw.Reset(nil) 56 | writerPool.Put(bw) 57 | return err 58 | } 59 | 60 | func (w *bufferedDelimitedWriter) Flush() error { 61 | return w.Writer.Flush() 62 | } 63 | 64 | // sendRequest sends out a request, but also makes sure to 65 | // measure the RTT for latency measurements. 66 | func (dht *IpfsDHT) sendRequest(ctx context.Context, p peer.ID, pmes *pb.Message) (*pb.Message, error) { 67 | ctx, _ = tag.New(ctx, metrics.UpsertMessageType(pmes)) 68 | 69 | ms, err := dht.messageSenderForPeer(ctx, p) 70 | if err != nil { 71 | return nil, err 72 | } 73 | 74 | rpmes, err := ms.SendRequest(ctx, pmes) 75 | if err != nil { 76 | return nil, err 77 | } 78 | return rpmes, nil 79 | } 80 | 81 | // sendMessage sends out a message 82 | func (dht *IpfsDHT) sendMessage(ctx context.Context, p peer.ID, pmes *pb.Message) error { 83 | ctx, _ = tag.New(ctx, metrics.UpsertMessageType(pmes)) 84 | 85 | ms, err := dht.messageSenderForPeer(ctx, p) 86 | if err != nil { 87 | return err 88 | } 89 | 90 | if err := ms.SendMessage(ctx, pmes); err != nil { 91 | return err 92 | } 93 | 94 | return nil 95 | } 96 | 97 | func (dht *IpfsDHT) messageSenderForPeer(ctx context.Context, p peer.ID) (*messageSender, error) { 98 | dht.smlk.Lock() 99 | ms, ok := dht.strmap[p] 100 | if ok { 101 | dht.smlk.Unlock() 102 | return ms, nil 103 | } 104 | ms = &messageSender{p: p, dht: dht, lk: newCtxMutex()} 105 | dht.strmap[p] = ms 106 | dht.smlk.Unlock() 107 | 108 | if err := ms.prepOrInvalidate(ctx); err != nil { 109 | dht.smlk.Lock() 110 | defer dht.smlk.Unlock() 111 | 112 | if msCur, ok := dht.strmap[p]; ok { 113 | // Changed. Use the new one, old one is invalid and 114 | // not in the map so we can just throw it away. 115 | if ms != msCur { 116 | return msCur, nil 117 | } 118 | // Not changed, remove the now invalid stream from the 119 | // map. 120 | delete(dht.strmap, p) 121 | } 122 | // Invalid but not in map. Must have been removed by a disconnect. 123 | return nil, err 124 | } 125 | // All ready to go. 126 | return ms, nil 127 | } 128 | 129 | type messageSender struct { 130 | s network.Stream 131 | r msgio.ReadCloser 132 | lk ctxMutex 133 | p peer.ID 134 | dht *IpfsDHT 135 | 136 | invalid bool 137 | singleMes int 138 | } 139 | 140 | // invalidate is called before this messageSender is removed from the strmap. 141 | // It prevents the messageSender from being reused/reinitialized and then 142 | // forgotten (leaving the stream open). 143 | func (ms *messageSender) invalidate() { 144 | ms.invalid = true 145 | if ms.s != nil { 146 | _ = ms.s.Reset() 147 | ms.s = nil 148 | } 149 | } 150 | 151 | func (ms *messageSender) prepOrInvalidate(ctx context.Context) error { 152 | if err := ms.lk.Lock(ctx); err != nil { 153 | return err 154 | } 155 | defer ms.lk.Unlock() 156 | 157 | if err := ms.prep(ctx); err != nil { 158 | ms.invalidate() 159 | return err 160 | } 161 | return nil 162 | } 163 | 164 | func (ms *messageSender) prep(ctx context.Context) error { 165 | if ms.invalid { 166 | return fmt.Errorf("message sender has been invalidated") 167 | } 168 | if ms.s != nil { 169 | return nil 170 | } 171 | 172 | // We only want to speak to peers using our primary protocols. We do not want to query any peer that only speaks 173 | // one of the secondary "server" protocols that we happen to support (e.g. older nodes that we can respond to for 174 | // backwards compatibility reasons). 175 | nstr, err := ms.dht.host.NewStream(ctx, ms.p, ms.dht.protocols...) 176 | if err != nil { 177 | return err 178 | } 179 | 180 | ms.r = msgio.NewVarintReaderSize(nstr, network.MessageSizeMax) 181 | ms.s = nstr 182 | 183 | return nil 184 | } 185 | 186 | // streamReuseTries is the number of times we will try to reuse a stream to a 187 | // given peer before giving up and reverting to the old one-message-per-stream 188 | // behaviour. 189 | const streamReuseTries = 3 190 | 191 | func (ms *messageSender) SendMessage(ctx context.Context, pmes *pb.Message) error { 192 | if err := ms.lk.Lock(ctx); err != nil { 193 | return err 194 | } 195 | defer ms.lk.Unlock() 196 | 197 | retry := false 198 | for { 199 | if err := ms.prep(ctx); err != nil { 200 | return err 201 | } 202 | 203 | if err := ms.writeMsg(pmes); err != nil { 204 | _ = ms.s.Reset() 205 | ms.s = nil 206 | 207 | if retry { 208 | return err 209 | } 210 | retry = true 211 | continue 212 | } 213 | 214 | if ms.singleMes > streamReuseTries { 215 | go helpers.FullClose(ms.s) 216 | ms.s = nil 217 | } else if retry { 218 | ms.singleMes++ 219 | } 220 | 221 | return nil 222 | } 223 | } 224 | 225 | func (ms *messageSender) SendRequest(ctx context.Context, pmes *pb.Message) (*pb.Message, error) { 226 | if err := ms.lk.Lock(ctx); err != nil { 227 | return nil, err 228 | } 229 | defer ms.lk.Unlock() 230 | 231 | retry := false 232 | for { 233 | if err := ms.prep(ctx); err != nil { 234 | return nil, err 235 | } 236 | 237 | if err := ms.writeMsg(pmes); err != nil { 238 | _ = ms.s.Reset() 239 | ms.s = nil 240 | 241 | if retry { 242 | return nil, err 243 | } 244 | retry = true 245 | continue 246 | } 247 | 248 | mes := new(pb.Message) 249 | if err := ms.ctxReadMsg(ctx, mes); err != nil { 250 | _ = ms.s.Reset() 251 | ms.s = nil 252 | 253 | if retry { 254 | return nil, err 255 | } 256 | retry = true 257 | continue 258 | } 259 | 260 | if ms.singleMes > streamReuseTries { 261 | go helpers.FullClose(ms.s) 262 | ms.s = nil 263 | } else if retry { 264 | ms.singleMes++ 265 | } 266 | 267 | return mes, nil 268 | } 269 | } 270 | 271 | func (ms *messageSender) writeMsg(pmes *pb.Message) error { 272 | return writeMsg(ms.s, pmes) 273 | } 274 | 275 | func (ms *messageSender) ctxReadMsg(ctx context.Context, mes *pb.Message) error { 276 | errc := make(chan error, 1) 277 | go func(r msgio.ReadCloser) { 278 | bytes, err := r.ReadMsg() 279 | defer r.ReleaseMsg(bytes) 280 | if err != nil { 281 | errc <- err 282 | return 283 | } 284 | errc <- mes.Unmarshal(bytes) 285 | }(ms.r) 286 | 287 | t := time.NewTimer(dhtReadMessageTimeout) 288 | defer t.Stop() 289 | 290 | select { 291 | case err := <-errc: 292 | return err 293 | case <-ctx.Done(): 294 | return ctx.Err() 295 | case <-t.C: 296 | return ErrReadTimeout 297 | } 298 | } 299 | -------------------------------------------------------------------------------- /dhtmock.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | host "github.com/libp2p/go-libp2p-core/host" 5 | "github.com/libp2p/go-libp2p-core/peer" 6 | "github.com/libp2p/go-libp2p-core/protocol" 7 | "sync" 8 | ) 9 | 10 | type IpfsDHT struct { 11 | host host.Host 12 | strmap map[peer.ID]*messageSender 13 | smlk sync.Mutex 14 | 15 | protocols []protocol.ID 16 | } 17 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/aschmahmann/dht-graph 2 | 3 | go 1.14 4 | 5 | require ( 6 | github.com/gogo/protobuf v1.3.1 7 | github.com/ipfs/go-cid v0.0.5 // indirect 8 | github.com/ipfs/go-ipfs-util v0.0.1 // indirect 9 | github.com/ipfs/go-log v1.0.4 10 | github.com/ipfs/go-log/v2 v2.0.5 11 | github.com/libp2p/go-libp2p v0.8.1 12 | github.com/libp2p/go-libp2p-core v0.5.1 13 | github.com/libp2p/go-libp2p-kad-dht v0.7.7 14 | github.com/libp2p/go-libp2p-kbucket v0.4.1 15 | github.com/libp2p/go-libp2p-record v0.1.2 16 | github.com/libp2p/go-msgio v0.0.4 17 | github.com/multiformats/go-base32 v0.0.3 // indirect 18 | github.com/multiformats/go-multiaddr v0.2.1 19 | github.com/multiformats/go-multihash v0.0.13 20 | go.opencensus.io v0.22.3 21 | golang.org/x/tools v0.0.0-20191216052735-49a3e744a425 // indirect 22 | ) 23 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= 3 | github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= 4 | github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= 5 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 6 | github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y= 7 | github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= 8 | github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= 9 | github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= 10 | github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= 11 | github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= 12 | github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= 13 | github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw= 14 | github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= 15 | github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= 16 | github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= 17 | github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= 18 | github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= 19 | github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= 20 | github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= 21 | github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= 22 | github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= 23 | github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= 24 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 25 | github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= 26 | github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= 27 | github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= 28 | github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= 29 | github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= 30 | github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= 31 | github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 32 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 33 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 34 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 35 | github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018 h1:6xT9KW8zLC5IlbaIF5Q7JNieBoACT7iW0YTxQHR0in0= 36 | github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018/go.mod h1:rQYf4tfk5sSwFsnDg3qYaBxSjsD9S8+59vW0dKUgme4= 37 | github.com/dgraph-io/badger v1.5.5-0.20190226225317-8115aed38f8f/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ= 38 | github.com/dgraph-io/badger v1.6.0-rc1/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= 39 | github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= 40 | github.com/dgraph-io/badger v1.6.1/go.mod h1:FRmFw3uxvcpa8zG3Rxs0th+hCLIuaQg8HlNV5bjgnuU= 41 | github.com/dgraph-io/ristretto v0.0.2/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= 42 | github.com/dgryski/go-farm v0.0.0-20190104051053-3adb47b1fb0f/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= 43 | github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= 44 | github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= 45 | github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= 46 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 47 | github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= 48 | github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= 49 | github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= 50 | github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= 51 | github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= 52 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 53 | github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I= 54 | github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 55 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 56 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 57 | github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= 58 | github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= 59 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 60 | github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 61 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 62 | github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= 63 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 64 | github.com/google/gopacket v1.1.17 h1:rMrlX2ZY2UbvT+sdz3+6J+pp2z+msCq9MxTU6ymxbBY= 65 | github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM= 66 | github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 67 | github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= 68 | github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 69 | github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= 70 | github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= 71 | github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= 72 | github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU= 73 | github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= 74 | github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= 75 | github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= 76 | github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 77 | github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 78 | github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= 79 | github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= 80 | github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= 81 | github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= 82 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 83 | github.com/huin/goupnp v1.0.0 h1:wg75sLpL6DZqwHQN6E1Cfk6mtfzS45z8OV+ic+DtHRo= 84 | github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= 85 | github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= 86 | github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= 87 | github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= 88 | github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= 89 | github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= 90 | github.com/ipfs/go-cid v0.0.4/go.mod h1:4LLaPOQwmk5z9LBgQnpkivrx8BJjUyGwTXCd5Xfj6+M= 91 | github.com/ipfs/go-cid v0.0.5 h1:o0Ix8e/ql7Zb5UVUJEUfjsWCIY8t48++9lR8qi6oiJU= 92 | github.com/ipfs/go-cid v0.0.5/go.mod h1:plgt+Y5MnOey4vO4UlUazGqdbEXuFYitED67FexhXog= 93 | github.com/ipfs/go-datastore v0.0.1/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= 94 | github.com/ipfs/go-datastore v0.1.0/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= 95 | github.com/ipfs/go-datastore v0.1.1/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRVNdgPHtbHw= 96 | github.com/ipfs/go-datastore v0.4.0/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= 97 | github.com/ipfs/go-datastore v0.4.1/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= 98 | github.com/ipfs/go-datastore v0.4.4/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= 99 | github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk= 100 | github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= 101 | github.com/ipfs/go-ds-badger v0.0.2/go.mod h1:Y3QpeSFWQf6MopLTiZD+VT6IC1yZqaGmjvRcKeSGij8= 102 | github.com/ipfs/go-ds-badger v0.0.5/go.mod h1:g5AuuCGmr7efyzQhLL8MzwqcauPojGPUaHzfGTzuE3s= 103 | github.com/ipfs/go-ds-badger v0.0.7/go.mod h1:qt0/fWzZDoPW6jpQeqUjR5kBfhDNB65jd9YlmAvpQBk= 104 | github.com/ipfs/go-ds-badger v0.2.1/go.mod h1:Tx7l3aTph3FMFrRS838dcSJh+jjA7cX9DrGVwx/NOwE= 105 | github.com/ipfs/go-ds-badger v0.2.3/go.mod h1:pEYw0rgg3FIrywKKnL+Snr+w/LjJZVMTBRn4FS6UHUk= 106 | github.com/ipfs/go-ds-leveldb v0.0.1/go.mod h1:feO8V3kubwsEF22n0YRQCffeb79OOYIykR4L04tMOYc= 107 | github.com/ipfs/go-ds-leveldb v0.1.0/go.mod h1:hqAW8y4bwX5LWcCtku2rFNX3vjDZCy5LZCg+cSZvYb8= 108 | github.com/ipfs/go-ds-leveldb v0.4.1/go.mod h1:jpbku/YqBSsBc1qgME8BkWS4AxzF2cEu1Ii2r79Hh9s= 109 | github.com/ipfs/go-ds-leveldb v0.4.2/go.mod h1:jpbku/YqBSsBc1qgME8BkWS4AxzF2cEu1Ii2r79Hh9s= 110 | github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= 111 | github.com/ipfs/go-ipfs-util v0.0.1 h1:Wz9bL2wB2YBJqggkA4dD7oSmqB4cAnpNbGrlHJulv50= 112 | github.com/ipfs/go-ipfs-util v0.0.1/go.mod h1:spsl5z8KUnrve+73pOhSVZND1SIxPW5RyBCNzQxlJBc= 113 | github.com/ipfs/go-ipns v0.0.2/go.mod h1:WChil4e0/m9cIINWLxZe1Jtf77oz5L05rO2ei/uKJ5U= 114 | github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM= 115 | github.com/ipfs/go-log v1.0.2/go.mod h1:1MNjMxe0u6xvJZgeqbJ8vdo2TKaGwZ1a0Bpza+sr2Sk= 116 | github.com/ipfs/go-log v1.0.3/go.mod h1:OsLySYkwIbiSUR/yBTdv1qPtcE4FW3WPWk/ewz9Ru+A= 117 | github.com/ipfs/go-log v1.0.4 h1:6nLQdX4W8P9yZZFH7mO+X/PzjN8Laozm/lMJ6esdgzY= 118 | github.com/ipfs/go-log v1.0.4/go.mod h1:oDCg2FkjogeFOhqqb+N39l2RpTNPL6F/StPkB3kPgcs= 119 | github.com/ipfs/go-log/v2 v2.0.2/go.mod h1:O7P1lJt27vWHhOwQmcFEvlmo49ry2VY2+JfBWFaa9+0= 120 | github.com/ipfs/go-log/v2 v2.0.3/go.mod h1:O7P1lJt27vWHhOwQmcFEvlmo49ry2VY2+JfBWFaa9+0= 121 | github.com/ipfs/go-log/v2 v2.0.5 h1:fL4YI+1g5V/b1Yxr1qAiXTMg1H8z9vx/VmJxBuQMHvU= 122 | github.com/ipfs/go-log/v2 v2.0.5/go.mod h1:eZs4Xt4ZUJQFM3DlanGhy7TkwwawCZcSByscwkWG+dw= 123 | github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= 124 | github.com/jackpal/go-nat-pmp v1.0.1/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= 125 | github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= 126 | github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= 127 | github.com/jbenet/go-cienv v0.0.0-20150120210510-1bb1476777ec/go.mod h1:rGaEvXB4uRSZMmzKNLoXvTu1sfx+1kv/DojUlPrSZGs= 128 | github.com/jbenet/go-cienv v0.1.0 h1:Vc/s0QbQtoxX8MwwSLWWh+xNNZvM3Lw7NsTcHrvvhMc= 129 | github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= 130 | github.com/jbenet/go-temp-err-catcher v0.0.0-20150120210811-aac704a3f4f2 h1:vhC1OXXiT9R2pczegwz6moDvuRpggaroAXhPIseh57A= 131 | github.com/jbenet/go-temp-err-catcher v0.0.0-20150120210811-aac704a3f4f2/go.mod h1:8GXXJV31xl8whumTzdZsTt3RnUIiPqzkyf7mxToRCMs= 132 | github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8/go.mod h1:Ly/wlsjFq/qrU3Rar62tu1gASgGw6chQbSh/XgIIXCY= 133 | github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= 134 | github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0o= 135 | github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= 136 | github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= 137 | github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= 138 | github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= 139 | github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0= 140 | github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= 141 | github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= 142 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 143 | github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= 144 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 145 | github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d h1:68u9r4wEvL3gYg2jvAOgROwZ3H+Y3hIDk4tbbmIjcYQ= 146 | github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= 147 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 148 | github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= 149 | github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 150 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 151 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 152 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 153 | github.com/libp2p/go-addr-util v0.0.1 h1:TpTQm9cXVRVSKsYbgQ7GKc3KbbHVTnbostgGaDEP+88= 154 | github.com/libp2p/go-addr-util v0.0.1/go.mod h1:4ac6O7n9rIAKB1dnd+s8IbbMXkt+oBpzX4/+RACcnlQ= 155 | github.com/libp2p/go-buffer-pool v0.0.1/go.mod h1:xtyIz9PMobb13WaxR6Zo1Pd1zXJKYg0a8KiIvDp3TzQ= 156 | github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOSqcmlfs= 157 | github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= 158 | github.com/libp2p/go-conn-security-multistream v0.1.0 h1:aqGmto+ttL/uJgX0JtQI0tD21CIEy5eYd1Hlp0juHY0= 159 | github.com/libp2p/go-conn-security-multistream v0.1.0/go.mod h1:aw6eD7LOsHEX7+2hJkDxw1MteijaVcI+/eP2/x3J1xc= 160 | github.com/libp2p/go-eventbus v0.1.0 h1:mlawomSAjjkk97QnYiEmHsLu7E136+2oCWSHRUvMfzQ= 161 | github.com/libp2p/go-eventbus v0.1.0/go.mod h1:vROgu5cs5T7cv7POWlWxBaVLxfSegC5UGQf8A2eEmx4= 162 | github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8= 163 | github.com/libp2p/go-flow-metrics v0.0.2/go.mod h1:HeoSNUrOJVK1jEpDqVEiUOIXqhbnS27omG0uWU5slZs= 164 | github.com/libp2p/go-flow-metrics v0.0.3 h1:8tAs/hSdNvUiLgtlSy3mxwxWP4I9y/jlkPFT7epKdeM= 165 | github.com/libp2p/go-flow-metrics v0.0.3/go.mod h1:HeoSNUrOJVK1jEpDqVEiUOIXqhbnS27omG0uWU5slZs= 166 | github.com/libp2p/go-libp2p v0.6.1/go.mod h1:CTFnWXogryAHjXAKEbOf1OWY+VeAP3lDMZkfEI5sT54= 167 | github.com/libp2p/go-libp2p v0.7.0/go.mod h1:hZJf8txWeCduQRDC/WSqBGMxaTHCOYHt2xSU1ivxn0k= 168 | github.com/libp2p/go-libp2p v0.7.4/go.mod h1:oXsBlTLF1q7pxr+9w6lqzS1ILpyHsaBPniVO7zIHGMw= 169 | github.com/libp2p/go-libp2p v0.8.1 h1:6AK178W4GmfGxV+L51bd54/fSWEjNR+S0DO0odk/CwI= 170 | github.com/libp2p/go-libp2p v0.8.1/go.mod h1:QRNH9pwdbEBpx5DTJYg+qxcVaDMAz3Ee/qDKwXujH5o= 171 | github.com/libp2p/go-libp2p-autonat v0.1.1/go.mod h1:OXqkeGOY2xJVWKAGV2inNF5aKN/djNA3fdpCWloIudE= 172 | github.com/libp2p/go-libp2p-autonat v0.2.0/go.mod h1:DX+9teU4pEEoZUqR1PiMlqliONQdNbfzE1C718tcViI= 173 | github.com/libp2p/go-libp2p-autonat v0.2.1/go.mod h1:MWtAhV5Ko1l6QBsHQNSuM6b1sRkXrpk0/LqCr+vCVxI= 174 | github.com/libp2p/go-libp2p-autonat v0.2.2 h1:4dlgcEEugTFWSvdG2UIFxhnOMpX76QaZSRAtXmYB8n4= 175 | github.com/libp2p/go-libp2p-autonat v0.2.2/go.mod h1:HsM62HkqZmHR2k1xgX34WuWDzk/nBwNHoeyyT4IWV6A= 176 | github.com/libp2p/go-libp2p-blankhost v0.1.1/go.mod h1:pf2fvdLJPsC1FsVrNP3DUUvMzUts2dsLLBEpo1vW1ro= 177 | github.com/libp2p/go-libp2p-blankhost v0.1.4 h1:I96SWjR4rK9irDHcHq3XHN6hawCRTPUADzkJacgZLvk= 178 | github.com/libp2p/go-libp2p-blankhost v0.1.4/go.mod h1:oJF0saYsAXQCSfDq254GMNmLNz6ZTHTOvtF4ZydUvwU= 179 | github.com/libp2p/go-libp2p-circuit v0.1.4/go.mod h1:CY67BrEjKNDhdTk8UgBX1Y/H5c3xkAcs3gnksxY7osU= 180 | github.com/libp2p/go-libp2p-circuit v0.2.1 h1:BDiBcQxX/ZJJ/yDl3sqZt1bjj4PkZCEi7IEpwxXr13k= 181 | github.com/libp2p/go-libp2p-circuit v0.2.1/go.mod h1:BXPwYDN5A8z4OEY9sOfr2DUQMLQvKt/6oku45YUmjIo= 182 | github.com/libp2p/go-libp2p-core v0.0.1/go.mod h1:g/VxnTZ/1ygHxH3dKok7Vno1VfpvGcGip57wjTU4fco= 183 | github.com/libp2p/go-libp2p-core v0.0.4/go.mod h1:jyuCQP356gzfCFtRKyvAbNkyeuxb7OlyhWZ3nls5d2I= 184 | github.com/libp2p/go-libp2p-core v0.2.0/go.mod h1:X0eyB0Gy93v0DZtSYbEM7RnMChm9Uv3j7yRXjO77xSI= 185 | github.com/libp2p/go-libp2p-core v0.2.2/go.mod h1:8fcwTbsG2B+lTgRJ1ICZtiM5GWCWZVoVrLaDRvIRng0= 186 | github.com/libp2p/go-libp2p-core v0.2.4/go.mod h1:STh4fdfa5vDYr0/SzYYeqnt+E6KfEV5VxfIrm0bcI0g= 187 | github.com/libp2p/go-libp2p-core v0.2.5/go.mod h1:6+5zJmKhsf7yHn1RbmYDu08qDUpIUxGdqHuEZckmZOA= 188 | github.com/libp2p/go-libp2p-core v0.3.0/go.mod h1:ACp3DmS3/N64c2jDzcV429ukDpicbL6+TrrxANBjPGw= 189 | github.com/libp2p/go-libp2p-core v0.3.1/go.mod h1:thvWy0hvaSBhnVBaW37BvzgVV68OUhgJJLAa6almrII= 190 | github.com/libp2p/go-libp2p-core v0.4.0/go.mod h1:49XGI+kc38oGVwqSBhDEwytaAxgZasHhFfQKibzTls0= 191 | github.com/libp2p/go-libp2p-core v0.5.0/go.mod h1:49XGI+kc38oGVwqSBhDEwytaAxgZasHhFfQKibzTls0= 192 | github.com/libp2p/go-libp2p-core v0.5.1 h1:6Cu7WljPQtGY2krBlMoD8L/zH3tMUsCbqNFH7cZwCoI= 193 | github.com/libp2p/go-libp2p-core v0.5.1/go.mod h1:uN7L2D4EvPCvzSH5SrhR72UWbnSGpt5/a35Sm4upn4Y= 194 | github.com/libp2p/go-libp2p-crypto v0.1.0/go.mod h1:sPUokVISZiy+nNuTTH/TY+leRSxnFj/2GLjtOTW90hI= 195 | github.com/libp2p/go-libp2p-discovery v0.2.0/go.mod h1:s4VGaxYMbw4+4+tsoQTqh7wfxg97AEdo4GYBt6BadWg= 196 | github.com/libp2p/go-libp2p-discovery v0.3.0 h1:+JnYBRLzZQtRq0mK3xhyjBwHytLmJXMTZkQfbw+UrGA= 197 | github.com/libp2p/go-libp2p-discovery v0.3.0/go.mod h1:o03drFnz9BVAZdzC/QUQ+NeQOu38Fu7LJGEOK2gQltw= 198 | github.com/libp2p/go-libp2p-kad-dht v0.7.7 h1:ABMuBpic5/vybCzV6hu2+XtBUuM2gUZozQRavgarSZ0= 199 | github.com/libp2p/go-libp2p-kad-dht v0.7.7/go.mod h1:28//9SIznp9csEX6m48BNm8sd3k3YNc0PukflUSbntE= 200 | github.com/libp2p/go-libp2p-kbucket v0.4.1 h1:6FyzbQuGLPzbMv3HiD232zqscIz5iB8ppJwb380+OGI= 201 | github.com/libp2p/go-libp2p-kbucket v0.4.1/go.mod h1:7sCeZx2GkNK1S6lQnGUW5JYZCFPnXzAZCCBBS70lytY= 202 | github.com/libp2p/go-libp2p-loggables v0.1.0 h1:h3w8QFfCt2UJl/0/NW4K829HX/0S4KD31PQ7m8UXXO8= 203 | github.com/libp2p/go-libp2p-loggables v0.1.0/go.mod h1:EyumB2Y6PrYjr55Q3/tiJ/o3xoDasoRYM7nOzEpoa90= 204 | github.com/libp2p/go-libp2p-mplex v0.2.0/go.mod h1:Ejl9IyjvXJ0T9iqUTE1jpYATQ9NM3g+OtR+EMMODbKo= 205 | github.com/libp2p/go-libp2p-mplex v0.2.1/go.mod h1:SC99Rxs8Vuzrf/6WhmH41kNn13TiYdAWNYHrwImKLnE= 206 | github.com/libp2p/go-libp2p-mplex v0.2.2/go.mod h1:74S9eum0tVQdAfFiKxAyKzNdSuLqw5oadDq7+L/FELo= 207 | github.com/libp2p/go-libp2p-mplex v0.2.3 h1:2zijwaJvpdesST2MXpI5w9wWFRgYtMcpRX7rrw0jmOo= 208 | github.com/libp2p/go-libp2p-mplex v0.2.3/go.mod h1:CK3p2+9qH9x+7ER/gWWDYJ3QW5ZxWDkm+dVvjfuG3ek= 209 | github.com/libp2p/go-libp2p-nat v0.0.5/go.mod h1:1qubaE5bTZMJE+E/uu2URroMbzdubFz1ChgiN79yKPE= 210 | github.com/libp2p/go-libp2p-nat v0.0.6 h1:wMWis3kYynCbHoyKLPBEMu4YRLltbm8Mk08HGSfvTkU= 211 | github.com/libp2p/go-libp2p-nat v0.0.6/go.mod h1:iV59LVhB3IkFvS6S6sauVTSOrNEANnINbI/fkaLimiw= 212 | github.com/libp2p/go-libp2p-netutil v0.1.0 h1:zscYDNVEcGxyUpMd0JReUZTrpMfia8PmLKcKF72EAMQ= 213 | github.com/libp2p/go-libp2p-netutil v0.1.0/go.mod h1:3Qv/aDqtMLTUyQeundkKsA+YCThNdbQD54k3TqjpbFU= 214 | github.com/libp2p/go-libp2p-peer v0.2.0/go.mod h1:RCffaCvUyW2CJmG2gAWVqwePwW7JMgxjsHm7+J5kjWY= 215 | github.com/libp2p/go-libp2p-peerstore v0.1.0/go.mod h1:2CeHkQsr8svp4fZ+Oi9ykN1HBb6u0MOvdJ7YIsmcwtY= 216 | github.com/libp2p/go-libp2p-peerstore v0.1.3/go.mod h1:BJ9sHlm59/80oSkpWgr1MyY1ciXAXV397W6h1GH/uKI= 217 | github.com/libp2p/go-libp2p-peerstore v0.1.4/go.mod h1:+4BDbDiiKf4PzpANZDAT+knVdLxvqh7hXOujessqdzs= 218 | github.com/libp2p/go-libp2p-peerstore v0.2.0/go.mod h1:N2l3eVIeAitSg3Pi2ipSrJYnqhVnMNQZo9nkSCuAbnQ= 219 | github.com/libp2p/go-libp2p-peerstore v0.2.1/go.mod h1:NQxhNjWxf1d4w6PihR8btWIRjwRLBr4TYKfNgrUkOPA= 220 | github.com/libp2p/go-libp2p-peerstore v0.2.2/go.mod h1:NQxhNjWxf1d4w6PihR8btWIRjwRLBr4TYKfNgrUkOPA= 221 | github.com/libp2p/go-libp2p-peerstore v0.2.3 h1:MofRq2l3c15vQpEygTetV+zRRrncz+ktiXW7H2EKoEQ= 222 | github.com/libp2p/go-libp2p-peerstore v0.2.3/go.mod h1:K8ljLdFn590GMttg/luh4caB/3g0vKuY01psze0upRw= 223 | github.com/libp2p/go-libp2p-pnet v0.2.0 h1:J6htxttBipJujEjz1y0a5+eYoiPcFHhSYHH6na5f0/k= 224 | github.com/libp2p/go-libp2p-pnet v0.2.0/go.mod h1:Qqvq6JH/oMZGwqs3N1Fqhv8NVhrdYcO0BW4wssv21LA= 225 | github.com/libp2p/go-libp2p-record v0.1.2 h1:M50VKzWnmUrk/M5/Dz99qO9Xh4vs8ijsK+7HkJvRP+0= 226 | github.com/libp2p/go-libp2p-record v0.1.2/go.mod h1:pal0eNcT5nqZaTV7UGhqeGqxFgGdsU/9W//C8dqjQDk= 227 | github.com/libp2p/go-libp2p-routing-helpers v0.2.1/go.mod h1:rTLUHlGDZbXHANJAWP2xW7ruPNJLj41/GnCBiR+qgjU= 228 | github.com/libp2p/go-libp2p-secio v0.1.0/go.mod h1:tMJo2w7h3+wN4pgU2LSYeiKPrfqBgkOsdiKK77hE7c8= 229 | github.com/libp2p/go-libp2p-secio v0.2.0/go.mod h1:2JdZepB8J5V9mBp79BmwsaPQhRPNN2NrnB2lKQcdy6g= 230 | github.com/libp2p/go-libp2p-secio v0.2.1/go.mod h1:cWtZpILJqkqrSkiYcDBh5lA3wbT2Q+hz3rJQq3iftD8= 231 | github.com/libp2p/go-libp2p-secio v0.2.2 h1:rLLPvShPQAcY6eNurKNZq3eZjPWfU9kXF2eI9jIYdrg= 232 | github.com/libp2p/go-libp2p-secio v0.2.2/go.mod h1:wP3bS+m5AUnFA+OFO7Er03uO1mncHG0uVwGrwvjYlNY= 233 | github.com/libp2p/go-libp2p-swarm v0.1.0/go.mod h1:wQVsCdjsuZoc730CgOvh5ox6K8evllckjebkdiY5ta4= 234 | github.com/libp2p/go-libp2p-swarm v0.2.2/go.mod h1:fvmtQ0T1nErXym1/aa1uJEyN7JzaTNyBcHImCxRpPKU= 235 | github.com/libp2p/go-libp2p-swarm v0.2.3 h1:uVkCb8Blfg7HQ/f30TyHn1g/uCwXsAET7pU0U59gx/A= 236 | github.com/libp2p/go-libp2p-swarm v0.2.3/go.mod h1:P2VO/EpxRyDxtChXz/VPVXyTnszHvokHKRhfkEgFKNM= 237 | github.com/libp2p/go-libp2p-testing v0.0.2/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= 238 | github.com/libp2p/go-libp2p-testing v0.0.3/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= 239 | github.com/libp2p/go-libp2p-testing v0.0.4/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= 240 | github.com/libp2p/go-libp2p-testing v0.1.0/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0= 241 | github.com/libp2p/go-libp2p-testing v0.1.1 h1:U03z3HnGI7Ni8Xx6ONVZvUFOAzWYmolWf5W5jAOPNmU= 242 | github.com/libp2p/go-libp2p-testing v0.1.1/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0= 243 | github.com/libp2p/go-libp2p-tls v0.1.3 h1:twKMhMu44jQO+HgQK9X8NHO5HkeJu2QbhLzLJpa8oNM= 244 | github.com/libp2p/go-libp2p-tls v0.1.3/go.mod h1:wZfuewxOndz5RTnCAxFliGjvYSDA40sKitV4c50uI1M= 245 | github.com/libp2p/go-libp2p-transport-upgrader v0.1.1/go.mod h1:IEtA6or8JUbsV07qPW4r01GnTenLW4oi3lOPbUMGJJA= 246 | github.com/libp2p/go-libp2p-transport-upgrader v0.2.0 h1:5EhPgQhXZNyfL22ERZTUoVp9UVVbNowWNVtELQaKCHk= 247 | github.com/libp2p/go-libp2p-transport-upgrader v0.2.0/go.mod h1:mQcrHj4asu6ArfSoMuyojOdjx73Q47cYD7s5+gZOlns= 248 | github.com/libp2p/go-libp2p-yamux v0.2.0/go.mod h1:Db2gU+XfLpm6E4rG5uGCFX6uXA8MEXOxFcRoXUODaK8= 249 | github.com/libp2p/go-libp2p-yamux v0.2.2/go.mod h1:lIohaR0pT6mOt0AZ0L2dFze9hds9Req3OfS+B+dv4qw= 250 | github.com/libp2p/go-libp2p-yamux v0.2.5/go.mod h1:Zpgj6arbyQrmZ3wxSZxfBmbdnWtbZ48OpsfmQVTErwA= 251 | github.com/libp2p/go-libp2p-yamux v0.2.7 h1:vzKu0NVtxvEIDGCv6mjKRcK0gipSgaXmJZ6jFv0d/dk= 252 | github.com/libp2p/go-libp2p-yamux v0.2.7/go.mod h1:X28ENrBMU/nm4I3Nx4sZ4dgjZ6VhLEn0XhIoZ5viCwU= 253 | github.com/libp2p/go-maddr-filter v0.0.4/go.mod h1:6eT12kSQMA9x2pvFQa+xesMKUBlj9VImZbj3B9FBH/Q= 254 | github.com/libp2p/go-maddr-filter v0.0.5 h1:CW3AgbMO6vUvT4kf87y4N+0P8KUl2aqLYhrGyDUbLSg= 255 | github.com/libp2p/go-maddr-filter v0.0.5/go.mod h1:Jk+36PMfIqCJhAnaASRH83bdAvfDRp/w6ENFaC9bG+M= 256 | github.com/libp2p/go-mplex v0.0.3/go.mod h1:pK5yMLmOoBR1pNCqDlA2GQrdAVTMkqFalaTWe7l4Yd0= 257 | github.com/libp2p/go-mplex v0.1.0/go.mod h1:SXgmdki2kwCUlCCbfGLEgHjC4pFqhTp0ZoV6aiKgxDU= 258 | github.com/libp2p/go-mplex v0.1.1/go.mod h1:Xgz2RDCi3co0LeZfgjm4OgUF15+sVR8SRcu3SFXI1lk= 259 | github.com/libp2p/go-mplex v0.1.2 h1:qOg1s+WdGLlpkrczDqmhYzyk3vCfsQ8+RxRTQjOZWwI= 260 | github.com/libp2p/go-mplex v0.1.2/go.mod h1:Xgz2RDCi3co0LeZfgjm4OgUF15+sVR8SRcu3SFXI1lk= 261 | github.com/libp2p/go-msgio v0.0.2/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= 262 | github.com/libp2p/go-msgio v0.0.4 h1:agEFehY3zWJFUHK6SEMR7UYmk2z6kC3oeCM7ybLhguA= 263 | github.com/libp2p/go-msgio v0.0.4/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= 264 | github.com/libp2p/go-nat v0.0.4/go.mod h1:Nmw50VAvKuk38jUBcmNh6p9lUJLoODbJRvYAa/+KSDo= 265 | github.com/libp2p/go-nat v0.0.5 h1:qxnwkco8RLKqVh1NmjQ+tJ8p8khNLFxuElYG/TwqW4Q= 266 | github.com/libp2p/go-nat v0.0.5/go.mod h1:B7NxsVNPZmRLvMOwiEO1scOSyjA56zxYAGv1yQgRkEU= 267 | github.com/libp2p/go-netroute v0.1.2 h1:UHhB35chwgvcRI392znJA3RCBtZ3MpE3ahNCN5MR4Xg= 268 | github.com/libp2p/go-netroute v0.1.2/go.mod h1:jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdmLPL2n9MKbk= 269 | github.com/libp2p/go-openssl v0.0.2/go.mod h1:v8Zw2ijCSWBQi8Pq5GAixw6DbFfa9u6VIYDXnvOXkc0= 270 | github.com/libp2p/go-openssl v0.0.3/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= 271 | github.com/libp2p/go-openssl v0.0.4 h1:d27YZvLoTyMhIN4njrkr8zMDOM4lfpHIp6A+TK9fovg= 272 | github.com/libp2p/go-openssl v0.0.4/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= 273 | github.com/libp2p/go-reuseport v0.0.1 h1:7PhkfH73VXfPJYKQ6JwS5I/eVcoyYi9IMNGc6FWpFLw= 274 | github.com/libp2p/go-reuseport v0.0.1/go.mod h1:jn6RmB1ufnQwl0Q1f+YxAj8isJgDCQzaaxIFYDhcYEA= 275 | github.com/libp2p/go-reuseport-transport v0.0.2/go.mod h1:YkbSDrvjUVDL6b8XqriyA20obEtsW9BLkuOUyQAOCbs= 276 | github.com/libp2p/go-reuseport-transport v0.0.3 h1:zzOeXnTooCkRvoH+bSXEfXhn76+LAiwoneM0gnXjF2M= 277 | github.com/libp2p/go-reuseport-transport v0.0.3/go.mod h1:Spv+MPft1exxARzP2Sruj2Wb5JSyHNncjf1Oi2dEbzM= 278 | github.com/libp2p/go-sockaddr v0.0.2 h1:tCuXfpA9rq7llM/v834RKc/Xvovy/AqM9kHvTV/jY/Q= 279 | github.com/libp2p/go-sockaddr v0.0.2/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= 280 | github.com/libp2p/go-stream-muxer v0.0.1/go.mod h1:bAo8x7YkSpadMTbtTaxGVHWUQsR/l5MEaHbKaliuT14= 281 | github.com/libp2p/go-stream-muxer-multistream v0.2.0 h1:714bRJ4Zy9mdhyTLJ+ZKiROmAFwUHpeRidG+q7LTQOg= 282 | github.com/libp2p/go-stream-muxer-multistream v0.2.0/go.mod h1:j9eyPol/LLRqT+GPLSxvimPhNph4sfYfMoDPd7HkzIc= 283 | github.com/libp2p/go-tcp-transport v0.1.0/go.mod h1:oJ8I5VXryj493DEJ7OsBieu8fcg2nHGctwtInJVpipc= 284 | github.com/libp2p/go-tcp-transport v0.1.1/go.mod h1:3HzGvLbx6etZjnFlERyakbaYPdfjg2pWP97dFZworkY= 285 | github.com/libp2p/go-tcp-transport v0.2.0 h1:YoThc549fzmNJIh7XjHVtMIFaEDRtIrtWciG5LyYAPo= 286 | github.com/libp2p/go-tcp-transport v0.2.0/go.mod h1:vX2U0CnWimU4h0SGSEsg++AzvBcroCGYw28kh94oLe0= 287 | github.com/libp2p/go-ws-transport v0.2.0/go.mod h1:9BHJz/4Q5A9ludYWKoGCFC5gUElzlHoKzu0yY9p/klM= 288 | github.com/libp2p/go-ws-transport v0.3.0 h1:mjo6pL5aVR9rCjl9wNq3DupbaQlyR61pzoOT2MdtxaA= 289 | github.com/libp2p/go-ws-transport v0.3.0/go.mod h1:bpgTJmRZAvVHrgHybCVyqoBmyLQ1fiZuEaBYusP5zsk= 290 | github.com/libp2p/go-yamux v1.2.2/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= 291 | github.com/libp2p/go-yamux v1.3.0/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= 292 | github.com/libp2p/go-yamux v1.3.3/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= 293 | github.com/libp2p/go-yamux v1.3.5 h1:ibuz4naPAully0pN6J/kmUARiqLpnDQIzI/8GCOrljg= 294 | github.com/libp2p/go-yamux v1.3.5/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= 295 | github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= 296 | github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= 297 | github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= 298 | github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= 299 | github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= 300 | github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= 301 | github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= 302 | github.com/miekg/dns v1.1.12/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= 303 | github.com/miekg/dns v1.1.28/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= 304 | github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= 305 | github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= 306 | github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= 307 | github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= 308 | github.com/minio/sha256-simd v0.1.0/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= 309 | github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= 310 | github.com/minio/sha256-simd v0.1.1 h1:5QHSlgo3nt5yKOJrC7W8w7X+NFl8cMPZm96iu8kKUJU= 311 | github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= 312 | github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 313 | github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 314 | github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= 315 | github.com/mr-tron/base58 v1.1.1/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= 316 | github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= 317 | github.com/mr-tron/base58 v1.1.3 h1:v+sk57XuaCKGXpWtVBX8YJzO7hMGx4Aajh4TQbdEFdc= 318 | github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= 319 | github.com/multiformats/go-base32 v0.0.3 h1:tw5+NhuwaOjJCC5Pp82QuXbrmLzWg7uxlMFp8Nq/kkI= 320 | github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= 321 | github.com/multiformats/go-multiaddr v0.0.1/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= 322 | github.com/multiformats/go-multiaddr v0.0.2/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= 323 | github.com/multiformats/go-multiaddr v0.0.4/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= 324 | github.com/multiformats/go-multiaddr v0.1.0/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= 325 | github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= 326 | github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4= 327 | github.com/multiformats/go-multiaddr v0.2.1 h1:SgG/cw5vqyB5QQe5FPe2TqggU9WtrA9X4nZw7LlVqOI= 328 | github.com/multiformats/go-multiaddr v0.2.1/go.mod h1:s/Apk6IyxfvMjDafnhJgJ3/46z7tZ04iMk5wP4QMGGE= 329 | github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= 330 | github.com/multiformats/go-multiaddr-dns v0.0.2/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= 331 | github.com/multiformats/go-multiaddr-dns v0.2.0 h1:YWJoIDwLePniH7OU5hBnDZV6SWuvJqJ0YtN6pLeH9zA= 332 | github.com/multiformats/go-multiaddr-dns v0.2.0/go.mod h1:TJ5pr5bBO7Y1B18djPuRsVkduhQH2YqYSbxWJzYGdK0= 333 | github.com/multiformats/go-multiaddr-fmt v0.0.1/go.mod h1:aBYjqL4T/7j4Qx+R73XSv/8JsgnRFlf0w2KGLCmXl3Q= 334 | github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= 335 | github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= 336 | github.com/multiformats/go-multiaddr-net v0.0.1/go.mod h1:nw6HSxNmCIQH27XPGBuX+d1tnvM7ihcFwHMSstNAVUU= 337 | github.com/multiformats/go-multiaddr-net v0.1.0/go.mod h1:5JNbcfBOP4dnhoZOv10JJVkJO0pCCEf8mTnipAo2UZQ= 338 | github.com/multiformats/go-multiaddr-net v0.1.1/go.mod h1:5JNbcfBOP4dnhoZOv10JJVkJO0pCCEf8mTnipAo2UZQ= 339 | github.com/multiformats/go-multiaddr-net v0.1.2/go.mod h1:QsWt3XK/3hwvNxZJp92iMQKME1qHfpYmyIjFVsSOY6Y= 340 | github.com/multiformats/go-multiaddr-net v0.1.3/go.mod h1:ilNnaM9HbmVFqsb/qcNysjCu4PVONlrBZpHIrw/qQuA= 341 | github.com/multiformats/go-multiaddr-net v0.1.4 h1:g6gwydsfADqFvrHoMkS0n9Ok9CG6F7ytOH/bJDkhIOY= 342 | github.com/multiformats/go-multiaddr-net v0.1.4/go.mod h1:ilNnaM9HbmVFqsb/qcNysjCu4PVONlrBZpHIrw/qQuA= 343 | github.com/multiformats/go-multibase v0.0.1 h1:PN9/v21eLywrFWdFNsFKaU04kLJzuYzmrJR+ubhT9qA= 344 | github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= 345 | github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= 346 | github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po= 347 | github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= 348 | github.com/multiformats/go-multihash v0.0.9/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= 349 | github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= 350 | github.com/multiformats/go-multihash v0.0.13 h1:06x+mk/zj1FoMsgNejLpy6QTvJqlSt/BhLEy87zidlc= 351 | github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= 352 | github.com/multiformats/go-multistream v0.1.0/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= 353 | github.com/multiformats/go-multistream v0.1.1 h1:JlAdpIFhBhGRLxe9W6Om0w++Gd6KMWoFPZL/dEnm9nI= 354 | github.com/multiformats/go-multistream v0.1.1/go.mod h1:KmHZ40hzVxiaiwlj3MEbYgK9JFk2/9UktWZAF54Du38= 355 | github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= 356 | github.com/multiformats/go-varint v0.0.2/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= 357 | github.com/multiformats/go-varint v0.0.5 h1:XVZwSo04Cs3j/jS0uAEPpT3JY6DzMcVLLoWOSnCxOjg= 358 | github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= 359 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 360 | github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 361 | github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 362 | github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU= 363 | github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= 364 | github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= 365 | github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= 366 | github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= 367 | github.com/onsi/gomega v1.9.0 h1:R1uwffexN6Pr340GtYRIdZmAiN4J+iw6WG4wog1DUXg= 368 | github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= 369 | github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= 370 | github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= 371 | github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= 372 | github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= 373 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 374 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 375 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 376 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 377 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 378 | github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 379 | github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= 380 | github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= 381 | github.com/smola/gocompat v0.2.0/go.mod h1:1B0MlxbmoZNo3h8guHp8HztB3BSYR5itql9qtVc0ypY= 382 | github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0= 383 | github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= 384 | github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= 385 | github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= 386 | github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= 387 | github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= 388 | github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= 389 | github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= 390 | github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= 391 | github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= 392 | github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 393 | github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= 394 | github.com/src-d/envconfig v1.0.0/go.mod h1:Q9YQZ7BKITldTBnoxsE5gOeB5y66RyPXeue/R4aaNBc= 395 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 396 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 397 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 398 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 399 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 400 | github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= 401 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 402 | github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= 403 | github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= 404 | github.com/wangjia184/sortedset v0.0.0-20160527075905-f5d03557ba30/go.mod h1:YkocrP2K2tcw938x9gCOmT5G5eCD6jsTz0SZuyAqwIE= 405 | github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 h1:EKhdznlJHPMoKr0XTrX+IlJs1LH3lyx2nfr1dOlZ79k= 406 | github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc= 407 | github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM= 408 | github.com/whyrusleeping/go-logging v0.0.1/go.mod h1:lDPYj54zutzG1XYfHAhcc7oNXEburHQBn+Iqd4yS4vE= 409 | github.com/whyrusleeping/mafmt v1.2.8 h1:TCghSl5kkwEE0j+sU/gudyhVMRlpBin8fMBBHg59EbA= 410 | github.com/whyrusleeping/mafmt v1.2.8/go.mod h1:faQJFPbLSxzD9xpA02ttW/tS9vZykNvXwGvqIpk20FA= 411 | github.com/whyrusleeping/mdns v0.0.0-20190826153040-b9b60ed33aa9/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4= 412 | github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 h1:E9S12nwJwEOXe2d6gT6qxdvqMnNq+VnSsKPgm2ZZNds= 413 | github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7/go.mod h1:X2c0RVCI1eSUFI8eLcY3c0423ykwiUdxLJtkDvruhjI= 414 | github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= 415 | github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= 416 | go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= 417 | go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA= 418 | go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 419 | go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8= 420 | go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 421 | go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= 422 | go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk= 423 | go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= 424 | go.uber.org/goleak v1.0.0 h1:qsup4IcBdlmsnGfqyLl4Ntn3C2XCCuKAE7DwHpScyUo= 425 | go.uber.org/goleak v1.0.0/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= 426 | go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= 427 | go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A= 428 | go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= 429 | go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= 430 | go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= 431 | go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= 432 | go.uber.org/zap v1.14.1 h1:nYDKopTbvAPq/NrUVZwT15y2lpROBiLLyoRTbXOYWOo= 433 | go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= 434 | golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 435 | golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 436 | golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 437 | golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 438 | golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 439 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 440 | golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 441 | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 442 | golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 443 | golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 444 | golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 445 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 446 | golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d h1:1ZiEyfaQIg3Qh0EoqpwAakHVhecoE5wlSg5GjnafJGw= 447 | golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 448 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 449 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 450 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 451 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 452 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= 453 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 454 | golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= 455 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 456 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 457 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 458 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 459 | golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 460 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 461 | golang.org/x/net v0.0.0-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 462 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 463 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 464 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 465 | golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g= 466 | golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 467 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 468 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 469 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 470 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 471 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 472 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 473 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 474 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 475 | golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 476 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 477 | golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 478 | golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 479 | golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 480 | golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 481 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 482 | golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 483 | golang.org/x/sys v0.0.0-20190526052359-791d8a0f4d09/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 484 | golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 485 | golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 486 | golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 487 | golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 488 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8= 489 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 490 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 491 | golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= 492 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 493 | golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 494 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 495 | golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 496 | golang.org/x/tools v0.0.0-20181130052023-1c3d964395ce/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 497 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 498 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 499 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 500 | golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 501 | golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 502 | golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 503 | golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 504 | golang.org/x/tools v0.0.0-20191216052735-49a3e744a425 h1:VvQyQJN0tSuecqgcIxMWnnfG5kSmgy9KZR9sW3W5QeA= 505 | golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 506 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 507 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA= 508 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 509 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 510 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 511 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 512 | google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 513 | google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 514 | google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 515 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 516 | google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= 517 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 518 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 519 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= 520 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 521 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 522 | gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= 523 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 524 | gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVYcSwSjGebuDL6176A1XskgbtNl64NSg+n8= 525 | gopkg.in/src-d/go-log.v1 v1.0.1/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE= 526 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= 527 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 528 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 529 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 530 | gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= 531 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 532 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 533 | honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= 534 | honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= 535 | -------------------------------------------------------------------------------- /lookup.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "github.com/libp2p/go-libp2p-core/peer" 7 | record_pb "github.com/libp2p/go-libp2p-record/pb" 8 | 9 | "github.com/multiformats/go-multihash" 10 | 11 | "github.com/libp2p/go-libp2p-core/routing" 12 | pb "github.com/libp2p/go-libp2p-kad-dht/pb" 13 | ) 14 | 15 | // getValueOrPeers queries a particular peer p for the value for 16 | // key. It returns either the value or a list of closer peers. 17 | // NOTE: It will update the dht's peerstore with any new addresses 18 | // it finds for the given peer. 19 | func (dht *IpfsDHT) getValueOrPeers(ctx context.Context, p peer.ID, key string) (*record_pb.Record, []*peer.AddrInfo, error) { 20 | pmes, err := dht.getValueSingle(ctx, p, key) 21 | if err != nil { 22 | return nil, nil, err 23 | } 24 | 25 | // Perhaps we were given closer peers 26 | peers := pb.PBPeersToPeerInfos(pmes.GetCloserPeers()) 27 | 28 | if record := pmes.GetRecord(); record != nil { 29 | return record, peers, err 30 | } 31 | 32 | if len(peers) > 0 { 33 | return nil, peers, nil 34 | } 35 | 36 | return nil, nil, routing.ErrNotFound 37 | } 38 | 39 | // getValueSingle simply performs the get value RPC with the given parameters 40 | func (dht *IpfsDHT) getValueSingle(ctx context.Context, p peer.ID, key string) (*pb.Message, error) { 41 | pmes := pb.NewMessage(pb.Message_GET_VALUE, []byte(key), 0) 42 | return dht.sendRequest(ctx, p, pmes) 43 | } 44 | 45 | func (dht *IpfsDHT) fp(ctx context.Context, p peer.ID, key multihash.Multihash) ([]*peer.AddrInfo, error) { 46 | // For DHT query command 47 | routing.PublishQueryEvent(ctx, &routing.QueryEvent{ 48 | Type: routing.SendingQuery, 49 | ID: p, 50 | }) 51 | 52 | pmes, err := dht.findProvidersSingle(ctx, p, key) 53 | if err != nil { 54 | return nil, err 55 | } 56 | 57 | provs := pb.PBPeersToPeerInfos(pmes.GetProviderPeers()) 58 | _ = provs 59 | 60 | // Give closer peers back to the query to be queried 61 | closer := pmes.GetCloserPeers() 62 | peers := pb.PBPeersToPeerInfos(closer) 63 | 64 | return peers, nil 65 | } 66 | 67 | // findPeerSingle asks peer 'p' if they know where the peer with id 'id' is 68 | func (dht *IpfsDHT) findPeerSingle(ctx context.Context, p peer.ID, id peer.ID) ([]*peer.AddrInfo, error) { 69 | pmes := pb.NewMessage(pb.Message_FIND_NODE, []byte(id), 0) 70 | res, err := dht.sendRequest(ctx, p, pmes) 71 | if err != nil { 72 | return nil, err 73 | } 74 | if res == nil { 75 | return nil, fmt.Errorf("null result returned") 76 | } 77 | return pb.PBPeersToPeerInfos(res.CloserPeers), nil 78 | } 79 | 80 | func (dht *IpfsDHT) findProvidersSingle(ctx context.Context, p peer.ID, key multihash.Multihash) (*pb.Message, error) { 81 | pmes := pb.NewMessage(pb.Message_GET_PROVIDERS, key, 0) 82 | return dht.sendRequest(ctx, p, pmes) 83 | } 84 | 85 | func (dht *IpfsDHT) makeProvRecord(key []byte) (*pb.Message, error) { 86 | pi := peer.AddrInfo{ 87 | ID: dht.host.ID(), 88 | Addrs: dht.host.Addrs(), 89 | } 90 | 91 | // // only share WAN-friendly addresses ?? 92 | // pi.Addrs = addrutil.WANShareableAddrs(pi.Addrs) 93 | if len(pi.Addrs) < 1 { 94 | return nil, fmt.Errorf("no known addresses for self, cannot put provider") 95 | } 96 | 97 | pmes := pb.NewMessage(pb.Message_ADD_PROVIDER, key, 0) 98 | pmes.ProviderPeers = pb.RawPeerInfosToPBPeers([]peer.AddrInfo{pi}) 99 | return pmes, nil 100 | } -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "flag" 6 | "fmt" 7 | "os" 8 | "time" 9 | 10 | "github.com/libp2p/go-libp2p" 11 | "github.com/libp2p/go-libp2p-core/peer" 12 | "github.com/libp2p/go-libp2p-core/protocol" 13 | 14 | kbucket "github.com/libp2p/go-libp2p-kbucket" 15 | "github.com/multiformats/go-multiaddr" 16 | ) 17 | 18 | func main(){ 19 | ctx, cancel := context.WithCancel(context.Background()) 20 | defer cancel() 21 | 22 | out := flag.String("o", "rt.dot", "output file location") 23 | outJson := flag.String("ojson", "rt.json", "output json file location") 24 | flag.Parse() 25 | 26 | peerMap := make(map[peer.ID]map[peer.ID]struct{}) 27 | allPeers := make([]*peer.AddrInfo, 0, 1000) 28 | allPeersSet := make(map[peer.ID]struct{}) 29 | 30 | h, err := libp2p.New(ctx) 31 | if err != nil { 32 | panic(err) 33 | } 34 | 35 | dhtmock := &IpfsDHT{ 36 | host: h, 37 | strmap: make(map[peer.ID]*messageSender), 38 | protocols: []protocol.ID{"/ipfs/kad/1.0.0"}, 39 | } 40 | 41 | //"/dnsaddr/sjc-2.bootstrap.libp2p.io/p2p/QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp" 42 | v2Addr := "/ip4/139.178.89.189/tcp/4001/p2p/QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp" 43 | v1Addr := "/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ" 44 | boosterAddr := "/ip4/207.148.19.196/tcp/20074/p2p/12D3KooWGXBbSZ3ko3UvoekdnnSrdmuFic3XHuNKvGcZyrH1mVxr" 45 | booster2Addr := "/ip4/18.185.241.99/tcp/20001/p2p/12D3KooWA4NVc1GytssyhxGqaT22kJ9XwdhCpS2VwNPPMw59Ctf4" 46 | hydra1 := "/ip4/64.225.116.25/tcp/30017/p2p/12D3KooWHHVPRYiXuWsVmATm8nduX7dXXpw3kC5Co1QSUYVLNXZN" 47 | 48 | allStarting := []string{v1Addr, v2Addr, boosterAddr, booster2Addr, hydra1, booster2Addr} 49 | _= allStarting 50 | 51 | startingPeer, err := multiaddr.NewMultiaddr(v1Addr) 52 | if err != nil { 53 | panic(err) 54 | } 55 | 56 | startingPeerInfo, err := peer.AddrInfoFromP2pAddr(startingPeer) 57 | if err != nil { 58 | panic(err) 59 | } 60 | dhtmock.host.Peerstore().AddAddrs(startingPeerInfo.ID, startingPeerInfo.Addrs, time.Hour) 61 | 62 | queryQueue := make(chan peer.ID, 1) 63 | queryResQueue := make(chan *queryResult, 1) 64 | 65 | maxQueries := 10000 66 | for i :=0; i < maxQueries; i++ { 67 | go func() { 68 | for { 69 | select{ 70 | case p := <- queryQueue: 71 | res := queryPeer(ctx, dhtmock, p) 72 | select { 73 | case queryResQueue <- res: 74 | case <-ctx.Done(): 75 | return 76 | } 77 | case <-ctx.Done(): 78 | return 79 | } 80 | } 81 | }() 82 | } 83 | 84 | allPeers = append(allPeers, startingPeerInfo) 85 | allPeersSet[startingPeerInfo.ID] = struct{}{} 86 | 87 | numPeersTotal := 1 88 | numPeersQueried := 0 89 | numOutstandingQueries := 0 90 | 91 | var nextPeer peer.ID 92 | var sendNextPeer chan peer.ID 93 | 94 | for numPeersQueried < numPeersTotal || numOutstandingQueries != 0 { 95 | if nextPeer == "" && numPeersQueried < numPeersTotal { 96 | nextPeer = allPeers[numPeersQueried].ID 97 | } 98 | 99 | if nextPeer == "" { 100 | sendNextPeer = nil 101 | } else { 102 | sendNextPeer = queryQueue 103 | } 104 | 105 | select { 106 | case res := <-queryResQueue: 107 | if res.err == nil { 108 | fmt.Printf("peer %v had %d peers\n", res.peer, len(res.data)) 109 | if _, ok := peerMap[res.peer]; !ok { 110 | rtPeers := make(map[peer.ID]struct{}, len(res.data)) 111 | for p := range res.data { 112 | rtPeers[p]= struct{}{} 113 | } 114 | peerMap[res.peer] = rtPeers 115 | } else { 116 | panic("how?") 117 | } 118 | 119 | for p, ai := range res.data { 120 | dhtmock.host.Peerstore().AddAddrs(p, ai.Addrs, time.Hour) 121 | if _, ok := allPeersSet[p]; !ok{ 122 | allPeersSet[p] = struct{}{} 123 | allPeers = append(allPeers, ai) 124 | numPeersTotal++ 125 | } 126 | } 127 | } 128 | numOutstandingQueries-- 129 | case sendNextPeer <- nextPeer: 130 | numOutstandingQueries++ 131 | numPeersQueried++ 132 | nextPeer = "" 133 | fmt.Printf("starting %d out of %d\n", numPeersQueried, len(allPeers)) 134 | case <-ctx.Done(): 135 | return 136 | } 137 | } 138 | 139 | OutputData(*out, *outJson, peerMap) 140 | } 141 | 142 | func OutputData(filePath, jsonFile string, peerMap map[peer.ID]map[peer.ID]struct{}) { 143 | f, err := os.Create(filePath) 144 | defer f.Close() 145 | 146 | if err != nil { 147 | panic(err) 148 | } 149 | f.WriteString("digraph D { \n") 150 | for p, rtPeers := range peerMap { 151 | for rtp := range rtPeers { 152 | f.WriteString(fmt.Sprintf("Z%v -> Z%v;\n", p, rtp)) 153 | } 154 | } 155 | f.WriteString("\n}") 156 | } 157 | 158 | type queryResult struct{ 159 | peer peer.ID 160 | data map[peer.ID]*peer.AddrInfo 161 | err error 162 | } 163 | 164 | func queryPeer(ctx context.Context, dhtmock *IpfsDHT, nextPeer peer.ID) *queryResult { 165 | tmpRT, err := kbucket.NewRoutingTable(20, kbucket.ConvertPeerID(nextPeer), time.Hour, dhtmock.host.Peerstore(), time.Hour) 166 | if err != nil { 167 | fmt.Printf("error creating rt for peer %v : %v\n", nextPeer, err) 168 | return &queryResult{nextPeer, nil, err} 169 | } 170 | 171 | localPeers := make(map[peer.ID]*peer.AddrInfo) 172 | for i := 0; i < 12; i++ { 173 | generatePeer, err := tmpRT.GenRandPeerID(uint(i)) 174 | if err != nil { 175 | panic(err) 176 | } 177 | peers, err := dhtmock.findPeerSingle(ctx, nextPeer, generatePeer) 178 | if err != nil { 179 | fmt.Printf("error finding data on peer %v with cpl %d : %v\n", nextPeer, i, err) 180 | break 181 | } 182 | for _, ai := range peers { 183 | if _, ok := localPeers[ai.ID]; !ok { 184 | localPeers[ai.ID] = ai 185 | } 186 | } 187 | } 188 | return &queryResult{nextPeer, localPeers, nil} 189 | } -------------------------------------------------------------------------------- /pb/Makefile: -------------------------------------------------------------------------------- 1 | PB = $(wildcard *.proto) 2 | GO = $(PB:.proto=.pb.go) 3 | 4 | all: $(GO) 5 | 6 | %.pb.go: %.proto 7 | protoc --proto_path=$(GOPATH)/src:. --gogofast_out=. $< 8 | 9 | clean: 10 | rm -f *.pb.go 11 | rm -f *.go 12 | -------------------------------------------------------------------------------- /pb/dht.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-gogo. DO NOT EDIT. 2 | // source: dht.proto 3 | 4 | package dht_pb 5 | 6 | import ( 7 | fmt "fmt" 8 | proto "github.com/gogo/protobuf/proto" 9 | pb "github.com/libp2p/go-libp2p-record/pb" 10 | io "io" 11 | math "math" 12 | math_bits "math/bits" 13 | ) 14 | 15 | // Reference imports to suppress errors if they are not otherwise used. 16 | var _ = proto.Marshal 17 | var _ = fmt.Errorf 18 | var _ = math.Inf 19 | 20 | // This is a compile-time assertion to ensure that this generated file 21 | // is compatible with the proto package it is being compiled against. 22 | // A compilation error at this line likely means your copy of the 23 | // proto package needs to be updated. 24 | const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package 25 | 26 | type Message_MessageType int32 27 | 28 | const ( 29 | Message_PUT_VALUE Message_MessageType = 0 30 | Message_GET_VALUE Message_MessageType = 1 31 | Message_ADD_PROVIDER Message_MessageType = 2 32 | Message_GET_PROVIDERS Message_MessageType = 3 33 | Message_FIND_NODE Message_MessageType = 4 34 | Message_PING Message_MessageType = 5 35 | ) 36 | 37 | var Message_MessageType_name = map[int32]string{ 38 | 0: "PUT_VALUE", 39 | 1: "GET_VALUE", 40 | 2: "ADD_PROVIDER", 41 | 3: "GET_PROVIDERS", 42 | 4: "FIND_NODE", 43 | 5: "PING", 44 | } 45 | 46 | var Message_MessageType_value = map[string]int32{ 47 | "PUT_VALUE": 0, 48 | "GET_VALUE": 1, 49 | "ADD_PROVIDER": 2, 50 | "GET_PROVIDERS": 3, 51 | "FIND_NODE": 4, 52 | "PING": 5, 53 | } 54 | 55 | func (x Message_MessageType) String() string { 56 | return proto.EnumName(Message_MessageType_name, int32(x)) 57 | } 58 | 59 | func (Message_MessageType) EnumDescriptor() ([]byte, []int) { 60 | return fileDescriptor_616a434b24c97ff4, []int{0, 0} 61 | } 62 | 63 | type Message_ConnectionType int32 64 | 65 | const ( 66 | // sender does not have a connection to peer, and no extra information (default) 67 | Message_NOT_CONNECTED Message_ConnectionType = 0 68 | // sender has a live connection to peer 69 | Message_CONNECTED Message_ConnectionType = 1 70 | // sender recently connected to peer 71 | Message_CAN_CONNECT Message_ConnectionType = 2 72 | // sender recently tried to connect to peer repeatedly but failed to connect 73 | // ("try" here is loose, but this should signal "made strong effort, failed") 74 | Message_CANNOT_CONNECT Message_ConnectionType = 3 75 | ) 76 | 77 | var Message_ConnectionType_name = map[int32]string{ 78 | 0: "NOT_CONNECTED", 79 | 1: "CONNECTED", 80 | 2: "CAN_CONNECT", 81 | 3: "CANNOT_CONNECT", 82 | } 83 | 84 | var Message_ConnectionType_value = map[string]int32{ 85 | "NOT_CONNECTED": 0, 86 | "CONNECTED": 1, 87 | "CAN_CONNECT": 2, 88 | "CANNOT_CONNECT": 3, 89 | } 90 | 91 | func (x Message_ConnectionType) String() string { 92 | return proto.EnumName(Message_ConnectionType_name, int32(x)) 93 | } 94 | 95 | func (Message_ConnectionType) EnumDescriptor() ([]byte, []int) { 96 | return fileDescriptor_616a434b24c97ff4, []int{0, 1} 97 | } 98 | 99 | type Message struct { 100 | // defines what type of message it is. 101 | Type Message_MessageType `protobuf:"varint,1,opt,name=type,proto3,enum=dht.pb.Message_MessageType" json:"type,omitempty"` 102 | // defines what coral cluster level this query/response belongs to. 103 | // in case we want to implement coral's cluster rings in the future. 104 | ClusterLevelRaw int32 `protobuf:"varint,10,opt,name=clusterLevelRaw,proto3" json:"clusterLevelRaw,omitempty"` 105 | // Used to specify the key associated with this message. 106 | // PUT_VALUE, GET_VALUE, ADD_PROVIDER, GET_PROVIDERS 107 | Key []byte `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"` 108 | // Used to return a value 109 | // PUT_VALUE, GET_VALUE 110 | Record *pb.Record `protobuf:"bytes,3,opt,name=record,proto3" json:"record,omitempty"` 111 | // Used to return peers closer to a key in a query 112 | // GET_VALUE, GET_PROVIDERS, FIND_NODE 113 | CloserPeers []*Message_Peer `protobuf:"bytes,8,rep,name=closerPeers,proto3" json:"closerPeers,omitempty"` 114 | // Used to return Providers 115 | // GET_VALUE, ADD_PROVIDER, GET_PROVIDERS 116 | ProviderPeers []*Message_Peer `protobuf:"bytes,9,rep,name=providerPeers,proto3" json:"providerPeers,omitempty"` 117 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 118 | XXX_unrecognized []byte `json:"-"` 119 | XXX_sizecache int32 `json:"-"` 120 | } 121 | 122 | func (m *Message) Reset() { *m = Message{} } 123 | func (m *Message) String() string { return proto.CompactTextString(m) } 124 | func (*Message) ProtoMessage() {} 125 | func (*Message) Descriptor() ([]byte, []int) { 126 | return fileDescriptor_616a434b24c97ff4, []int{0} 127 | } 128 | func (m *Message) XXX_Unmarshal(b []byte) error { 129 | return m.Unmarshal(b) 130 | } 131 | func (m *Message) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 132 | if deterministic { 133 | return xxx_messageInfo_Message.Marshal(b, m, deterministic) 134 | } else { 135 | b = b[:cap(b)] 136 | n, err := m.MarshalToSizedBuffer(b) 137 | if err != nil { 138 | return nil, err 139 | } 140 | return b[:n], nil 141 | } 142 | } 143 | func (m *Message) XXX_Merge(src proto.Message) { 144 | xxx_messageInfo_Message.Merge(m, src) 145 | } 146 | func (m *Message) XXX_Size() int { 147 | return m.Size() 148 | } 149 | func (m *Message) XXX_DiscardUnknown() { 150 | xxx_messageInfo_Message.DiscardUnknown(m) 151 | } 152 | 153 | var xxx_messageInfo_Message proto.InternalMessageInfo 154 | 155 | func (m *Message) GetType() Message_MessageType { 156 | if m != nil { 157 | return m.Type 158 | } 159 | return Message_PUT_VALUE 160 | } 161 | 162 | func (m *Message) GetClusterLevelRaw() int32 { 163 | if m != nil { 164 | return m.ClusterLevelRaw 165 | } 166 | return 0 167 | } 168 | 169 | func (m *Message) GetKey() []byte { 170 | if m != nil { 171 | return m.Key 172 | } 173 | return nil 174 | } 175 | 176 | func (m *Message) GetRecord() *pb.Record { 177 | if m != nil { 178 | return m.Record 179 | } 180 | return nil 181 | } 182 | 183 | func (m *Message) GetCloserPeers() []*Message_Peer { 184 | if m != nil { 185 | return m.CloserPeers 186 | } 187 | return nil 188 | } 189 | 190 | func (m *Message) GetProviderPeers() []*Message_Peer { 191 | if m != nil { 192 | return m.ProviderPeers 193 | } 194 | return nil 195 | } 196 | 197 | type Message_Peer struct { 198 | // ID of a given peer. 199 | Id []byte `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` 200 | // multiaddrs for a given peer 201 | Addrs [][]byte `protobuf:"bytes,2,rep,name=addrs,proto3" json:"addrs,omitempty"` 202 | // used to signal the sender's connection capabilities to the peer 203 | Connection Message_ConnectionType `protobuf:"varint,3,opt,name=connection,proto3,enum=dht.pb.Message_ConnectionType" json:"connection,omitempty"` 204 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 205 | XXX_unrecognized []byte `json:"-"` 206 | XXX_sizecache int32 `json:"-"` 207 | } 208 | 209 | func (m *Message_Peer) Reset() { *m = Message_Peer{} } 210 | func (m *Message_Peer) String() string { return proto.CompactTextString(m) } 211 | func (*Message_Peer) ProtoMessage() {} 212 | func (*Message_Peer) Descriptor() ([]byte, []int) { 213 | return fileDescriptor_616a434b24c97ff4, []int{0, 0} 214 | } 215 | func (m *Message_Peer) XXX_Unmarshal(b []byte) error { 216 | return m.Unmarshal(b) 217 | } 218 | func (m *Message_Peer) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 219 | if deterministic { 220 | return xxx_messageInfo_Message_Peer.Marshal(b, m, deterministic) 221 | } else { 222 | b = b[:cap(b)] 223 | n, err := m.MarshalToSizedBuffer(b) 224 | if err != nil { 225 | return nil, err 226 | } 227 | return b[:n], nil 228 | } 229 | } 230 | func (m *Message_Peer) XXX_Merge(src proto.Message) { 231 | xxx_messageInfo_Message_Peer.Merge(m, src) 232 | } 233 | func (m *Message_Peer) XXX_Size() int { 234 | return m.Size() 235 | } 236 | func (m *Message_Peer) XXX_DiscardUnknown() { 237 | xxx_messageInfo_Message_Peer.DiscardUnknown(m) 238 | } 239 | 240 | var xxx_messageInfo_Message_Peer proto.InternalMessageInfo 241 | 242 | func (m *Message_Peer) GetId() []byte { 243 | if m != nil { 244 | return m.Id 245 | } 246 | return nil 247 | } 248 | 249 | func (m *Message_Peer) GetAddrs() [][]byte { 250 | if m != nil { 251 | return m.Addrs 252 | } 253 | return nil 254 | } 255 | 256 | func (m *Message_Peer) GetConnection() Message_ConnectionType { 257 | if m != nil { 258 | return m.Connection 259 | } 260 | return Message_NOT_CONNECTED 261 | } 262 | 263 | func init() { 264 | proto.RegisterEnum("dht.pb.Message_MessageType", Message_MessageType_name, Message_MessageType_value) 265 | proto.RegisterEnum("dht.pb.Message_ConnectionType", Message_ConnectionType_name, Message_ConnectionType_value) 266 | proto.RegisterType((*Message)(nil), "dht.pb.Message") 267 | proto.RegisterType((*Message_Peer)(nil), "dht.pb.Message.Peer") 268 | } 269 | 270 | func init() { proto.RegisterFile("dht.proto", fileDescriptor_616a434b24c97ff4) } 271 | 272 | var fileDescriptor_616a434b24c97ff4 = []byte{ 273 | // 428 bytes of a gzipped FileDescriptorProto 274 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x52, 0xc1, 0x6e, 0x9b, 0x40, 275 | 0x10, 0xed, 0x02, 0x76, 0xe3, 0x01, 0x93, 0xcd, 0x28, 0x07, 0x94, 0x4a, 0x16, 0xf2, 0x89, 0x1e, 276 | 0x02, 0x12, 0x95, 0x7a, 0xe8, 0xa1, 0x92, 0x0b, 0x34, 0xb2, 0x94, 0x62, 0x6b, 0xeb, 0xa4, 0x47, 277 | 0xcb, 0xc0, 0xca, 0x41, 0xa5, 0x5e, 0x04, 0x24, 0x95, 0xbf, 0xb0, 0x3d, 0xf6, 0x13, 0x2a, 0x7f, 278 | 0x49, 0x05, 0x84, 0x16, 0xfb, 0xd0, 0xd3, 0xbe, 0x37, 0xf3, 0xde, 0xce, 0xdb, 0xd1, 0xc2, 0x28, 279 | 0x79, 0xa8, 0xec, 0xbc, 0x10, 0x95, 0xc0, 0x61, 0x03, 0xa3, 0x2b, 0x77, 0x9b, 0x56, 0x0f, 0x8f, 280 | 0x91, 0x1d, 0x8b, 0x6f, 0x4e, 0x96, 0x46, 0xb9, 0x9b, 0x3b, 0x5b, 0x71, 0xdd, 0xa2, 0xeb, 0x82, 281 | 0xc7, 0xa2, 0x48, 0x9c, 0x3c, 0x72, 0x5a, 0xd4, 0x7a, 0xa7, 0x3f, 0x14, 0x78, 0xf9, 0x89, 0x97, 282 | 0xe5, 0x66, 0xcb, 0xd1, 0x01, 0xa5, 0xda, 0xe7, 0xdc, 0x20, 0x26, 0xb1, 0x74, 0xf7, 0x95, 0xdd, 283 | 0x5e, 0x6b, 0x3f, 0xb7, 0xbb, 0x73, 0xb5, 0xcf, 0x39, 0x6b, 0x84, 0x68, 0xc1, 0x79, 0x9c, 0x3d, 284 | 0x96, 0x15, 0x2f, 0x6e, 0xf9, 0x13, 0xcf, 0xd8, 0xe6, 0xbb, 0x01, 0x26, 0xb1, 0x06, 0xec, 0xb4, 285 | 0x8c, 0x14, 0xe4, 0xaf, 0x7c, 0x6f, 0x48, 0x26, 0xb1, 0x34, 0x56, 0x43, 0x7c, 0x0d, 0xc3, 0x36, 286 | 0x88, 0x21, 0x9b, 0xc4, 0x52, 0xdd, 0x0b, 0xbb, 0xcb, 0x15, 0xd9, 0xac, 0x41, 0xec, 0x59, 0x80, 287 | 0x6f, 0x41, 0x8d, 0x33, 0x51, 0xf2, 0x62, 0xc9, 0x79, 0x51, 0x1a, 0x67, 0xa6, 0x6c, 0xa9, 0xee, 288 | 0xe5, 0x69, 0xbc, 0xba, 0xc9, 0xfa, 0x42, 0x7c, 0x07, 0xe3, 0xbc, 0x10, 0x4f, 0x69, 0xd2, 0x39, 289 | 0x47, 0xff, 0x71, 0x1e, 0x4b, 0xaf, 0x32, 0x50, 0x6a, 0x80, 0x3a, 0x48, 0x69, 0xd2, 0x6c, 0x44, 290 | 0x63, 0x52, 0x9a, 0xe0, 0x25, 0x0c, 0x36, 0x49, 0x52, 0x94, 0x86, 0x64, 0xca, 0x96, 0xc6, 0x5a, 291 | 0x82, 0xef, 0x01, 0x62, 0xb1, 0xdb, 0xf1, 0xb8, 0x4a, 0xc5, 0xae, 0x79, 0x90, 0xee, 0x4e, 0x4e, 292 | 0xc7, 0x78, 0x7f, 0x15, 0xcd, 0x0a, 0x7b, 0x8e, 0x69, 0x0a, 0x6a, 0x6f, 0xbb, 0x38, 0x86, 0xd1, 293 | 0xf2, 0x6e, 0xb5, 0xbe, 0x9f, 0xdd, 0xde, 0x05, 0xf4, 0x45, 0x4d, 0x6f, 0x82, 0x8e, 0x12, 0xa4, 294 | 0xa0, 0xcd, 0x7c, 0x7f, 0xbd, 0x64, 0x8b, 0xfb, 0xb9, 0x1f, 0x30, 0x2a, 0xe1, 0x05, 0x8c, 0x6b, 295 | 0x41, 0x57, 0xf9, 0x4c, 0xe5, 0xda, 0xf3, 0x71, 0x1e, 0xfa, 0xeb, 0x70, 0xe1, 0x07, 0x54, 0xc1, 296 | 0x33, 0x50, 0x96, 0xf3, 0xf0, 0x86, 0x0e, 0xa6, 0x5f, 0x40, 0x3f, 0x0e, 0x52, 0xbb, 0xc3, 0xc5, 297 | 0x6a, 0xed, 0x2d, 0xc2, 0x30, 0xf0, 0x56, 0x81, 0xdf, 0x4e, 0xfc, 0x47, 0x09, 0x9e, 0x83, 0xea, 298 | 0xcd, 0xc2, 0x4e, 0x41, 0x25, 0x44, 0xd0, 0xbd, 0x59, 0xd8, 0x73, 0x51, 0xf9, 0x83, 0xf6, 0xf3, 299 | 0x30, 0x21, 0xbf, 0x0e, 0x13, 0xf2, 0xfb, 0x30, 0x21, 0xd1, 0xb0, 0xf9, 0x5e, 0x6f, 0xfe, 0x04, 300 | 0x00, 0x00, 0xff, 0xff, 0xf4, 0x3c, 0x3f, 0x3f, 0xa7, 0x02, 0x00, 0x00, 301 | } 302 | 303 | func (m *Message) Marshal() (dAtA []byte, err error) { 304 | size := m.Size() 305 | dAtA = make([]byte, size) 306 | n, err := m.MarshalToSizedBuffer(dAtA[:size]) 307 | if err != nil { 308 | return nil, err 309 | } 310 | return dAtA[:n], nil 311 | } 312 | 313 | func (m *Message) MarshalTo(dAtA []byte) (int, error) { 314 | size := m.Size() 315 | return m.MarshalToSizedBuffer(dAtA[:size]) 316 | } 317 | 318 | func (m *Message) MarshalToSizedBuffer(dAtA []byte) (int, error) { 319 | i := len(dAtA) 320 | _ = i 321 | var l int 322 | _ = l 323 | if m.XXX_unrecognized != nil { 324 | i -= len(m.XXX_unrecognized) 325 | copy(dAtA[i:], m.XXX_unrecognized) 326 | } 327 | if m.ClusterLevelRaw != 0 { 328 | i = encodeVarintDht(dAtA, i, uint64(m.ClusterLevelRaw)) 329 | i-- 330 | dAtA[i] = 0x50 331 | } 332 | if len(m.ProviderPeers) > 0 { 333 | for iNdEx := len(m.ProviderPeers) - 1; iNdEx >= 0; iNdEx-- { 334 | { 335 | size, err := m.ProviderPeers[iNdEx].MarshalToSizedBuffer(dAtA[:i]) 336 | if err != nil { 337 | return 0, err 338 | } 339 | i -= size 340 | i = encodeVarintDht(dAtA, i, uint64(size)) 341 | } 342 | i-- 343 | dAtA[i] = 0x4a 344 | } 345 | } 346 | if len(m.CloserPeers) > 0 { 347 | for iNdEx := len(m.CloserPeers) - 1; iNdEx >= 0; iNdEx-- { 348 | { 349 | size, err := m.CloserPeers[iNdEx].MarshalToSizedBuffer(dAtA[:i]) 350 | if err != nil { 351 | return 0, err 352 | } 353 | i -= size 354 | i = encodeVarintDht(dAtA, i, uint64(size)) 355 | } 356 | i-- 357 | dAtA[i] = 0x42 358 | } 359 | } 360 | if m.Record != nil { 361 | { 362 | size, err := m.Record.MarshalToSizedBuffer(dAtA[:i]) 363 | if err != nil { 364 | return 0, err 365 | } 366 | i -= size 367 | i = encodeVarintDht(dAtA, i, uint64(size)) 368 | } 369 | i-- 370 | dAtA[i] = 0x1a 371 | } 372 | if len(m.Key) > 0 { 373 | i -= len(m.Key) 374 | copy(dAtA[i:], m.Key) 375 | i = encodeVarintDht(dAtA, i, uint64(len(m.Key))) 376 | i-- 377 | dAtA[i] = 0x12 378 | } 379 | if m.Type != 0 { 380 | i = encodeVarintDht(dAtA, i, uint64(m.Type)) 381 | i-- 382 | dAtA[i] = 0x8 383 | } 384 | return len(dAtA) - i, nil 385 | } 386 | 387 | func (m *Message_Peer) Marshal() (dAtA []byte, err error) { 388 | size := m.Size() 389 | dAtA = make([]byte, size) 390 | n, err := m.MarshalToSizedBuffer(dAtA[:size]) 391 | if err != nil { 392 | return nil, err 393 | } 394 | return dAtA[:n], nil 395 | } 396 | 397 | func (m *Message_Peer) MarshalTo(dAtA []byte) (int, error) { 398 | size := m.Size() 399 | return m.MarshalToSizedBuffer(dAtA[:size]) 400 | } 401 | 402 | func (m *Message_Peer) MarshalToSizedBuffer(dAtA []byte) (int, error) { 403 | i := len(dAtA) 404 | _ = i 405 | var l int 406 | _ = l 407 | if m.XXX_unrecognized != nil { 408 | i -= len(m.XXX_unrecognized) 409 | copy(dAtA[i:], m.XXX_unrecognized) 410 | } 411 | if m.Connection != 0 { 412 | i = encodeVarintDht(dAtA, i, uint64(m.Connection)) 413 | i-- 414 | dAtA[i] = 0x18 415 | } 416 | if len(m.Addrs) > 0 { 417 | for iNdEx := len(m.Addrs) - 1; iNdEx >= 0; iNdEx-- { 418 | i -= len(m.Addrs[iNdEx]) 419 | copy(dAtA[i:], m.Addrs[iNdEx]) 420 | i = encodeVarintDht(dAtA, i, uint64(len(m.Addrs[iNdEx]))) 421 | i-- 422 | dAtA[i] = 0x12 423 | } 424 | } 425 | if len(m.Id) > 0 { 426 | i -= len(m.Id) 427 | copy(dAtA[i:], m.Id) 428 | i = encodeVarintDht(dAtA, i, uint64(len(m.Id))) 429 | i-- 430 | dAtA[i] = 0xa 431 | } 432 | return len(dAtA) - i, nil 433 | } 434 | 435 | func encodeVarintDht(dAtA []byte, offset int, v uint64) int { 436 | offset -= sovDht(v) 437 | base := offset 438 | for v >= 1<<7 { 439 | dAtA[offset] = uint8(v&0x7f | 0x80) 440 | v >>= 7 441 | offset++ 442 | } 443 | dAtA[offset] = uint8(v) 444 | return base 445 | } 446 | func (m *Message) Size() (n int) { 447 | if m == nil { 448 | return 0 449 | } 450 | var l int 451 | _ = l 452 | if m.Type != 0 { 453 | n += 1 + sovDht(uint64(m.Type)) 454 | } 455 | l = len(m.Key) 456 | if l > 0 { 457 | n += 1 + l + sovDht(uint64(l)) 458 | } 459 | if m.Record != nil { 460 | l = m.Record.Size() 461 | n += 1 + l + sovDht(uint64(l)) 462 | } 463 | if len(m.CloserPeers) > 0 { 464 | for _, e := range m.CloserPeers { 465 | l = e.Size() 466 | n += 1 + l + sovDht(uint64(l)) 467 | } 468 | } 469 | if len(m.ProviderPeers) > 0 { 470 | for _, e := range m.ProviderPeers { 471 | l = e.Size() 472 | n += 1 + l + sovDht(uint64(l)) 473 | } 474 | } 475 | if m.ClusterLevelRaw != 0 { 476 | n += 1 + sovDht(uint64(m.ClusterLevelRaw)) 477 | } 478 | if m.XXX_unrecognized != nil { 479 | n += len(m.XXX_unrecognized) 480 | } 481 | return n 482 | } 483 | 484 | func (m *Message_Peer) Size() (n int) { 485 | if m == nil { 486 | return 0 487 | } 488 | var l int 489 | _ = l 490 | l = len(m.Id) 491 | if l > 0 { 492 | n += 1 + l + sovDht(uint64(l)) 493 | } 494 | if len(m.Addrs) > 0 { 495 | for _, b := range m.Addrs { 496 | l = len(b) 497 | n += 1 + l + sovDht(uint64(l)) 498 | } 499 | } 500 | if m.Connection != 0 { 501 | n += 1 + sovDht(uint64(m.Connection)) 502 | } 503 | if m.XXX_unrecognized != nil { 504 | n += len(m.XXX_unrecognized) 505 | } 506 | return n 507 | } 508 | 509 | func sovDht(x uint64) (n int) { 510 | return (math_bits.Len64(x|1) + 6) / 7 511 | } 512 | func sozDht(x uint64) (n int) { 513 | return sovDht(uint64((x << 1) ^ uint64((int64(x) >> 63)))) 514 | } 515 | func (m *Message) Unmarshal(dAtA []byte) error { 516 | l := len(dAtA) 517 | iNdEx := 0 518 | for iNdEx < l { 519 | preIndex := iNdEx 520 | var wire uint64 521 | for shift := uint(0); ; shift += 7 { 522 | if shift >= 64 { 523 | return ErrIntOverflowDht 524 | } 525 | if iNdEx >= l { 526 | return io.ErrUnexpectedEOF 527 | } 528 | b := dAtA[iNdEx] 529 | iNdEx++ 530 | wire |= uint64(b&0x7F) << shift 531 | if b < 0x80 { 532 | break 533 | } 534 | } 535 | fieldNum := int32(wire >> 3) 536 | wireType := int(wire & 0x7) 537 | if wireType == 4 { 538 | return fmt.Errorf("proto: Message: wiretype end group for non-group") 539 | } 540 | if fieldNum <= 0 { 541 | return fmt.Errorf("proto: Message: illegal tag %d (wire type %d)", fieldNum, wire) 542 | } 543 | switch fieldNum { 544 | case 1: 545 | if wireType != 0 { 546 | return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) 547 | } 548 | m.Type = 0 549 | for shift := uint(0); ; shift += 7 { 550 | if shift >= 64 { 551 | return ErrIntOverflowDht 552 | } 553 | if iNdEx >= l { 554 | return io.ErrUnexpectedEOF 555 | } 556 | b := dAtA[iNdEx] 557 | iNdEx++ 558 | m.Type |= Message_MessageType(b&0x7F) << shift 559 | if b < 0x80 { 560 | break 561 | } 562 | } 563 | case 2: 564 | if wireType != 2 { 565 | return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType) 566 | } 567 | var byteLen int 568 | for shift := uint(0); ; shift += 7 { 569 | if shift >= 64 { 570 | return ErrIntOverflowDht 571 | } 572 | if iNdEx >= l { 573 | return io.ErrUnexpectedEOF 574 | } 575 | b := dAtA[iNdEx] 576 | iNdEx++ 577 | byteLen |= int(b&0x7F) << shift 578 | if b < 0x80 { 579 | break 580 | } 581 | } 582 | if byteLen < 0 { 583 | return ErrInvalidLengthDht 584 | } 585 | postIndex := iNdEx + byteLen 586 | if postIndex < 0 { 587 | return ErrInvalidLengthDht 588 | } 589 | if postIndex > l { 590 | return io.ErrUnexpectedEOF 591 | } 592 | m.Key = append(m.Key[:0], dAtA[iNdEx:postIndex]...) 593 | if m.Key == nil { 594 | m.Key = []byte{} 595 | } 596 | iNdEx = postIndex 597 | case 3: 598 | if wireType != 2 { 599 | return fmt.Errorf("proto: wrong wireType = %d for field Record", wireType) 600 | } 601 | var msglen int 602 | for shift := uint(0); ; shift += 7 { 603 | if shift >= 64 { 604 | return ErrIntOverflowDht 605 | } 606 | if iNdEx >= l { 607 | return io.ErrUnexpectedEOF 608 | } 609 | b := dAtA[iNdEx] 610 | iNdEx++ 611 | msglen |= int(b&0x7F) << shift 612 | if b < 0x80 { 613 | break 614 | } 615 | } 616 | if msglen < 0 { 617 | return ErrInvalidLengthDht 618 | } 619 | postIndex := iNdEx + msglen 620 | if postIndex < 0 { 621 | return ErrInvalidLengthDht 622 | } 623 | if postIndex > l { 624 | return io.ErrUnexpectedEOF 625 | } 626 | if m.Record == nil { 627 | m.Record = &pb.Record{} 628 | } 629 | if err := m.Record.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { 630 | return err 631 | } 632 | iNdEx = postIndex 633 | case 8: 634 | if wireType != 2 { 635 | return fmt.Errorf("proto: wrong wireType = %d for field CloserPeers", wireType) 636 | } 637 | var msglen int 638 | for shift := uint(0); ; shift += 7 { 639 | if shift >= 64 { 640 | return ErrIntOverflowDht 641 | } 642 | if iNdEx >= l { 643 | return io.ErrUnexpectedEOF 644 | } 645 | b := dAtA[iNdEx] 646 | iNdEx++ 647 | msglen |= int(b&0x7F) << shift 648 | if b < 0x80 { 649 | break 650 | } 651 | } 652 | if msglen < 0 { 653 | return ErrInvalidLengthDht 654 | } 655 | postIndex := iNdEx + msglen 656 | if postIndex < 0 { 657 | return ErrInvalidLengthDht 658 | } 659 | if postIndex > l { 660 | return io.ErrUnexpectedEOF 661 | } 662 | m.CloserPeers = append(m.CloserPeers, &Message_Peer{}) 663 | if err := m.CloserPeers[len(m.CloserPeers)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { 664 | return err 665 | } 666 | iNdEx = postIndex 667 | case 9: 668 | if wireType != 2 { 669 | return fmt.Errorf("proto: wrong wireType = %d for field ProviderPeers", wireType) 670 | } 671 | var msglen int 672 | for shift := uint(0); ; shift += 7 { 673 | if shift >= 64 { 674 | return ErrIntOverflowDht 675 | } 676 | if iNdEx >= l { 677 | return io.ErrUnexpectedEOF 678 | } 679 | b := dAtA[iNdEx] 680 | iNdEx++ 681 | msglen |= int(b&0x7F) << shift 682 | if b < 0x80 { 683 | break 684 | } 685 | } 686 | if msglen < 0 { 687 | return ErrInvalidLengthDht 688 | } 689 | postIndex := iNdEx + msglen 690 | if postIndex < 0 { 691 | return ErrInvalidLengthDht 692 | } 693 | if postIndex > l { 694 | return io.ErrUnexpectedEOF 695 | } 696 | m.ProviderPeers = append(m.ProviderPeers, &Message_Peer{}) 697 | if err := m.ProviderPeers[len(m.ProviderPeers)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { 698 | return err 699 | } 700 | iNdEx = postIndex 701 | case 10: 702 | if wireType != 0 { 703 | return fmt.Errorf("proto: wrong wireType = %d for field ClusterLevelRaw", wireType) 704 | } 705 | m.ClusterLevelRaw = 0 706 | for shift := uint(0); ; shift += 7 { 707 | if shift >= 64 { 708 | return ErrIntOverflowDht 709 | } 710 | if iNdEx >= l { 711 | return io.ErrUnexpectedEOF 712 | } 713 | b := dAtA[iNdEx] 714 | iNdEx++ 715 | m.ClusterLevelRaw |= int32(b&0x7F) << shift 716 | if b < 0x80 { 717 | break 718 | } 719 | } 720 | default: 721 | iNdEx = preIndex 722 | skippy, err := skipDht(dAtA[iNdEx:]) 723 | if err != nil { 724 | return err 725 | } 726 | if skippy < 0 { 727 | return ErrInvalidLengthDht 728 | } 729 | if (iNdEx + skippy) < 0 { 730 | return ErrInvalidLengthDht 731 | } 732 | if (iNdEx + skippy) > l { 733 | return io.ErrUnexpectedEOF 734 | } 735 | m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) 736 | iNdEx += skippy 737 | } 738 | } 739 | 740 | if iNdEx > l { 741 | return io.ErrUnexpectedEOF 742 | } 743 | return nil 744 | } 745 | func (m *Message_Peer) Unmarshal(dAtA []byte) error { 746 | l := len(dAtA) 747 | iNdEx := 0 748 | for iNdEx < l { 749 | preIndex := iNdEx 750 | var wire uint64 751 | for shift := uint(0); ; shift += 7 { 752 | if shift >= 64 { 753 | return ErrIntOverflowDht 754 | } 755 | if iNdEx >= l { 756 | return io.ErrUnexpectedEOF 757 | } 758 | b := dAtA[iNdEx] 759 | iNdEx++ 760 | wire |= uint64(b&0x7F) << shift 761 | if b < 0x80 { 762 | break 763 | } 764 | } 765 | fieldNum := int32(wire >> 3) 766 | wireType := int(wire & 0x7) 767 | if wireType == 4 { 768 | return fmt.Errorf("proto: Peer: wiretype end group for non-group") 769 | } 770 | if fieldNum <= 0 { 771 | return fmt.Errorf("proto: Peer: illegal tag %d (wire type %d)", fieldNum, wire) 772 | } 773 | switch fieldNum { 774 | case 1: 775 | if wireType != 2 { 776 | return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) 777 | } 778 | var byteLen int 779 | for shift := uint(0); ; shift += 7 { 780 | if shift >= 64 { 781 | return ErrIntOverflowDht 782 | } 783 | if iNdEx >= l { 784 | return io.ErrUnexpectedEOF 785 | } 786 | b := dAtA[iNdEx] 787 | iNdEx++ 788 | byteLen |= int(b&0x7F) << shift 789 | if b < 0x80 { 790 | break 791 | } 792 | } 793 | if byteLen < 0 { 794 | return ErrInvalidLengthDht 795 | } 796 | postIndex := iNdEx + byteLen 797 | if postIndex < 0 { 798 | return ErrInvalidLengthDht 799 | } 800 | if postIndex > l { 801 | return io.ErrUnexpectedEOF 802 | } 803 | m.Id = append(m.Id[:0], dAtA[iNdEx:postIndex]...) 804 | if m.Id == nil { 805 | m.Id = []byte{} 806 | } 807 | iNdEx = postIndex 808 | case 2: 809 | if wireType != 2 { 810 | return fmt.Errorf("proto: wrong wireType = %d for field Addrs", wireType) 811 | } 812 | var byteLen int 813 | for shift := uint(0); ; shift += 7 { 814 | if shift >= 64 { 815 | return ErrIntOverflowDht 816 | } 817 | if iNdEx >= l { 818 | return io.ErrUnexpectedEOF 819 | } 820 | b := dAtA[iNdEx] 821 | iNdEx++ 822 | byteLen |= int(b&0x7F) << shift 823 | if b < 0x80 { 824 | break 825 | } 826 | } 827 | if byteLen < 0 { 828 | return ErrInvalidLengthDht 829 | } 830 | postIndex := iNdEx + byteLen 831 | if postIndex < 0 { 832 | return ErrInvalidLengthDht 833 | } 834 | if postIndex > l { 835 | return io.ErrUnexpectedEOF 836 | } 837 | m.Addrs = append(m.Addrs, make([]byte, postIndex-iNdEx)) 838 | copy(m.Addrs[len(m.Addrs)-1], dAtA[iNdEx:postIndex]) 839 | iNdEx = postIndex 840 | case 3: 841 | if wireType != 0 { 842 | return fmt.Errorf("proto: wrong wireType = %d for field Connection", wireType) 843 | } 844 | m.Connection = 0 845 | for shift := uint(0); ; shift += 7 { 846 | if shift >= 64 { 847 | return ErrIntOverflowDht 848 | } 849 | if iNdEx >= l { 850 | return io.ErrUnexpectedEOF 851 | } 852 | b := dAtA[iNdEx] 853 | iNdEx++ 854 | m.Connection |= Message_ConnectionType(b&0x7F) << shift 855 | if b < 0x80 { 856 | break 857 | } 858 | } 859 | default: 860 | iNdEx = preIndex 861 | skippy, err := skipDht(dAtA[iNdEx:]) 862 | if err != nil { 863 | return err 864 | } 865 | if skippy < 0 { 866 | return ErrInvalidLengthDht 867 | } 868 | if (iNdEx + skippy) < 0 { 869 | return ErrInvalidLengthDht 870 | } 871 | if (iNdEx + skippy) > l { 872 | return io.ErrUnexpectedEOF 873 | } 874 | m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) 875 | iNdEx += skippy 876 | } 877 | } 878 | 879 | if iNdEx > l { 880 | return io.ErrUnexpectedEOF 881 | } 882 | return nil 883 | } 884 | func skipDht(dAtA []byte) (n int, err error) { 885 | l := len(dAtA) 886 | iNdEx := 0 887 | depth := 0 888 | for iNdEx < l { 889 | var wire uint64 890 | for shift := uint(0); ; shift += 7 { 891 | if shift >= 64 { 892 | return 0, ErrIntOverflowDht 893 | } 894 | if iNdEx >= l { 895 | return 0, io.ErrUnexpectedEOF 896 | } 897 | b := dAtA[iNdEx] 898 | iNdEx++ 899 | wire |= (uint64(b) & 0x7F) << shift 900 | if b < 0x80 { 901 | break 902 | } 903 | } 904 | wireType := int(wire & 0x7) 905 | switch wireType { 906 | case 0: 907 | for shift := uint(0); ; shift += 7 { 908 | if shift >= 64 { 909 | return 0, ErrIntOverflowDht 910 | } 911 | if iNdEx >= l { 912 | return 0, io.ErrUnexpectedEOF 913 | } 914 | iNdEx++ 915 | if dAtA[iNdEx-1] < 0x80 { 916 | break 917 | } 918 | } 919 | case 1: 920 | iNdEx += 8 921 | case 2: 922 | var length int 923 | for shift := uint(0); ; shift += 7 { 924 | if shift >= 64 { 925 | return 0, ErrIntOverflowDht 926 | } 927 | if iNdEx >= l { 928 | return 0, io.ErrUnexpectedEOF 929 | } 930 | b := dAtA[iNdEx] 931 | iNdEx++ 932 | length |= (int(b) & 0x7F) << shift 933 | if b < 0x80 { 934 | break 935 | } 936 | } 937 | if length < 0 { 938 | return 0, ErrInvalidLengthDht 939 | } 940 | iNdEx += length 941 | if iNdEx < 0 { 942 | return 0, ErrInvalidLengthDht 943 | } 944 | case 3: 945 | depth++ 946 | case 4: 947 | if depth == 0 { 948 | return 0, ErrUnexpectedEndOfGroupDht 949 | } 950 | depth-- 951 | case 5: 952 | iNdEx += 4 953 | default: 954 | return 0, fmt.Errorf("proto: illegal wireType %d", wireType) 955 | } 956 | if depth == 0 { 957 | return iNdEx, nil 958 | } 959 | } 960 | return 0, io.ErrUnexpectedEOF 961 | } 962 | 963 | var ( 964 | ErrInvalidLengthDht = fmt.Errorf("proto: negative length found during unmarshaling") 965 | ErrIntOverflowDht = fmt.Errorf("proto: integer overflow") 966 | ErrUnexpectedEndOfGroupDht = fmt.Errorf("proto: unexpected end of group") 967 | ) 968 | -------------------------------------------------------------------------------- /pb/dht.proto: -------------------------------------------------------------------------------- 1 | // In order to re-generate the golang packages for `Message` you will need... 2 | // 1. Protobuf binary (tested with protoc 3.0.0). - https://github.com/gogo/protobuf/releases 3 | // 2. Gogo Protobuf (tested with gogo 0.3). - https://github.com/gogo/protobuf 4 | // 3. To have cloned `libp2p/go-libp2p-{record,kad-dht}` under the same directory. 5 | // Now from `libp2p/go-libp2p-kad-dht/pb` you can run... 6 | // `protoc --gogo_out=. --proto_path=../../go-libp2p-record/pb/ --proto_path=./ dht.proto` 7 | 8 | syntax = "proto3"; 9 | package dht.pb; 10 | 11 | import "github.com/libp2p/go-libp2p-record/pb/record.proto"; 12 | 13 | message Message { 14 | enum MessageType { 15 | PUT_VALUE = 0; 16 | GET_VALUE = 1; 17 | ADD_PROVIDER = 2; 18 | GET_PROVIDERS = 3; 19 | FIND_NODE = 4; 20 | PING = 5; 21 | } 22 | 23 | enum ConnectionType { 24 | // sender does not have a connection to peer, and no extra information (default) 25 | NOT_CONNECTED = 0; 26 | 27 | // sender has a live connection to peer 28 | CONNECTED = 1; 29 | 30 | // sender recently connected to peer 31 | CAN_CONNECT = 2; 32 | 33 | // sender recently tried to connect to peer repeatedly but failed to connect 34 | // ("try" here is loose, but this should signal "made strong effort, failed") 35 | CANNOT_CONNECT = 3; 36 | } 37 | 38 | message Peer { 39 | // ID of a given peer. 40 | bytes id = 1; 41 | 42 | // multiaddrs for a given peer 43 | repeated bytes addrs = 2; 44 | 45 | // used to signal the sender's connection capabilities to the peer 46 | ConnectionType connection = 3; 47 | } 48 | 49 | // defines what type of message it is. 50 | MessageType type = 1; 51 | 52 | // defines what coral cluster level this query/response belongs to. 53 | // in case we want to implement coral's cluster rings in the future. 54 | int32 clusterLevelRaw = 10; 55 | 56 | // Used to specify the key associated with this message. 57 | // PUT_VALUE, GET_VALUE, ADD_PROVIDER, GET_PROVIDERS 58 | bytes key = 2; 59 | 60 | // Used to return a value 61 | // PUT_VALUE, GET_VALUE 62 | record.pb.Record record = 3; 63 | 64 | // Used to return peers closer to a key in a query 65 | // GET_VALUE, GET_PROVIDERS, FIND_NODE 66 | repeated Peer closerPeers = 8; 67 | 68 | // Used to return Providers 69 | // GET_VALUE, ADD_PROVIDER, GET_PROVIDERS 70 | repeated Peer providerPeers = 9; 71 | } 72 | -------------------------------------------------------------------------------- /pb/message.go: -------------------------------------------------------------------------------- 1 | package dht_pb 2 | 3 | import ( 4 | "github.com/libp2p/go-libp2p-core/network" 5 | "github.com/libp2p/go-libp2p-core/peer" 6 | 7 | logging "github.com/ipfs/go-log" 8 | ma "github.com/multiformats/go-multiaddr" 9 | ) 10 | 11 | var log = logging.Logger("dht.pb") 12 | 13 | type PeerRoutingInfo struct { 14 | peer.AddrInfo 15 | network.Connectedness 16 | } 17 | 18 | // NewMessage constructs a new dht message with given type, key, and level 19 | func NewMessage(typ Message_MessageType, key []byte, level int) *Message { 20 | m := &Message{ 21 | Type: typ, 22 | Key: key, 23 | } 24 | m.SetClusterLevel(level) 25 | return m 26 | } 27 | 28 | func peerRoutingInfoToPBPeer(p PeerRoutingInfo) *Message_Peer { 29 | pbp := new(Message_Peer) 30 | 31 | pbp.Addrs = make([][]byte, len(p.Addrs)) 32 | for i, maddr := range p.Addrs { 33 | pbp.Addrs[i] = maddr.Bytes() // Bytes, not String. Compressed. 34 | } 35 | s := string(p.ID) 36 | pbp.Id = []byte(s) 37 | c := ConnectionType(p.Connectedness) 38 | pbp.Connection = c 39 | return pbp 40 | } 41 | 42 | func peerInfoToPBPeer(p peer.AddrInfo) *Message_Peer { 43 | pbp := new(Message_Peer) 44 | 45 | pbp.Addrs = make([][]byte, len(p.Addrs)) 46 | for i, maddr := range p.Addrs { 47 | pbp.Addrs[i] = maddr.Bytes() // Bytes, not String. Compressed. 48 | } 49 | pbp.Id = []byte(p.ID) 50 | return pbp 51 | } 52 | 53 | // PBPeerToPeer turns a *Message_Peer into its peer.AddrInfo counterpart 54 | func PBPeerToPeerInfo(pbp *Message_Peer) *peer.AddrInfo { 55 | return &peer.AddrInfo{ 56 | ID: peer.ID(pbp.GetId()), 57 | Addrs: pbp.Addresses(), 58 | } 59 | } 60 | 61 | // RawPeerInfosToPBPeers converts a slice of Peers into a slice of *Message_Peers, 62 | // ready to go out on the wire. 63 | func RawPeerInfosToPBPeers(peers []peer.AddrInfo) []*Message_Peer { 64 | pbpeers := make([]*Message_Peer, len(peers)) 65 | for i, p := range peers { 66 | pbpeers[i] = peerInfoToPBPeer(p) 67 | } 68 | return pbpeers 69 | } 70 | 71 | // PeersToPBPeers converts given []peer.Peer into a set of []*Message_Peer, 72 | // which can be written to a message and sent out. the key thing this function 73 | // does (in addition to PeersToPBPeers) is set the ConnectionType with 74 | // information from the given network.Network. 75 | func PeerInfosToPBPeers(n network.Network, peers []peer.AddrInfo) []*Message_Peer { 76 | pbps := RawPeerInfosToPBPeers(peers) 77 | for i, pbp := range pbps { 78 | c := ConnectionType(n.Connectedness(peers[i].ID)) 79 | pbp.Connection = c 80 | } 81 | return pbps 82 | } 83 | 84 | func PeerRoutingInfosToPBPeers(peers []PeerRoutingInfo) []*Message_Peer { 85 | pbpeers := make([]*Message_Peer, len(peers)) 86 | for i, p := range peers { 87 | pbpeers[i] = peerRoutingInfoToPBPeer(p) 88 | } 89 | return pbpeers 90 | } 91 | 92 | // PBPeersToPeerInfos converts given []*Message_Peer into []peer.AddrInfo 93 | // Invalid addresses will be silently omitted. 94 | func PBPeersToPeerInfos(pbps []*Message_Peer) []*peer.AddrInfo { 95 | peers := make([]*peer.AddrInfo, 0, len(pbps)) 96 | for _, pbp := range pbps { 97 | peers = append(peers, PBPeerToPeerInfo(pbp)) 98 | } 99 | return peers 100 | } 101 | 102 | // Addresses returns a multiaddr associated with the Message_Peer entry 103 | func (m *Message_Peer) Addresses() []ma.Multiaddr { 104 | if m == nil { 105 | return nil 106 | } 107 | 108 | maddrs := make([]ma.Multiaddr, 0, len(m.Addrs)) 109 | for _, addr := range m.Addrs { 110 | maddr, err := ma.NewMultiaddrBytes(addr) 111 | if err != nil { 112 | log.Debugw("error decoding multiaddr for peer", "peer", m.GetId(), "error", err) 113 | continue 114 | } 115 | 116 | maddrs = append(maddrs, maddr) 117 | } 118 | return maddrs 119 | } 120 | 121 | // GetClusterLevel gets and adjusts the cluster level on the message. 122 | // a +/- 1 adjustment is needed to distinguish a valid first level (1) and 123 | // default "no value" protobuf behavior (0) 124 | func (m *Message) GetClusterLevel() int { 125 | level := m.GetClusterLevelRaw() - 1 126 | if level < 0 { 127 | return 0 128 | } 129 | return int(level) 130 | } 131 | 132 | // SetClusterLevel adjusts and sets the cluster level on the message. 133 | // a +/- 1 adjustment is needed to distinguish a valid first level (1) and 134 | // default "no value" protobuf behavior (0) 135 | func (m *Message) SetClusterLevel(level int) { 136 | lvl := int32(level) 137 | m.ClusterLevelRaw = lvl + 1 138 | } 139 | 140 | // ConnectionType returns a Message_ConnectionType associated with the 141 | // network.Connectedness. 142 | func ConnectionType(c network.Connectedness) Message_ConnectionType { 143 | switch c { 144 | default: 145 | return Message_NOT_CONNECTED 146 | case network.NotConnected: 147 | return Message_NOT_CONNECTED 148 | case network.Connected: 149 | return Message_CONNECTED 150 | case network.CanConnect: 151 | return Message_CAN_CONNECT 152 | case network.CannotConnect: 153 | return Message_CANNOT_CONNECT 154 | } 155 | } 156 | 157 | // Connectedness returns an network.Connectedness associated with the 158 | // Message_ConnectionType. 159 | func Connectedness(c Message_ConnectionType) network.Connectedness { 160 | switch c { 161 | default: 162 | return network.NotConnected 163 | case Message_NOT_CONNECTED: 164 | return network.NotConnected 165 | case Message_CONNECTED: 166 | return network.Connected 167 | case Message_CAN_CONNECT: 168 | return network.CanConnect 169 | case Message_CANNOT_CONNECT: 170 | return network.CannotConnect 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /pb/message_test.go: -------------------------------------------------------------------------------- 1 | package dht_pb 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestBadAddrsDontReturnNil(t *testing.T) { 8 | mp := new(Message_Peer) 9 | mp.Addrs = [][]byte{[]byte("NOT A VALID MULTIADDR")} 10 | 11 | addrs := mp.Addresses() 12 | if len(addrs) > 0 { 13 | t.Fatal("shouldnt have any multiaddrs") 14 | } 15 | } 16 | --------------------------------------------------------------------------------