diff --git a/go.mod b/go.mod index e480afe..ce69ef7 100644 --- a/go.mod +++ b/go.mod @@ -8,14 +8,15 @@ require ( github.com/ipfs/go-ds-leveldb v0.4.1 github.com/ipfs/go-log v1.0.2 github.com/libp2p/go-buffer-pool v0.0.2 - github.com/libp2p/go-libp2p-core v0.3.0 + github.com/libp2p/go-libp2p-core v0.4.0 github.com/multiformats/go-base32 v0.0.3 - github.com/multiformats/go-multiaddr v0.2.0 + github.com/multiformats/go-multiaddr v0.2.1 github.com/multiformats/go-multiaddr-fmt v0.1.0 github.com/multiformats/go-multiaddr-net v0.1.2 github.com/multiformats/go-multihash v0.0.13 github.com/pkg/errors v0.9.1 github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 + golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5 // indirect ) go 1.13 diff --git a/go.sum b/go.sum index 98492f7..cc934e2 100644 --- a/go.sum +++ b/go.sum @@ -20,7 +20,6 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -32,7 +31,6 @@ github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4 github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= @@ -47,23 +45,16 @@ github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8l github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gxed/hashland/keccakpg v0.0.1 h1:wrk3uMNaMxbXiHibbPO4S0ymqJMm41WiudyFSs7UnsU= -github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU= -github.com/gxed/hashland/murmur3 v0.0.1 h1:SheiaIt0sda5K+8FLz952/1iWS9zrnKsEJaOJu4ZbSc= -github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/ipfs/go-cid v0.0.3 h1:UIAh32wymBpStoe83YCzwVQQ5Oy/H0FdxvUS6DJDzms= -github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= +github.com/ipfs/go-cid v0.0.5 h1:o0Ix8e/ql7Zb5UVUJEUfjsWCIY8t48++9lR8qi6oiJU= +github.com/ipfs/go-cid v0.0.5/go.mod h1:plgt+Y5MnOey4vO4UlUazGqdbEXuFYitED67FexhXog= github.com/ipfs/go-datastore v0.4.0/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= -github.com/ipfs/go-datastore v0.4.1 h1:W4ZfzyhNi3xmuU5dQhjfuRn/wFuqEE1KnOmmQiOevEY= github.com/ipfs/go-datastore v0.4.1/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= -github.com/ipfs/go-datastore v0.4.2 h1:h8/n7WPzhp239kkLws+epN3Ic7YtcBPgcaXfEfdVDWM= -github.com/ipfs/go-datastore v0.4.2/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= github.com/ipfs/go-datastore v0.4.4 h1:rjvQ9+muFaJ+QZ7dN5B1MSDNQ0JVZKkkES/rMZmA8X8= github.com/ipfs/go-datastore v0.4.4/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= github.com/ipfs/go-ds-badger v0.2.1 h1:RsC9DDlwFhFdfT+s2PeC8joxbSp2YMufK8w/RBOxKtk= @@ -71,14 +62,12 @@ github.com/ipfs/go-ds-badger v0.2.1/go.mod h1:Tx7l3aTph3FMFrRS838dcSJh+jjA7cX9Dr github.com/ipfs/go-ds-leveldb v0.4.1 h1:zaoLcP8zs4Aj9k8fA4cowyOyNBIvy9Dnt6hf7mHRY7s= github.com/ipfs/go-ds-leveldb v0.4.1/go.mod h1:jpbku/YqBSsBc1qgME8BkWS4AxzF2cEu1Ii2r79Hh9s= github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= -github.com/ipfs/go-log v0.0.1 h1:9XTUN/rW64BCG1YhPK9Hoy3q8nr4gOmHHBpgFdfw6Lc= github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM= github.com/ipfs/go-log v1.0.2 h1:s19ZwJxH8rPWzypjcDpqPLIyV7BnbLqvpli3iZoqYK0= github.com/ipfs/go-log v1.0.2/go.mod h1:1MNjMxe0u6xvJZgeqbJ8vdo2TKaGwZ1a0Bpza+sr2Sk= github.com/ipfs/go-log/v2 v2.0.2 h1:xguurydRdfKMJjKyxNXNU8lYP0VZH1NUwJRwUorjuEw= github.com/ipfs/go-log/v2 v2.0.2/go.mod h1:O7P1lJt27vWHhOwQmcFEvlmo49ry2VY2+JfBWFaa9+0= github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= -github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8 h1:bspPhN+oKYFk5fcGNuQzp6IGzYQSenLEgH3s6jkXrWw= github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8/go.mod h1:Ly/wlsjFq/qrU3Rar62tu1gASgGw6chQbSh/XgIIXCY= github.com/jbenet/goprocess v0.1.3 h1:YKyIEECS/XvcfHtBzxtjBBbWK+MbvA6dG8ASiqwvr10= github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= @@ -99,56 +88,45 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOSqcmlfs= github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= github.com/libp2p/go-flow-metrics v0.0.3/go.mod h1:HeoSNUrOJVK1jEpDqVEiUOIXqhbnS27omG0uWU5slZs= -github.com/libp2p/go-libp2p-core v0.3.0 h1:F7PqduvrztDtFsAa/bcheQ3azmNo+Nq7m8hQY5GiUW8= -github.com/libp2p/go-libp2p-core v0.3.0/go.mod h1:ACp3DmS3/N64c2jDzcV429ukDpicbL6+TrrxANBjPGw= +github.com/libp2p/go-libp2p-core v0.4.0 h1:LjZJP/Yy4q8kc724izkYQ9v6YkAmkKCOaE5jLv/NZRo= +github.com/libp2p/go-libp2p-core v0.4.0/go.mod h1:49XGI+kc38oGVwqSBhDEwytaAxgZasHhFfQKibzTls0= github.com/libp2p/go-openssl v0.0.4 h1:d27YZvLoTyMhIN4njrkr8zMDOM4lfpHIp6A+TK9fovg= github.com/libp2p/go-openssl v0.0.4/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329 h1:2gxZ0XQIU/5z3Z3bUBu+FXuk2pFbkN6tcwi/pjyaDic= github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= -github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16 h1:5W7KhL8HVF3XCFOweFD3BNESdnO8ewyYTFT2R+/b8FQ= -github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= github.com/minio/sha256-simd v0.1.1 h1:5QHSlgo3nt5yKOJrC7W8w7X+NFl8cMPZm96iu8kKUJU= github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= -github.com/mr-tron/base58 v1.1.2 h1:ZEw4I2EgPKDJ2iEw0cNmLB3ROrEmkOtXIkaG7wZg+78= github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mr-tron/base58 v1.1.3 h1:v+sk57XuaCKGXpWtVBX8YJzO7hMGx4Aajh4TQbdEFdc= github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/multiformats/go-base32 v0.0.3 h1:tw5+NhuwaOjJCC5Pp82QuXbrmLzWg7uxlMFp8Nq/kkI= github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= -github.com/multiformats/go-multiaddr v0.1.1 h1:rVAztJYMhCQ7vEFr8FvxW3mS+HF2eY/oPbOMeS0ZDnE= github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= -github.com/multiformats/go-multiaddr v0.2.0 h1:lR52sFwcTCuQb6bTfnXF6zA2XfyYvyd+5a9qECv/J90= github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4= +github.com/multiformats/go-multiaddr v0.2.1 h1:SgG/cw5vqyB5QQe5FPe2TqggU9WtrA9X4nZw7LlVqOI= +github.com/multiformats/go-multiaddr v0.2.1/go.mod h1:s/Apk6IyxfvMjDafnhJgJ3/46z7tZ04iMk5wP4QMGGE= github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= github.com/multiformats/go-multiaddr-net v0.1.2 h1:P7zcBH9FRETdPkDrylcXVjQLQ2t1JQtNItZULWNWgeg= github.com/multiformats/go-multiaddr-net v0.1.2/go.mod h1:QsWt3XK/3hwvNxZJp92iMQKME1qHfpYmyIjFVsSOY6Y= github.com/multiformats/go-multibase v0.0.1 h1:PN9/v21eLywrFWdFNsFKaU04kLJzuYzmrJR+ubhT9qA= github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= -github.com/multiformats/go-multihash v0.0.1 h1:HHwN1K12I+XllBCrqKnhX949Orn4oawPkegHMu2vDqQ= -github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= -github.com/multiformats/go-multihash v0.0.8 h1:wrYcW5yxSi3dU07n5jnuS5PrNwyHy0zRHGVoUugWvXg= github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= -github.com/multiformats/go-multihash v0.0.10 h1:lMoNbh2Ssd9PUF74Nz008KGzGPlfeV6wH3rit5IIGCM= -github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= github.com/multiformats/go-multihash v0.0.13 h1:06x+mk/zj1FoMsgNejLpy6QTvJqlSt/BhLEy87zidlc= github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= -github.com/multiformats/go-varint v0.0.1 h1:TR/0rdQtnNxuN2IhiB639xC3tWM4IUi7DkTBVTdGW/M= github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= +github.com/multiformats/go-varint v0.0.2/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/multiformats/go-varint v0.0.5 h1:XVZwSo04Cs3j/jS0uAEPpT3JY6DzMcVLLoWOSnCxOjg= github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -156,12 +134,10 @@ github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/opentracing/opentracing-go v1.0.2 h1:3jA2P6O1F9UOrWVpwrIo17pu01KWvNWg4X946/Y5Zwg= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -169,7 +145,6 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/smola/gocompat v0.2.0 h1:6b1oIMlUXIpz//VKEDzPVBK8KG7beVwmHIUEBIs/Pns= github.com/smola/gocompat v0.2.0/go.mod h1:1B0MlxbmoZNo3h8guHp8HztB3BSYR5itql9qtVc0ypY= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= @@ -185,7 +160,6 @@ github.com/src-d/envconfig v1.0.0/go.mod h1:Q9YQZ7BKITldTBnoxsE5gOeB5y66RyPXeue/ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -194,11 +168,10 @@ github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpP github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 h1:EKhdznlJHPMoKr0XTrX+IlJs1LH3lyx2nfr1dOlZ79k= github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc= -github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc h1:9lDbC6Rz4bwmou+oE6Dt4Cb2BGMur5eR/GYptkKUVHo= github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM= github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= @@ -208,7 +181,6 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 h1:1wopBVtVdWnn03fZelqdXTqk7U7zPQCb+T4rbU9ZEoU= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -220,15 +192,12 @@ golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190227160552-c95aed5357e7 h1:C2F/nMkR/9sfUTpvR3QrjBuTdvMUC/cFajkphs1YLQo= golang.org/x/net v0.0.0-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -237,15 +206,12 @@ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb h1:fgwFCsaw9buMuxNd6+DQfAuSFqbNiQZpcgJQAgJsK6k= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5 h1:LfCXLvNmTYH9kEmVgqbnsWfruoXZIrh4YBgqVHtDvw0= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= @@ -255,7 +221,6 @@ golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20181130052023-1c3d964395ce/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd h1:/e+gpKk9r3dJobndpTytxS2gOy6m5uvpg+ISQoEcusQ= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= @@ -265,7 +230,6 @@ google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRn google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -275,7 +239,6 @@ gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVY gopkg.in/src-d/go-log.v1 v1.0.1/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/pb/pstore.pb.go b/pb/pstore.pb.go index c3dbaeb..c7d9980 100644 --- a/pb/pstore.pb.go +++ b/pb/pstore.pb.go @@ -29,6 +29,8 @@ type AddrBookRecord struct { Id *ProtoPeerID `protobuf:"bytes,1,opt,name=id,proto3,customtype=ProtoPeerID" json:"id,omitempty"` // The multiaddresses. This is a sorted list where element 0 expires the soonest. Addrs []*AddrBookRecord_AddrEntry `protobuf:"bytes,2,rep,name=addrs,proto3" json:"addrs,omitempty"` + // The most recently received signed PeerRecord. + CertifiedRecord *AddrBookRecord_CertifiedRecord `protobuf:"bytes,3,opt,name=certified_record,json=certifiedRecord,proto3" json:"certified_record,omitempty"` } func (m *AddrBookRecord) Reset() { *m = AddrBookRecord{} } @@ -71,6 +73,13 @@ func (m *AddrBookRecord) GetAddrs() []*AddrBookRecord_AddrEntry { return nil } +func (m *AddrBookRecord) GetCertifiedRecord() *AddrBookRecord_CertifiedRecord { + if m != nil { + return m.CertifiedRecord + } + return nil +} + // AddrEntry represents a single multiaddress. type AddrBookRecord_AddrEntry struct { Addr *ProtoAddr `protobuf:"bytes,1,opt,name=addr,proto3,customtype=ProtoAddr" json:"addr,omitempty"` @@ -127,31 +136,93 @@ func (m *AddrBookRecord_AddrEntry) GetTtl() int64 { return 0 } +// CertifiedRecord contains a serialized signed PeerRecord used to +// populate the signedAddrs list. +type AddrBookRecord_CertifiedRecord struct { + // The Seq counter from the signed PeerRecord envelope + Seq uint64 `protobuf:"varint,1,opt,name=seq,proto3" json:"seq,omitempty"` + // The serialized bytes of the SignedEnvelope containing the PeerRecord. + Raw []byte `protobuf:"bytes,2,opt,name=raw,proto3" json:"raw,omitempty"` +} + +func (m *AddrBookRecord_CertifiedRecord) Reset() { *m = AddrBookRecord_CertifiedRecord{} } +func (m *AddrBookRecord_CertifiedRecord) String() string { return proto.CompactTextString(m) } +func (*AddrBookRecord_CertifiedRecord) ProtoMessage() {} +func (*AddrBookRecord_CertifiedRecord) Descriptor() ([]byte, []int) { + return fileDescriptor_f96873690e08a98f, []int{0, 1} +} +func (m *AddrBookRecord_CertifiedRecord) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *AddrBookRecord_CertifiedRecord) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_AddrBookRecord_CertifiedRecord.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *AddrBookRecord_CertifiedRecord) XXX_Merge(src proto.Message) { + xxx_messageInfo_AddrBookRecord_CertifiedRecord.Merge(m, src) +} +func (m *AddrBookRecord_CertifiedRecord) XXX_Size() int { + return m.Size() +} +func (m *AddrBookRecord_CertifiedRecord) XXX_DiscardUnknown() { + xxx_messageInfo_AddrBookRecord_CertifiedRecord.DiscardUnknown(m) +} + +var xxx_messageInfo_AddrBookRecord_CertifiedRecord proto.InternalMessageInfo + +func (m *AddrBookRecord_CertifiedRecord) GetSeq() uint64 { + if m != nil { + return m.Seq + } + return 0 +} + +func (m *AddrBookRecord_CertifiedRecord) GetRaw() []byte { + if m != nil { + return m.Raw + } + return nil +} + func init() { proto.RegisterType((*AddrBookRecord)(nil), "pstore.pb.AddrBookRecord") proto.RegisterType((*AddrBookRecord_AddrEntry)(nil), "pstore.pb.AddrBookRecord.AddrEntry") + proto.RegisterType((*AddrBookRecord_CertifiedRecord)(nil), "pstore.pb.AddrBookRecord.CertifiedRecord") } func init() { proto.RegisterFile("pstore.proto", fileDescriptor_f96873690e08a98f) } var fileDescriptor_f96873690e08a98f = []byte{ - // 255 bytes of a gzipped FileDescriptorProto + // 322 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x29, 0x28, 0x2e, 0xc9, 0x2f, 0x4a, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x84, 0xf1, 0x92, 0xa4, 0x74, 0xd3, 0x33, 0x4b, 0x32, 0x4a, 0x93, 0xf4, 0x92, 0xf3, 0x73, 0xf5, 0xd3, 0xf3, 0xd3, 0xf3, 0xf5, 0xc1, - 0x2a, 0x92, 0x4a, 0xd3, 0xc0, 0x3c, 0x30, 0x07, 0xcc, 0x82, 0xe8, 0x54, 0x3a, 0xc6, 0xc8, 0xc5, + 0x2a, 0x92, 0x4a, 0xd3, 0xc0, 0x3c, 0x30, 0x07, 0xcc, 0x82, 0xe8, 0x54, 0xba, 0xcc, 0xc4, 0xc5, 0xe7, 0x98, 0x92, 0x52, 0xe4, 0x94, 0x9f, 0x9f, 0x1d, 0x94, 0x9a, 0x9c, 0x5f, 0x94, 0x22, 0x24, 0xcf, 0xc5, 0x94, 0x99, 0x22, 0xc1, 0xa8, 0xc0, 0xa8, 0xc1, 0xe3, 0xc4, 0x7f, 0xeb, 0x9e, 0x3c, 0x77, 0x00, 0x48, 0x65, 0x40, 0x6a, 0x6a, 0x91, 0xa7, 0x4b, 0x10, 0x53, 0x66, 0x8a, 0x90, 0x25, 0x17, 0x6b, 0x62, 0x4a, 0x4a, 0x51, 0xb1, 0x04, 0x93, 0x02, 0xb3, 0x06, 0xb7, 0x91, 0xb2, 0x1e, - 0xdc, 0x76, 0x3d, 0x54, 0xa3, 0xc0, 0x5c, 0xd7, 0xbc, 0x92, 0xa2, 0xca, 0x20, 0x88, 0x0e, 0xa9, - 0x08, 0x2e, 0x4e, 0xb8, 0x98, 0x90, 0x22, 0x17, 0x0b, 0x48, 0x14, 0x6a, 0x15, 0xef, 0xad, 0x7b, - 0xf2, 0x9c, 0x60, 0xab, 0x40, 0x2a, 0x82, 0xc0, 0x52, 0x42, 0x62, 0x5c, 0x6c, 0xa9, 0x15, 0x05, - 0x99, 0x45, 0x95, 0x12, 0x4c, 0x0a, 0x8c, 0x1a, 0xcc, 0x41, 0x50, 0x9e, 0x90, 0x00, 0x17, 0x73, - 0x49, 0x49, 0x8e, 0x04, 0x33, 0x58, 0x10, 0xc4, 0x74, 0x52, 0xf8, 0xf1, 0x50, 0x8e, 0xf1, 0xc0, - 0x23, 0x39, 0xc6, 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x48, 0x8e, 0x71, - 0xc2, 0x63, 0x39, 0x86, 0x0b, 0x8f, 0xe5, 0x18, 0x6e, 0x3c, 0x96, 0x63, 0x48, 0x62, 0x03, 0xfb, - 0xd8, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0xb1, 0x1a, 0x16, 0x43, 0x3b, 0x01, 0x00, 0x00, + 0xdc, 0x76, 0x3d, 0x54, 0xa3, 0xc0, 0x5c, 0xd7, 0xbc, 0x92, 0xa2, 0xca, 0x20, 0x88, 0x0e, 0xa1, + 0x10, 0x2e, 0x81, 0xe4, 0xd4, 0xa2, 0x92, 0xcc, 0xb4, 0xcc, 0xd4, 0x94, 0xf8, 0x22, 0xb0, 0x22, + 0x09, 0x66, 0x05, 0x46, 0x0d, 0x6e, 0x23, 0x4d, 0xdc, 0xa6, 0x38, 0xc3, 0x74, 0x40, 0xf8, 0x41, + 0xfc, 0xc9, 0xa8, 0x02, 0x52, 0x11, 0x5c, 0x9c, 0x70, 0x9b, 0x84, 0x14, 0xb9, 0x58, 0x40, 0x76, + 0x41, 0x3d, 0xc0, 0x7b, 0xeb, 0x9e, 0x3c, 0x27, 0xd8, 0x03, 0x20, 0x15, 0x41, 0x60, 0x29, 0x21, + 0x31, 0x2e, 0xb6, 0xd4, 0x8a, 0x82, 0xcc, 0xa2, 0x4a, 0x09, 0x26, 0x05, 0x46, 0x0d, 0xe6, 0x20, + 0x28, 0x4f, 0x48, 0x80, 0x8b, 0xb9, 0xa4, 0x24, 0x07, 0xec, 0x20, 0xe6, 0x20, 0x10, 0x53, 0xca, + 0x94, 0x8b, 0x1f, 0xcd, 0x76, 0x90, 0xa2, 0xe2, 0xd4, 0x42, 0xb0, 0xf1, 0x2c, 0x41, 0x20, 0x26, + 0x48, 0xa4, 0x28, 0xb1, 0x1c, 0x6c, 0x16, 0x4f, 0x10, 0x88, 0xe9, 0xa4, 0xf0, 0xe3, 0xa1, 0x1c, + 0xe3, 0x81, 0x47, 0x72, 0x8c, 0x27, 0x1e, 0xc9, 0x31, 0x5e, 0x78, 0x24, 0xc7, 0xf8, 0xe0, 0x91, + 0x1c, 0xe3, 0x84, 0xc7, 0x72, 0x0c, 0x17, 0x1e, 0xcb, 0x31, 0xdc, 0x78, 0x2c, 0xc7, 0x90, 0xc4, + 0x06, 0x0e, 0x7e, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0x29, 0xcd, 0xe8, 0xd4, 0xc8, 0x01, + 0x00, 0x00, } func (m *AddrBookRecord) Marshal() (dAtA []byte, err error) { @@ -174,6 +245,18 @@ func (m *AddrBookRecord) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.CertifiedRecord != nil { + { + size, err := m.CertifiedRecord.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPstore(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } if len(m.Addrs) > 0 { for iNdEx := len(m.Addrs) - 1; iNdEx >= 0; iNdEx-- { { @@ -248,6 +331,41 @@ func (m *AddrBookRecord_AddrEntry) MarshalToSizedBuffer(dAtA []byte) (int, error return len(dAtA) - i, nil } +func (m *AddrBookRecord_CertifiedRecord) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *AddrBookRecord_CertifiedRecord) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *AddrBookRecord_CertifiedRecord) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Raw) > 0 { + i -= len(m.Raw) + copy(dAtA[i:], m.Raw) + i = encodeVarintPstore(dAtA, i, uint64(len(m.Raw))) + i-- + dAtA[i] = 0x12 + } + if m.Seq != 0 { + i = encodeVarintPstore(dAtA, i, uint64(m.Seq)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + func encodeVarintPstore(dAtA []byte, offset int, v uint64) int { offset -= sovPstore(v) base := offset @@ -269,6 +387,9 @@ func NewPopulatedAddrBookRecord(r randyPstore, easy bool) *AddrBookRecord { this.Addrs[i] = NewPopulatedAddrBookRecord_AddrEntry(r, easy) } } + if r.Intn(5) != 0 { + this.CertifiedRecord = NewPopulatedAddrBookRecord_CertifiedRecord(r, easy) + } if !easy && r.Intn(10) != 0 { } return this @@ -290,6 +411,19 @@ func NewPopulatedAddrBookRecord_AddrEntry(r randyPstore, easy bool) *AddrBookRec return this } +func NewPopulatedAddrBookRecord_CertifiedRecord(r randyPstore, easy bool) *AddrBookRecord_CertifiedRecord { + this := &AddrBookRecord_CertifiedRecord{} + this.Seq = uint64(uint64(r.Uint32())) + v2 := r.Intn(100) + this.Raw = make([]byte, v2) + for i := 0; i < v2; i++ { + this.Raw[i] = byte(r.Intn(256)) + } + if !easy && r.Intn(10) != 0 { + } + return this +} + type randyPstore interface { Float32() float32 Float64() float64 @@ -309,9 +443,9 @@ func randUTF8RunePstore(r randyPstore) rune { return rune(ru + 61) } func randStringPstore(r randyPstore) string { - v2 := r.Intn(100) - tmps := make([]rune, v2) - for i := 0; i < v2; i++ { + v3 := r.Intn(100) + tmps := make([]rune, v3) + for i := 0; i < v3; i++ { tmps[i] = randUTF8RunePstore(r) } return string(tmps) @@ -333,11 +467,11 @@ func randFieldPstore(dAtA []byte, r randyPstore, fieldNumber int, wire int) []by switch wire { case 0: dAtA = encodeVarintPopulatePstore(dAtA, uint64(key)) - v3 := r.Int63() + v4 := r.Int63() if r.Intn(2) == 0 { - v3 *= -1 + v4 *= -1 } - dAtA = encodeVarintPopulatePstore(dAtA, uint64(v3)) + dAtA = encodeVarintPopulatePstore(dAtA, uint64(v4)) case 1: dAtA = encodeVarintPopulatePstore(dAtA, uint64(key)) dAtA = append(dAtA, byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256))) @@ -378,6 +512,10 @@ func (m *AddrBookRecord) Size() (n int) { n += 1 + l + sovPstore(uint64(l)) } } + if m.CertifiedRecord != nil { + l = m.CertifiedRecord.Size() + n += 1 + l + sovPstore(uint64(l)) + } return n } @@ -400,6 +538,22 @@ func (m *AddrBookRecord_AddrEntry) Size() (n int) { return n } +func (m *AddrBookRecord_CertifiedRecord) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Seq != 0 { + n += 1 + sovPstore(uint64(m.Seq)) + } + l = len(m.Raw) + if l > 0 { + n += 1 + l + sovPstore(uint64(l)) + } + return n +} + func sovPstore(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -504,6 +658,42 @@ func (m *AddrBookRecord) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CertifiedRecord", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPstore + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPstore + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPstore + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.CertifiedRecord == nil { + m.CertifiedRecord = &AddrBookRecord_CertifiedRecord{} + } + if err := m.CertifiedRecord.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipPstore(dAtA[iNdEx:]) @@ -654,6 +844,112 @@ func (m *AddrBookRecord_AddrEntry) Unmarshal(dAtA []byte) error { } return nil } +func (m *AddrBookRecord_CertifiedRecord) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPstore + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: CertifiedRecord: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CertifiedRecord: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Seq", wireType) + } + m.Seq = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPstore + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Seq |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Raw", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPstore + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthPstore + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthPstore + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Raw = append(m.Raw[:0], dAtA[iNdEx:postIndex]...) + if m.Raw == nil { + m.Raw = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipPstore(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthPstore + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthPstore + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipPstore(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/pb/pstore.proto b/pb/pstore.proto index 3894534..0d1abd1 100644 --- a/pb/pstore.proto +++ b/pb/pstore.proto @@ -14,6 +14,9 @@ message AddrBookRecord { // The multiaddresses. This is a sorted list where element 0 expires the soonest. repeated AddrEntry addrs = 2; + // The most recently received signed PeerRecord. + CertifiedRecord certified_record = 3; + // AddrEntry represents a single multiaddress. message AddrEntry { bytes addr = 1 [(gogoproto.customtype) = "ProtoAddr"]; @@ -24,4 +27,14 @@ message AddrBookRecord { // The original TTL of this address. int64 ttl = 3; } + + // CertifiedRecord contains a serialized signed PeerRecord used to + // populate the signedAddrs list. + message CertifiedRecord { + // The Seq counter from the signed PeerRecord envelope + uint64 seq = 1; + + // The serialized bytes of the SignedEnvelope containing the PeerRecord. + bytes raw = 2; + } } diff --git a/pb/pstorepb_test.go b/pb/pstorepb_test.go index 3569d04..12d2980 100644 --- a/pb/pstorepb_test.go +++ b/pb/pstorepb_test.go @@ -98,6 +98,46 @@ func BenchmarkAddrBookRecord_AddrEntryProtoUnmarshal(b *testing.B) { b.SetBytes(int64(total / b.N)) } +func BenchmarkAddrBookRecord_CertifiedRecordProtoMarshal(b *testing.B) { + popr := math_rand.New(math_rand.NewSource(616)) + total := 0 + pops := make([]*AddrBookRecord_CertifiedRecord, 10000) + for i := 0; i < 10000; i++ { + pops[i] = NewPopulatedAddrBookRecord_CertifiedRecord(popr, false) + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + dAtA, err := github_com_gogo_protobuf_proto.Marshal(pops[i%10000]) + if err != nil { + panic(err) + } + total += len(dAtA) + } + b.SetBytes(int64(total / b.N)) +} + +func BenchmarkAddrBookRecord_CertifiedRecordProtoUnmarshal(b *testing.B) { + popr := math_rand.New(math_rand.NewSource(616)) + total := 0 + datas := make([][]byte, 10000) + for i := 0; i < 10000; i++ { + dAtA, err := github_com_gogo_protobuf_proto.Marshal(NewPopulatedAddrBookRecord_CertifiedRecord(popr, false)) + if err != nil { + panic(err) + } + datas[i] = dAtA + } + msg := &AddrBookRecord_CertifiedRecord{} + b.ResetTimer() + for i := 0; i < b.N; i++ { + total += len(datas[i%10000]) + if err := github_com_gogo_protobuf_proto.Unmarshal(datas[i%10000], msg); err != nil { + panic(err) + } + } + b.SetBytes(int64(total / b.N)) +} + func BenchmarkAddrBookRecordSize(b *testing.B) { popr := math_rand.New(math_rand.NewSource(616)) total := 0 @@ -126,4 +166,18 @@ func BenchmarkAddrBookRecord_AddrEntrySize(b *testing.B) { b.SetBytes(int64(total / b.N)) } +func BenchmarkAddrBookRecord_CertifiedRecordSize(b *testing.B) { + popr := math_rand.New(math_rand.NewSource(616)) + total := 0 + pops := make([]*AddrBookRecord_CertifiedRecord, 1000) + for i := 0; i < 1000; i++ { + pops[i] = NewPopulatedAddrBookRecord_CertifiedRecord(popr, false) + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + total += pops[i%1000].Size() + } + b.SetBytes(int64(total / b.N)) +} + //These tests are generated by github.com/gogo/protobuf/plugin/testgen diff --git a/peerstore.go b/peerstore.go index 3331b4a..278a5f8 100644 --- a/peerstore.go +++ b/peerstore.go @@ -21,6 +21,7 @@ type peerstore struct { // NewPeerstore creates a data structure that stores peer data, backed by the // supplied implementations of KeyBook, AddrBook and PeerMetadata. +// Deprecated: use pstoreds.NewPeerstore or peerstoremem.NewPeerstore instead. func NewPeerstore(kb pstore.KeyBook, ab pstore.AddrBook, pb pstore.ProtoBook, md pstore.PeerMetadata) pstore.Peerstore { return &peerstore{ KeyBook: kb, diff --git a/pstoreds/addr_book.go b/pstoreds/addr_book.go index 9e04283..12cb081 100644 --- a/pstoreds/addr_book.go +++ b/pstoreds/addr_book.go @@ -3,20 +3,21 @@ package pstoreds import ( "context" "fmt" + "github.com/libp2p/go-libp2p-core/record" "sort" "sync" "time" ds "github.com/ipfs/go-datastore" - query "github.com/ipfs/go-datastore/query" + "github.com/ipfs/go-datastore/query" logging "github.com/ipfs/go-log" - peer "github.com/libp2p/go-libp2p-core/peer" + "github.com/libp2p/go-libp2p-core/peer" pstore "github.com/libp2p/go-libp2p-core/peerstore" pb "github.com/libp2p/go-libp2p-peerstore/pb" - pstoremem "github.com/libp2p/go-libp2p-peerstore/pstoremem" + "github.com/libp2p/go-libp2p-peerstore/pstoremem" - lru "github.com/hashicorp/golang-lru" + "github.com/hashicorp/golang-lru" b32 "github.com/multiformats/go-base32" ma "github.com/multiformats/go-multiaddr" ) @@ -47,6 +48,7 @@ type addrsRecord struct { // marked for deletion, in which case we call ds.Delete. To be called within a lock. func (r *addrsRecord) flush(write ds.Write) (err error) { key := addrBookBase.ChildString(b32.RawStdEncoding.EncodeToString([]byte(r.Id.ID))) + if len(r.Addrs) == 0 { if err = write.Delete(key); err == nil { r.dirty = false @@ -83,37 +85,49 @@ func (r *addrsRecord) flush(write ds.Write) (err error) { // If the return value is true, the caller should perform a flush immediately to sync the record with the store. func (r *addrsRecord) clean() (chgd bool) { now := time.Now().Unix() - if !r.dirty && len(r.Addrs) > 0 && r.Addrs[0].Expiry > now { + addrsLen := len(r.Addrs) + + if !r.dirty && !r.hasExpiredAddrs(now) { // record is not dirty, and we have no expired entries to purge. return false } - if len(r.Addrs) == 0 { + if addrsLen == 0 { // this is a ghost record; let's signal it has to be written. // flush() will take care of doing the deletion. return true } - if r.dirty && len(r.Addrs) > 1 { - // the record has been modified, so it may need resorting. - // we keep addresses sorted by expiration, where 0 is the soonest expiring. + if r.dirty && addrsLen > 1 { sort.Slice(r.Addrs, func(i, j int) bool { return r.Addrs[i].Expiry < r.Addrs[j].Expiry }) } + r.Addrs = removeExpired(r.Addrs, now) + + return r.dirty || len(r.Addrs) != addrsLen +} + +func (r *addrsRecord) hasExpiredAddrs(now int64) bool { + if len(r.Addrs) > 0 && r.Addrs[0].Expiry <= now { + return true + } + return false +} + +func removeExpired(entries []*pb.AddrBookRecord_AddrEntry, now int64) []*pb.AddrBookRecord_AddrEntry { // since addresses are sorted by expiration, we find the first // survivor and split the slice on its index. pivot := -1 - for i, addr := range r.Addrs { + for i, addr := range entries { if addr.Expiry > now { break } pivot = i } - r.Addrs = r.Addrs[pivot+1:] - return r.dirty || pivot >= 0 + return entries[pivot+1:] } // dsAddrBook is an address book backed by a Datastore with a GC procedure to purge expired entries. It uses an @@ -133,6 +147,7 @@ type dsAddrBook struct { } var _ pstore.AddrBook = (*dsAddrBook)(nil) +var _ pstore.CertifiedAddrBook = (*dsAddrBook)(nil) // NewAddrBook initializes a new datastore-backed address book. It serves as a drop-in replacement for pstoremem // (memory-backed peerstore), and works with any datastore implementing the ds.Batching interface. @@ -240,7 +255,91 @@ func (ab *dsAddrBook) AddAddrs(p peer.ID, addrs []ma.Multiaddr, ttl time.Duratio return } addrs = cleanAddrs(addrs) - ab.setAddrs(p, addrs, ttl, ttlExtend) + ab.setAddrs(p, addrs, ttl, ttlExtend, false) +} + +// ConsumePeerRecord adds addresses from a signed peer.PeerRecord (contained in +// a record.Envelope), which will expire after the given TTL. +// See https://godoc.org/github.com/libp2p/go-libp2p-core/peerstore#CertifiedAddrBook for more details. +func (ab *dsAddrBook) ConsumePeerRecord(recordEnvelope *record.Envelope, ttl time.Duration) (bool, error) { + r, err := recordEnvelope.Record() + if err != nil { + return false, err + } + rec, ok := r.(*peer.PeerRecord) + if !ok { + return false, fmt.Errorf("envelope did not contain PeerRecord") + } + if !rec.PeerID.MatchesPublicKey(recordEnvelope.PublicKey) { + return false, fmt.Errorf("signing key does not match PeerID in PeerRecord") + } + + // ensure that the seq number from envelope is > any previously received seq no + if ab.latestPeerRecordSeq(rec.PeerID) >= rec.Seq { + return false, nil + } + + addrs := cleanAddrs(rec.Addrs) + err = ab.setAddrs(rec.PeerID, addrs, ttl, ttlExtend, true) + if err != nil { + return false, err + } + + err = ab.storeSignedPeerRecord(rec.PeerID, recordEnvelope, rec) + if err != nil { + return false, err + } + return true, nil +} + +func (ab *dsAddrBook) latestPeerRecordSeq(p peer.ID) uint64 { + pr, err := ab.loadRecord(p, true, false) + if err != nil || len(pr.Addrs) == 0 || pr.CertifiedRecord == nil || len(pr.CertifiedRecord.Raw) == 0 { + return 0 + } + return pr.CertifiedRecord.Seq +} + +func (ab *dsAddrBook) storeSignedPeerRecord(p peer.ID, envelope *record.Envelope, rec *peer.PeerRecord) error { + envelopeBytes, err := envelope.Marshal() + if err != nil { + return err + } + // reload record and add routing state + // this has to be done after we add the addresses, since if + // we try to flush a datastore record with no addresses, + // it will just get deleted + pr, err := ab.loadRecord(p, true, false) + if err != nil { + return err + } + pr.CertifiedRecord = &pb.AddrBookRecord_CertifiedRecord{ + Seq: rec.Seq, + Raw: envelopeBytes, + } + pr.dirty = true + err = pr.flush(ab.ds) + return err +} + +// GetPeerRecord returns a record.Envelope containing a peer.PeerRecord for the +// given peer id, if one exists. +// Returns nil if no signed PeerRecord exists for the peer. +func (ab *dsAddrBook) GetPeerRecord(p peer.ID) *record.Envelope { + pr, err := ab.loadRecord(p, true, false) + if err != nil { + log.Errorf("unable to load record for peer %s: %v", p.Pretty(), err) + return nil + } + if pr.CertifiedRecord == nil || len(pr.CertifiedRecord.Raw) == 0 || len(pr.Addrs) == 0 { + return nil + } + state, _, err := record.ConsumeEnvelope(pr.CertifiedRecord.Raw, peer.PeerRecordEnvelopeDomain) + if err != nil { + log.Errorf("error unmarshaling stored signed peer record for peer %s: %v", p.Pretty(), err) + return nil + } + return state } // SetAddr will add or update the TTL of an address in the AddrBook. @@ -255,7 +354,7 @@ func (ab *dsAddrBook) SetAddrs(p peer.ID, addrs []ma.Multiaddr, ttl time.Duratio ab.deleteAddrs(p, addrs) return } - ab.setAddrs(p, addrs, ttl, ttlOverride) + ab.setAddrs(p, addrs, ttl, ttlOverride, false) } // UpdateAddrs will update any addresses for a given peer and TTL combination to @@ -295,9 +394,9 @@ func (ab *dsAddrBook) Addrs(p peer.ID) []ma.Multiaddr { pr.RLock() defer pr.RUnlock() - addrs := make([]ma.Multiaddr, 0, len(pr.Addrs)) - for _, a := range pr.Addrs { - addrs = append(addrs, a.Addr) + addrs := make([]ma.Multiaddr, len(pr.Addrs)) + for i, a := range pr.Addrs { + addrs[i] = a.Addr } return addrs } @@ -330,7 +429,7 @@ func (ab *dsAddrBook) ClearAddrs(p peer.ID) { } } -func (ab *dsAddrBook) setAddrs(p peer.ID, addrs []ma.Multiaddr, ttl time.Duration, mode ttlWriteMode) (err error) { +func (ab *dsAddrBook) setAddrs(p peer.ID, addrs []ma.Multiaddr, ttl time.Duration, mode ttlWriteMode, signed bool) (err error) { pr, err := ab.loadRecord(p, true, false) if err != nil { return fmt.Errorf("failed to load peerstore entry for peer %v while setting addrs, err: %v", p, err) @@ -339,14 +438,19 @@ func (ab *dsAddrBook) setAddrs(p peer.ID, addrs []ma.Multiaddr, ttl time.Duratio pr.Lock() defer pr.Unlock() - newExp := time.Now().Add(ttl).Unix() - existed := make([]bool, len(addrs)) // keeps track of which addrs we found. + // // if we have a signed PeerRecord, ignore attempts to add unsigned addrs + // if !signed && pr.CertifiedRecord != nil { + // return nil + // } -Outer: - for i, incoming := range addrs { - for _, have := range pr.Addrs { + newExp := time.Now().Add(ttl).Unix() + // TODO this is very inefficient O(m*n); we could build a map to use as an + // index, and test against it. That would turn it into O(m+n). This code + // will be refactored entirely anyway, and it's not being used by users + // (that we know of); so OK to keep it for now. + updateExisting := func(entryList []*pb.AddrBookRecord_AddrEntry, incoming ma.Multiaddr) *pb.AddrBookRecord_AddrEntry { + for _, have := range entryList { if incoming.Equal(have.Addr) { - existed[i] = true switch mode { case ttlOverride: have.Ttl = int64(ttl) @@ -361,38 +465,73 @@ Outer: default: panic("BUG: unimplemented ttl mode") } - - // we found the address, and addresses cannot be duplicate, - // so let's move on to the next. - continue Outer + return have } } + return nil } - // add addresses we didn't hold. - var added []*pb.AddrBookRecord_AddrEntry - for i, e := range existed { - if e { - continue - } - addr := addrs[i] - entry := &pb.AddrBookRecord_AddrEntry{ - Addr: &pb.ProtoAddr{Multiaddr: addr}, - Ttl: int64(ttl), - Expiry: newExp, + var entries []*pb.AddrBookRecord_AddrEntry + for _, incoming := range addrs { + existingEntry := updateExisting(pr.Addrs, incoming) + + if existingEntry == nil { + // if signed { + // entries = append(entries, existingEntry) + // } + // } else { + // new addr, add & broadcast + entry := &pb.AddrBookRecord_AddrEntry{ + Addr: &pb.ProtoAddr{Multiaddr: incoming}, + Ttl: int64(ttl), + Expiry: newExp, + } + entries = append(entries, entry) + + // note: there's a minor chance that writing the record will fail, in which case we would've broadcast + // the addresses without persisting them. This is very unlikely and not much of an issue. + ab.subsManager.BroadcastAddr(p, incoming) } - added = append(added, entry) - // note: there's a minor chance that writing the record will fail, in which case we would've broadcast - // the addresses without persisting them. This is very unlikely and not much of an issue. - ab.subsManager.BroadcastAddr(p, addr) } - pr.Addrs = append(pr.Addrs, added...) + // if signed { + // // when adding signed addrs, we want to keep _only_ the incoming addrs + // pr.Addrs = entries + // } else { + pr.Addrs = append(pr.Addrs, entries...) + // } + pr.dirty = true pr.clean() return pr.flush(ab.ds) } +// deletes addresses in place, avoiding copies until we encounter the first deletion. +// does not preserve order, but entries are re-sorted before flushing to disk anyway. +func deleteInPlace(s []*pb.AddrBookRecord_AddrEntry, addrs []ma.Multiaddr) []*pb.AddrBookRecord_AddrEntry { + if s == nil || len(addrs) == 0 { + return s + } + survived := len(s) +Outer: + for i, addr := range s { + for _, del := range addrs { + if !addr.Addr.Equal(del) { + continue + } + survived-- + // if there are no survivors, bail out + if survived == 0 { + break Outer + } + s[i] = s[survived] + // we've already dealt with s[i], move to the next + continue Outer + } + } + return s[:survived] +} + func (ab *dsAddrBook) deleteAddrs(p peer.ID, addrs []ma.Multiaddr) (err error) { pr, err := ab.loadRecord(p, false, false) if err != nil { @@ -406,20 +545,7 @@ func (ab *dsAddrBook) deleteAddrs(p peer.ID, addrs []ma.Multiaddr) (err error) { pr.Lock() defer pr.Unlock() - // deletes addresses in place, and avoiding copies until we encounter the first deletion. - survived := 0 - for i, addr := range pr.Addrs { - for _, del := range addrs { - if addr.Addr.Equal(del) { - continue - } - if i != survived { - pr.Addrs[survived] = pr.Addrs[i] - } - survived++ - } - } - pr.Addrs = pr.Addrs[:survived] + pr.Addrs = deleteInPlace(pr.Addrs, addrs) pr.dirty = true pr.clean() diff --git a/pstoreds/keybook.go b/pstoreds/keybook.go index 64b73a3..35021b2 100644 --- a/pstoreds/keybook.go +++ b/pstoreds/keybook.go @@ -28,7 +28,7 @@ type dsKeyBook struct { var _ pstore.KeyBook = (*dsKeyBook)(nil) -func NewKeyBook(_ context.Context, store ds.Datastore, _ Options) (pstore.KeyBook, error) { +func NewKeyBook(_ context.Context, store ds.Datastore, _ Options) (*dsKeyBook, error) { return &dsKeyBook{store}, nil } diff --git a/pstoreds/metadata.go b/pstoreds/metadata.go index f54f382..4d285af 100644 --- a/pstoreds/metadata.go +++ b/pstoreds/metadata.go @@ -36,7 +36,7 @@ func init() { // See `init()` to learn which types are registered by default. Modules wishing to store // values of other types will need to `gob.Register()` them explicitly, or else callers // will receive runtime errors. -func NewPeerMetadata(_ context.Context, store ds.Datastore, _ Options) (pstore.PeerMetadata, error) { +func NewPeerMetadata(_ context.Context, store ds.Datastore, _ Options) (*dsPeerMetadata, error) { return &dsPeerMetadata{store}, nil } diff --git a/pstoreds/peerstore.go b/pstoreds/peerstore.go index 99b381d..3c8aa0f 100644 --- a/pstoreds/peerstore.go +++ b/pstoreds/peerstore.go @@ -2,6 +2,8 @@ package pstoreds import ( "context" + "fmt" + "io" "time" base32 "github.com/multiformats/go-base32" @@ -47,8 +49,17 @@ func DefaultOpts() Options { } } +type pstoreds struct { + peerstore.Metrics + + dsKeyBook + dsAddrBook + dsProtoBook + dsPeerMetadata +} + // NewPeerstore creates a peerstore backed by the provided persistent datastore. -func NewPeerstore(ctx context.Context, store ds.Batching, opts Options) (peerstore.Peerstore, error) { +func NewPeerstore(ctx context.Context, store ds.Batching, opts Options) (*pstoreds, error) { addrBook, err := NewAddrBook(ctx, store, opts) if err != nil { return nil, err @@ -66,7 +77,13 @@ func NewPeerstore(ctx context.Context, store ds.Batching, opts Options) (peersto protoBook := NewProtoBook(peerMetadata) - ps := pstore.NewPeerstore(keyBook, addrBook, protoBook, peerMetadata) + ps := &pstoreds{ + Metrics: pstore.NewMetrics(), + dsKeyBook: *keyBook, + dsAddrBook: *addrBook, + dsPeerMetadata: *peerMetadata, + dsProtoBook: *protoBook, + } return ps, nil } @@ -103,3 +120,47 @@ func uniquePeerIds(ds ds.Datastore, prefix ds.Key, extractor func(result query.R } return ids, nil } + +func (ps *pstoreds) Close() (err error) { + var errs []error + weakClose := func(name string, c interface{}) { + if cl, ok := c.(io.Closer); ok { + if err = cl.Close(); err != nil { + errs = append(errs, fmt.Errorf("%s error: %s", name, err)) + } + } + } + + weakClose("keybook", ps.dsKeyBook) + weakClose("addressbook", ps.dsAddrBook) + weakClose("protobook", ps.dsProtoBook) + weakClose("peermetadata", ps.dsPeerMetadata) + + if len(errs) > 0 { + return fmt.Errorf("failed while closing peerstore; err(s): %q", errs) + } + return nil +} + +func (ps *pstoreds) Peers() peer.IDSlice { + set := map[peer.ID]struct{}{} + for _, p := range ps.PeersWithKeys() { + set[p] = struct{}{} + } + for _, p := range ps.PeersWithAddrs() { + set[p] = struct{}{} + } + + pps := make(peer.IDSlice, 0, len(set)) + for p := range set { + pps = append(pps, p) + } + return pps +} + +func (ps *pstoreds) PeerInfo(p peer.ID) peer.AddrInfo { + return peer.AddrInfo{ + ID: p, + Addrs: ps.dsAddrBook.Addrs(p), + } +} diff --git a/pstoreds/protobook.go b/pstoreds/protobook.go index fc084d6..27e70f5 100644 --- a/pstoreds/protobook.go +++ b/pstoreds/protobook.go @@ -26,7 +26,7 @@ type dsProtoBook struct { var _ pstore.ProtoBook = (*dsProtoBook)(nil) -func NewProtoBook(meta pstore.PeerMetadata) pstore.ProtoBook { +func NewProtoBook(meta pstore.PeerMetadata) *dsProtoBook { return &dsProtoBook{ meta: meta, segments: func() (ret protoSegments) { diff --git a/pstoremem/addr_book.go b/pstoremem/addr_book.go index ec0b1c9..c0db4f5 100644 --- a/pstoremem/addr_book.go +++ b/pstoremem/addr_book.go @@ -2,16 +2,18 @@ package pstoremem import ( "context" + "fmt" "sort" "sync" "time" logging "github.com/ipfs/go-log" - peer "github.com/libp2p/go-libp2p-core/peer" + "github.com/libp2p/go-libp2p-core/peer" + pstore "github.com/libp2p/go-libp2p-core/peerstore" + "github.com/libp2p/go-libp2p-core/record" ma "github.com/multiformats/go-multiaddr" - pstore "github.com/libp2p/go-libp2p-core/peerstore" - addr "github.com/libp2p/go-libp2p-peerstore/addr" + "github.com/libp2p/go-libp2p-peerstore/addr" ) var log = logging.Logger("peerstore") @@ -26,6 +28,11 @@ func (e *expiringAddr) ExpiredBy(t time.Time) bool { return t.After(e.Expires) } +type peerRecordState struct { + Envelope *record.Envelope + Seq uint64 +} + type addrSegments [256]*addrSegment type addrSegment struct { @@ -35,10 +42,12 @@ type addrSegment struct { // space unused. storing the *values* directly in the map will // drastically increase the space waste. In our case, by 6x. addrs map[peer.ID]map[string]*expiringAddr + + signedPeerRecords map[peer.ID]*peerRecordState } -func (s *addrSegments) get(p peer.ID) *addrSegment { - return s[byte(p[len(p)-1])] +func (segments *addrSegments) get(p peer.ID) *addrSegment { + return segments[byte(p[len(p)-1])] } // memoryAddrBook manages addresses. @@ -52,14 +61,17 @@ type memoryAddrBook struct { } var _ pstore.AddrBook = (*memoryAddrBook)(nil) +var _ pstore.CertifiedAddrBook = (*memoryAddrBook)(nil) -func NewAddrBook() pstore.AddrBook { +func NewAddrBook() *memoryAddrBook { ctx, cancel := context.WithCancel(context.Background()) ab := &memoryAddrBook{ segments: func() (ret addrSegments) { for i, _ := range ret { - ret[i] = &addrSegment{addrs: make(map[peer.ID]map[string]*expiringAddr)} + ret[i] = &addrSegment{ + addrs: make(map[peer.ID]map[string]*expiringAddr), + signedPeerRecords: make(map[peer.ID]*peerRecordState)} } return ret }(), @@ -98,6 +110,7 @@ func (mab *memoryAddrBook) gc() { now := time.Now() for _, s := range mab.segments { s.Lock() + var collectedPeers []peer.ID for p, amap := range s.addrs { for k, addr := range amap { if addr.ExpiredBy(now) { @@ -106,23 +119,30 @@ func (mab *memoryAddrBook) gc() { } if len(amap) == 0 { delete(s.addrs, p) + collectedPeers = append(collectedPeers, p) } } + // remove signed records for peers whose signed addrs have all been removed + for _, p := range collectedPeers { + delete(s.signedPeerRecords, p) + } s.Unlock() } - } func (mab *memoryAddrBook) PeersWithAddrs() peer.IDSlice { - var pids peer.IDSlice + // deduplicate, since the same peer could have both signed & unsigned addrs + pidSet := peer.NewSet() for _, s := range mab.segments { s.RLock() - for pid, _ := range s.addrs { - pids = append(pids, pid) + for pid, amap := range s.addrs { + if amap != nil && len(amap) > 0 { + pidSet.Add(pid) + } } s.RUnlock() } - return pids + return pidSet.Peers() } // AddAddr calls AddAddrs(p, []ma.Multiaddr{addr}, ttl) @@ -134,6 +154,48 @@ func (mab *memoryAddrBook) AddAddr(p peer.ID, addr ma.Multiaddr, ttl time.Durati // (time-to-live), after which the address is no longer valid. // This function never reduces the TTL or expiration of an address. func (mab *memoryAddrBook) AddAddrs(p peer.ID, addrs []ma.Multiaddr, ttl time.Duration) { + // if we have a valid peer record, ignore unsigned addrs + // peerRec := mab.GetPeerRecord(p) + // if peerRec != nil { + // return + // } + mab.addAddrs(p, addrs, ttl, false) +} + +// ConsumePeerRecord adds addresses from a signed peer.PeerRecord (contained in +// a record.Envelope), which will expire after the given TTL. +// See https://godoc.org/github.com/libp2p/go-libp2p-core/peerstore#CertifiedAddrBook for more details. +func (mab *memoryAddrBook) ConsumePeerRecord(recordEnvelope *record.Envelope, ttl time.Duration) (bool, error) { + r, err := recordEnvelope.Record() + if err != nil { + return false, err + } + rec, ok := r.(*peer.PeerRecord) + if !ok { + return false, fmt.Errorf("unable to process envelope: not a PeerRecord") + } + if !rec.PeerID.MatchesPublicKey(recordEnvelope.PublicKey) { + return false, fmt.Errorf("signing key does not match PeerID in PeerRecord") + } + + // ensure seq is greater than last received + s := mab.segments.get(rec.PeerID) + s.Lock() + lastState, found := s.signedPeerRecords[rec.PeerID] + if found && lastState.Seq >= rec.Seq { + s.Unlock() + return false, nil + } + s.signedPeerRecords[rec.PeerID] = &peerRecordState{ + Envelope: recordEnvelope, + Seq: rec.Seq, + } + s.Unlock() // need to release the lock, since addAddrs will try to take it + mab.addAddrs(rec.PeerID, rec.Addrs, ttl, true) + return true, nil +} + +func (mab *memoryAddrBook) addAddrs(p peer.ID, addrs []ma.Multiaddr, ttl time.Duration, signed bool) { // if ttl is zero, exit. nothing to do. if ttl <= 0 { return @@ -143,26 +205,33 @@ func (mab *memoryAddrBook) AddAddrs(p peer.ID, addrs []ma.Multiaddr, ttl time.Du s.Lock() defer s.Unlock() - amap := s.addrs[p] - if amap == nil { - amap = make(map[string]*expiringAddr, len(addrs)) + amap, ok := s.addrs[p] + if !ok { + amap = make(map[string]*expiringAddr) s.addrs[p] = amap } + exp := time.Now().Add(ttl) + addrSet := make(map[string]struct{}, len(addrs)) for _, addr := range addrs { if addr == nil { log.Warnf("was passed nil multiaddr for %s", p) continue } - asBytes := addr.Bytes() - a, found := amap[string(asBytes)] // won't allocate. + k := string(addr.Bytes()) + addrSet[k] = struct{}{} + + // find the highest TTL and Expiry time between + // existing records and function args + a, found := amap[k] // won't allocate. + if !found { - // not found, save and announce it. - amap[string(asBytes)] = &expiringAddr{Addr: addr, Expires: exp, TTL: ttl} + // not found, announce it. + entry := &expiringAddr{Addr: addr, Expires: exp, TTL: ttl} + amap[k] = entry mab.subManager.BroadcastAddr(p, addr) } else { - // Update expiration/TTL independently. - // We never want to reduce either. + // update ttl & exp to whichever is greater between new and existing entry if ttl > a.TTL { a.TTL = ttl } @@ -171,6 +240,21 @@ func (mab *memoryAddrBook) AddAddrs(p peer.ID, addrs []ma.Multiaddr, ttl time.Du } } } + + // // when adding signed addrs, make sure only the addrs from the input list remain. + // if signed { + // for k := range amap { + // _, ok := addrSet[k] + // if !ok { + // delete(amap, k) + // } + // } + // } + + // if we've expired all the signed addresses for a peer, remove their signed routing state record + if len(addrs) == 0 { + delete(s.signedPeerRecords, p) + } } // SetAddr calls mgr.SetAddrs(p, addr, ttl) @@ -185,9 +269,9 @@ func (mab *memoryAddrBook) SetAddrs(p peer.ID, addrs []ma.Multiaddr, ttl time.Du s.Lock() defer s.Unlock() - amap := s.addrs[p] - if amap == nil { - amap = make(map[string]*expiringAddr, len(addrs)) + amap, ok := s.addrs[p] + if !ok { + amap = make(map[string]*expiringAddr) s.addrs[p] = amap } @@ -197,16 +281,22 @@ func (mab *memoryAddrBook) SetAddrs(p peer.ID, addrs []ma.Multiaddr, ttl time.Du log.Warnf("was passed nil multiaddr for %s", p) continue } + aBytes := addr.Bytes() + key := string(aBytes) // re-set all of them for new ttl. - aBytes := addr.Bytes() if ttl > 0 { - amap[string(aBytes)] = &expiringAddr{Addr: addr, Expires: exp, TTL: ttl} + amap[key] = &expiringAddr{Addr: addr, Expires: exp, TTL: ttl} mab.subManager.BroadcastAddr(p, addr) } else { - delete(amap, string(aBytes)) + delete(amap, key) } } + + // if we've expired all the signed addresses for a peer, remove their signed routing state record + if len(amap) == 0 { + delete(s.signedPeerRecords, p) + } } // UpdateAddrs updates the addresses associated with the given peer that have @@ -215,35 +305,39 @@ func (mab *memoryAddrBook) UpdateAddrs(p peer.ID, oldTTL time.Duration, newTTL t s := mab.segments.get(p) s.Lock() defer s.Unlock() - + exp := time.Now().Add(newTTL) amap, found := s.addrs[p] - if !found { - return + if found { + for k, a := range amap { + if oldTTL == a.TTL { + a.TTL = newTTL + a.Expires = exp + amap[k] = a + } + } } - exp := time.Now().Add(newTTL) - for k, addr := range amap { - if oldTTL == addr.TTL { - addr.TTL = newTTL - addr.Expires = exp - amap[k] = addr - } + // if we've expired all the signed addresses for a peer, remove their signed routing state record + if len(amap) == 0 { + delete(s.signedPeerRecords, p) } } -// Addresses returns all known (and valid) addresses for a given +// Addrs returns all known (and valid) addresses for a given peer func (mab *memoryAddrBook) Addrs(p peer.ID) []ma.Multiaddr { s := mab.segments.get(p) s.RLock() defer s.RUnlock() - amap, found := s.addrs[p] - if !found { - return nil - } + return validAddrs(s.addrs[p]) +} +func validAddrs(amap map[string]*expiringAddr) []ma.Multiaddr { now := time.Now() good := make([]ma.Multiaddr, 0, len(amap)) + if amap == nil { + return good + } for _, m := range amap { if !m.ExpiredBy(now) { good = append(good, m.Addr) @@ -253,6 +347,28 @@ func (mab *memoryAddrBook) Addrs(p peer.ID) []ma.Multiaddr { return good } +// GetPeerRecord returns a Envelope containing a PeerRecord for the +// given peer id, if one exists. +// Returns nil if no signed PeerRecord exists for the peer. +func (mab *memoryAddrBook) GetPeerRecord(p peer.ID) *record.Envelope { + s := mab.segments.get(p) + s.RLock() + defer s.RUnlock() + + // although the signed record gets garbage collected when all addrs inside it are expired, + // we may be in between the expiration time and the GC interval + // so, we check to see if we have any valid signed addrs before returning the record + if len(validAddrs(s.addrs[p])) == 0 { + return nil + } + + state := s.signedPeerRecords[p] + if state == nil { + return nil + } + return state.Envelope +} + // ClearAddrs removes all previously stored addresses func (mab *memoryAddrBook) ClearAddrs(p peer.ID) { s := mab.segments.get(p) @@ -260,6 +376,7 @@ func (mab *memoryAddrBook) ClearAddrs(p peer.ID) { defer s.Unlock() delete(s.addrs, p) + delete(s.signedPeerRecords, p) } // AddrStream returns a channel on which all new addresses discovered for a diff --git a/pstoremem/keybook.go b/pstoremem/keybook.go index f6ab84d..79f2550 100644 --- a/pstoremem/keybook.go +++ b/pstoremem/keybook.go @@ -19,7 +19,7 @@ type memoryKeyBook struct { var _ pstore.KeyBook = (*memoryKeyBook)(nil) // noop new, but in the future we may want to do some init work. -func NewKeyBook() pstore.KeyBook { +func NewKeyBook() *memoryKeyBook { return &memoryKeyBook{ pks: map[peer.ID]ic.PubKey{}, sks: map[peer.ID]ic.PrivKey{}, diff --git a/pstoremem/metadata.go b/pstoremem/metadata.go index 821c2b6..7ded769 100644 --- a/pstoremem/metadata.go +++ b/pstoremem/metadata.go @@ -27,7 +27,7 @@ type memoryPeerMetadata struct { var _ pstore.PeerMetadata = (*memoryPeerMetadata)(nil) -func NewPeerMetadata() pstore.PeerMetadata { +func NewPeerMetadata() *memoryPeerMetadata { return &memoryPeerMetadata{ ds: make(map[metakey]interface{}), interned: make(map[string]interface{}), diff --git a/pstoremem/peerstore.go b/pstoremem/peerstore.go index c7cbd67..f16887d 100644 --- a/pstoremem/peerstore.go +++ b/pstoremem/peerstore.go @@ -1,12 +1,73 @@ package pstoremem -import pstore "github.com/libp2p/go-libp2p-peerstore" +import ( + "fmt" + "github.com/libp2p/go-libp2p-core/peer" + "github.com/libp2p/go-libp2p-core/peerstore" + pstore "github.com/libp2p/go-libp2p-peerstore" + "io" +) + +type pstoremem struct { + peerstore.Metrics + + memoryKeyBook + memoryAddrBook + memoryProtoBook + memoryPeerMetadata +} // NewPeerstore creates an in-memory threadsafe collection of peers. -func NewPeerstore() pstore.Peerstore { - return pstore.NewPeerstore( - NewKeyBook(), - NewAddrBook(), - NewProtoBook(), - NewPeerMetadata()) +func NewPeerstore() *pstoremem { + return &pstoremem{ + Metrics: pstore.NewMetrics(), + memoryKeyBook: *NewKeyBook(), + memoryAddrBook: *NewAddrBook(), + memoryProtoBook: *NewProtoBook(), + memoryPeerMetadata: *NewPeerMetadata(), + } +} + +func (ps *pstoremem) Close() (err error) { + var errs []error + weakClose := func(name string, c interface{}) { + if cl, ok := c.(io.Closer); ok { + if err = cl.Close(); err != nil { + errs = append(errs, fmt.Errorf("%s error: %s", name, err)) + } + } + } + + weakClose("keybook", ps.memoryKeyBook) + weakClose("addressbook", ps.memoryAddrBook) + weakClose("protobook", ps.memoryProtoBook) + weakClose("peermetadata", ps.memoryPeerMetadata) + + if len(errs) > 0 { + return fmt.Errorf("failed while closing peerstore; err(s): %q", errs) + } + return nil +} + +func (ps *pstoremem) Peers() peer.IDSlice { + set := map[peer.ID]struct{}{} + for _, p := range ps.PeersWithKeys() { + set[p] = struct{}{} + } + for _, p := range ps.PeersWithAddrs() { + set[p] = struct{}{} + } + + pps := make(peer.IDSlice, 0, len(set)) + for p := range set { + pps = append(pps, p) + } + return pps +} + +func (ps *pstoremem) PeerInfo(p peer.ID) peer.AddrInfo { + return peer.AddrInfo{ + ID: p, + Addrs: ps.memoryAddrBook.Addrs(p), + } } diff --git a/pstoremem/protobook.go b/pstoremem/protobook.go index d627c6c..04d8ec4 100644 --- a/pstoremem/protobook.go +++ b/pstoremem/protobook.go @@ -28,7 +28,7 @@ type memoryProtoBook struct { var _ pstore.ProtoBook = (*memoryProtoBook)(nil) -func NewProtoBook() pstore.ProtoBook { +func NewProtoBook() *memoryProtoBook { return &memoryProtoBook{ interned: make(map[string]string, 256), segments: func() (ret protoSegments) { diff --git a/test/addr_book_suite.go b/test/addr_book_suite.go index ea6078c..f05a418 100644 --- a/test/addr_book_suite.go +++ b/test/addr_book_suite.go @@ -1,6 +1,11 @@ package test import ( + "github.com/libp2p/go-libp2p-core/crypto" + "github.com/libp2p/go-libp2p-core/peer" + "github.com/libp2p/go-libp2p-core/record" + "github.com/libp2p/go-libp2p-core/test" + "github.com/multiformats/go-multiaddr" "testing" "time" @@ -16,6 +21,7 @@ var addressBookSuite = map[string]func(book pstore.AddrBook) func(*testing.T){ "AddressesExpire": testAddressesExpire, "ClearWithIter": testClearWithIterator, "PeersWithAddresses": testPeersWithAddrs, + "CertifiedAddresses": testCertifiedAddresses, } type AddrBookFactory func() (pstore.AddrBook, func()) @@ -168,6 +174,30 @@ func testSetNegativeTTLClears(m pstore.AddrBook) func(t *testing.T) { survivors = append(survivors[0:74], survivors[75:]...) AssertAddressesEqual(t, survivors, m.Addrs(id)) + + // remove _all_ the addresses + m.SetAddrs(id, survivors, -1) + if len(m.Addrs(id)) != 0 { + t.Error("expected empty address list after clearing all addresses") + } + + // add half, but try to remove more than we added + m.SetAddrs(id, addrs[:50], time.Hour) + m.SetAddrs(id, addrs, -1) + if len(m.Addrs(id)) != 0 { + t.Error("expected empty address list after clearing all addresses") + } + + // try to remove the same addr multiple times + m.SetAddrs(id, addrs[:5], time.Hour) + repeated := make([]multiaddr.Multiaddr, 10) + for i := 0; i < len(repeated); i++ { + repeated[i] = addrs[0] + } + m.SetAddrs(id, repeated, -1) + if len(m.Addrs(id)) != 4 { + t.Errorf("expected 4 addrs after removing one, got %d", len(m.Addrs(id))) + } } } @@ -331,3 +361,113 @@ func testPeersWithAddrs(m pstore.AddrBook) func(t *testing.T) { }) } } + +func testCertifiedAddresses(m pstore.AddrBook) func(*testing.T) { + return func(t *testing.T) { + cab := m.(pstore.CertifiedAddrBook) + + priv, _, err := test.RandTestKeyPair(crypto.Ed25519, 256) + if err != nil { + t.Errorf("error generating testing keys: %v", err) + } + + id, _ := peer.IDFromPrivateKey(priv) + allAddrs := GenerateAddrs(10) + certifiedAddrs := allAddrs[:5] + uncertifiedAddrs := allAddrs[5:] + rec := peer.NewPeerRecord() + rec.PeerID = id + rec.Addrs = certifiedAddrs + signedRec, err := record.Seal(rec, priv) + if err != nil { + t.Errorf("error creating signed routing record: %v", err) + } + + // add a few non-certified addrs + m.AddAddrs(id, uncertifiedAddrs, time.Hour) + + // make sure they're present + AssertAddressesEqual(t, uncertifiedAddrs, m.Addrs(id)) + + // add the signed record to addr book + _, err = cab.ConsumePeerRecord(signedRec, time.Hour) + if err != nil { + t.Errorf("error adding signed routing record to addrbook: %v", err) + } + + // the non-certified addrs should be gone & we should get only certified addrs back from Addrs + // AssertAddressesEqual(t, certifiedAddrs, m.Addrs(id)) + AssertAddressesEqual(t, allAddrs, m.Addrs(id)) + + // PeersWithAddrs should return a single peer + if len(m.PeersWithAddrs()) != 1 { + t.Errorf("expected PeersWithAddrs to return 1, got %d", len(m.PeersWithAddrs())) + } + + // adding the same peer record again should result in the record being ignored + accepted, err := cab.ConsumePeerRecord(signedRec, time.Hour) + if accepted { + t.Error("Expected record with duplicate sequence number to be ignored") + } + if err != nil { + t.Errorf("Expected record with duplicate sequence number to be ignored without error, got err: %s", err) + } + + // once certified addrs exist, trying to add non-certified addrs should have no effect + // m.AddAddrs(id, uncertifiedAddrs, time.Hour) + // AssertAddressesEqual(t, certifiedAddrs, m.Addrs(id)) + m.AddAddrs(id, uncertifiedAddrs, time.Hour) + AssertAddressesEqual(t, allAddrs, m.Addrs(id)) + + // we should be able to retrieve the signed peer record + rec2 := cab.GetPeerRecord(id) + if rec2 == nil || !signedRec.Equal(rec2) { + t.Error("unable to retrieve signed routing record from addrbook") + } + + // Adding a new envelope should clear existing certified addresses. + // Only the newly-added ones should remain + certifiedAddrs = certifiedAddrs[:3] + rec = peer.NewPeerRecord() + rec.PeerID = id + rec.Addrs = certifiedAddrs + signedRec, err = record.Seal(rec, priv) + test.AssertNilError(t, err) + _, err = cab.ConsumePeerRecord(signedRec, time.Hour) + test.AssertNilError(t, err) + // AssertAddressesEqual(t, certifiedAddrs, m.Addrs(id)) + AssertAddressesEqual(t, allAddrs, m.Addrs(id)) + + // update TTL on signed addrs to -1 to remove them. + // the signed routing record should be deleted + // m.SetAddrs(id, certifiedAddrs, -1) + m.SetAddrs(id, allAddrs, -1) + if len(m.Addrs(id)) != 0 { + t.Error("expected zero certified addrs after setting TTL to -1") + } + if cab.GetPeerRecord(id) != nil { + t.Error("expected signed peer record to be removed when addresses expire") + } + + // Test that natural TTL expiration clears signed peer records + _, err = cab.ConsumePeerRecord(signedRec, time.Second) + test.AssertNilError(t, err) + AssertAddressesEqual(t, certifiedAddrs, m.Addrs(id)) + + time.Sleep(2 * time.Second) + if cab.GetPeerRecord(id) != nil { + t.Error("expected signed peer record to be removed when addresses expire") + } + + // adding a peer record that's signed with the wrong key should fail + priv2, _, err := test.RandTestKeyPair(crypto.Ed25519, 256) + test.AssertNilError(t, err) + env, err := record.Seal(rec, priv2) + test.AssertNilError(t, err) + + accepted, err = cab.ConsumePeerRecord(env, time.Second) + if accepted || err == nil { + t.Error("expected adding a PeerRecord that's signed with the wrong key to fail") + } + } +} diff --git a/test/peerstore_suite.go b/test/peerstore_suite.go index a0ae326..8a62962 100644 --- a/test/peerstore_suite.go +++ b/test/peerstore_suite.go @@ -23,6 +23,7 @@ var peerstoreSuite = map[string]func(pstore.Peerstore) func(*testing.T){ "PeerstoreProtoStore": testPeerstoreProtoStore, "BasicPeerstore": testBasicPeerstore, "Metadata": testMetadata, + "CertifiedAddrBook": testCertifiedAddrBook, } type PeerstoreFactory func() (pstore.Peerstore, func()) @@ -357,6 +358,15 @@ func testMetadata(ps pstore.Peerstore) func(t *testing.T) { } } +func testCertifiedAddrBook(ps pstore.Peerstore) func(*testing.T) { + return func(t *testing.T) { + _, ok := ps.(pstore.CertifiedAddrBook) + if !ok { + t.Error("expected peerstore to implement CertifiedAddrBook interface") + } + } +} + func getAddrs(t *testing.T, n int) []ma.Multiaddr { var addrs []ma.Multiaddr for i := 0; i < n; i++ {