├── .gitignore ├── .travis.yml ├── LICENSE ├── Makefile ├── README.md ├── client.go ├── codecov.yml ├── go.mod ├── go.sum ├── pb ├── pubsub.pb.go └── pubsub.proto ├── pubsubgrpc.go ├── pubsubgrpc_test.go └── server.go /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | vendor/ 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - '1.12' 5 | 6 | env: 7 | global: 8 | - GO111MODULE=on 9 | 10 | install: 11 | - go mod download 12 | 13 | before_script: 14 | - go vet ./... 15 | - go build ./... 16 | - go test -run xxxx ./... 17 | 18 | script: 19 | - go test -race -short -coverprofile=coverage.txt ./... 20 | 21 | after_success: 22 | - bash <(curl -s https://codecov.io/bash) 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: proto 2 | proto: 3 | protoc -I pb pb/pubsub.proto --go_out=plugins=grpc:pb -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # go-libp2p-pubsub-grpc (pubsubgrpc) 2 | 3 | [![GoDoc](https://godoc.org/github.com/RTradeLtd/go-libp2p-pubsub-grpc?status.svg)](https://godoc.org/github.com/RTradeLtd/go-libp2p-pubsub-grpc) [![codecov](https://codecov.io/gh/RTradeLtd/go-libp2p-pubsub-grpc/branch/master/graph/badge.svg)](https://codecov.io/gh/RTradeLtd/go-libp2p-pubsub-grpc) [![Build Status](https://travis-ci.com/RTradeLtd/go-libp2p-pubsub-grpc.svg?branch=master)](https://travis-ci.com/RTradeLtd/go-libp2p-pubsub-grpc) 4 | 5 | 6 | `pubsubgrpc` provides a LibP2P PubSub framework that can be used as a stand-alone gRPC pubsub server and API, or as a module/component of existing gRPC servers to provide LibP2P PubSub functionality. It uses `proto3` and borrows some ideas from [libp2p/go-libp2p-daemon](https://github.com/libp2p/go-libp2p-daemon/blob/master/pb/p2pd.proto) and [libp2p/go-libp2p-pubsub](https://github.com/libp2p/go-libp2p-pubsub/tree/master/pb). 7 | 8 | # usage 9 | 10 | There are two ways of using this library: 11 | 12 | 1) One is to construct a standalone pubsub server with a gRPC api (see `server.go`) 13 | 2) Provide pubsub functionality to already existing gRPC servers (see `pubsubgrpc.go`) 14 | 15 | If using the standalone pubsub server, there is a golang client in `client.go` that can be used. 16 | 17 | # todo: 18 | 19 | * once go-libp2p-pubsub has discovery, use it. -------------------------------------------------------------------------------- /client.go: -------------------------------------------------------------------------------- 1 | package pubsubgrpc 2 | 3 | import ( 4 | "google.golang.org/grpc" 5 | "google.golang.org/grpc/credentials" 6 | 7 | "fmt" 8 | 9 | "github.com/RTradeLtd/go-libp2p-pubsub-grpc/pb" 10 | "github.com/RTradeLtd/grpc/dialer" 11 | ) 12 | 13 | // Client is used to communicate 14 | // with the gRPC Server service 15 | type Client struct { 16 | pb.PubSubServiceClient 17 | conn *grpc.ClientConn 18 | } 19 | 20 | // NewClient is used to instantiate a pubsub grpc client 21 | func NewClient(certPath, authKey, url string) (*Client, error) { 22 | var ( 23 | dialOpts []grpc.DialOption 24 | ) 25 | if certPath != "" { 26 | creds, err := credentials.NewClientTLSFromFile(certPath, "") 27 | if err != nil { 28 | return nil, fmt.Errorf("could not load tls cert: %s", err) 29 | } 30 | dialOpts = append(dialOpts, grpc.WithTransportCredentials(creds)) 31 | if authKey != "" { 32 | dialOpts = append(dialOpts, 33 | grpc.WithPerRPCCredentials(dialer.NewCredentials(authKey, true))) 34 | } 35 | } else { 36 | dialOpts = append(dialOpts, grpc.WithInsecure()) 37 | if authKey != "" { 38 | dialOpts = append(dialOpts, 39 | grpc.WithPerRPCCredentials(dialer.NewCredentials(authKey, false))) 40 | } 41 | } 42 | conn, err := grpc.Dial(url, dialOpts...) 43 | if err != nil { 44 | return nil, err 45 | } 46 | return &Client{ 47 | conn: conn, 48 | PubSubServiceClient: pb.NewPubSubServiceClient(conn), 49 | }, nil 50 | } 51 | 52 | // Close is used to terminate our connection 53 | // to the grpc server 54 | func (c *Client) Close() error { 55 | return c.conn.Close() 56 | } 57 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | precision: 2 3 | round: up 4 | range: "50...90" 5 | status: 6 | project: 7 | default: 8 | threshold: 1 9 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/RTradeLtd/go-libp2p-pubsub-grpc 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/RTradeLtd/go-libp2p-connmgr v1.0.0 7 | github.com/RTradeLtd/go-libp2p-testutils v1.0.0 8 | github.com/RTradeLtd/grpc v2.0.0+incompatible 9 | github.com/golang/protobuf v1.3.1 10 | github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 11 | github.com/ipfs/go-datastore v0.0.5 12 | github.com/ipfs/go-ipfs-config v0.0.6 13 | github.com/ipfs/go-ipfs-keystore v0.0.1 14 | github.com/ipfs/go-ipns v0.0.1 15 | github.com/libp2p/go-libp2p v0.1.1 16 | github.com/libp2p/go-libp2p-circuit v0.1.0 17 | github.com/libp2p/go-libp2p-core v0.0.3 18 | github.com/libp2p/go-libp2p-discovery v0.1.0 19 | github.com/libp2p/go-libp2p-kad-dht v0.1.1 20 | github.com/libp2p/go-libp2p-peerstore v0.1.0 21 | github.com/libp2p/go-libp2p-pnet v0.1.0 22 | github.com/libp2p/go-libp2p-pubsub v0.1.0 23 | github.com/libp2p/go-libp2p-record v0.1.0 24 | github.com/multiformats/go-multiaddr v0.0.4 25 | github.com/sirupsen/logrus v1.4.2 // indirect 26 | go.uber.org/zap v1.10.0 27 | google.golang.org/grpc v1.21.1 28 | ) 29 | -------------------------------------------------------------------------------- /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/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 4 | github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y= 5 | github.com/RTradeLtd/go-libp2p-connmgr v1.0.0 h1:RFLSCTKnmMp9PYpg0NRy+LMTDsBlEP916VW3TSO3eOY= 6 | github.com/RTradeLtd/go-libp2p-connmgr v1.0.0/go.mod h1:CvB5NlNS7PDuWgY45gTFyiI29Rg+nUWXj0qCcVKtLps= 7 | github.com/RTradeLtd/go-libp2p-pubsub-grpc v0.0.0-20190612071716-a99d1b5aa836 h1:PUXJA9MxIaQWc60aG/ZsqZommRdUqlXeNchX5tafb6E= 8 | github.com/RTradeLtd/go-libp2p-pubsub-grpc v0.0.0-20190612071716-a99d1b5aa836/go.mod h1:7zcsDqaT9yykZQrCcGoaAceL3iZHjJRXv23y/9vJ4bE= 9 | github.com/RTradeLtd/go-libp2p-testutils v1.0.0 h1:LlYKQPuj00jjbjp3PvLRkt8lqaT/yA1oJ2Ob2uZ3yIc= 10 | github.com/RTradeLtd/go-libp2p-testutils v1.0.0/go.mod h1:UhJZon/4xobiwp+r57od2PWd89kND8R4qHj5lIO+624= 11 | github.com/RTradeLtd/grpc v2.0.0+incompatible h1:4/I8CityZtNusVw0/zVS2vNwgKd/hex3UJORgYP4fpI= 12 | github.com/RTradeLtd/grpc v2.0.0+incompatible/go.mod h1:wtgJzW1fsgyF4iRl9Fdz5dg2Xa6uuo01msxyAPQJHks= 13 | github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= 14 | github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= 15 | github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c h1:aEbSeNALREWXk0G7UdNhR3ayBV7tZ4M2PNmnrCAph6Q= 16 | github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= 17 | github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= 18 | github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= 19 | github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= 20 | github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= 21 | github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= 22 | github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= 23 | github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= 24 | github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= 25 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 26 | github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= 27 | github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= 28 | github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 29 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 30 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 31 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 32 | github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018 h1:6xT9KW8zLC5IlbaIF5Q7JNieBoACT7iW0YTxQHR0in0= 33 | github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018/go.mod h1:rQYf4tfk5sSwFsnDg3qYaBxSjsD9S8+59vW0dKUgme4= 34 | github.com/dgraph-io/badger v1.5.5-0.20190226225317-8115aed38f8f/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ= 35 | github.com/dgryski/go-farm v0.0.0-20190104051053-3adb47b1fb0f/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= 36 | github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= 37 | github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5/go.mod h1:JpoxHjuQauoxiFMl1ie8Xc/7TfLuMZ5eOCONd1sUBHg= 38 | github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= 39 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 40 | github.com/go-check/check v0.0.0-20180628173108-788fd7840127 h1:0gkP6mzaMqkmpcJYCFOLkIBwI7xFExG03bbkOkCvUPI= 41 | github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= 42 | github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= 43 | github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= 44 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= 45 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 46 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 47 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 48 | github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= 49 | github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= 50 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 51 | github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 52 | github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= 53 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 54 | github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= 55 | github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 56 | github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= 57 | github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= 58 | github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 h1:Iju5GlWwrvL6UBg4zJJt3btmonfrMlCDdsejg4CZE7c= 59 | github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= 60 | github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU= 61 | github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= 62 | github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 63 | github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= 64 | github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 65 | github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= 66 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 67 | github.com/huin/goupnp v1.0.0 h1:wg75sLpL6DZqwHQN6E1Cfk6mtfzS45z8OV+ic+DtHRo= 68 | github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= 69 | github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= 70 | github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= 71 | github.com/ipfs/go-cid v0.0.2 h1:tuuKaZPU1M6HcejsO3AcYWW8sZ8MTvyxfc4uqB4eFE8= 72 | github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= 73 | github.com/ipfs/go-datastore v0.0.1/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= 74 | github.com/ipfs/go-datastore v0.0.5 h1:q3OfiOZV5rlsK1H5V8benjeUApRfMGs4Mrhmr6NriQo= 75 | github.com/ipfs/go-datastore v0.0.5/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= 76 | github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk= 77 | github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= 78 | github.com/ipfs/go-ds-badger v0.0.2/go.mod h1:Y3QpeSFWQf6MopLTiZD+VT6IC1yZqaGmjvRcKeSGij8= 79 | github.com/ipfs/go-ds-leveldb v0.0.1/go.mod h1:feO8V3kubwsEF22n0YRQCffeb79OOYIykR4L04tMOYc= 80 | github.com/ipfs/go-ipfs-config v0.0.6 h1:jzK9Tl8S0oWBir3F5ObtGgnHRPdqQ0MYiCmwXtV3Ps4= 81 | github.com/ipfs/go-ipfs-config v0.0.6/go.mod h1:IGkVTacurWv9WFKc7IBPjHGM/7hi6+PEClqUb/l2BIM= 82 | github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= 83 | github.com/ipfs/go-ipfs-keystore v0.0.1 h1:sE4lNCZYl7OsgZp4Nmm4TCvIN3ub5tTDfjT6lIh6Brk= 84 | github.com/ipfs/go-ipfs-keystore v0.0.1/go.mod h1:5WjcKN1ESzCVzYKo5JvO1iYHLE0n626HL/cr3dSkqBs= 85 | github.com/ipfs/go-ipfs-util v0.0.1 h1:Wz9bL2wB2YBJqggkA4dD7oSmqB4cAnpNbGrlHJulv50= 86 | github.com/ipfs/go-ipfs-util v0.0.1/go.mod h1:spsl5z8KUnrve+73pOhSVZND1SIxPW5RyBCNzQxlJBc= 87 | github.com/ipfs/go-ipns v0.0.1 h1:5vX0+ehF55YWxE8Pmf4eB8szcP+fh24AXnvCkOmSLCc= 88 | github.com/ipfs/go-ipns v0.0.1/go.mod h1:HOiAXgGiH0wCSwsFM1IKdOy6YGT4iZafcsUKni703/g= 89 | github.com/ipfs/go-log v0.0.1 h1:9XTUN/rW64BCG1YhPK9Hoy3q8nr4gOmHHBpgFdfw6Lc= 90 | github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM= 91 | github.com/ipfs/go-todocounter v0.0.1 h1:kITWA5ZcQZfrUnDNkRn04Xzh0YFaDFXsoO2A81Eb6Lw= 92 | github.com/ipfs/go-todocounter v0.0.1/go.mod h1:l5aErvQc8qKE2r7NDMjmq5UNAvuZy0rC8BHOplkWvZ4= 93 | github.com/jackpal/gateway v1.0.5 h1:qzXWUJfuMdlLMtt0a3Dgt+xkWQiA5itDEITVJtuSwMc= 94 | github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= 95 | github.com/jackpal/go-nat-pmp v1.0.1 h1:i0LektDkO1QlrTm/cSuP+PyBCDnYvjPLGl4LdWEMiaA= 96 | github.com/jackpal/go-nat-pmp v1.0.1/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= 97 | github.com/jbenet/go-cienv v0.0.0-20150120210510-1bb1476777ec/go.mod h1:rGaEvXB4uRSZMmzKNLoXvTu1sfx+1kv/DojUlPrSZGs= 98 | github.com/jbenet/go-cienv v0.1.0 h1:Vc/s0QbQtoxX8MwwSLWWh+xNNZvM3Lw7NsTcHrvvhMc= 99 | github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= 100 | github.com/jbenet/go-temp-err-catcher v0.0.0-20150120210811-aac704a3f4f2 h1:vhC1OXXiT9R2pczegwz6moDvuRpggaroAXhPIseh57A= 101 | github.com/jbenet/go-temp-err-catcher v0.0.0-20150120210811-aac704a3f4f2/go.mod h1:8GXXJV31xl8whumTzdZsTt3RnUIiPqzkyf7mxToRCMs= 102 | github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8/go.mod h1:Ly/wlsjFq/qrU3Rar62tu1gASgGw6chQbSh/XgIIXCY= 103 | github.com/jbenet/goprocess v0.1.3 h1:YKyIEECS/XvcfHtBzxtjBBbWK+MbvA6dG8ASiqwvr10= 104 | github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= 105 | github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= 106 | github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= 107 | github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= 108 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 109 | github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= 110 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 111 | github.com/koron/go-ssdp v0.0.0-20180514024734-4a0ed625a78b h1:wxtKgYHEncAU00muMD06dzLiahtGM1eouRNOzVV7tdQ= 112 | github.com/koron/go-ssdp v0.0.0-20180514024734-4a0ed625a78b/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= 113 | github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= 114 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 115 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 116 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 117 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 118 | github.com/libp2p/go-addr-util v0.0.1 h1:TpTQm9cXVRVSKsYbgQ7GKc3KbbHVTnbostgGaDEP+88= 119 | github.com/libp2p/go-addr-util v0.0.1/go.mod h1:4ac6O7n9rIAKB1dnd+s8IbbMXkt+oBpzX4/+RACcnlQ= 120 | github.com/libp2p/go-buffer-pool v0.0.1/go.mod h1:xtyIz9PMobb13WaxR6Zo1Pd1zXJKYg0a8KiIvDp3TzQ= 121 | github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOSqcmlfs= 122 | github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= 123 | github.com/libp2p/go-conn-security-multistream v0.1.0 h1:aqGmto+ttL/uJgX0JtQI0tD21CIEy5eYd1Hlp0juHY0= 124 | github.com/libp2p/go-conn-security-multistream v0.1.0/go.mod h1:aw6eD7LOsHEX7+2hJkDxw1MteijaVcI+/eP2/x3J1xc= 125 | github.com/libp2p/go-flow-metrics v0.0.1 h1:0gxuFd2GuK7IIP5pKljLwps6TvcuYgvG7Atqi3INF5s= 126 | github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8= 127 | github.com/libp2p/go-libp2p v0.1.0/go.mod h1:6D/2OBauqLUoqcADOJpn9WbKqvaM07tDw68qHM0BxUM= 128 | github.com/libp2p/go-libp2p v0.1.1 h1:52sB0TJuDk2nYMcMfHOKaPoaayDZjaYVCq6Vk1ejUTk= 129 | github.com/libp2p/go-libp2p v0.1.1/go.mod h1:I00BRo1UuUSdpuc8Q2mN7yDF/oTUTRAX6JWpTiK9Rp8= 130 | github.com/libp2p/go-libp2p-autonat v0.1.0 h1:aCWAu43Ri4nU0ZPO7NyLzUvvfqd0nE3dX0R/ZGYVgOU= 131 | github.com/libp2p/go-libp2p-autonat v0.1.0/go.mod h1:1tLf2yXxiE/oKGtDwPYWTSYG3PtvYlJmg7NeVtPRqH8= 132 | github.com/libp2p/go-libp2p-blankhost v0.1.1 h1:X919sCh+KLqJcNRApj43xCSiQRYqOSI88Fdf55ngf78= 133 | github.com/libp2p/go-libp2p-blankhost v0.1.1/go.mod h1:pf2fvdLJPsC1FsVrNP3DUUvMzUts2dsLLBEpo1vW1ro= 134 | github.com/libp2p/go-libp2p-circuit v0.1.0 h1:eniLL3Y9aq/sryfyV1IAHj5rlvuyj3b7iz8tSiZpdhY= 135 | github.com/libp2p/go-libp2p-circuit v0.1.0/go.mod h1:Ahq4cY3V9VJcHcn1SBXjr78AbFkZeIRmfunbA7pmFh8= 136 | github.com/libp2p/go-libp2p-core v0.0.1/go.mod h1:g/VxnTZ/1ygHxH3dKok7Vno1VfpvGcGip57wjTU4fco= 137 | github.com/libp2p/go-libp2p-core v0.0.3 h1:+IonUYY0nJZLb5Fdv6a6DOjtGP1L8Bb3faamiI2q5FY= 138 | github.com/libp2p/go-libp2p-core v0.0.3/go.mod h1:j+YQMNz9WNSkNezXOsahp9kwZBKBvxLpKD316QWSJXE= 139 | github.com/libp2p/go-libp2p-crypto v0.0.1/go.mod h1:yJkNyDmO341d5wwXxDUGO0LykUVT72ImHNUqh5D/dBE= 140 | github.com/libp2p/go-libp2p-crypto v0.1.0 h1:k9MFy+o2zGDNGsaoZl0MA3iZ75qXxr9OOoAZF+sD5OQ= 141 | github.com/libp2p/go-libp2p-crypto v0.1.0/go.mod h1:sPUokVISZiy+nNuTTH/TY+leRSxnFj/2GLjtOTW90hI= 142 | github.com/libp2p/go-libp2p-discovery v0.1.0 h1:j+R6cokKcGbnZLf4kcNwpx6mDEUPF3N6SrqMymQhmvs= 143 | github.com/libp2p/go-libp2p-discovery v0.1.0/go.mod h1:4F/x+aldVHjHDHuX85x1zWoFTGElt8HnoDzwkFZm29g= 144 | github.com/libp2p/go-libp2p-kad-dht v0.1.0 h1:cupGornmncdQCnjArAv9Txkqy43wgQCxoe/5pfIDF/4= 145 | github.com/libp2p/go-libp2p-kad-dht v0.1.0/go.mod h1:EiH74cOsCxcu2Yh1XxQMpf1uHcLNm/hYEJBOIRlzHNE= 146 | github.com/libp2p/go-libp2p-kad-dht v0.1.1 h1:IH6NQuoUv5w5e1O8Jc3KyVDtr0rNd0G9aaADpLI1xVo= 147 | github.com/libp2p/go-libp2p-kad-dht v0.1.1/go.mod h1:1kj2Rk5pX3/0RwqMm9AMNCT7DzcMHYhgDN5VTi+cY0M= 148 | github.com/libp2p/go-libp2p-kbucket v0.2.0 h1:FB2a0VkOTNGTP5gu/I444u4WabNM9V1zCkQcWb7zajI= 149 | github.com/libp2p/go-libp2p-kbucket v0.2.0/go.mod h1:JNymBToym3QXKBMKGy3m29+xprg0EVr/GJFHxFEdgh8= 150 | github.com/libp2p/go-libp2p-loggables v0.1.0 h1:h3w8QFfCt2UJl/0/NW4K829HX/0S4KD31PQ7m8UXXO8= 151 | github.com/libp2p/go-libp2p-loggables v0.1.0/go.mod h1:EyumB2Y6PrYjr55Q3/tiJ/o3xoDasoRYM7nOzEpoa90= 152 | github.com/libp2p/go-libp2p-mplex v0.2.0/go.mod h1:Ejl9IyjvXJ0T9iqUTE1jpYATQ9NM3g+OtR+EMMODbKo= 153 | github.com/libp2p/go-libp2p-mplex v0.2.1 h1:E1xaJBQnbSiTHGI1gaBKmKhu1TUKkErKJnE8iGvirYI= 154 | github.com/libp2p/go-libp2p-mplex v0.2.1/go.mod h1:SC99Rxs8Vuzrf/6WhmH41kNn13TiYdAWNYHrwImKLnE= 155 | github.com/libp2p/go-libp2p-nat v0.0.4 h1:+KXK324yaY701On8a0aGjTnw8467kW3ExKcqW2wwmyw= 156 | github.com/libp2p/go-libp2p-nat v0.0.4/go.mod h1:N9Js/zVtAXqaeT99cXgTV9e75KpnWCvVOiGzlcHmBbY= 157 | github.com/libp2p/go-libp2p-netutil v0.1.0 h1:zscYDNVEcGxyUpMd0JReUZTrpMfia8PmLKcKF72EAMQ= 158 | github.com/libp2p/go-libp2p-netutil v0.1.0/go.mod h1:3Qv/aDqtMLTUyQeundkKsA+YCThNdbQD54k3TqjpbFU= 159 | github.com/libp2p/go-libp2p-peer v0.0.1/go.mod h1:nXQvOBbwVqoP+T5Y5nCjeH4sP9IX/J0AMzcDUVruVoo= 160 | github.com/libp2p/go-libp2p-peer v0.2.0 h1:EQ8kMjaCUwt/Y5uLgjT8iY2qg0mGUT0N1zUjer50DsY= 161 | github.com/libp2p/go-libp2p-peer v0.2.0/go.mod h1:RCffaCvUyW2CJmG2gAWVqwePwW7JMgxjsHm7+J5kjWY= 162 | github.com/libp2p/go-libp2p-peerstore v0.0.1/go.mod h1:RabLyPVJLuNQ+GFyoEkfi8H4Ti6k/HtZJ7YKgtSq+20= 163 | github.com/libp2p/go-libp2p-peerstore v0.1.0 h1:MKh7pRNPHSh1fLPj8u/M/s/napdmeNpoi9BRy9lPN0E= 164 | github.com/libp2p/go-libp2p-peerstore v0.1.0/go.mod h1:2CeHkQsr8svp4fZ+Oi9ykN1HBb6u0MOvdJ7YIsmcwtY= 165 | github.com/libp2p/go-libp2p-pnet v0.1.0 h1:kRUES28dktfnHNIRW4Ro78F7rKBHBiw5MJpl0ikrLIA= 166 | github.com/libp2p/go-libp2p-pnet v0.1.0/go.mod h1:ZkyZw3d0ZFOex71halXRihWf9WH/j3OevcJdTmD0lyE= 167 | github.com/libp2p/go-libp2p-pubsub v0.1.0 h1:SmQeMa7IUv5vadh0fYgYsafWCBA1sCy5d/68kIYqGcU= 168 | github.com/libp2p/go-libp2p-pubsub v0.1.0/go.mod h1:ZwlKzRSe1eGvSIdU5bD7+8RZN/Uzw0t1Bp9R1znpR/Q= 169 | github.com/libp2p/go-libp2p-record v0.0.1/go.mod h1:grzqg263Rug/sRex85QrDOLntdFAymLDLm7lxMgU79Q= 170 | github.com/libp2p/go-libp2p-record v0.1.0 h1:wHwBGbFzymoIl69BpgwIu0O6ta3TXGcMPvHUAcodzRc= 171 | github.com/libp2p/go-libp2p-record v0.1.0/go.mod h1:ujNc8iuE5dlKWVy6wuL6dd58t0n7xI4hAIl8pE6wu5Q= 172 | github.com/libp2p/go-libp2p-routing v0.1.0 h1:hFnj3WR3E2tOcKaGpyzfP4gvFZ3t8JkQmbapN0Ct+oU= 173 | github.com/libp2p/go-libp2p-routing v0.1.0/go.mod h1:zfLhI1RI8RLEzmEaaPwzonRvXeeSHddONWkcTcB54nE= 174 | github.com/libp2p/go-libp2p-secio v0.1.0 h1:NNP5KLxuP97sE5Bu3iuwOWyT/dKEGMN5zSLMWdB7GTQ= 175 | github.com/libp2p/go-libp2p-secio v0.1.0/go.mod h1:tMJo2w7h3+wN4pgU2LSYeiKPrfqBgkOsdiKK77hE7c8= 176 | github.com/libp2p/go-libp2p-swarm v0.1.0 h1:HrFk2p0awrGEgch9JXK/qp/hfjqQfgNxpLWnCiWPg5s= 177 | github.com/libp2p/go-libp2p-swarm v0.1.0/go.mod h1:wQVsCdjsuZoc730CgOvh5ox6K8evllckjebkdiY5ta4= 178 | github.com/libp2p/go-libp2p-testing v0.0.2/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= 179 | github.com/libp2p/go-libp2p-testing v0.0.3/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= 180 | github.com/libp2p/go-libp2p-testing v0.0.4 h1:Qev57UR47GcLPXWjrunv5aLIQGO4n9mhI/8/EIrEEFc= 181 | github.com/libp2p/go-libp2p-testing v0.0.4/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= 182 | github.com/libp2p/go-libp2p-transport-upgrader v0.1.1 h1:PZMS9lhjK9VytzMCW3tWHAXtKXmlURSc3ZdvwEcKCzw= 183 | github.com/libp2p/go-libp2p-transport-upgrader v0.1.1/go.mod h1:IEtA6or8JUbsV07qPW4r01GnTenLW4oi3lOPbUMGJJA= 184 | github.com/libp2p/go-libp2p-yamux v0.2.0/go.mod h1:Db2gU+XfLpm6E4rG5uGCFX6uXA8MEXOxFcRoXUODaK8= 185 | github.com/libp2p/go-libp2p-yamux v0.2.1 h1:Q3XYNiKCC2vIxrvUJL+Jg1kiyeEaIDNKLjgEjo3VQdI= 186 | github.com/libp2p/go-libp2p-yamux v0.2.1/go.mod h1:1FBXiHDk1VyRM1C0aez2bCfHQ4vMZKkAQzZbkSQt5fI= 187 | github.com/libp2p/go-maddr-filter v0.0.4 h1:hx8HIuuwk34KePddrp2mM5ivgPkZ09JH4AvsALRbFUs= 188 | github.com/libp2p/go-maddr-filter v0.0.4/go.mod h1:6eT12kSQMA9x2pvFQa+xesMKUBlj9VImZbj3B9FBH/Q= 189 | github.com/libp2p/go-mplex v0.0.3/go.mod h1:pK5yMLmOoBR1pNCqDlA2GQrdAVTMkqFalaTWe7l4Yd0= 190 | github.com/libp2p/go-mplex v0.1.0 h1:/nBTy5+1yRyY82YaO6HXQRnO5IAGsXTjEJaR3LdTPc0= 191 | github.com/libp2p/go-mplex v0.1.0/go.mod h1:SXgmdki2kwCUlCCbfGLEgHjC4pFqhTp0ZoV6aiKgxDU= 192 | github.com/libp2p/go-msgio v0.0.2 h1:ivPvEKHxmVkTClHzg6RXTYHqaJQ0V9cDbq+6lKb3UV0= 193 | github.com/libp2p/go-msgio v0.0.2/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= 194 | github.com/libp2p/go-msgio v0.0.4 h1:agEFehY3zWJFUHK6SEMR7UYmk2z6kC3oeCM7ybLhguA= 195 | github.com/libp2p/go-msgio v0.0.4/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= 196 | github.com/libp2p/go-nat v0.0.3 h1:l6fKV+p0Xa354EqQOQP+d8CivdLM4kl5GxC1hSc/UeI= 197 | github.com/libp2p/go-nat v0.0.3/go.mod h1:88nUEt0k0JD45Bk93NIwDqjlhiOwOoV36GchpcVc1yI= 198 | github.com/libp2p/go-reuseport v0.0.1 h1:7PhkfH73VXfPJYKQ6JwS5I/eVcoyYi9IMNGc6FWpFLw= 199 | github.com/libp2p/go-reuseport v0.0.1/go.mod h1:jn6RmB1ufnQwl0Q1f+YxAj8isJgDCQzaaxIFYDhcYEA= 200 | github.com/libp2p/go-reuseport-transport v0.0.2 h1:WglMwyXyBu61CMkjCCtnmqNqnjib0GIEjMiHTwR/KN4= 201 | github.com/libp2p/go-reuseport-transport v0.0.2/go.mod h1:YkbSDrvjUVDL6b8XqriyA20obEtsW9BLkuOUyQAOCbs= 202 | github.com/libp2p/go-stream-muxer v0.0.1/go.mod h1:bAo8x7YkSpadMTbtTaxGVHWUQsR/l5MEaHbKaliuT14= 203 | github.com/libp2p/go-stream-muxer-multistream v0.2.0 h1:714bRJ4Zy9mdhyTLJ+ZKiROmAFwUHpeRidG+q7LTQOg= 204 | github.com/libp2p/go-stream-muxer-multistream v0.2.0/go.mod h1:j9eyPol/LLRqT+GPLSxvimPhNph4sfYfMoDPd7HkzIc= 205 | github.com/libp2p/go-tcp-transport v0.1.0 h1:IGhowvEqyMFknOar4FWCKSWE0zL36UFKQtiRQD60/8o= 206 | github.com/libp2p/go-tcp-transport v0.1.0/go.mod h1:oJ8I5VXryj493DEJ7OsBieu8fcg2nHGctwtInJVpipc= 207 | github.com/libp2p/go-ws-transport v0.1.0 h1:F+0OvvdmPTDsVc4AjPHjV7L7Pk1B7D5QwtDcKE2oag4= 208 | github.com/libp2p/go-ws-transport v0.1.0/go.mod h1:rjw1MG1LU9YDC6gzmwObkPd/Sqwhw7yT74kj3raBFuo= 209 | github.com/libp2p/go-yamux v1.2.2/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= 210 | github.com/libp2p/go-yamux v1.2.3 h1:xX8A36vpXb59frIzWFdEgptLMsOANMFq2K7fPRlunYI= 211 | github.com/libp2p/go-yamux v1.2.3/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= 212 | github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg= 213 | github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= 214 | github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= 215 | github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= 216 | github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw= 217 | github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= 218 | github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= 219 | github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= 220 | github.com/miekg/dns v1.1.12/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= 221 | github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= 222 | github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= 223 | github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= 224 | github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= 225 | github.com/minio/sha256-simd v0.1.0 h1:U41/2erhAKcmSI14xh/ZTUdBPOzDOIfS93ibzUSl8KM= 226 | github.com/minio/sha256-simd v0.1.0/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= 227 | github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= 228 | github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 229 | github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= 230 | github.com/mr-tron/base58 v1.1.1/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= 231 | github.com/mr-tron/base58 v1.1.2 h1:ZEw4I2EgPKDJ2iEw0cNmLB3ROrEmkOtXIkaG7wZg+78= 232 | github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= 233 | github.com/multiformats/go-base32 v0.0.3 h1:tw5+NhuwaOjJCC5Pp82QuXbrmLzWg7uxlMFp8Nq/kkI= 234 | github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= 235 | github.com/multiformats/go-multiaddr v0.0.1/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= 236 | github.com/multiformats/go-multiaddr v0.0.2/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= 237 | github.com/multiformats/go-multiaddr v0.0.4 h1:WgMSI84/eRLdbptXMkMWDXPjPq7SPLIgGUVm2eroyU4= 238 | github.com/multiformats/go-multiaddr v0.0.4/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= 239 | github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= 240 | github.com/multiformats/go-multiaddr-dns v0.0.2 h1:/Bbsgsy3R6e3jf2qBahzNHzww6usYaZ0NhNH3sqdFS8= 241 | github.com/multiformats/go-multiaddr-dns v0.0.2/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= 242 | github.com/multiformats/go-multiaddr-fmt v0.0.1 h1:5YjeOIzbX8OTKVaN72aOzGIYW7PnrZrnkDyOfAWRSMA= 243 | github.com/multiformats/go-multiaddr-fmt v0.0.1/go.mod h1:aBYjqL4T/7j4Qx+R73XSv/8JsgnRFlf0w2KGLCmXl3Q= 244 | github.com/multiformats/go-multiaddr-net v0.0.1 h1:76O59E3FavvHqNg7jvzWzsPSW5JSi/ek0E4eiDVbg9g= 245 | github.com/multiformats/go-multiaddr-net v0.0.1/go.mod h1:nw6HSxNmCIQH27XPGBuX+d1tnvM7ihcFwHMSstNAVUU= 246 | github.com/multiformats/go-multibase v0.0.1 h1:PN9/v21eLywrFWdFNsFKaU04kLJzuYzmrJR+ubhT9qA= 247 | github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= 248 | github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= 249 | github.com/multiformats/go-multihash v0.0.5 h1:1wxmCvTXAifAepIMyF39vZinRw5sbqjPs/UIi93+uik= 250 | github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po= 251 | github.com/multiformats/go-multihash v0.0.6 h1:cAVKO4epVd+SSpYJQD6d3vbdqQJvsrtGbTGzsp+V094= 252 | github.com/multiformats/go-multihash v0.0.6/go.mod h1:XuKXPp8VHcTygube3OWZC+aZrA+H1IhmjoCDtJc7PXM= 253 | github.com/multiformats/go-multistream v0.1.0 h1:UpO6jrsjqs46mqAK3n6wKRYFhugss9ArzbyUzU+4wkQ= 254 | github.com/multiformats/go-multistream v0.1.0/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= 255 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 256 | github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 257 | github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w= 258 | github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 259 | github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= 260 | github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo= 261 | github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= 262 | github.com/opentracing/opentracing-go v1.0.2 h1:3jA2P6O1F9UOrWVpwrIo17pu01KWvNWg4X946/Y5Zwg= 263 | github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= 264 | github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= 265 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 266 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 267 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 268 | github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= 269 | github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= 270 | github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0= 271 | github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= 272 | github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= 273 | github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= 274 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 275 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 276 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 277 | github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= 278 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 279 | github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= 280 | github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc h1:BCPnHtcboadS0DvysUuJXZ4lWVv5Bh5i7+tbIyi+ck4= 281 | github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc/go.mod h1:r45hJU7yEoA81k6MWNhpMj/kms0n14dkzkxYHoB96UM= 282 | github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 h1:EKhdznlJHPMoKr0XTrX+IlJs1LH3lyx2nfr1dOlZ79k= 283 | github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc= 284 | github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc h1:9lDbC6Rz4bwmou+oE6Dt4Cb2BGMur5eR/GYptkKUVHo= 285 | github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM= 286 | github.com/whyrusleeping/go-notifier v0.0.0-20170827234753-097c5d47330f h1:M/lL30eFZTKnomXY6huvM6G0+gVquFNf6mxghaWlFUg= 287 | github.com/whyrusleeping/go-notifier v0.0.0-20170827234753-097c5d47330f/go.mod h1:cZNvX9cFybI01GriPRMXDtczuvUhgbcYr9iCGaNlRv8= 288 | github.com/whyrusleeping/mafmt v1.2.8 h1:TCghSl5kkwEE0j+sU/gudyhVMRlpBin8fMBBHg59EbA= 289 | github.com/whyrusleeping/mafmt v1.2.8/go.mod h1:faQJFPbLSxzD9xpA02ttW/tS9vZykNvXwGvqIpk20FA= 290 | github.com/whyrusleeping/mdns v0.0.0-20180901202407-ef14215e6b30/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4= 291 | github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 h1:E9S12nwJwEOXe2d6gT6qxdvqMnNq+VnSsKPgm2ZZNds= 292 | github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7/go.mod h1:X2c0RVCI1eSUFI8eLcY3c0423ykwiUdxLJtkDvruhjI= 293 | github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee h1:lYbXeSvJi5zk5GLKVuid9TVjS9a0OmLIDKTfoZBL6Ow= 294 | github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee/go.mod h1:m2aV4LZI4Aez7dP5PMyVKEHhUyEJ/RjmPEDOpDvudHg= 295 | go.opencensus.io v0.21.0 h1:mU6zScU4U1YAFPHEHYk+3JC4SY7JxgkqS10ZOSyksNg= 296 | go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= 297 | go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= 298 | go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= 299 | go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= 300 | go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= 301 | go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= 302 | go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= 303 | golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 304 | golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 305 | golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 306 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 307 | golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 308 | golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 309 | golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5 h1:8dUaAV7K4uHsF56JQWkprecIQKdPHtR9jCHF5nB8uzc= 310 | golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 311 | golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 312 | golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443 h1:IcSOAf4PyMp3U3XbIEj1/xJ2BjNN2jWv7JoyOsMxXUU= 313 | golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 314 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 315 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 316 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 317 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 318 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 319 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 320 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 321 | golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 322 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 323 | golang.org/x/net v0.0.0-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 324 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 325 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= 326 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 327 | golang.org/x/net v0.0.0-20190613194153-d28f0bde5980 h1:dfGZHvZk057jK2MCeWus/TowKpJ8y4AmooUzdBSR9GU= 328 | golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 329 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 330 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 331 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 332 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 333 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 334 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 335 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 336 | golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 337 | golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 338 | golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 339 | golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= 340 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 341 | golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= 342 | golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 343 | golang.org/x/sys v0.0.0-20190614160838-b47fdc937951 h1:ZUgGZ7PSkne6oY+VgAvayrB16owfm9/DKAtgWubzgzU= 344 | golang.org/x/sys v0.0.0-20190614160838-b47fdc937951/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 345 | golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= 346 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 347 | golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 348 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 349 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 350 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 351 | golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522 h1:bhOzK9QyoD0ogCnFro1m2mz41+Ib0oOhfJnBp5MR4K4= 352 | golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 353 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 354 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 355 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 356 | google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 357 | google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19 h1:Lj2SnHtxkRGJDqnGaSjo+CCdIieEnwVazbOXILwQemk= 358 | google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 359 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 360 | google.golang.org/grpc v1.21.1 h1:j6XxA85m/6txkUCHvzlV5f+HBNl/1r5cZ2A/3IEFOO8= 361 | google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= 362 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 363 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= 364 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 365 | gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= 366 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 367 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= 368 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 369 | gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= 370 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 371 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 372 | -------------------------------------------------------------------------------- /pb/pubsub.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // source: pubsub.proto 3 | 4 | package pb 5 | 6 | import ( 7 | context "context" 8 | fmt "fmt" 9 | proto "github.com/golang/protobuf/proto" 10 | grpc "google.golang.org/grpc" 11 | math "math" 12 | ) 13 | 14 | // Reference imports to suppress errors if they are not otherwise used. 15 | var _ = proto.Marshal 16 | var _ = fmt.Errorf 17 | var _ = math.Inf 18 | 19 | // This is a compile-time assertion to ensure that this generated file 20 | // is compatible with the proto package it is being compiled against. 21 | // A compilation error at this line likely means your copy of the 22 | // proto package needs to be updated. 23 | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package 24 | 25 | // Empty message is used for requests 26 | // and responses that dont need any particular 27 | // data. 28 | type Empty struct { 29 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 30 | XXX_unrecognized []byte `json:"-"` 31 | XXX_sizecache int32 `json:"-"` 32 | } 33 | 34 | func (m *Empty) Reset() { *m = Empty{} } 35 | func (m *Empty) String() string { return proto.CompactTextString(m) } 36 | func (*Empty) ProtoMessage() {} 37 | func (*Empty) Descriptor() ([]byte, []int) { 38 | return fileDescriptor_91df006b05e20cf7, []int{0} 39 | } 40 | 41 | func (m *Empty) XXX_Unmarshal(b []byte) error { 42 | return xxx_messageInfo_Empty.Unmarshal(m, b) 43 | } 44 | func (m *Empty) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 45 | return xxx_messageInfo_Empty.Marshal(b, m, deterministic) 46 | } 47 | func (m *Empty) XXX_Merge(src proto.Message) { 48 | xxx_messageInfo_Empty.Merge(m, src) 49 | } 50 | func (m *Empty) XXX_Size() int { 51 | return xxx_messageInfo_Empty.Size(m) 52 | } 53 | func (m *Empty) XXX_DiscardUnknown() { 54 | xxx_messageInfo_Empty.DiscardUnknown(m) 55 | } 56 | 57 | var xxx_messageInfo_Empty proto.InternalMessageInfo 58 | 59 | // ListPeersRequest is used to return a list of 60 | // peers that are subscribed to the given topic(s) 61 | type ListPeersRequest struct { 62 | // the topics for which we should 63 | // list peers for 64 | Topics []string `protobuf:"bytes,1,rep,name=topics,proto3" json:"topics,omitempty"` 65 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 66 | XXX_unrecognized []byte `json:"-"` 67 | XXX_sizecache int32 `json:"-"` 68 | } 69 | 70 | func (m *ListPeersRequest) Reset() { *m = ListPeersRequest{} } 71 | func (m *ListPeersRequest) String() string { return proto.CompactTextString(m) } 72 | func (*ListPeersRequest) ProtoMessage() {} 73 | func (*ListPeersRequest) Descriptor() ([]byte, []int) { 74 | return fileDescriptor_91df006b05e20cf7, []int{1} 75 | } 76 | 77 | func (m *ListPeersRequest) XXX_Unmarshal(b []byte) error { 78 | return xxx_messageInfo_ListPeersRequest.Unmarshal(m, b) 79 | } 80 | func (m *ListPeersRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 81 | return xxx_messageInfo_ListPeersRequest.Marshal(b, m, deterministic) 82 | } 83 | func (m *ListPeersRequest) XXX_Merge(src proto.Message) { 84 | xxx_messageInfo_ListPeersRequest.Merge(m, src) 85 | } 86 | func (m *ListPeersRequest) XXX_Size() int { 87 | return xxx_messageInfo_ListPeersRequest.Size(m) 88 | } 89 | func (m *ListPeersRequest) XXX_DiscardUnknown() { 90 | xxx_messageInfo_ListPeersRequest.DiscardUnknown(m) 91 | } 92 | 93 | var xxx_messageInfo_ListPeersRequest proto.InternalMessageInfo 94 | 95 | func (m *ListPeersRequest) GetTopics() []string { 96 | if m != nil { 97 | return m.Topics 98 | } 99 | return nil 100 | } 101 | 102 | // ListPeersResponse is a response to a ListPeersRequest 103 | type ListPeersResponse struct { 104 | Peers []*ListPeersResponse_Peer `protobuf:"bytes,1,rep,name=peers,proto3" json:"peers,omitempty"` 105 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 106 | XXX_unrecognized []byte `json:"-"` 107 | XXX_sizecache int32 `json:"-"` 108 | } 109 | 110 | func (m *ListPeersResponse) Reset() { *m = ListPeersResponse{} } 111 | func (m *ListPeersResponse) String() string { return proto.CompactTextString(m) } 112 | func (*ListPeersResponse) ProtoMessage() {} 113 | func (*ListPeersResponse) Descriptor() ([]byte, []int) { 114 | return fileDescriptor_91df006b05e20cf7, []int{2} 115 | } 116 | 117 | func (m *ListPeersResponse) XXX_Unmarshal(b []byte) error { 118 | return xxx_messageInfo_ListPeersResponse.Unmarshal(m, b) 119 | } 120 | func (m *ListPeersResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 121 | return xxx_messageInfo_ListPeersResponse.Marshal(b, m, deterministic) 122 | } 123 | func (m *ListPeersResponse) XXX_Merge(src proto.Message) { 124 | xxx_messageInfo_ListPeersResponse.Merge(m, src) 125 | } 126 | func (m *ListPeersResponse) XXX_Size() int { 127 | return xxx_messageInfo_ListPeersResponse.Size(m) 128 | } 129 | func (m *ListPeersResponse) XXX_DiscardUnknown() { 130 | xxx_messageInfo_ListPeersResponse.DiscardUnknown(m) 131 | } 132 | 133 | var xxx_messageInfo_ListPeersResponse proto.InternalMessageInfo 134 | 135 | func (m *ListPeersResponse) GetPeers() []*ListPeersResponse_Peer { 136 | if m != nil { 137 | return m.Peers 138 | } 139 | return nil 140 | } 141 | 142 | type ListPeersResponse_Peer struct { 143 | Topic string `protobuf:"bytes,1,opt,name=topic,proto3" json:"topic,omitempty"` 144 | PeerID string `protobuf:"bytes,2,opt,name=peerID,proto3" json:"peerID,omitempty"` 145 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 146 | XXX_unrecognized []byte `json:"-"` 147 | XXX_sizecache int32 `json:"-"` 148 | } 149 | 150 | func (m *ListPeersResponse_Peer) Reset() { *m = ListPeersResponse_Peer{} } 151 | func (m *ListPeersResponse_Peer) String() string { return proto.CompactTextString(m) } 152 | func (*ListPeersResponse_Peer) ProtoMessage() {} 153 | func (*ListPeersResponse_Peer) Descriptor() ([]byte, []int) { 154 | return fileDescriptor_91df006b05e20cf7, []int{2, 0} 155 | } 156 | 157 | func (m *ListPeersResponse_Peer) XXX_Unmarshal(b []byte) error { 158 | return xxx_messageInfo_ListPeersResponse_Peer.Unmarshal(m, b) 159 | } 160 | func (m *ListPeersResponse_Peer) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 161 | return xxx_messageInfo_ListPeersResponse_Peer.Marshal(b, m, deterministic) 162 | } 163 | func (m *ListPeersResponse_Peer) XXX_Merge(src proto.Message) { 164 | xxx_messageInfo_ListPeersResponse_Peer.Merge(m, src) 165 | } 166 | func (m *ListPeersResponse_Peer) XXX_Size() int { 167 | return xxx_messageInfo_ListPeersResponse_Peer.Size(m) 168 | } 169 | func (m *ListPeersResponse_Peer) XXX_DiscardUnknown() { 170 | xxx_messageInfo_ListPeersResponse_Peer.DiscardUnknown(m) 171 | } 172 | 173 | var xxx_messageInfo_ListPeersResponse_Peer proto.InternalMessageInfo 174 | 175 | func (m *ListPeersResponse_Peer) GetTopic() string { 176 | if m != nil { 177 | return m.Topic 178 | } 179 | return "" 180 | } 181 | 182 | func (m *ListPeersResponse_Peer) GetPeerID() string { 183 | if m != nil { 184 | return m.PeerID 185 | } 186 | return "" 187 | } 188 | 189 | // PublishRequest is a message used to publish data to a topic 190 | type PublishRequest struct { 191 | Topic string `protobuf:"bytes,1,opt,name=topic,proto3" json:"topic,omitempty"` 192 | Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` 193 | Advertise bool `protobuf:"varint,3,opt,name=advertise,proto3" json:"advertise,omitempty"` 194 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 195 | XXX_unrecognized []byte `json:"-"` 196 | XXX_sizecache int32 `json:"-"` 197 | } 198 | 199 | func (m *PublishRequest) Reset() { *m = PublishRequest{} } 200 | func (m *PublishRequest) String() string { return proto.CompactTextString(m) } 201 | func (*PublishRequest) ProtoMessage() {} 202 | func (*PublishRequest) Descriptor() ([]byte, []int) { 203 | return fileDescriptor_91df006b05e20cf7, []int{3} 204 | } 205 | 206 | func (m *PublishRequest) XXX_Unmarshal(b []byte) error { 207 | return xxx_messageInfo_PublishRequest.Unmarshal(m, b) 208 | } 209 | func (m *PublishRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 210 | return xxx_messageInfo_PublishRequest.Marshal(b, m, deterministic) 211 | } 212 | func (m *PublishRequest) XXX_Merge(src proto.Message) { 213 | xxx_messageInfo_PublishRequest.Merge(m, src) 214 | } 215 | func (m *PublishRequest) XXX_Size() int { 216 | return xxx_messageInfo_PublishRequest.Size(m) 217 | } 218 | func (m *PublishRequest) XXX_DiscardUnknown() { 219 | xxx_messageInfo_PublishRequest.DiscardUnknown(m) 220 | } 221 | 222 | var xxx_messageInfo_PublishRequest proto.InternalMessageInfo 223 | 224 | func (m *PublishRequest) GetTopic() string { 225 | if m != nil { 226 | return m.Topic 227 | } 228 | return "" 229 | } 230 | 231 | func (m *PublishRequest) GetData() []byte { 232 | if m != nil { 233 | return m.Data 234 | } 235 | return nil 236 | } 237 | 238 | func (m *PublishRequest) GetAdvertise() bool { 239 | if m != nil { 240 | return m.Advertise 241 | } 242 | return false 243 | } 244 | 245 | // SubscribeRequest is used to initiate a subscription 246 | // to a given pubsub topic and stream received messages 247 | type SubscribeRequest struct { 248 | // the topic we should subscribe to 249 | Topic string `protobuf:"bytes,1,opt,name=topic,proto3" json:"topic,omitempty"` 250 | // indicates whether the server should 251 | // perform service discover for peers on the same topic 252 | Discover bool `protobuf:"varint,2,opt,name=discover,proto3" json:"discover,omitempty"` 253 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 254 | XXX_unrecognized []byte `json:"-"` 255 | XXX_sizecache int32 `json:"-"` 256 | } 257 | 258 | func (m *SubscribeRequest) Reset() { *m = SubscribeRequest{} } 259 | func (m *SubscribeRequest) String() string { return proto.CompactTextString(m) } 260 | func (*SubscribeRequest) ProtoMessage() {} 261 | func (*SubscribeRequest) Descriptor() ([]byte, []int) { 262 | return fileDescriptor_91df006b05e20cf7, []int{4} 263 | } 264 | 265 | func (m *SubscribeRequest) XXX_Unmarshal(b []byte) error { 266 | return xxx_messageInfo_SubscribeRequest.Unmarshal(m, b) 267 | } 268 | func (m *SubscribeRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 269 | return xxx_messageInfo_SubscribeRequest.Marshal(b, m, deterministic) 270 | } 271 | func (m *SubscribeRequest) XXX_Merge(src proto.Message) { 272 | xxx_messageInfo_SubscribeRequest.Merge(m, src) 273 | } 274 | func (m *SubscribeRequest) XXX_Size() int { 275 | return xxx_messageInfo_SubscribeRequest.Size(m) 276 | } 277 | func (m *SubscribeRequest) XXX_DiscardUnknown() { 278 | xxx_messageInfo_SubscribeRequest.DiscardUnknown(m) 279 | } 280 | 281 | var xxx_messageInfo_SubscribeRequest proto.InternalMessageInfo 282 | 283 | func (m *SubscribeRequest) GetTopic() string { 284 | if m != nil { 285 | return m.Topic 286 | } 287 | return "" 288 | } 289 | 290 | func (m *SubscribeRequest) GetDiscover() bool { 291 | if m != nil { 292 | return m.Discover 293 | } 294 | return false 295 | } 296 | 297 | // Topics is a response that returns 298 | // the names of all known topics 299 | type TopicsResponse struct { 300 | Names []string `protobuf:"bytes,1,rep,name=names,proto3" json:"names,omitempty"` 301 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 302 | XXX_unrecognized []byte `json:"-"` 303 | XXX_sizecache int32 `json:"-"` 304 | } 305 | 306 | func (m *TopicsResponse) Reset() { *m = TopicsResponse{} } 307 | func (m *TopicsResponse) String() string { return proto.CompactTextString(m) } 308 | func (*TopicsResponse) ProtoMessage() {} 309 | func (*TopicsResponse) Descriptor() ([]byte, []int) { 310 | return fileDescriptor_91df006b05e20cf7, []int{5} 311 | } 312 | 313 | func (m *TopicsResponse) XXX_Unmarshal(b []byte) error { 314 | return xxx_messageInfo_TopicsResponse.Unmarshal(m, b) 315 | } 316 | func (m *TopicsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 317 | return xxx_messageInfo_TopicsResponse.Marshal(b, m, deterministic) 318 | } 319 | func (m *TopicsResponse) XXX_Merge(src proto.Message) { 320 | xxx_messageInfo_TopicsResponse.Merge(m, src) 321 | } 322 | func (m *TopicsResponse) XXX_Size() int { 323 | return xxx_messageInfo_TopicsResponse.Size(m) 324 | } 325 | func (m *TopicsResponse) XXX_DiscardUnknown() { 326 | xxx_messageInfo_TopicsResponse.DiscardUnknown(m) 327 | } 328 | 329 | var xxx_messageInfo_TopicsResponse proto.InternalMessageInfo 330 | 331 | func (m *TopicsResponse) GetNames() []string { 332 | if m != nil { 333 | return m.Names 334 | } 335 | return nil 336 | } 337 | 338 | // PubSubMessageResposne is a received pubsub message 339 | // sent as a response to a subscription rpc call 340 | type PubSubMessageResponse struct { 341 | From []byte `protobuf:"bytes,1,opt,name=from,proto3" json:"from,omitempty"` 342 | Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` 343 | Seqno []byte `protobuf:"bytes,3,opt,name=seqno,proto3" json:"seqno,omitempty"` 344 | TopicIDs []string `protobuf:"bytes,4,rep,name=topicIDs,proto3" json:"topicIDs,omitempty"` 345 | Signature []byte `protobuf:"bytes,5,opt,name=signature,proto3" json:"signature,omitempty"` 346 | Key []byte `protobuf:"bytes,6,opt,name=key,proto3" json:"key,omitempty"` 347 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 348 | XXX_unrecognized []byte `json:"-"` 349 | XXX_sizecache int32 `json:"-"` 350 | } 351 | 352 | func (m *PubSubMessageResponse) Reset() { *m = PubSubMessageResponse{} } 353 | func (m *PubSubMessageResponse) String() string { return proto.CompactTextString(m) } 354 | func (*PubSubMessageResponse) ProtoMessage() {} 355 | func (*PubSubMessageResponse) Descriptor() ([]byte, []int) { 356 | return fileDescriptor_91df006b05e20cf7, []int{6} 357 | } 358 | 359 | func (m *PubSubMessageResponse) XXX_Unmarshal(b []byte) error { 360 | return xxx_messageInfo_PubSubMessageResponse.Unmarshal(m, b) 361 | } 362 | func (m *PubSubMessageResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 363 | return xxx_messageInfo_PubSubMessageResponse.Marshal(b, m, deterministic) 364 | } 365 | func (m *PubSubMessageResponse) XXX_Merge(src proto.Message) { 366 | xxx_messageInfo_PubSubMessageResponse.Merge(m, src) 367 | } 368 | func (m *PubSubMessageResponse) XXX_Size() int { 369 | return xxx_messageInfo_PubSubMessageResponse.Size(m) 370 | } 371 | func (m *PubSubMessageResponse) XXX_DiscardUnknown() { 372 | xxx_messageInfo_PubSubMessageResponse.DiscardUnknown(m) 373 | } 374 | 375 | var xxx_messageInfo_PubSubMessageResponse proto.InternalMessageInfo 376 | 377 | func (m *PubSubMessageResponse) GetFrom() []byte { 378 | if m != nil { 379 | return m.From 380 | } 381 | return nil 382 | } 383 | 384 | func (m *PubSubMessageResponse) GetData() []byte { 385 | if m != nil { 386 | return m.Data 387 | } 388 | return nil 389 | } 390 | 391 | func (m *PubSubMessageResponse) GetSeqno() []byte { 392 | if m != nil { 393 | return m.Seqno 394 | } 395 | return nil 396 | } 397 | 398 | func (m *PubSubMessageResponse) GetTopicIDs() []string { 399 | if m != nil { 400 | return m.TopicIDs 401 | } 402 | return nil 403 | } 404 | 405 | func (m *PubSubMessageResponse) GetSignature() []byte { 406 | if m != nil { 407 | return m.Signature 408 | } 409 | return nil 410 | } 411 | 412 | func (m *PubSubMessageResponse) GetKey() []byte { 413 | if m != nil { 414 | return m.Key 415 | } 416 | return nil 417 | } 418 | 419 | func init() { 420 | proto.RegisterType((*Empty)(nil), "pb.Empty") 421 | proto.RegisterType((*ListPeersRequest)(nil), "pb.ListPeersRequest") 422 | proto.RegisterType((*ListPeersResponse)(nil), "pb.ListPeersResponse") 423 | proto.RegisterType((*ListPeersResponse_Peer)(nil), "pb.ListPeersResponse.Peer") 424 | proto.RegisterType((*PublishRequest)(nil), "pb.PublishRequest") 425 | proto.RegisterType((*SubscribeRequest)(nil), "pb.SubscribeRequest") 426 | proto.RegisterType((*TopicsResponse)(nil), "pb.TopicsResponse") 427 | proto.RegisterType((*PubSubMessageResponse)(nil), "pb.PubSubMessageResponse") 428 | } 429 | 430 | func init() { proto.RegisterFile("pubsub.proto", fileDescriptor_91df006b05e20cf7) } 431 | 432 | var fileDescriptor_91df006b05e20cf7 = []byte{ 433 | // 425 bytes of a gzipped FileDescriptorProto 434 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x53, 0x4d, 0x6f, 0xd3, 0x40, 435 | 0x10, 0x8d, 0x9b, 0x38, 0x8d, 0x87, 0x50, 0x85, 0x51, 0x8a, 0x8c, 0xc5, 0x21, 0xda, 0x03, 0x8a, 436 | 0x50, 0x15, 0x55, 0x85, 0x13, 0x27, 0x0e, 0x41, 0xa8, 0x12, 0x48, 0xd1, 0x86, 0x03, 0x57, 0x6f, 437 | 0x32, 0x14, 0x0b, 0x12, 0xbb, 0x3b, 0xbb, 0x91, 0x2a, 0x7e, 0x0d, 0x3f, 0x8f, 0x7f, 0x81, 0x76, 438 | 0x9c, 0x3a, 0x25, 0x58, 0xbd, 0xcd, 0x7b, 0x7a, 0xb3, 0xf3, 0xf5, 0x16, 0x86, 0x95, 0x37, 0xec, 439 | 0xcd, 0xac, 0xb2, 0xa5, 0x2b, 0xf1, 0xa4, 0x32, 0xea, 0x14, 0xe2, 0x0f, 0x9b, 0xca, 0xdd, 0xa9, 440 | 0xd7, 0x30, 0xfa, 0x54, 0xb0, 0x5b, 0x10, 0x59, 0xd6, 0x74, 0xeb, 0x89, 0x1d, 0x3e, 0x87, 0xbe, 441 | 0x2b, 0xab, 0x62, 0xc5, 0x69, 0x34, 0xe9, 0x4e, 0x13, 0xbd, 0x47, 0xea, 0x17, 0x3c, 0x7b, 0xa0, 442 | 0xe5, 0xaa, 0xdc, 0x32, 0xe1, 0x25, 0xc4, 0x55, 0x20, 0x44, 0xfb, 0xe4, 0x2a, 0x9b, 0x55, 0x66, 443 | 0xf6, 0x9f, 0x6a, 0x16, 0x90, 0xae, 0x85, 0xd9, 0x5b, 0xe8, 0x05, 0x88, 0x63, 0x88, 0xe5, 0xe1, 444 | 0x34, 0x9a, 0x44, 0xd3, 0x44, 0xd7, 0x20, 0x14, 0x0f, 0xb2, 0xeb, 0x79, 0x7a, 0x22, 0xf4, 0x1e, 445 | 0xa9, 0xaf, 0x70, 0xb6, 0xf0, 0xe6, 0x67, 0xc1, 0xdf, 0xef, 0xdb, 0x6c, 0xcf, 0x47, 0xe8, 0xad, 446 | 0x73, 0x97, 0x4b, 0xf6, 0x50, 0x4b, 0x8c, 0x2f, 0x21, 0xc9, 0xd7, 0x3b, 0xb2, 0xae, 0x60, 0x4a, 447 | 0xbb, 0x93, 0x68, 0x3a, 0xd0, 0x07, 0x42, 0xcd, 0x61, 0xb4, 0xf4, 0x86, 0x57, 0xb6, 0x30, 0xf4, 448 | 0xf8, 0xdb, 0x19, 0x0c, 0xd6, 0x05, 0xaf, 0xca, 0x1d, 0x59, 0x79, 0x7f, 0xa0, 0x1b, 0xac, 0x5e, 449 | 0xc1, 0xd9, 0x17, 0x59, 0x53, 0xb3, 0x99, 0x31, 0xc4, 0xdb, 0x7c, 0x43, 0xf7, 0x5b, 0xac, 0x81, 450 | 0xfa, 0x1d, 0xc1, 0xf9, 0xc2, 0x9b, 0xa5, 0x37, 0x9f, 0x89, 0x39, 0xbf, 0xa1, 0x46, 0x8f, 0xd0, 451 | 0xfb, 0x66, 0xcb, 0x8d, 0x94, 0x1c, 0x6a, 0x89, 0x5b, 0xa7, 0x19, 0x43, 0xcc, 0x74, 0xbb, 0x2d, 452 | 0x65, 0x92, 0xa1, 0xae, 0x41, 0xe8, 0x4d, 0x9a, 0xbc, 0x9e, 0x73, 0xda, 0x93, 0x82, 0x0d, 0x0e, 453 | 0xf3, 0x73, 0x71, 0xb3, 0xcd, 0x9d, 0xb7, 0x94, 0xc6, 0x92, 0x75, 0x20, 0x70, 0x04, 0xdd, 0x1f, 454 | 0x74, 0x97, 0xf6, 0x85, 0x0f, 0xe1, 0xd5, 0x9f, 0x08, 0x9e, 0xd6, 0x3d, 0x2e, 0xc9, 0xee, 0x8a, 455 | 0x15, 0xe1, 0x05, 0x24, 0x1f, 0xc9, 0xd5, 0x03, 0x62, 0x12, 0x6e, 0x2c, 0xf6, 0xc9, 0x30, 0x84, 456 | 0xff, 0xce, 0xad, 0x3a, 0xf8, 0x0e, 0x92, 0xc6, 0x02, 0x38, 0x3e, 0x72, 0x84, 0x2c, 0x38, 0x3b, 457 | 0x6f, 0xf5, 0x89, 0xea, 0xe0, 0x7b, 0x48, 0x9a, 0x6b, 0xd4, 0xb9, 0xc7, 0xc7, 0xc9, 0x5e, 0x04, 458 | 0xb6, 0x75, 0x87, 0xaa, 0x73, 0x19, 0xe1, 0x05, 0x9c, 0xee, 0x9d, 0x82, 0xb8, 0x57, 0x3e, 0xb0, 459 | 0x4d, 0x76, 0xe8, 0x5e, 0x75, 0xa6, 0x91, 0xe9, 0xcb, 0xa7, 0x78, 0xf3, 0x37, 0x00, 0x00, 0xff, 460 | 0xff, 0x12, 0x15, 0x51, 0x80, 0x24, 0x03, 0x00, 0x00, 461 | } 462 | 463 | // Reference imports to suppress errors if they are not otherwise used. 464 | var _ context.Context 465 | var _ grpc.ClientConn 466 | 467 | // This is a compile-time assertion to ensure that this generated file 468 | // is compatible with the grpc package it is being compiled against. 469 | const _ = grpc.SupportPackageIsVersion4 470 | 471 | // PubSubServiceClient is the client API for PubSubService service. 472 | // 473 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. 474 | type PubSubServiceClient interface { 475 | // GetTopics is used to return a list of all 476 | // known topics the pubsub instance is subscribed to. 477 | // 478 | // This is a unary rpc 479 | GetTopics(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*TopicsResponse, error) 480 | // ListPeers is used to return a list of peers subscribed 481 | // to a given topic or topics. 482 | // 483 | // This is a unary rpc 484 | ListPeers(ctx context.Context, in *ListPeersRequest, opts ...grpc.CallOption) (*ListPeersResponse, error) 485 | // Subscribe is used to subscribe to a topic and receive messages 486 | // Server will stream the messages received on the topic specified 487 | // during the initial subscription call, and send each message 488 | // back to the client as it is received. 489 | // 490 | // This is a server streaming rpc 491 | Subscribe(ctx context.Context, in *SubscribeRequest, opts ...grpc.CallOption) (PubSubService_SubscribeClient, error) 492 | // Publish is used to send a stream of messages to a pubsub topic. 493 | // 494 | // This is a client streaming rpc 495 | Publish(ctx context.Context, opts ...grpc.CallOption) (PubSubService_PublishClient, error) 496 | } 497 | 498 | type pubSubServiceClient struct { 499 | cc *grpc.ClientConn 500 | } 501 | 502 | func NewPubSubServiceClient(cc *grpc.ClientConn) PubSubServiceClient { 503 | return &pubSubServiceClient{cc} 504 | } 505 | 506 | func (c *pubSubServiceClient) GetTopics(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*TopicsResponse, error) { 507 | out := new(TopicsResponse) 508 | err := c.cc.Invoke(ctx, "/pb.PubSubService/GetTopics", in, out, opts...) 509 | if err != nil { 510 | return nil, err 511 | } 512 | return out, nil 513 | } 514 | 515 | func (c *pubSubServiceClient) ListPeers(ctx context.Context, in *ListPeersRequest, opts ...grpc.CallOption) (*ListPeersResponse, error) { 516 | out := new(ListPeersResponse) 517 | err := c.cc.Invoke(ctx, "/pb.PubSubService/ListPeers", in, out, opts...) 518 | if err != nil { 519 | return nil, err 520 | } 521 | return out, nil 522 | } 523 | 524 | func (c *pubSubServiceClient) Subscribe(ctx context.Context, in *SubscribeRequest, opts ...grpc.CallOption) (PubSubService_SubscribeClient, error) { 525 | stream, err := c.cc.NewStream(ctx, &_PubSubService_serviceDesc.Streams[0], "/pb.PubSubService/Subscribe", opts...) 526 | if err != nil { 527 | return nil, err 528 | } 529 | x := &pubSubServiceSubscribeClient{stream} 530 | if err := x.ClientStream.SendMsg(in); err != nil { 531 | return nil, err 532 | } 533 | if err := x.ClientStream.CloseSend(); err != nil { 534 | return nil, err 535 | } 536 | return x, nil 537 | } 538 | 539 | type PubSubService_SubscribeClient interface { 540 | Recv() (*PubSubMessageResponse, error) 541 | grpc.ClientStream 542 | } 543 | 544 | type pubSubServiceSubscribeClient struct { 545 | grpc.ClientStream 546 | } 547 | 548 | func (x *pubSubServiceSubscribeClient) Recv() (*PubSubMessageResponse, error) { 549 | m := new(PubSubMessageResponse) 550 | if err := x.ClientStream.RecvMsg(m); err != nil { 551 | return nil, err 552 | } 553 | return m, nil 554 | } 555 | 556 | func (c *pubSubServiceClient) Publish(ctx context.Context, opts ...grpc.CallOption) (PubSubService_PublishClient, error) { 557 | stream, err := c.cc.NewStream(ctx, &_PubSubService_serviceDesc.Streams[1], "/pb.PubSubService/Publish", opts...) 558 | if err != nil { 559 | return nil, err 560 | } 561 | x := &pubSubServicePublishClient{stream} 562 | return x, nil 563 | } 564 | 565 | type PubSubService_PublishClient interface { 566 | Send(*PublishRequest) error 567 | CloseAndRecv() (*Empty, error) 568 | grpc.ClientStream 569 | } 570 | 571 | type pubSubServicePublishClient struct { 572 | grpc.ClientStream 573 | } 574 | 575 | func (x *pubSubServicePublishClient) Send(m *PublishRequest) error { 576 | return x.ClientStream.SendMsg(m) 577 | } 578 | 579 | func (x *pubSubServicePublishClient) CloseAndRecv() (*Empty, error) { 580 | if err := x.ClientStream.CloseSend(); err != nil { 581 | return nil, err 582 | } 583 | m := new(Empty) 584 | if err := x.ClientStream.RecvMsg(m); err != nil { 585 | return nil, err 586 | } 587 | return m, nil 588 | } 589 | 590 | // PubSubServiceServer is the server API for PubSubService service. 591 | type PubSubServiceServer interface { 592 | // GetTopics is used to return a list of all 593 | // known topics the pubsub instance is subscribed to. 594 | // 595 | // This is a unary rpc 596 | GetTopics(context.Context, *Empty) (*TopicsResponse, error) 597 | // ListPeers is used to return a list of peers subscribed 598 | // to a given topic or topics. 599 | // 600 | // This is a unary rpc 601 | ListPeers(context.Context, *ListPeersRequest) (*ListPeersResponse, error) 602 | // Subscribe is used to subscribe to a topic and receive messages 603 | // Server will stream the messages received on the topic specified 604 | // during the initial subscription call, and send each message 605 | // back to the client as it is received. 606 | // 607 | // This is a server streaming rpc 608 | Subscribe(*SubscribeRequest, PubSubService_SubscribeServer) error 609 | // Publish is used to send a stream of messages to a pubsub topic. 610 | // 611 | // This is a client streaming rpc 612 | Publish(PubSubService_PublishServer) error 613 | } 614 | 615 | func RegisterPubSubServiceServer(s *grpc.Server, srv PubSubServiceServer) { 616 | s.RegisterService(&_PubSubService_serviceDesc, srv) 617 | } 618 | 619 | func _PubSubService_GetTopics_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 620 | in := new(Empty) 621 | if err := dec(in); err != nil { 622 | return nil, err 623 | } 624 | if interceptor == nil { 625 | return srv.(PubSubServiceServer).GetTopics(ctx, in) 626 | } 627 | info := &grpc.UnaryServerInfo{ 628 | Server: srv, 629 | FullMethod: "/pb.PubSubService/GetTopics", 630 | } 631 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 632 | return srv.(PubSubServiceServer).GetTopics(ctx, req.(*Empty)) 633 | } 634 | return interceptor(ctx, in, info, handler) 635 | } 636 | 637 | func _PubSubService_ListPeers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 638 | in := new(ListPeersRequest) 639 | if err := dec(in); err != nil { 640 | return nil, err 641 | } 642 | if interceptor == nil { 643 | return srv.(PubSubServiceServer).ListPeers(ctx, in) 644 | } 645 | info := &grpc.UnaryServerInfo{ 646 | Server: srv, 647 | FullMethod: "/pb.PubSubService/ListPeers", 648 | } 649 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 650 | return srv.(PubSubServiceServer).ListPeers(ctx, req.(*ListPeersRequest)) 651 | } 652 | return interceptor(ctx, in, info, handler) 653 | } 654 | 655 | func _PubSubService_Subscribe_Handler(srv interface{}, stream grpc.ServerStream) error { 656 | m := new(SubscribeRequest) 657 | if err := stream.RecvMsg(m); err != nil { 658 | return err 659 | } 660 | return srv.(PubSubServiceServer).Subscribe(m, &pubSubServiceSubscribeServer{stream}) 661 | } 662 | 663 | type PubSubService_SubscribeServer interface { 664 | Send(*PubSubMessageResponse) error 665 | grpc.ServerStream 666 | } 667 | 668 | type pubSubServiceSubscribeServer struct { 669 | grpc.ServerStream 670 | } 671 | 672 | func (x *pubSubServiceSubscribeServer) Send(m *PubSubMessageResponse) error { 673 | return x.ServerStream.SendMsg(m) 674 | } 675 | 676 | func _PubSubService_Publish_Handler(srv interface{}, stream grpc.ServerStream) error { 677 | return srv.(PubSubServiceServer).Publish(&pubSubServicePublishServer{stream}) 678 | } 679 | 680 | type PubSubService_PublishServer interface { 681 | SendAndClose(*Empty) error 682 | Recv() (*PublishRequest, error) 683 | grpc.ServerStream 684 | } 685 | 686 | type pubSubServicePublishServer struct { 687 | grpc.ServerStream 688 | } 689 | 690 | func (x *pubSubServicePublishServer) SendAndClose(m *Empty) error { 691 | return x.ServerStream.SendMsg(m) 692 | } 693 | 694 | func (x *pubSubServicePublishServer) Recv() (*PublishRequest, error) { 695 | m := new(PublishRequest) 696 | if err := x.ServerStream.RecvMsg(m); err != nil { 697 | return nil, err 698 | } 699 | return m, nil 700 | } 701 | 702 | var _PubSubService_serviceDesc = grpc.ServiceDesc{ 703 | ServiceName: "pb.PubSubService", 704 | HandlerType: (*PubSubServiceServer)(nil), 705 | Methods: []grpc.MethodDesc{ 706 | { 707 | MethodName: "GetTopics", 708 | Handler: _PubSubService_GetTopics_Handler, 709 | }, 710 | { 711 | MethodName: "ListPeers", 712 | Handler: _PubSubService_ListPeers_Handler, 713 | }, 714 | }, 715 | Streams: []grpc.StreamDesc{ 716 | { 717 | StreamName: "Subscribe", 718 | Handler: _PubSubService_Subscribe_Handler, 719 | ServerStreams: true, 720 | }, 721 | { 722 | StreamName: "Publish", 723 | Handler: _PubSubService_Publish_Handler, 724 | ClientStreams: true, 725 | }, 726 | }, 727 | Metadata: "pubsub.proto", 728 | } 729 | -------------------------------------------------------------------------------- /pb/pubsub.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package pb; 3 | 4 | // PubSubService is used to expose libp2p pubsub 5 | // access over a gRPC API for use with other applications 6 | // that may not want to deal with integration of libp2p pubsub 7 | service PubSubService { 8 | // GetTopics is used to return a list of all 9 | // known topics the pubsub instance is subscribed to. 10 | // 11 | // This is a unary rpc 12 | rpc GetTopics(Empty) returns (TopicsResponse) { }; 13 | 14 | // ListPeers is used to return a list of peers subscribed 15 | // to a given topic or topics. 16 | // 17 | // This is a unary rpc 18 | rpc ListPeers(ListPeersRequest) returns (ListPeersResponse) { }; 19 | 20 | // Subscribe is used to subscribe to a topic and receive messages 21 | // Server will stream the messages received on the topic specified 22 | // during the initial subscription call, and send each message 23 | // back to the client as it is received. 24 | // 25 | // This is a server streaming rpc 26 | rpc Subscribe(SubscribeRequest) returns (stream PubSubMessageResponse) { }; 27 | 28 | // Publish is used to send a stream of messages to a pubsub topic. 29 | // 30 | // This is a client streaming rpc 31 | rpc Publish(stream PublishRequest) returns (Empty) { }; 32 | } 33 | 34 | // Empty message is used for requests 35 | // and responses that dont need any particular 36 | // data. 37 | message Empty {} 38 | 39 | // ListPeersRequest is used to return a list of 40 | // peers that are subscribed to the given topic(s) 41 | message ListPeersRequest { 42 | // the topics for which we should 43 | // list peers for 44 | repeated string topics = 1; 45 | } 46 | 47 | // ListPeersResponse is a response to a ListPeersRequest 48 | message ListPeersResponse { 49 | message Peer { 50 | string topic = 1; 51 | string peerID = 2; 52 | } 53 | repeated Peer peers = 1; 54 | } 55 | 56 | // PublishRequest is a message used to publish data to a topic 57 | message PublishRequest { 58 | string topic = 1; 59 | bytes data = 2; 60 | bool advertise = 3; 61 | } 62 | 63 | // SubscribeRequest is used to initiate a subscription 64 | // to a given pubsub topic and stream received messages 65 | message SubscribeRequest { 66 | // the topic we should subscribe to 67 | string topic = 1; 68 | // indicates whether the server should 69 | // perform service discover for peers on the same topic 70 | bool discover = 2; 71 | } 72 | 73 | // Topics is a response that returns 74 | // the names of all known topics 75 | message TopicsResponse { 76 | repeated string names = 1; 77 | } 78 | 79 | // PubSubMessageResposne is a received pubsub message 80 | // sent as a response to a subscription rpc call 81 | message PubSubMessageResponse { 82 | bytes from = 1; 83 | bytes data = 2; 84 | bytes seqno = 3; 85 | repeated string topicIDs = 4; 86 | bytes signature = 5; 87 | bytes key = 6; 88 | } 89 | 90 | -------------------------------------------------------------------------------- /pubsubgrpc.go: -------------------------------------------------------------------------------- 1 | package pubsubgrpc 2 | 3 | import ( 4 | "context" 5 | "io" 6 | 7 | pb "github.com/RTradeLtd/go-libp2p-pubsub-grpc/pb" 8 | "github.com/libp2p/go-libp2p-core/host" 9 | discovery "github.com/libp2p/go-libp2p-discovery" 10 | ps "github.com/libp2p/go-libp2p-pubsub" 11 | "go.uber.org/zap" 12 | ) 13 | 14 | // Service is a libp2p pubsub service component 15 | type Service struct { 16 | ps *ps.PubSub 17 | sd *discovery.RoutingDiscovery 18 | h host.Host 19 | l *zap.SugaredLogger 20 | } 21 | 22 | // NewService creates and returns a new libp2p pubsub service 23 | func NewService( 24 | ps *ps.PubSub, 25 | sd *discovery.RoutingDiscovery, 26 | h host.Host, 27 | l *zap.SugaredLogger, 28 | ) Service { 29 | return Service{ 30 | ps: ps, 31 | sd: sd, 32 | h: h, 33 | l: l, 34 | } 35 | } 36 | 37 | // GetTopics is used to return a list of all known topics the pubsub instance is subscribed to. 38 | func (s *Service) GetTopics(ctx context.Context, req *pb.Empty) (*pb.TopicsResponse, error) { 39 | return &pb.TopicsResponse{Names: s.ps.GetTopics()}, nil 40 | } 41 | 42 | // ListPeers is used to return a list of peers subscribed to a given topic or topics 43 | func (s *Service) ListPeers(ctx context.Context, req *pb.ListPeersRequest) (*pb.ListPeersResponse, error) { 44 | var peers []*pb.ListPeersResponse_Peer 45 | for _, topic := range req.GetTopics() { 46 | pids := s.ps.ListPeers(topic) 47 | for _, pid := range pids { 48 | peers = append(peers, &pb.ListPeersResponse_Peer{Topic: topic, PeerID: pid.String()}) 49 | } 50 | } 51 | return &pb.ListPeersResponse{Peers: peers}, nil 52 | } 53 | 54 | // Subscribe is used to subscribe to a topic and receive messages 55 | func (s *Service) Subscribe(req *pb.SubscribeRequest, stream pb.PubSubService_SubscribeServer) error { 56 | sub, err := s.ps.Subscribe(req.GetTopic()) 57 | if err != nil { 58 | return err 59 | } 60 | // we're joining a pubsub room 61 | // so we should ensure that we're discovering 62 | // peers that are also on this room 63 | if req.GetDiscover() { 64 | go s.handleDiscover(stream.Context(), req.GetTopic()) 65 | } 66 | for { 67 | proto2Msg, err := sub.Next(stream.Context()) 68 | if err != nil { 69 | return err 70 | } 71 | if proto2Msg == nil { 72 | continue 73 | } 74 | // since libp2p-pubsub is using proto2 and we are using proto3 75 | // we need to copy fields, and format as needed 76 | proto3Msg := &pb.PubSubMessageResponse{ 77 | From: []byte(proto2Msg.GetFrom().String()), 78 | Data: proto2Msg.GetData(), 79 | Seqno: proto2Msg.GetSeqno(), 80 | TopicIDs: proto2Msg.GetTopicIDs(), 81 | Signature: proto2Msg.GetSignature(), 82 | Key: proto2Msg.GetKey(), 83 | } 84 | if err := stream.Send(proto3Msg); err != nil { 85 | return err 86 | } 87 | } 88 | } 89 | 90 | // Publish is used to send a stream of messages to a pubsub topic. 91 | func (s *Service) Publish(stream pb.PubSubService_PublishServer) error { 92 | // defer stream closure 93 | defer stream.SendAndClose(&pb.Empty{}) 94 | var sent = make(map[string]bool) 95 | for { 96 | msg, err := stream.Recv() 97 | if err != nil && err == io.EOF { 98 | return nil 99 | } else if err != nil { 100 | return err 101 | } 102 | // prevent multiple goroutines for the same topic 103 | // only advertise if specified 104 | if !sent[msg.GetTopic()] && msg.GetAdvertise() { 105 | sent[msg.GetTopic()] = true 106 | go s.handleAnnounce(stream.Context(), msg.GetTopic()) 107 | } 108 | if err := s.ps.Publish(msg.GetTopic(), msg.GetData()); err != nil { 109 | return err 110 | } 111 | } 112 | } 113 | 114 | func (s *Service) handleAnnounce(ctx context.Context, ns string) error { 115 | _, err := s.sd.Advertise(ctx, ns) 116 | return err 117 | } 118 | 119 | // handleDiscover is used to trigger discovery of 120 | // peers that are part of a particular pubsub room 121 | func (s *Service) handleDiscover(ctx context.Context, ns string) error { 122 | peerChan, err := s.sd.FindPeers(ctx, ns) 123 | if err != nil { 124 | return err 125 | } 126 | for peer := range peerChan { 127 | go s.h.Connect(ctx, peer) 128 | } 129 | return nil 130 | } 131 | -------------------------------------------------------------------------------- /pubsubgrpc_test.go: -------------------------------------------------------------------------------- 1 | package pubsubgrpc_test 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "io" 7 | "sync" 8 | "testing" 9 | "time" 10 | 11 | "github.com/RTradeLtd/go-libp2p-pubsub-grpc/pb" 12 | 13 | pubsubgrpc "github.com/RTradeLtd/go-libp2p-pubsub-grpc" 14 | testutils "github.com/RTradeLtd/go-libp2p-testutils" 15 | discovery "github.com/libp2p/go-libp2p-discovery" 16 | ps "github.com/libp2p/go-libp2p-pubsub" 17 | "github.com/multiformats/go-multiaddr" 18 | ) 19 | 20 | const ( 21 | serverAddr = "127.0.0.1:9090" 22 | serverProtocol = "tcp" 23 | ) 24 | 25 | func TestPubSubService(t *testing.T) { 26 | ctx, cancel := context.WithCancel(context.Background()) 27 | wg := &sync.WaitGroup{} 28 | logger := testutils.NewLogger(t) 29 | pk := testutils.NewPrivateKey(t) 30 | dstore := testutils.NewDatastore(t) 31 | pstore := testutils.NewPeerstore(t) 32 | addrs := []multiaddr.Multiaddr{testutils.NewMultiaddr(t)} 33 | host, dht := testutils.NewLibp2pHostAndDHT(ctx, t, logger.Desugar(), dstore, pstore, pk, addrs, nil) 34 | pubsub, err := ps.NewGossipSub(ctx, host) 35 | if err != nil { 36 | cancel() 37 | t.Fatal(err) 38 | } 39 | pubsubService := pubsubgrpc.NewService(pubsub, discovery.NewRoutingDiscovery(dht), host, logger) 40 | if err != nil { 41 | cancel() 42 | t.Fatal(err) 43 | } 44 | go func() { 45 | if err := pubsubgrpc.NewServer( 46 | ctx, wg, pubsubService, "tcp", serverAddr, 47 | ); err != nil { 48 | cancel() 49 | t.Fatal(err) 50 | } 51 | }() 52 | // wait for the gRPC server to spin up 53 | time.Sleep(time.Second * 5) 54 | client, err := pubsubgrpc.NewClient("", "", serverAddr) 55 | if err != nil { 56 | cancel() 57 | t.Fatal(err) 58 | } 59 | 60 | subStream, err := client.Subscribe(ctx, &pb.SubscribeRequest{Topic: "hello", Discover: true}) 61 | if err != nil { 62 | cancel() 63 | t.Fatal(err) 64 | } 65 | 66 | defer subStream.CloseSend() 67 | go func() { 68 | for { 69 | msg, err := subStream.Recv() 70 | if err != nil && err == io.EOF { 71 | return 72 | } else if err != nil { 73 | fmt.Println("got error", err.Error()) 74 | return 75 | } 76 | 77 | if msg.GetFrom() != nil { 78 | fmt.Println("from", string(msg.GetFrom())) 79 | } 80 | if msg.GetData() != nil { 81 | fmt.Println("data", string(msg.GetData())) 82 | } 83 | if msg.GetSeqno() != nil { 84 | fmt.Println("seqno", string(msg.GetSeqno())) 85 | } 86 | if msg.GetTopicIDs() != nil { 87 | fmt.Println("topicIDs", msg.GetTopicIDs()) 88 | } 89 | if msg.GetSignature() != nil { 90 | fmt.Println("signature", msg.GetSignature()) 91 | } 92 | if msg.GetKey() != nil { 93 | fmt.Println("key", msg.GetKey()) 94 | } 95 | } 96 | }() 97 | 98 | pubStream, err := client.Publish(ctx) 99 | if err != nil { 100 | cancel() 101 | t.Fatal(err) 102 | } 103 | 104 | if err := pubStream.Send(&pb.PublishRequest{Topic: "hello", Data: []byte("world"), Advertise: true}); err != nil { 105 | cancel() 106 | t.Fatal(err) 107 | } 108 | if _, err := pubStream.CloseAndRecv(); err != nil && err != io.EOF { 109 | cancel() 110 | t.Fatal(err) 111 | } 112 | if _, err := client.ListPeers(ctx, &pb.ListPeersRequest{Topics: []string{"hello"}}); err != nil { 113 | cancel() 114 | t.Fatal(err) 115 | } 116 | 117 | var foundHelloTopic bool 118 | resp, err := client.GetTopics(ctx, &pb.Empty{}) 119 | if err != nil { 120 | cancel() 121 | t.Fatal(err) 122 | } 123 | for _, topic := range resp.GetNames() { 124 | if topic == "hello" { 125 | foundHelloTopic = true 126 | break 127 | } 128 | } 129 | if !foundHelloTopic { 130 | cancel() 131 | t.Fatal("failed to find hello topic") 132 | } 133 | // we need to sleep to give enough time for our goroutine 134 | // that processes messages to have enough time to pick up the sent messages 135 | time.Sleep(time.Second * 15) 136 | // end publishing test 137 | client.Close() 138 | cancel() 139 | 140 | wg.Wait() 141 | } 142 | -------------------------------------------------------------------------------- /server.go: -------------------------------------------------------------------------------- 1 | package pubsubgrpc 2 | 3 | import ( 4 | "context" 5 | "net" 6 | 7 | "sync" 8 | 9 | "github.com/RTradeLtd/go-libp2p-pubsub-grpc/pb" 10 | "google.golang.org/grpc" 11 | ) 12 | 13 | // Server is used to run the libp2p pubsub grpc server 14 | // it enables communicating pubsub messages over grpc 15 | type Server struct { 16 | Service 17 | } 18 | 19 | // NewServer is used to intiialize a pubsub grpc server and run it 20 | func NewServer(ctx context.Context, wg *sync.WaitGroup, service Service, protocol, url string, serverOpts ...grpc.ServerOption) error { 21 | lis, err := net.Listen(protocol, url) 22 | if err != nil { 23 | return err 24 | } 25 | srv := &Server{service} 26 | gServer := grpc.NewServer(serverOpts...) 27 | pb.RegisterPubSubServiceServer(gServer, srv) 28 | wg.Add(1) 29 | go func() { 30 | defer wg.Done() 31 | select { 32 | case <-ctx.Done(): 33 | service.l.Info("shutting server down") 34 | gServer.GracefulStop() 35 | return 36 | } 37 | }() 38 | return gServer.Serve(lis) 39 | } 40 | --------------------------------------------------------------------------------