mirror of
https://github.com/libp2p/go-libp2p-core.git
synced 2024-12-26 23:30:27 +08:00
Signed envelopes & routing records (#73)
* add SignedEnvelope type * use struct for SignedEnvelope instead of exposing protobuf directly * doc comments for envelopes * tests for SignedEnvelopes * add helpers to make routing records for Host * fix doc comment * go fmt * add method to peerstore to retrieve signed routing records * update to match spec changes * just use nanoseconds * use proto3 & rename fields to match spec changes * use proto3 for routing records * make envelope fields private & validate on unmarshal * use buffer pool for envelope signatures * tests for RoutingState * go fmt * rename Equals -> Equal, add some comments * use test helpers * get rid of unsigned RoutingState struct, only expose SignedRoutingState * rm batching SignedRoutingStates accessor in peerstore the datastore peerstore implementation doesn't support batched reads, so it's no more efficient to get a bunch of states at once than it is to call SignedRoutingState multiple times. * whitespace * expose struct fields & remove accessors * use camelCase in protos for consistency * use multiformats uvarint for length-prefixes * remove payloadType check when unmarhaling * rm stray ref to golang/protobuf * define CertifiedAddrBook to avoid breaking API change * add events for updated addresses and routing state * remove SignedRoutingStateFromHost helper moving this to go-libp2p * add routing state records, extend peerstore API * fix: rebuild protos with new gogofaster generator * filter private addrs from signed routing records * envelope: use byte slices from pool; adjust interface. * move envelope to record package. * move protobuf files; adjust imports everywhere. * rename RoutingStateRecord -> PeerRecord also removes embedded reference to Envelope from the record, as that was confusing. as a result, the CertifiedAddrBook now accepts/returns record.SignedEnvelope instead of a specialized type. * hoist Seq from PeerRecord to SignedEnvelope * test that PeerRecords can't be signed by wrong key * commit go.sum * add Seq field to envelope signature * fix proto_path in Makefile * fix import ordering * comments for PeerRecord proto message also removes the seq field from PeerMessage proto, since it was moved to the SignedEnvelope * use Record type for envelope payloads * rename SignedEnvelope -> Envelope, unmarshal payload in ConsumeEnvelope * return buffer to pool before early return * doc comments * rename CertifiedAddrBook methods, update comments * cache unmarshalled Record payload inside Envelope * doc comments * store reflect.Type when registering Record * Revert "return buffer to pool before early return"8d8da386f2
misread this - unsigned will be nil if there's an error, so it was right the way it was * use a DefaultRecord for unregistered PayloadTypes instead of returning an error if we don't have a registered Record for a given PayloadType, we can have a catch-all DefaultRecord type that just preserves the original payload as a []byte * cleanup DefaultRecord code a bit - removes unused error return from blankRecordForPayloadType - just references instead of copying in DefaultRecord.UnmarshalRecord I figure this is likely safe, since we'll be unmarshalling from the payload of an Envelope, which shouldn't get altered after it's created. * use explicit payloadType in MakeEnvelopeWithRecord * Revert DefaultRecord commitsae3bc7bdfb
a26c845a76
* doc comments * move Seq field back to PeerRecord * make diffs optional in EvtLocalAddressesUpdated * more envelope tests * replace MakeEnvelope with record.Seal also: - add Domain and Codec fields to Record interface * fix import * add interface check * rename ProcessPeerRecord -> ConsumePeerRecord also, adds bool `accepted` return value * rename event field, add doc comment * peer record protobuf: fix field casing. * record protobuf: add docs and fix casing. * cleanup: group imports. * nit: split test/utils.go => test/{addrs,errors}.go. Co-authored-by: Raúl Kripalani <raul.kripalani@gmail.com>
This commit is contained in:
parent
e075dc9f00
commit
7b2888dfdb
@ -4,7 +4,7 @@ GO = $(PB:.proto=.pb.go)
|
||||
all: $(GO)
|
||||
|
||||
%.pb.go: %.proto
|
||||
protoc --proto_path=$(GOPATH)/src:. --gogofaster_out=. $<
|
||||
protoc --proto_path=$(PWD)/../..:. --gogofaster_out=. $<
|
||||
|
||||
clean:
|
||||
rm -f *.pb.go
|
||||
|
@ -2,6 +2,8 @@ syntax = "proto2";
|
||||
|
||||
package crypto.pb;
|
||||
|
||||
option go_package = "github.com/libp2p/go-libp2p-core/crypto/pb";
|
||||
|
||||
enum KeyType {
|
||||
RSA = 0;
|
||||
Ed25519 = 1;
|
||||
|
82
event/addrs.go
Normal file
82
event/addrs.go
Normal file
@ -0,0 +1,82 @@
|
||||
package event
|
||||
|
||||
import (
|
||||
"github.com/libp2p/go-libp2p-core/record"
|
||||
ma "github.com/multiformats/go-multiaddr"
|
||||
)
|
||||
|
||||
// AddrAction represents an action taken on one of a Host's listen addresses.
|
||||
// It is used to add context to address change events in EvtLocalAddressesUpdated.
|
||||
type AddrAction int
|
||||
|
||||
const (
|
||||
// Unknown means that the event producer was unable to determine why the address
|
||||
// is in the current state.
|
||||
Unknown AddrAction = iota
|
||||
|
||||
// Added means that the address is new and was not present prior to the event.
|
||||
Added
|
||||
|
||||
// Maintained means that the address was not altered between the current and
|
||||
// previous states.
|
||||
Maintained
|
||||
|
||||
// Removed means that the address was removed from the Host.
|
||||
Removed
|
||||
)
|
||||
|
||||
// UpdatedAddress is used in the EvtLocalAddressesUpdated event to convey
|
||||
// address change information.
|
||||
type UpdatedAddress struct {
|
||||
// Address contains the address that was updated.
|
||||
Address ma.Multiaddr
|
||||
|
||||
// Action indicates what action was taken on the address during the
|
||||
// event. May be Unknown if the event producer cannot produce diffs.
|
||||
Action AddrAction
|
||||
}
|
||||
|
||||
// EvtLocalAddressesUpdated should be emitted when the set of listen addresses for
|
||||
// the local host changes. This may happen for a number of reasons. For example,
|
||||
// we may have opened a new relay connection, established a new NAT mapping via
|
||||
// UPnP, or been informed of our observed address by another peer.
|
||||
//
|
||||
// EvtLocalAddressesUpdated contains a snapshot of the current listen addresses,
|
||||
// and may also contain a diff between the current state and the previous state.
|
||||
// If the event producer is capable of creating a diff, the Diffs field will be
|
||||
// true, and event consumers can inspect the Action field of each UpdatedAddress
|
||||
// to see how each address was modified.
|
||||
//
|
||||
// For example, the Action will tell you whether an address in
|
||||
// the Current list was Added by the event producer, or was Maintained without
|
||||
// changes. Addresses that were removed from the Host will have the AddrAction
|
||||
// of Removed, and will be in the Removed list.
|
||||
//
|
||||
// If the event producer is not capable or producing diffs, the Diffs field will
|
||||
// be false, the Removed list will always be empty, and the Action for each
|
||||
// UpdatedAddress in the Current list will be Unknown.
|
||||
type EvtLocalAddressesUpdated struct {
|
||||
|
||||
// Diffs indicates whether this event contains a diff of the Host's previous
|
||||
// address set.
|
||||
Diffs bool
|
||||
|
||||
// Current contains all current listen addresses for the Host.
|
||||
// If Diffs == true, the Action field of each UpdatedAddress will tell
|
||||
// you whether an address was Added, or was Maintained from the previous
|
||||
// state.
|
||||
Current []UpdatedAddress
|
||||
|
||||
// Removed contains addresses that were removed from the Host.
|
||||
// This field is only set when Diffs == true.
|
||||
Removed []UpdatedAddress
|
||||
}
|
||||
|
||||
// EvtLocalPeerRoutingStateUpdated should be emitted when a new signed PeerRecord
|
||||
// for the local peer has been produced. This will happen whenever the set of listen
|
||||
// addresses changes.
|
||||
type EvtLocalPeerRecordUpdated struct {
|
||||
// Record contains the updated peer.PeerRecord, wrapped in a record.Envelope and
|
||||
// signed by the Host's private key.
|
||||
Record *record.Envelope
|
||||
}
|
2
go.mod
2
go.mod
@ -6,12 +6,14 @@ require (
|
||||
github.com/gogo/protobuf v1.3.1
|
||||
github.com/ipfs/go-cid v0.0.4
|
||||
github.com/jbenet/goprocess v0.1.3
|
||||
github.com/libp2p/go-buffer-pool v0.0.1
|
||||
github.com/libp2p/go-flow-metrics v0.0.3
|
||||
github.com/libp2p/go-openssl v0.0.4
|
||||
github.com/minio/sha256-simd v0.1.1
|
||||
github.com/mr-tron/base58 v1.1.3
|
||||
github.com/multiformats/go-multiaddr v0.2.0
|
||||
github.com/multiformats/go-multihash v0.0.13
|
||||
github.com/multiformats/go-varint v0.0.5
|
||||
github.com/smola/gocompat v0.2.0
|
||||
go.opencensus.io v0.22.2
|
||||
)
|
||||
|
51
go.sum
51
go.sum
@ -1,77 +1,54 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg=
|
||||
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
|
||||
github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw=
|
||||
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
|
||||
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo=
|
||||
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
|
||||
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d h1:yJzD/yFppdVCf6ApMkVy8cUxV0XrxdP9rVf6D87/Mng=
|
||||
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
|
||||
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw=
|
||||
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg=
|
||||
github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd h1:qdGvebPBDuYDPGi1WCPjy1tGyMpmDK8IEapSsszn7HE=
|
||||
github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY=
|
||||
github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723 h1:ZA/jbKoGcVAnER6pCHPEkGdZOV7U1oLUedErBHCUMs0=
|
||||
github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=
|
||||
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc=
|
||||
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
|
||||
github.com/btcsuite/winsvc v1.0.0 h1:J9B4L7e3oqhXOcm+2IuNApwzQec85lE+QaikUcCs+dk=
|
||||
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495 h1:6IyqGr3fnd0tM3YxipK27TUskaOVUjU2nG45yzwcQKY=
|
||||
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
|
||||
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
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/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/ipfs/go-cid v0.0.3 h1:UIAh32wymBpStoe83YCzwVQQ5Oy/H0FdxvUS6DJDzms=
|
||||
github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
|
||||
github.com/ipfs/go-cid v0.0.4 h1:UlfXKrZx1DjZoBhQHmNHLC1fK1dUJDN20Y28A7s+gJ8=
|
||||
github.com/ipfs/go-cid v0.0.4/go.mod h1:4LLaPOQwmk5z9LBgQnpkivrx8BJjUyGwTXCd5Xfj6+M=
|
||||
github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA=
|
||||
github.com/jbenet/goprocess v0.1.3 h1:YKyIEECS/XvcfHtBzxtjBBbWK+MbvA6dG8ASiqwvr10=
|
||||
github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4=
|
||||
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89 h1:12K8AlpT0/6QUXSfV0yi4Q0jkbq8NDtIKFtF61AoqV0=
|
||||
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI=
|
||||
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
|
||||
github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0=
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 h1:FOOIBWrEkLgmlgGfMuZT83xIwfPDxEI2OHu6xUmJMFE=
|
||||
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/libp2p/go-buffer-pool v0.0.1 h1:9Rrn/H46cXjaA2HQ5Y8lyhOS1NhTkZ4yuEs2r3Eechg=
|
||||
github.com/libp2p/go-buffer-pool v0.0.1/go.mod h1:xtyIz9PMobb13WaxR6Zo1Pd1zXJKYg0a8KiIvDp3TzQ=
|
||||
github.com/libp2p/go-flow-metrics v0.0.3 h1:8tAs/hSdNvUiLgtlSy3mxwxWP4I9y/jlkPFT7epKdeM=
|
||||
github.com/libp2p/go-flow-metrics v0.0.3/go.mod h1:HeoSNUrOJVK1jEpDqVEiUOIXqhbnS27omG0uWU5slZs=
|
||||
github.com/libp2p/go-openssl v0.0.4 h1:d27YZvLoTyMhIN4njrkr8zMDOM4lfpHIp6A+TK9fovg=
|
||||
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/libp2p/go-openssl v0.0.4/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc=
|
||||
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=
|
||||
@ -83,27 +60,24 @@ github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1f
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||
github.com/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/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.2 h1:HWYHNSyyllbQopmVIF5K7JKJugiah+L9/kuZKHbmNdQ=
|
||||
github.com/multiformats/go-multiaddr v0.1.2/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4=
|
||||
github.com/multiformats/go-multiaddr v0.1.0/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44=
|
||||
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-net v0.1.1 h1:jFFKUuXTXv+3ARyHZi3XUqQO+YWMKgBdhEvuGRfnL6s=
|
||||
github.com/multiformats/go-multiaddr-net v0.1.1/go.mod h1:5JNbcfBOP4dnhoZOv10JJVkJO0pCCEf8mTnipAo2UZQ=
|
||||
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=
|
||||
@ -116,13 +90,11 @@ github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXS
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo=
|
||||
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=
|
||||
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
||||
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
@ -130,9 +102,7 @@ github.com/src-d/envconfig v1.0.0 h1:/AJi6DtjFhZKNx3OB2qMsq7y4yT5//AeSZIe7rk+PX8
|
||||
github.com/src-d/envconfig v1.0.0/go.mod h1:Q9YQZ7BKITldTBnoxsE5gOeB5y66RyPXeue/R4aaNBc=
|
||||
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 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/x-cray/logrus-prefixed-formatter v0.5.2 h1:00txxvfBM9muc0jiLIEAkAcIMJzfthRT6usrui8uGmg=
|
||||
github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE=
|
||||
@ -141,8 +111,6 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
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-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-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=
|
||||
@ -154,9 +122,7 @@ 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-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
|
||||
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/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
@ -167,9 +133,7 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190219092855-153ac476189d h1:Z0Ahzd7HltpJtjAHHxX8QFP3j1yYgiuvjbjRzDj/KH0=
|
||||
golang.org/x/sys v0.0.0-20190219092855-153ac476189d/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=
|
||||
@ -180,7 +144,6 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
|
||||
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181130052023-1c3d964395ce/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c h1:vamGzbGri8IKo20MQncCuljcQ5uAO6kaCeawQPVblAI=
|
||||
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=
|
||||
@ -190,9 +153,7 @@ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoA
|
||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
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 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
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/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d h1:mXa4inJUuWOoA4uEROxtJ3VMELMlVkIxIfcR0HBekAM=
|
||||
@ -200,8 +161,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 h1:heWvX7J6qbGWbeFS/aRmiy1eYaT+QMV6wNvHDyMjQV4=
|
||||
gopkg.in/src-d/go-log.v1 v1.0.1/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE=
|
||||
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=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
11
peer/pb/Makefile
Normal file
11
peer/pb/Makefile
Normal file
@ -0,0 +1,11 @@
|
||||
PB = $(wildcard *.proto)
|
||||
GO = $(PB:.proto=.pb.go)
|
||||
|
||||
all: $(GO)
|
||||
|
||||
%.pb.go: %.proto
|
||||
protoc --proto_path=$(PWD):$(PWD)/../.. --gogofaster_out=. $<
|
||||
|
||||
clean:
|
||||
rm -f *.pb.go
|
||||
rm -f *.go
|
606
peer/pb/peer_record.pb.go
Normal file
606
peer/pb/peer_record.pb.go
Normal file
@ -0,0 +1,606 @@
|
||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: peer_record.proto
|
||||
|
||||
package peer_pb
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
io "io"
|
||||
math "math"
|
||||
math_bits "math/bits"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
// PeerRecord messages contain information that is useful to share with other peers.
|
||||
// Currently, a PeerRecord contains the public listen addresses for a peer, but this
|
||||
// is expected to expand to include other information in the future.
|
||||
//
|
||||
// PeerRecords are designed to be serialized to bytes and placed inside of
|
||||
// SignedEnvelopes before sharing with other peers.
|
||||
// See https://github.com/libp2p/go-libp2p-core/record/pb/envelope.proto for
|
||||
// the SignedEnvelope definition.
|
||||
type PeerRecord struct {
|
||||
// peer_id contains a libp2p peer id in its binary representation.
|
||||
PeerId []byte `protobuf:"bytes,1,opt,name=peer_id,json=peerId,proto3" json:"peer_id,omitempty"`
|
||||
// seq contains a monotonically-increasing sequence counter to order PeerRecords in time.
|
||||
Seq uint64 `protobuf:"varint,2,opt,name=seq,proto3" json:"seq,omitempty"`
|
||||
// addresses is a list of public listen addresses for the peer.
|
||||
Addresses []*PeerRecord_AddressInfo `protobuf:"bytes,3,rep,name=addresses,proto3" json:"addresses,omitempty"`
|
||||
}
|
||||
|
||||
func (m *PeerRecord) Reset() { *m = PeerRecord{} }
|
||||
func (m *PeerRecord) String() string { return proto.CompactTextString(m) }
|
||||
func (*PeerRecord) ProtoMessage() {}
|
||||
func (*PeerRecord) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_dc0d8059ab0ad14d, []int{0}
|
||||
}
|
||||
func (m *PeerRecord) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *PeerRecord) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_PeerRecord.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 *PeerRecord) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_PeerRecord.Merge(m, src)
|
||||
}
|
||||
func (m *PeerRecord) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *PeerRecord) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_PeerRecord.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_PeerRecord proto.InternalMessageInfo
|
||||
|
||||
func (m *PeerRecord) GetPeerId() []byte {
|
||||
if m != nil {
|
||||
return m.PeerId
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *PeerRecord) GetSeq() uint64 {
|
||||
if m != nil {
|
||||
return m.Seq
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *PeerRecord) GetAddresses() []*PeerRecord_AddressInfo {
|
||||
if m != nil {
|
||||
return m.Addresses
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddressInfo is a wrapper around a binary multiaddr. It is defined as a
|
||||
// separate message to allow us to add per-address metadata in the future.
|
||||
type PeerRecord_AddressInfo struct {
|
||||
Multiaddr []byte `protobuf:"bytes,1,opt,name=multiaddr,proto3" json:"multiaddr,omitempty"`
|
||||
}
|
||||
|
||||
func (m *PeerRecord_AddressInfo) Reset() { *m = PeerRecord_AddressInfo{} }
|
||||
func (m *PeerRecord_AddressInfo) String() string { return proto.CompactTextString(m) }
|
||||
func (*PeerRecord_AddressInfo) ProtoMessage() {}
|
||||
func (*PeerRecord_AddressInfo) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_dc0d8059ab0ad14d, []int{0, 0}
|
||||
}
|
||||
func (m *PeerRecord_AddressInfo) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *PeerRecord_AddressInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_PeerRecord_AddressInfo.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 *PeerRecord_AddressInfo) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_PeerRecord_AddressInfo.Merge(m, src)
|
||||
}
|
||||
func (m *PeerRecord_AddressInfo) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *PeerRecord_AddressInfo) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_PeerRecord_AddressInfo.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_PeerRecord_AddressInfo proto.InternalMessageInfo
|
||||
|
||||
func (m *PeerRecord_AddressInfo) GetMultiaddr() []byte {
|
||||
if m != nil {
|
||||
return m.Multiaddr
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*PeerRecord)(nil), "peer.pb.PeerRecord")
|
||||
proto.RegisterType((*PeerRecord_AddressInfo)(nil), "peer.pb.PeerRecord.AddressInfo")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("peer_record.proto", fileDescriptor_dc0d8059ab0ad14d) }
|
||||
|
||||
var fileDescriptor_dc0d8059ab0ad14d = []byte{
|
||||
// 189 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x2c, 0x48, 0x4d, 0x2d,
|
||||
0x8a, 0x2f, 0x4a, 0x4d, 0xce, 0x2f, 0x4a, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x07,
|
||||
0x09, 0xe9, 0x15, 0x24, 0x29, 0x2d, 0x66, 0xe4, 0xe2, 0x0a, 0x48, 0x4d, 0x2d, 0x0a, 0x02, 0xcb,
|
||||
0x0a, 0x89, 0x73, 0x81, 0x65, 0xe2, 0x33, 0x53, 0x24, 0x18, 0x15, 0x18, 0x35, 0x78, 0x82, 0xd8,
|
||||
0x40, 0x5c, 0xcf, 0x14, 0x21, 0x01, 0x2e, 0xe6, 0xe2, 0xd4, 0x42, 0x09, 0x26, 0x05, 0x46, 0x0d,
|
||||
0x96, 0x20, 0x10, 0x53, 0xc8, 0x96, 0x8b, 0x33, 0x31, 0x25, 0xa5, 0x28, 0xb5, 0xb8, 0x38, 0xb5,
|
||||
0x58, 0x82, 0x59, 0x81, 0x59, 0x83, 0xdb, 0x48, 0x5e, 0x0f, 0x6a, 0xac, 0x1e, 0xc2, 0x48, 0x3d,
|
||||
0x47, 0x88, 0x22, 0xcf, 0xbc, 0xb4, 0xfc, 0x20, 0x84, 0x0e, 0x29, 0x6d, 0x2e, 0x6e, 0x24, 0x19,
|
||||
0x21, 0x19, 0x2e, 0xce, 0xdc, 0xd2, 0x9c, 0x92, 0x4c, 0x90, 0x02, 0xa8, 0xd5, 0x08, 0x01, 0x27,
|
||||
0x89, 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, 0xc7, 0x18,
|
||||
0x10, 0x00, 0x00, 0xff, 0xff, 0xcb, 0x99, 0x56, 0x19, 0xe4, 0x00, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *PeerRecord) 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 *PeerRecord) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.Size()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *PeerRecord) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Addresses) > 0 {
|
||||
for iNdEx := len(m.Addresses) - 1; iNdEx >= 0; iNdEx-- {
|
||||
{
|
||||
size, err := m.Addresses[iNdEx].MarshalToSizedBuffer(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = encodeVarintPeerRecord(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x1a
|
||||
}
|
||||
}
|
||||
if m.Seq != 0 {
|
||||
i = encodeVarintPeerRecord(dAtA, i, uint64(m.Seq))
|
||||
i--
|
||||
dAtA[i] = 0x10
|
||||
}
|
||||
if len(m.PeerId) > 0 {
|
||||
i -= len(m.PeerId)
|
||||
copy(dAtA[i:], m.PeerId)
|
||||
i = encodeVarintPeerRecord(dAtA, i, uint64(len(m.PeerId)))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *PeerRecord_AddressInfo) 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 *PeerRecord_AddressInfo) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.Size()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *PeerRecord_AddressInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Multiaddr) > 0 {
|
||||
i -= len(m.Multiaddr)
|
||||
copy(dAtA[i:], m.Multiaddr)
|
||||
i = encodeVarintPeerRecord(dAtA, i, uint64(len(m.Multiaddr)))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func encodeVarintPeerRecord(dAtA []byte, offset int, v uint64) int {
|
||||
offset -= sovPeerRecord(v)
|
||||
base := offset
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return base
|
||||
}
|
||||
func (m *PeerRecord) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
l = len(m.PeerId)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovPeerRecord(uint64(l))
|
||||
}
|
||||
if m.Seq != 0 {
|
||||
n += 1 + sovPeerRecord(uint64(m.Seq))
|
||||
}
|
||||
if len(m.Addresses) > 0 {
|
||||
for _, e := range m.Addresses {
|
||||
l = e.Size()
|
||||
n += 1 + l + sovPeerRecord(uint64(l))
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *PeerRecord_AddressInfo) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
l = len(m.Multiaddr)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovPeerRecord(uint64(l))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovPeerRecord(x uint64) (n int) {
|
||||
return (math_bits.Len64(x|1) + 6) / 7
|
||||
}
|
||||
func sozPeerRecord(x uint64) (n int) {
|
||||
return sovPeerRecord(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (m *PeerRecord) 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 ErrIntOverflowPeerRecord
|
||||
}
|
||||
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: PeerRecord: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: PeerRecord: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field PeerId", wireType)
|
||||
}
|
||||
var byteLen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowPeerRecord
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
byteLen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if byteLen < 0 {
|
||||
return ErrInvalidLengthPeerRecord
|
||||
}
|
||||
postIndex := iNdEx + byteLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthPeerRecord
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.PeerId = append(m.PeerId[:0], dAtA[iNdEx:postIndex]...)
|
||||
if m.PeerId == nil {
|
||||
m.PeerId = []byte{}
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
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 ErrIntOverflowPeerRecord
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.Seq |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Addresses", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowPeerRecord
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthPeerRecord
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthPeerRecord
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Addresses = append(m.Addresses, &PeerRecord_AddressInfo{})
|
||||
if err := m.Addresses[len(m.Addresses)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipPeerRecord(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthPeerRecord
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
return ErrInvalidLengthPeerRecord
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *PeerRecord_AddressInfo) 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 ErrIntOverflowPeerRecord
|
||||
}
|
||||
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: AddressInfo: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: AddressInfo: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Multiaddr", wireType)
|
||||
}
|
||||
var byteLen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowPeerRecord
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
byteLen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if byteLen < 0 {
|
||||
return ErrInvalidLengthPeerRecord
|
||||
}
|
||||
postIndex := iNdEx + byteLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthPeerRecord
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Multiaddr = append(m.Multiaddr[:0], dAtA[iNdEx:postIndex]...)
|
||||
if m.Multiaddr == nil {
|
||||
m.Multiaddr = []byte{}
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipPeerRecord(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthPeerRecord
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
return ErrInvalidLengthPeerRecord
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipPeerRecord(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
depth := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowPeerRecord
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowPeerRecord
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowPeerRecord
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthPeerRecord
|
||||
}
|
||||
iNdEx += length
|
||||
case 3:
|
||||
depth++
|
||||
case 4:
|
||||
if depth == 0 {
|
||||
return 0, ErrUnexpectedEndOfGroupPeerRecord
|
||||
}
|
||||
depth--
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
if iNdEx < 0 {
|
||||
return 0, ErrInvalidLengthPeerRecord
|
||||
}
|
||||
if depth == 0 {
|
||||
return iNdEx, nil
|
||||
}
|
||||
}
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthPeerRecord = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowPeerRecord = fmt.Errorf("proto: integer overflow")
|
||||
ErrUnexpectedEndOfGroupPeerRecord = fmt.Errorf("proto: unexpected end of group")
|
||||
)
|
29
peer/pb/peer_record.proto
Normal file
29
peer/pb/peer_record.proto
Normal file
@ -0,0 +1,29 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package peer.pb;
|
||||
|
||||
// PeerRecord messages contain information that is useful to share with other peers.
|
||||
// Currently, a PeerRecord contains the public listen addresses for a peer, but this
|
||||
// is expected to expand to include other information in the future.
|
||||
//
|
||||
// PeerRecords are designed to be serialized to bytes and placed inside of
|
||||
// SignedEnvelopes before sharing with other peers.
|
||||
// See https://github.com/libp2p/go-libp2p-core/record/pb/envelope.proto for
|
||||
// the SignedEnvelope definition.
|
||||
message PeerRecord {
|
||||
|
||||
// AddressInfo is a wrapper around a binary multiaddr. It is defined as a
|
||||
// separate message to allow us to add per-address metadata in the future.
|
||||
message AddressInfo {
|
||||
bytes multiaddr = 1;
|
||||
}
|
||||
|
||||
// peer_id contains a libp2p peer id in its binary representation.
|
||||
bytes peer_id = 1;
|
||||
|
||||
// seq contains a monotonically-increasing sequence counter to order PeerRecords in time.
|
||||
uint64 seq = 2;
|
||||
|
||||
// addresses is a list of public listen addresses for the peer.
|
||||
repeated AddressInfo addresses = 3;
|
||||
}
|
208
peer/record.go
Normal file
208
peer/record.go
Normal file
@ -0,0 +1,208 @@
|
||||
package peer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
pb "github.com/libp2p/go-libp2p-core/peer/pb"
|
||||
"github.com/libp2p/go-libp2p-core/record"
|
||||
|
||||
ma "github.com/multiformats/go-multiaddr"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
)
|
||||
|
||||
var _ record.Record = (*PeerRecord)(nil)
|
||||
|
||||
func init() {
|
||||
record.RegisterType(&PeerRecord{})
|
||||
}
|
||||
|
||||
// The domain string used for peer records contained in a Envelope.
|
||||
const PeerRecordEnvelopeDomain = "libp2p-peer-record"
|
||||
|
||||
// The type hint used to identify peer records in a Envelope.
|
||||
// Defined in https://github.com/multiformats/multicodec/blob/master/table.csv
|
||||
// with name "libp2p-peer-record"
|
||||
var PeerRecordEnvelopePayloadType = []byte{0x03, 0x01}
|
||||
|
||||
// PeerRecord contains information that is broadly useful to share with other peers,
|
||||
// either through a direct exchange (as in the libp2p identify protocol), or through
|
||||
// a Peer Routing provider, such as a DHT.
|
||||
//
|
||||
// Currently, a PeerRecord contains the public listen addresses for a peer, but this
|
||||
// is expected to expand to include other information in the future.
|
||||
//
|
||||
// PeerRecords are ordered in time by their Seq field. Newer PeerRecords must have
|
||||
// greater Seq values than older records. The NewPeerRecord function will create
|
||||
// a PeerRecord with a timestamp-based Seq value. The other PeerRecord fields should
|
||||
// be set by the caller:
|
||||
//
|
||||
// rec := peer.NewPeerRecord()
|
||||
// rec.PeerID = aPeerID
|
||||
// rec.Addrs = someAddrs
|
||||
//
|
||||
// Alternatively, you can construct a PeerRecord struct directly and use the TimestampSeq
|
||||
// helper to set the Seq field:
|
||||
//
|
||||
// rec := peer.PeerRecord{PeerID: aPeerID, Addrs: someAddrs, Seq: peer.TimestampSeq()}
|
||||
//
|
||||
// Failing to set the Seq field will not result in an error, however, a PeerRecord with a
|
||||
// Seq value of zero may be ignored or rejected by other peers.
|
||||
//
|
||||
// PeerRecords are intended to be shared with other peers inside a signed
|
||||
// routing.Envelope, and PeerRecord implements the routing.Record interface
|
||||
// to facilitate this.
|
||||
//
|
||||
// To share a PeerRecord, first call Sign to wrap the record in a Envelope
|
||||
// and sign it with the local peer's private key:
|
||||
//
|
||||
// rec := &PeerRecord{PeerID: myPeerId, Addrs: myAddrs}
|
||||
// envelope, err := rec.Sign(myPrivateKey)
|
||||
//
|
||||
// The resulting record.Envelope can be marshalled to a []byte and shared
|
||||
// publicly. As a convenience, the MarshalSigned method will produce the
|
||||
// Envelope and marshal it to a []byte in one go:
|
||||
//
|
||||
// rec := &PeerRecord{PeerID: myPeerId, Addrs: myAddrs}
|
||||
// recordBytes, err := rec.MarshalSigned(myPrivateKey)
|
||||
//
|
||||
// To validate and unmarshal a signed PeerRecord from a remote peer,
|
||||
// "consume" the containing envelope, which will return both the
|
||||
// routing.Envelope and the inner Record. The Record must be cast to
|
||||
// a PeerRecord pointer before use:
|
||||
//
|
||||
// envelope, untypedRecord, err := ConsumeEnvelope(envelopeBytes, PeerRecordEnvelopeDomain)
|
||||
// if err != nil {
|
||||
// handleError(err)
|
||||
// return
|
||||
// }
|
||||
// peerRec := untypedRecord.(*PeerRecord)
|
||||
//
|
||||
type PeerRecord struct {
|
||||
// PeerID is the ID of the peer this record pertains to.
|
||||
PeerID ID
|
||||
|
||||
// Addrs contains the public addresses of the peer this record pertains to.
|
||||
Addrs []ma.Multiaddr
|
||||
|
||||
// Seq is a monotonically-increasing sequence counter that's used to order
|
||||
// PeerRecords in time. The interval between Seq values is unspecified,
|
||||
// but newer PeerRecords MUST have a greater Seq value than older records
|
||||
// for the same peer.
|
||||
Seq uint64
|
||||
}
|
||||
|
||||
// NewPeerRecord returns a PeerRecord with a timestamp-based sequence number.
|
||||
// The returned record is otherwise empty and should be populated by the caller.
|
||||
func NewPeerRecord() *PeerRecord {
|
||||
return &PeerRecord{Seq: TimestampSeq()}
|
||||
}
|
||||
|
||||
// PeerRecordFromAddrInfo creates a PeerRecord from an AddrInfo struct.
|
||||
// The returned record will have a timestamp-based sequence number.
|
||||
func PeerRecordFromAddrInfo(info AddrInfo) *PeerRecord {
|
||||
rec := NewPeerRecord()
|
||||
rec.PeerID = info.ID
|
||||
rec.Addrs = info.Addrs
|
||||
return rec
|
||||
}
|
||||
|
||||
// TimestampSeq is a helper to generate a timestamp-based sequence number for a PeerRecord.
|
||||
func TimestampSeq() uint64 {
|
||||
return uint64(time.Now().UnixNano())
|
||||
}
|
||||
|
||||
// Domain is used when signing and validating PeerRecords contained in Envelopes.
|
||||
// It is constant for all PeerRecord instances.
|
||||
func (r *PeerRecord) Domain() string {
|
||||
return PeerRecordEnvelopeDomain
|
||||
}
|
||||
|
||||
// Codec is a binary identifier for the PeerRecord type. It is constant for all PeerRecord instances.
|
||||
func (r *PeerRecord) Codec() []byte {
|
||||
return PeerRecordEnvelopePayloadType
|
||||
}
|
||||
|
||||
// UnmarshalRecord parses a PeerRecord from a byte slice.
|
||||
// This method is called automatically when consuming a record.Envelope
|
||||
// whose PayloadType indicates that it contains a PeerRecord.
|
||||
// It is generally not necessary or recommended to call this method directly.
|
||||
func (r *PeerRecord) UnmarshalRecord(bytes []byte) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("cannot unmarshal PeerRecord to nil receiver")
|
||||
}
|
||||
|
||||
var msg pb.PeerRecord
|
||||
err := proto.Unmarshal(bytes, &msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var id ID
|
||||
err = id.UnmarshalBinary(msg.PeerId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.PeerID = id
|
||||
r.Addrs = addrsFromProtobuf(msg.Addresses)
|
||||
r.Seq = msg.Seq
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalRecord serializes a PeerRecord to a byte slice.
|
||||
// This method is called automatically when constructing a routing.Envelope
|
||||
// using Seal or PeerRecord.Sign.
|
||||
func (r *PeerRecord) MarshalRecord() ([]byte, error) {
|
||||
idBytes, err := r.PeerID.MarshalBinary()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
msg := pb.PeerRecord{
|
||||
PeerId: idBytes,
|
||||
Addresses: addrsToProtobuf(r.Addrs),
|
||||
Seq: r.Seq,
|
||||
}
|
||||
return proto.Marshal(&msg)
|
||||
}
|
||||
|
||||
// Equal returns true if the other PeerRecord is identical to this one.
|
||||
func (r *PeerRecord) Equal(other *PeerRecord) bool {
|
||||
if other == nil {
|
||||
return r == nil
|
||||
}
|
||||
if r.PeerID != other.PeerID {
|
||||
return false
|
||||
}
|
||||
if r.Seq != other.Seq {
|
||||
return false
|
||||
}
|
||||
if len(r.Addrs) != len(other.Addrs) {
|
||||
return false
|
||||
}
|
||||
for i, _ := range r.Addrs {
|
||||
if !r.Addrs[i].Equal(other.Addrs[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func addrsFromProtobuf(addrs []*pb.PeerRecord_AddressInfo) []ma.Multiaddr {
|
||||
var out []ma.Multiaddr
|
||||
for _, addr := range addrs {
|
||||
a, err := ma.NewMultiaddrBytes(addr.Multiaddr)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
out = append(out, a)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func addrsToProtobuf(addrs []ma.Multiaddr) []*pb.PeerRecord_AddressInfo {
|
||||
var out []*pb.PeerRecord_AddressInfo
|
||||
for _, addr := range addrs {
|
||||
out = append(out, &pb.PeerRecord_AddressInfo{Multiaddr: addr.Bytes()})
|
||||
}
|
||||
return out
|
||||
}
|
54
peer/record_test.go
Normal file
54
peer/record_test.go
Normal file
@ -0,0 +1,54 @@
|
||||
package peer_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
||||
func TestPeerRecordConstants(t *testing.T) {
|
||||
msgf := "Changing the %s may cause peer records to be incompatible with older versions. " +
|
||||
"If you've already thought that through, please update this test so that it passes with the new values."
|
||||
rec := PeerRecord{}
|
||||
if rec.Domain() != "libp2p-peer-record" {
|
||||
t.Errorf(msgf, "signing domain")
|
||||
}
|
||||
if !bytes.Equal(rec.Codec(), []byte{0x03, 0x01}) {
|
||||
t.Errorf(msgf, "codec value")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSignedPeerRecordFromEnvelope(t *testing.T) {
|
||||
priv, _, err := test.RandTestKeyPair(crypto.Ed25519, 256)
|
||||
test.AssertNilError(t, err)
|
||||
|
||||
addrs := test.GenerateTestAddrs(10)
|
||||
id, err := IDFromPrivateKey(priv)
|
||||
test.AssertNilError(t, err)
|
||||
|
||||
rec := &PeerRecord{PeerID: id, Addrs: addrs, Seq: TimestampSeq()}
|
||||
envelope, err := record.Seal(rec, priv)
|
||||
test.AssertNilError(t, err)
|
||||
|
||||
t.Run("is unaltered after round-trip serde", func(t *testing.T) {
|
||||
envBytes, err := envelope.Marshal()
|
||||
test.AssertNilError(t, err)
|
||||
|
||||
env2, untypedRecord, err := record.ConsumeEnvelope(envBytes, PeerRecordEnvelopeDomain)
|
||||
test.AssertNilError(t, err)
|
||||
rec2, ok := untypedRecord.(*PeerRecord)
|
||||
if !ok {
|
||||
t.Error("unmarshaled record is not a *PeerRecord")
|
||||
}
|
||||
if !rec.Equal(rec2) {
|
||||
t.Error("expected peer record to be unaltered after round-trip serde")
|
||||
}
|
||||
if !envelope.Equal(env2) {
|
||||
t.Error("expected signed envelope to be unchanged after round-trip serde")
|
||||
}
|
||||
})
|
||||
}
|
@ -9,9 +9,9 @@ import (
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
|
||||
ic "github.com/libp2p/go-libp2p-core/crypto"
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
"github.com/libp2p/go-libp2p-core/record"
|
||||
|
||||
ma "github.com/multiformats/go-multiaddr"
|
||||
)
|
||||
@ -107,7 +107,7 @@ type AddrBook interface {
|
||||
// the given oldTTL to have the given newTTL.
|
||||
UpdateAddrs(p peer.ID, oldTTL time.Duration, newTTL time.Duration)
|
||||
|
||||
// Addresses returns all known (and valid) addresses for a given peer
|
||||
// Addrs returns all known (and valid) addresses for a given peer.
|
||||
Addrs(p peer.ID) []ma.Multiaddr
|
||||
|
||||
// AddrStream returns a channel that gets all addresses for a given
|
||||
@ -122,6 +122,80 @@ type AddrBook interface {
|
||||
PeersWithAddrs() peer.IDSlice
|
||||
}
|
||||
|
||||
// CertifiedAddrBook manages "self-certified" addresses for remote peers.
|
||||
// Self-certified addresses are contained in peer.PeerRecords
|
||||
// which are wrapped in a record.Envelope and signed by the peer
|
||||
// to whom they belong.
|
||||
//
|
||||
// Certified addresses (CA) are generally more secure than uncertified
|
||||
// addresses (UA). Consequently, CAs beat and displace UAs. When the
|
||||
// peerstore learns CAs for a peer, it will reject UAs for the same peer
|
||||
// (as long as the former haven't expired).
|
||||
// Furthermore, peer records act like sequenced snapshots of CAs. Therefore,
|
||||
// processing a peer record that's newer than the last one seen overwrites
|
||||
// all addresses with the incoming ones.
|
||||
//
|
||||
// This interface is most useful when combined with AddrBook.
|
||||
// To test whether a given AddrBook / Peerstore implementation supports
|
||||
// certified addresses, callers should use the GetCertifiedAddrBook helper or
|
||||
// type-assert on the CertifiedAddrBook interface:
|
||||
//
|
||||
// if cab, ok := aPeerstore.(CertifiedAddrBook); ok {
|
||||
// cab.ConsumePeerRecord(signedPeerRecord, aTTL)
|
||||
// }
|
||||
//
|
||||
type CertifiedAddrBook interface {
|
||||
// ConsumePeerRecord adds addresses from a signed peer.PeerRecord (contained in
|
||||
// a record.Envelope), which will expire after the given TTL.
|
||||
//
|
||||
// The 'accepted' return value indicates that the record was successfully processed
|
||||
// and integrated into the CertifiedAddrBook state. If 'accepted' is false but no
|
||||
// error is returned, it means that the record was ignored, most likely because
|
||||
// a newer record exists for the same peer.
|
||||
//
|
||||
// Signed records added via this method will be stored without
|
||||
// alteration as long as the address TTLs remain valid. The Envelopes
|
||||
// containing the PeerRecords can be retrieved by calling GetPeerRecord(peerID).
|
||||
//
|
||||
// If the signed PeerRecord belongs to a peer that already has certified
|
||||
// addresses in the CertifiedAddrBook, the new addresses will replace the
|
||||
// older ones, iff the new record has a higher sequence number than the
|
||||
// existing record. Attempting to add a peer record with a
|
||||
// sequence number that's <= an existing record for the same peer will not
|
||||
// result in an error, but the record will be ignored, and the 'accepted'
|
||||
// bool return value will be false.
|
||||
//
|
||||
// If the CertifiedAddrBook is also an AddrBook (which is most likely the case),
|
||||
// adding certified addresses for a peer will *replace* any
|
||||
// existing non-certified addresses for that peer, and only the certified
|
||||
// addresses will be returned from AddrBook.Addrs thereafter.
|
||||
//
|
||||
// Likewise, once certified addresses have been added for a given peer,
|
||||
// any non-certified addresses added via AddrBook.AddAddrs or
|
||||
// AddrBook.SetAddrs will be ignored. AddrBook.SetAddrs may still be used
|
||||
// to update the TTL of certified addresses that have previously been
|
||||
// added via ConsumePeerRecord.
|
||||
ConsumePeerRecord(s *record.Envelope, ttl time.Duration) (accepted bool, err error)
|
||||
|
||||
// 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.
|
||||
GetPeerRecord(p peer.ID) *record.Envelope
|
||||
}
|
||||
|
||||
// GetCertifiedAddrBook is a helper to "upcast" an AddrBook to a
|
||||
// CertifiedAddrBook by using type assertion. If the given AddrBook
|
||||
// is also a CertifiedAddrBook, it will be returned, and the ok return
|
||||
// value will be true. Returns (nil, false) if the AddrBook is not a
|
||||
// CertifiedAddrBook.
|
||||
//
|
||||
// Note that since Peerstore embeds the AddrBook interface, you can also
|
||||
// call GetCertifiedAddrBook(myPeerstore).
|
||||
func GetCertifiedAddrBook(ab AddrBook) (cab CertifiedAddrBook, ok bool) {
|
||||
cab, ok = ab.(CertifiedAddrBook)
|
||||
return cab, ok
|
||||
}
|
||||
|
||||
// KeyBook tracks the keys of Peers.
|
||||
type KeyBook interface {
|
||||
// PubKey stores the public key of a peer.
|
||||
|
297
record/envelope.go
Normal file
297
record/envelope.go
Normal file
@ -0,0 +1,297 @@
|
||||
package record
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/libp2p/go-libp2p-core/crypto"
|
||||
pb "github.com/libp2p/go-libp2p-core/record/pb"
|
||||
|
||||
pool "github.com/libp2p/go-buffer-pool"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/multiformats/go-varint"
|
||||
)
|
||||
|
||||
// Envelope contains an arbitrary []byte payload, signed by a libp2p peer.
|
||||
//
|
||||
// Envelopes are signed in the context of a particular "domain", which is a
|
||||
// string specified when creating and verifying the envelope. You must know the
|
||||
// domain string used to produce the envelope in order to verify the signature
|
||||
// and access the payload.
|
||||
type Envelope struct {
|
||||
// The public key that can be used to verify the signature and derive the peer id of the signer.
|
||||
PublicKey crypto.PubKey
|
||||
|
||||
// A binary identifier that indicates what kind of data is contained in the payload.
|
||||
// TODO(yusef): enforce multicodec prefix
|
||||
PayloadType []byte
|
||||
|
||||
// The envelope payload.
|
||||
RawPayload []byte
|
||||
|
||||
// The signature of the domain string :: type hint :: payload.
|
||||
signature []byte
|
||||
|
||||
// the unmarshalled payload as a Record, cached on first access via the Record accessor method
|
||||
cached Record
|
||||
unmarshalError error
|
||||
unmarshalOnce sync.Once
|
||||
}
|
||||
|
||||
var ErrEmptyDomain = errors.New("envelope domain must not be empty")
|
||||
var ErrEmptyPayloadType = errors.New("payloadType must not be empty")
|
||||
var ErrInvalidSignature = errors.New("invalid signature or incorrect domain")
|
||||
|
||||
// Seal marshals the given Record, places the marshaled bytes inside an Envelope,
|
||||
// and signs with the given private key.
|
||||
func Seal(rec Record, privateKey crypto.PrivKey) (*Envelope, error) {
|
||||
payload, err := rec.MarshalRecord()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error marshaling record: %v", err)
|
||||
}
|
||||
|
||||
domain := rec.Domain()
|
||||
payloadType := rec.Codec()
|
||||
if domain == "" {
|
||||
return nil, ErrEmptyDomain
|
||||
}
|
||||
|
||||
if len(payloadType) == 0 {
|
||||
return nil, ErrEmptyPayloadType
|
||||
}
|
||||
|
||||
unsigned, err := makeUnsigned(domain, payloadType, payload)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer pool.Put(unsigned)
|
||||
|
||||
sig, err := privateKey.Sign(unsigned)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Envelope{
|
||||
PublicKey: privateKey.GetPublic(),
|
||||
PayloadType: payloadType,
|
||||
RawPayload: payload,
|
||||
signature: sig,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ConsumeEnvelope unmarshals a serialized Envelope and validates its
|
||||
// signature using the provided 'domain' string. If validation fails, an error
|
||||
// is returned, along with the unmarshalled envelope so it can be inspected.
|
||||
//
|
||||
// On success, ConsumeEnvelope returns the Envelope itself, as well as the inner payload,
|
||||
// unmarshalled into a concrete Record type. The actual type of the returned Record depends
|
||||
// on what has been registered for the Envelope's PayloadType (see RegisterType for details).
|
||||
//
|
||||
// You can type assert on the returned Record to convert it to an instance of the concrete
|
||||
// Record type:
|
||||
//
|
||||
// envelope, rec, err := ConsumeEnvelope(envelopeBytes, peer.PeerRecordEnvelopeDomain)
|
||||
// if err != nil {
|
||||
// handleError(envelope, err) // envelope may be non-nil, even if errors occur!
|
||||
// return
|
||||
// }
|
||||
// peerRec, ok := rec.(*peer.PeerRecord)
|
||||
// if ok {
|
||||
// doSomethingWithPeerRecord(peerRec)
|
||||
// }
|
||||
//
|
||||
// Important: you MUST check the error value before using the returned Envelope. In some error
|
||||
// cases, including when the envelope signature is invalid, both the Envelope and an error will
|
||||
// be returned. This allows you to inspect the unmarshalled but invalid Envelope. As a result,
|
||||
// you must not assume that any non-nil Envelope returned from this function is valid.
|
||||
//
|
||||
// If the Envelope signature is valid, but no Record type is registered for the Envelope's
|
||||
// PayloadType, ErrPayloadTypeNotRegistered will be returned, along with the Envelope and
|
||||
// a nil Record.
|
||||
func ConsumeEnvelope(data []byte, domain string) (envelope *Envelope, rec Record, err error) {
|
||||
e, err := UnmarshalEnvelope(data)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed when unmarshalling the envelope: %w", err)
|
||||
}
|
||||
|
||||
err = e.validate(domain)
|
||||
if err != nil {
|
||||
return e, nil, fmt.Errorf("failed to validate envelope: %w", err)
|
||||
}
|
||||
|
||||
rec, err = e.Record()
|
||||
if err != nil {
|
||||
return e, nil, fmt.Errorf("failed to unmarshal envelope payload: %w", err)
|
||||
}
|
||||
return e, rec, nil
|
||||
}
|
||||
|
||||
// ConsumeTypedEnvelope unmarshals a serialized Envelope and validates its
|
||||
// signature. If validation fails, an error is returned, along with the unmarshalled
|
||||
// envelope so it can be inspected.
|
||||
//
|
||||
// Unlike ConsumeEnvelope, ConsumeTypedEnvelope does not try to automatically determine
|
||||
// the type of Record to unmarshal the Envelope's payload into. Instead, the caller provides
|
||||
// a destination Record instance, which will unmarshal the Envelope payload. It is the caller's
|
||||
// responsibility to determine whether the given Record type is able to unmarshal the payload
|
||||
// correctly.
|
||||
//
|
||||
// rec := &MyRecordType{}
|
||||
// envelope, err := ConsumeTypedEnvelope(envelopeBytes, rec)
|
||||
// if err != nil {
|
||||
// handleError(envelope, err)
|
||||
// }
|
||||
// doSomethingWithRecord(rec)
|
||||
//
|
||||
// Important: you MUST check the error value before using the returned Envelope. In some error
|
||||
// cases, including when the envelope signature is invalid, both the Envelope and an error will
|
||||
// be returned. This allows you to inspect the unmarshalled but invalid Envelope. As a result,
|
||||
// you must not assume that any non-nil Envelope returned from this function is valid.
|
||||
func ConsumeTypedEnvelope(data []byte, destRecord Record) (envelope *Envelope, err error) {
|
||||
e, err := UnmarshalEnvelope(data)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed when unmarshalling the envelope: %w", err)
|
||||
}
|
||||
|
||||
err = e.validate(destRecord.Domain())
|
||||
if err != nil {
|
||||
return e, fmt.Errorf("failed to validate envelope: %w", err)
|
||||
}
|
||||
|
||||
err = destRecord.UnmarshalRecord(e.RawPayload)
|
||||
if err != nil {
|
||||
return e, fmt.Errorf("failed to unmarshal envelope payload: %w", err)
|
||||
}
|
||||
e.cached = destRecord
|
||||
return e, nil
|
||||
}
|
||||
|
||||
// UnmarshalEnvelope unmarshals a serialized Envelope protobuf message,
|
||||
// without validating its contents. Most users should use ConsumeEnvelope.
|
||||
func UnmarshalEnvelope(data []byte) (*Envelope, error) {
|
||||
var e pb.Envelope
|
||||
if err := proto.Unmarshal(data, &e); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
key, err := crypto.PublicKeyFromProto(e.PublicKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Envelope{
|
||||
PublicKey: key,
|
||||
PayloadType: e.PayloadType,
|
||||
RawPayload: e.Payload,
|
||||
signature: e.Signature,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Marshal returns a byte slice containing a serialized protobuf representation
|
||||
// of a Envelope.
|
||||
func (e *Envelope) Marshal() ([]byte, error) {
|
||||
key, err := crypto.PublicKeyToProto(e.PublicKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
msg := pb.Envelope{
|
||||
PublicKey: key,
|
||||
PayloadType: e.PayloadType,
|
||||
Payload: e.RawPayload,
|
||||
Signature: e.signature,
|
||||
}
|
||||
return proto.Marshal(&msg)
|
||||
}
|
||||
|
||||
// Equal returns true if the other Envelope has the same public key,
|
||||
// payload, payload type, and signature. This implies that they were also
|
||||
// created with the same domain string.
|
||||
func (e *Envelope) Equal(other *Envelope) bool {
|
||||
if other == nil {
|
||||
return e == nil
|
||||
}
|
||||
return e.PublicKey.Equals(other.PublicKey) &&
|
||||
bytes.Compare(e.PayloadType, other.PayloadType) == 0 &&
|
||||
bytes.Compare(e.signature, other.signature) == 0 &&
|
||||
bytes.Compare(e.RawPayload, other.RawPayload) == 0
|
||||
}
|
||||
|
||||
// Record returns the Envelope's payload unmarshalled as a Record.
|
||||
// The concrete type of the returned Record depends on which Record
|
||||
// type was registered for the Envelope's PayloadType - see record.RegisterType.
|
||||
//
|
||||
// Once unmarshalled, the Record is cached for future access.
|
||||
func (e *Envelope) Record() (Record, error) {
|
||||
e.unmarshalOnce.Do(func() {
|
||||
if e.cached != nil {
|
||||
return
|
||||
}
|
||||
e.cached, e.unmarshalError = unmarshalRecordPayload(e.PayloadType, e.RawPayload)
|
||||
})
|
||||
return e.cached, e.unmarshalError
|
||||
}
|
||||
|
||||
// TypedRecord unmarshals the Envelope's payload to the given Record instance.
|
||||
// It is the caller's responsibility to ensure that the Record type is capable
|
||||
// of unmarshalling the Envelope payload. Callers can inspect the Envelope's
|
||||
// PayloadType field to determine the correct type of Record to use.
|
||||
//
|
||||
// This method will always unmarshal the Envelope payload even if a cached record
|
||||
// exists.
|
||||
func (e *Envelope) TypedRecord(dest Record) error {
|
||||
return dest.UnmarshalRecord(e.RawPayload)
|
||||
}
|
||||
|
||||
// validate returns nil if the envelope signature is valid for the given 'domain',
|
||||
// or an error if signature validation fails.
|
||||
func (e *Envelope) validate(domain string) error {
|
||||
unsigned, err := makeUnsigned(domain, e.PayloadType, e.RawPayload)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer pool.Put(unsigned)
|
||||
|
||||
valid, err := e.PublicKey.Verify(unsigned, e.signature)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed while verifying signature: %w", err)
|
||||
}
|
||||
if !valid {
|
||||
return ErrInvalidSignature
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// makeUnsigned is a helper function that prepares a buffer to sign or verify.
|
||||
// It returns a byte slice from a pool. The caller MUST return this slice to the
|
||||
// pool.
|
||||
func makeUnsigned(domain string, payloadType []byte, payload []byte) ([]byte, error) {
|
||||
var (
|
||||
fields = [][]byte{[]byte(domain), payloadType, payload}
|
||||
|
||||
// fields are prefixed with their length as an unsigned varint. we
|
||||
// compute the lengths before allocating the sig buffer so we know how
|
||||
// much space to add for the lengths
|
||||
flen = make([][]byte, len(fields))
|
||||
size = 0
|
||||
)
|
||||
|
||||
for i, f := range fields {
|
||||
l := len(f)
|
||||
flen[i] = varint.ToUvarint(uint64(l))
|
||||
size += l + len(flen[i])
|
||||
}
|
||||
|
||||
b := pool.Get(size)
|
||||
|
||||
var s int
|
||||
for i, f := range fields {
|
||||
s += copy(b[s:], flen[i])
|
||||
s += copy(b[s:], f)
|
||||
}
|
||||
|
||||
return b[:s], nil
|
||||
}
|
313
record/envelope_test.go
Normal file
313
record/envelope_test.go
Normal file
@ -0,0 +1,313 @@
|
||||
package record_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
crypto "github.com/libp2p/go-libp2p-core/crypto"
|
||||
. "github.com/libp2p/go-libp2p-core/record"
|
||||
pb "github.com/libp2p/go-libp2p-core/record/pb"
|
||||
"github.com/libp2p/go-libp2p-core/test"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
)
|
||||
|
||||
type simpleRecord struct {
|
||||
testDomain *string
|
||||
testCodec []byte
|
||||
message string
|
||||
}
|
||||
|
||||
func (r *simpleRecord) Domain() string {
|
||||
if r.testDomain != nil {
|
||||
return *r.testDomain
|
||||
}
|
||||
return "libp2p-testing"
|
||||
}
|
||||
|
||||
func (r *simpleRecord) Codec() []byte {
|
||||
if r.testCodec != nil {
|
||||
return r.testCodec
|
||||
}
|
||||
return []byte("/libp2p/testdata")
|
||||
}
|
||||
|
||||
func (r *simpleRecord) MarshalRecord() ([]byte, error) {
|
||||
return []byte(r.message), nil
|
||||
}
|
||||
|
||||
func (r *simpleRecord) UnmarshalRecord(buf []byte) error {
|
||||
r.message = string(buf)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Make an envelope, verify & open it, marshal & unmarshal it
|
||||
func TestEnvelopeHappyPath(t *testing.T) {
|
||||
var (
|
||||
rec = &simpleRecord{message: "hello world!"}
|
||||
priv, pub, err = test.RandTestKeyPair(crypto.Ed25519, 256)
|
||||
)
|
||||
|
||||
test.AssertNilError(t, err)
|
||||
|
||||
payload, err := rec.MarshalRecord()
|
||||
test.AssertNilError(t, err)
|
||||
|
||||
envelope, err := Seal(rec, priv)
|
||||
test.AssertNilError(t, err)
|
||||
|
||||
if !envelope.PublicKey.Equals(pub) {
|
||||
t.Error("envelope has unexpected public key")
|
||||
}
|
||||
|
||||
if bytes.Compare(rec.Codec(), envelope.PayloadType) != 0 {
|
||||
t.Error("PayloadType does not match record Codec")
|
||||
}
|
||||
|
||||
serialized, err := envelope.Marshal()
|
||||
test.AssertNilError(t, err)
|
||||
|
||||
RegisterType(&simpleRecord{})
|
||||
deserialized, rec2, err := ConsumeEnvelope(serialized, rec.Domain())
|
||||
test.AssertNilError(t, err)
|
||||
|
||||
if bytes.Compare(deserialized.RawPayload, payload) != 0 {
|
||||
t.Error("payload of envelope does not match input")
|
||||
}
|
||||
|
||||
if !envelope.Equal(deserialized) {
|
||||
t.Error("round-trip serde results in unequal envelope structures")
|
||||
}
|
||||
|
||||
typedRec, ok := rec2.(*simpleRecord)
|
||||
if !ok {
|
||||
t.Error("expected ConsumeEnvelope to return record with type registered for payloadType")
|
||||
}
|
||||
if typedRec.message != "hello world!" {
|
||||
t.Error("unexpected alteration of record")
|
||||
}
|
||||
}
|
||||
|
||||
func TestConsumeTypedEnvelope(t *testing.T) {
|
||||
var (
|
||||
rec = simpleRecord{message: "hello world!"}
|
||||
priv, _, err = test.RandTestKeyPair(crypto.Ed25519, 256)
|
||||
)
|
||||
|
||||
envelope, err := Seal(&rec, priv)
|
||||
test.AssertNilError(t, err)
|
||||
|
||||
envelopeBytes, err := envelope.Marshal()
|
||||
test.AssertNilError(t, err)
|
||||
|
||||
rec2 := &simpleRecord{}
|
||||
_, err = ConsumeTypedEnvelope(envelopeBytes, rec2)
|
||||
test.AssertNilError(t, err)
|
||||
|
||||
if rec2.message != "hello world!" {
|
||||
t.Error("unexpected alteration of record")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMakeEnvelopeFailsWithEmptyDomain(t *testing.T) {
|
||||
var (
|
||||
rec = simpleRecord{message: "hello world!"}
|
||||
domain = ""
|
||||
priv, _, err = test.RandTestKeyPair(crypto.Ed25519, 256)
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// override domain with empty string
|
||||
rec.testDomain = &domain
|
||||
|
||||
_, err = Seal(&rec, priv)
|
||||
test.ExpectError(t, err, "making an envelope with an empty domain should fail")
|
||||
}
|
||||
|
||||
func TestMakeEnvelopeFailsWithEmptyPayloadType(t *testing.T) {
|
||||
var (
|
||||
rec = simpleRecord{message: "hello world!"}
|
||||
priv, _, err = test.RandTestKeyPair(crypto.Ed25519, 256)
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// override payload with empty slice
|
||||
rec.testCodec = []byte{}
|
||||
|
||||
_, err = Seal(&rec, priv)
|
||||
test.ExpectError(t, err, "making an envelope with an empty payloadType should fail")
|
||||
}
|
||||
|
||||
type failingRecord struct {
|
||||
allowMarshal bool
|
||||
allowUnmarshal bool
|
||||
}
|
||||
|
||||
func (r failingRecord) Domain() string {
|
||||
return "testing"
|
||||
}
|
||||
|
||||
func (r failingRecord) Codec() []byte {
|
||||
return []byte("doesn't matter")
|
||||
}
|
||||
|
||||
func (r failingRecord) MarshalRecord() ([]byte, error) {
|
||||
if r.allowMarshal {
|
||||
return []byte{}, nil
|
||||
}
|
||||
return nil, errors.New("marshal failed")
|
||||
}
|
||||
func (r failingRecord) UnmarshalRecord(data []byte) error {
|
||||
if r.allowUnmarshal {
|
||||
return nil
|
||||
}
|
||||
return errors.New("unmarshal failed")
|
||||
}
|
||||
|
||||
func TestSealFailsIfRecordMarshalFails(t *testing.T) {
|
||||
var (
|
||||
priv, _, err = test.RandTestKeyPair(crypto.Ed25519, 256)
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
rec := failingRecord{}
|
||||
_, err = Seal(rec, priv)
|
||||
test.ExpectError(t, err, "Seal should fail if Record fails to marshal")
|
||||
}
|
||||
|
||||
func TestConsumeEnvelopeFailsIfEnvelopeUnmarshalFails(t *testing.T) {
|
||||
_, _, err := ConsumeEnvelope([]byte("not an Envelope protobuf"), "doesn't-matter")
|
||||
test.ExpectError(t, err, "ConsumeEnvelope should fail if Envelope fails to unmarshal")
|
||||
}
|
||||
|
||||
func TestConsumeEnvelopeFailsIfRecordUnmarshalFails(t *testing.T) {
|
||||
var (
|
||||
priv, _, err = test.RandTestKeyPair(crypto.Ed25519, 256)
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
RegisterType(failingRecord{})
|
||||
rec := failingRecord{allowMarshal: true}
|
||||
env, err := Seal(rec, priv)
|
||||
test.AssertNilError(t, err)
|
||||
envBytes, err := env.Marshal()
|
||||
test.AssertNilError(t, err)
|
||||
|
||||
_, _, err = ConsumeEnvelope(envBytes, rec.Domain())
|
||||
test.ExpectError(t, err, "ConsumeEnvelope should fail if Record fails to unmarshal")
|
||||
}
|
||||
|
||||
func TestConsumeTypedEnvelopeFailsIfRecordUnmarshalFails(t *testing.T) {
|
||||
var (
|
||||
priv, _, err = test.RandTestKeyPair(crypto.Ed25519, 256)
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
RegisterType(failingRecord{})
|
||||
rec := failingRecord{allowMarshal: true}
|
||||
env, err := Seal(rec, priv)
|
||||
test.AssertNilError(t, err)
|
||||
envBytes, err := env.Marshal()
|
||||
test.AssertNilError(t, err)
|
||||
|
||||
rec2 := failingRecord{}
|
||||
_, err = ConsumeTypedEnvelope(envBytes, rec2)
|
||||
test.ExpectError(t, err, "ConsumeTypedEnvelope should fail if Record fails to unmarshal")
|
||||
}
|
||||
|
||||
func TestEnvelopeValidateFailsForDifferentDomain(t *testing.T) {
|
||||
var (
|
||||
rec = &simpleRecord{message: "hello world"}
|
||||
priv, _, err = test.RandTestKeyPair(crypto.Ed25519, 256)
|
||||
)
|
||||
|
||||
test.AssertNilError(t, err)
|
||||
|
||||
envelope, err := Seal(rec, priv)
|
||||
test.AssertNilError(t, err)
|
||||
|
||||
serialized, err := envelope.Marshal()
|
||||
|
||||
// try to open our modified envelope
|
||||
_, _, err = ConsumeEnvelope(serialized, "wrong-domain")
|
||||
test.ExpectError(t, err, "should not be able to open envelope with incorrect domain")
|
||||
}
|
||||
|
||||
func TestEnvelopeValidateFailsIfPayloadTypeIsAltered(t *testing.T) {
|
||||
var (
|
||||
rec = &simpleRecord{message: "hello world!"}
|
||||
domain = "libp2p-testing"
|
||||
priv, _, err = test.RandTestKeyPair(crypto.Ed25519, 256)
|
||||
)
|
||||
|
||||
test.AssertNilError(t, err)
|
||||
|
||||
envelope, err := Seal(rec, priv)
|
||||
test.AssertNilError(t, err)
|
||||
|
||||
serialized := alterMessageAndMarshal(t, envelope, func(msg *pb.Envelope) {
|
||||
msg.PayloadType = []byte("foo")
|
||||
})
|
||||
|
||||
// try to open our modified envelope
|
||||
_, _, err = ConsumeEnvelope(serialized, domain)
|
||||
test.ExpectError(t, err, "should not be able to open envelope with modified PayloadType")
|
||||
}
|
||||
|
||||
func TestEnvelopeValidateFailsIfContentsAreAltered(t *testing.T) {
|
||||
var (
|
||||
rec = &simpleRecord{message: "hello world!"}
|
||||
domain = "libp2p-testing"
|
||||
priv, _, err = test.RandTestKeyPair(crypto.Ed25519, 256)
|
||||
)
|
||||
|
||||
test.AssertNilError(t, err)
|
||||
|
||||
envelope, err := Seal(rec, priv)
|
||||
test.AssertNilError(t, err)
|
||||
|
||||
serialized := alterMessageAndMarshal(t, envelope, func(msg *pb.Envelope) {
|
||||
msg.Payload = []byte("totally legit, trust me")
|
||||
})
|
||||
|
||||
// try to open our modified envelope
|
||||
_, _, err = ConsumeEnvelope(serialized, domain)
|
||||
test.ExpectError(t, err, "should not be able to open envelope with modified payload")
|
||||
}
|
||||
|
||||
// Since we're outside of the crypto package (to avoid import cycles with test package),
|
||||
// we can't alter the fields in a Envelope directly. This helper marshals
|
||||
// the envelope to a protobuf and calls the alterMsg function, which should
|
||||
// alter the protobuf message.
|
||||
// Returns the serialized altered protobuf message.
|
||||
func alterMessageAndMarshal(t *testing.T, envelope *Envelope, alterMsg func(*pb.Envelope)) []byte {
|
||||
t.Helper()
|
||||
|
||||
serialized, err := envelope.Marshal()
|
||||
test.AssertNilError(t, err)
|
||||
|
||||
msg := pb.Envelope{}
|
||||
err = proto.Unmarshal(serialized, &msg)
|
||||
test.AssertNilError(t, err)
|
||||
|
||||
alterMsg(&msg)
|
||||
serialized, err = msg.Marshal()
|
||||
test.AssertNilError(t, err)
|
||||
|
||||
return serialized
|
||||
}
|
11
record/pb/Makefile
Normal file
11
record/pb/Makefile
Normal file
@ -0,0 +1,11 @@
|
||||
PB = $(wildcard *.proto)
|
||||
GO = $(PB:.proto=.pb.go)
|
||||
|
||||
all: $(GO)
|
||||
|
||||
%.pb.go: %.proto
|
||||
protoc --proto_path=$(PWD):$(PWD)/../.. --gogofaster_out=. $<
|
||||
|
||||
clean:
|
||||
rm -f *.pb.go
|
||||
rm -f *.go
|
504
record/pb/envelope.pb.go
Normal file
504
record/pb/envelope.pb.go
Normal file
@ -0,0 +1,504 @@
|
||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: envelope.proto
|
||||
|
||||
package record_pb
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
pb "github.com/libp2p/go-libp2p-core/crypto/pb"
|
||||
io "io"
|
||||
math "math"
|
||||
math_bits "math/bits"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
// Envelope encloses a signed payload produced by a peer, along with the public
|
||||
// key of the keypair it was signed with so that it can be statelessly validated
|
||||
// by the receiver.
|
||||
//
|
||||
// The payload is prefixed with a byte string that determines the type, so it
|
||||
// can be deserialized deterministically. Often, this byte string is a
|
||||
// multicodec.
|
||||
type Envelope struct {
|
||||
// public_key is the public key of the keypair the enclosed payload was
|
||||
// signed with.
|
||||
PublicKey *pb.PublicKey `protobuf:"bytes,1,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"`
|
||||
// payload_type encodes the type of payload, so that it can be deserialized
|
||||
// deterministically.
|
||||
PayloadType []byte `protobuf:"bytes,2,opt,name=payload_type,json=payloadType,proto3" json:"payload_type,omitempty"`
|
||||
// payload is the actual payload carried inside this envelope.
|
||||
Payload []byte `protobuf:"bytes,3,opt,name=payload,proto3" json:"payload,omitempty"`
|
||||
// signature is the signature produced by the private key corresponding to
|
||||
// the enclosed public key, over the payload, prefixing a domain string for
|
||||
// additional security.
|
||||
Signature []byte `protobuf:"bytes,5,opt,name=signature,proto3" json:"signature,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Envelope) Reset() { *m = Envelope{} }
|
||||
func (m *Envelope) String() string { return proto.CompactTextString(m) }
|
||||
func (*Envelope) ProtoMessage() {}
|
||||
func (*Envelope) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_ee266e8c558e9dc5, []int{0}
|
||||
}
|
||||
func (m *Envelope) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *Envelope) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_Envelope.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 *Envelope) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Envelope.Merge(m, src)
|
||||
}
|
||||
func (m *Envelope) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *Envelope) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Envelope.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Envelope proto.InternalMessageInfo
|
||||
|
||||
func (m *Envelope) GetPublicKey() *pb.PublicKey {
|
||||
if m != nil {
|
||||
return m.PublicKey
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Envelope) GetPayloadType() []byte {
|
||||
if m != nil {
|
||||
return m.PayloadType
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Envelope) GetPayload() []byte {
|
||||
if m != nil {
|
||||
return m.Payload
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Envelope) GetSignature() []byte {
|
||||
if m != nil {
|
||||
return m.Signature
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Envelope)(nil), "record.pb.Envelope")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("envelope.proto", fileDescriptor_ee266e8c558e9dc5) }
|
||||
|
||||
var fileDescriptor_ee266e8c558e9dc5 = []byte{
|
||||
// 205 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4b, 0xcd, 0x2b, 0x4b,
|
||||
0xcd, 0xc9, 0x2f, 0x48, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x2c, 0x4a, 0x4d, 0xce,
|
||||
0x2f, 0x4a, 0xd1, 0x2b, 0x48, 0x92, 0x12, 0x4b, 0x2e, 0xaa, 0x2c, 0x28, 0xc9, 0xd7, 0x2f, 0x48,
|
||||
0xd2, 0x87, 0xb0, 0x20, 0x4a, 0x94, 0x66, 0x31, 0x72, 0x71, 0xb8, 0x42, 0x75, 0x09, 0x19, 0x73,
|
||||
0x71, 0x15, 0x94, 0x26, 0xe5, 0x64, 0x26, 0xc7, 0x67, 0xa7, 0x56, 0x4a, 0x30, 0x2a, 0x30, 0x6a,
|
||||
0x70, 0x1b, 0x89, 0xe8, 0xc1, 0xd4, 0x27, 0xe9, 0x05, 0x80, 0x25, 0xbd, 0x53, 0x2b, 0x83, 0x38,
|
||||
0x0b, 0x60, 0x4c, 0x21, 0x45, 0x2e, 0x9e, 0x82, 0xc4, 0xca, 0x9c, 0xfc, 0xc4, 0x94, 0xf8, 0x92,
|
||||
0xca, 0x82, 0x54, 0x09, 0x26, 0x05, 0x46, 0x0d, 0x9e, 0x20, 0x6e, 0xa8, 0x58, 0x48, 0x65, 0x41,
|
||||
0xaa, 0x90, 0x04, 0x17, 0x3b, 0x94, 0x2b, 0xc1, 0x0c, 0x96, 0x85, 0x71, 0x85, 0x64, 0xb8, 0x38,
|
||||
0x8b, 0x33, 0xd3, 0xf3, 0x12, 0x4b, 0x4a, 0x8b, 0x52, 0x25, 0x58, 0xc1, 0x72, 0x08, 0x01, 0x27,
|
||||
0x89, 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, 0xbb, 0xde, 0x18,
|
||||
0x10, 0x00, 0x00, 0xff, 0xff, 0xaa, 0x0b, 0xd9, 0x6d, 0xf2, 0x00, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *Envelope) 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 *Envelope) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.Size()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *Envelope) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Signature) > 0 {
|
||||
i -= len(m.Signature)
|
||||
copy(dAtA[i:], m.Signature)
|
||||
i = encodeVarintEnvelope(dAtA, i, uint64(len(m.Signature)))
|
||||
i--
|
||||
dAtA[i] = 0x2a
|
||||
}
|
||||
if len(m.Payload) > 0 {
|
||||
i -= len(m.Payload)
|
||||
copy(dAtA[i:], m.Payload)
|
||||
i = encodeVarintEnvelope(dAtA, i, uint64(len(m.Payload)))
|
||||
i--
|
||||
dAtA[i] = 0x1a
|
||||
}
|
||||
if len(m.PayloadType) > 0 {
|
||||
i -= len(m.PayloadType)
|
||||
copy(dAtA[i:], m.PayloadType)
|
||||
i = encodeVarintEnvelope(dAtA, i, uint64(len(m.PayloadType)))
|
||||
i--
|
||||
dAtA[i] = 0x12
|
||||
}
|
||||
if m.PublicKey != nil {
|
||||
{
|
||||
size, err := m.PublicKey.MarshalToSizedBuffer(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = encodeVarintEnvelope(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func encodeVarintEnvelope(dAtA []byte, offset int, v uint64) int {
|
||||
offset -= sovEnvelope(v)
|
||||
base := offset
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return base
|
||||
}
|
||||
func (m *Envelope) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
if m.PublicKey != nil {
|
||||
l = m.PublicKey.Size()
|
||||
n += 1 + l + sovEnvelope(uint64(l))
|
||||
}
|
||||
l = len(m.PayloadType)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovEnvelope(uint64(l))
|
||||
}
|
||||
l = len(m.Payload)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovEnvelope(uint64(l))
|
||||
}
|
||||
l = len(m.Signature)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovEnvelope(uint64(l))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovEnvelope(x uint64) (n int) {
|
||||
return (math_bits.Len64(x|1) + 6) / 7
|
||||
}
|
||||
func sozEnvelope(x uint64) (n int) {
|
||||
return sovEnvelope(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (m *Envelope) 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 ErrIntOverflowEnvelope
|
||||
}
|
||||
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: Envelope: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: Envelope: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field PublicKey", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowEnvelope
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthEnvelope
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthEnvelope
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if m.PublicKey == nil {
|
||||
m.PublicKey = &pb.PublicKey{}
|
||||
}
|
||||
if err := m.PublicKey.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field PayloadType", wireType)
|
||||
}
|
||||
var byteLen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowEnvelope
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
byteLen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if byteLen < 0 {
|
||||
return ErrInvalidLengthEnvelope
|
||||
}
|
||||
postIndex := iNdEx + byteLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthEnvelope
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.PayloadType = append(m.PayloadType[:0], dAtA[iNdEx:postIndex]...)
|
||||
if m.PayloadType == nil {
|
||||
m.PayloadType = []byte{}
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Payload", wireType)
|
||||
}
|
||||
var byteLen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowEnvelope
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
byteLen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if byteLen < 0 {
|
||||
return ErrInvalidLengthEnvelope
|
||||
}
|
||||
postIndex := iNdEx + byteLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthEnvelope
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Payload = append(m.Payload[:0], dAtA[iNdEx:postIndex]...)
|
||||
if m.Payload == nil {
|
||||
m.Payload = []byte{}
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 5:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Signature", wireType)
|
||||
}
|
||||
var byteLen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowEnvelope
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
byteLen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if byteLen < 0 {
|
||||
return ErrInvalidLengthEnvelope
|
||||
}
|
||||
postIndex := iNdEx + byteLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthEnvelope
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Signature = append(m.Signature[:0], dAtA[iNdEx:postIndex]...)
|
||||
if m.Signature == nil {
|
||||
m.Signature = []byte{}
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipEnvelope(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthEnvelope
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
return ErrInvalidLengthEnvelope
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipEnvelope(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
depth := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowEnvelope
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowEnvelope
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowEnvelope
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthEnvelope
|
||||
}
|
||||
iNdEx += length
|
||||
case 3:
|
||||
depth++
|
||||
case 4:
|
||||
if depth == 0 {
|
||||
return 0, ErrUnexpectedEndOfGroupEnvelope
|
||||
}
|
||||
depth--
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
if iNdEx < 0 {
|
||||
return 0, ErrInvalidLengthEnvelope
|
||||
}
|
||||
if depth == 0 {
|
||||
return iNdEx, nil
|
||||
}
|
||||
}
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthEnvelope = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowEnvelope = fmt.Errorf("proto: integer overflow")
|
||||
ErrUnexpectedEndOfGroupEnvelope = fmt.Errorf("proto: unexpected end of group")
|
||||
)
|
30
record/pb/envelope.proto
Normal file
30
record/pb/envelope.proto
Normal file
@ -0,0 +1,30 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package record.pb;
|
||||
|
||||
import "crypto/pb/crypto.proto";
|
||||
|
||||
// Envelope encloses a signed payload produced by a peer, along with the public
|
||||
// key of the keypair it was signed with so that it can be statelessly validated
|
||||
// by the receiver.
|
||||
//
|
||||
// The payload is prefixed with a byte string that determines the type, so it
|
||||
// can be deserialized deterministically. Often, this byte string is a
|
||||
// multicodec.
|
||||
message Envelope {
|
||||
// public_key is the public key of the keypair the enclosed payload was
|
||||
// signed with.
|
||||
crypto.pb.PublicKey public_key = 1;
|
||||
|
||||
// payload_type encodes the type of payload, so that it can be deserialized
|
||||
// deterministically.
|
||||
bytes payload_type = 2;
|
||||
|
||||
// payload is the actual payload carried inside this envelope.
|
||||
bytes payload = 3;
|
||||
|
||||
// signature is the signature produced by the private key corresponding to
|
||||
// the enclosed public key, over the payload, prefixing a domain string for
|
||||
// additional security.
|
||||
bytes signature = 5;
|
||||
}
|
102
record/record.go
Normal file
102
record/record.go
Normal file
@ -0,0 +1,102 @@
|
||||
package record
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrPayloadTypeNotRegistered is returned from ConsumeEnvelope when the Envelope's
|
||||
// PayloadType does not match any registered Record types.
|
||||
ErrPayloadTypeNotRegistered = errors.New("payload type is not registered")
|
||||
|
||||
payloadTypeRegistry = make(map[string]reflect.Type)
|
||||
)
|
||||
|
||||
// Record represents a data type that can be used as the payload of an Envelope.
|
||||
// The Record interface defines the methods used to marshal and unmarshal a Record
|
||||
// type to a byte slice.
|
||||
//
|
||||
// Record types may be "registered" as the default for a given Envelope.PayloadType
|
||||
// using the RegisterType function. Once a Record type has been registered,
|
||||
// an instance of that type will be created and used to unmarshal the payload of
|
||||
// any Envelope with the registered PayloadType when the Envelope is opened using
|
||||
// the ConsumeEnvelope function.
|
||||
//
|
||||
// To use an unregistered Record type instead, use ConsumeTypedEnvelope and pass in
|
||||
// an instance of the Record type that you'd like the Envelope's payload to be
|
||||
// unmarshaled into.
|
||||
type Record interface {
|
||||
|
||||
// Domain is the "signature domain" used when signing and verifying a particular
|
||||
// Record type. The Domain string should be unique to your Record type, and all
|
||||
// instances of the Record type must have the same Domain string.
|
||||
Domain() string
|
||||
|
||||
// Codec is a binary identifier for this type of record, ideally a registered multicodec
|
||||
// (see https://github.com/multiformats/multicodec).
|
||||
// When a Record is put into an Envelope (see record.Seal), the Codec value will be used
|
||||
// as the Envelope's PayloadType. When the Envelope is later unsealed, the PayloadType
|
||||
// will be used to lookup the correct Record type to unmarshal the Envelope payload into.
|
||||
Codec() []byte
|
||||
|
||||
// MarshalRecord converts a Record instance to a []byte, so that it can be used as an
|
||||
// Envelope payload.
|
||||
MarshalRecord() ([]byte, error)
|
||||
|
||||
// UnmarshalRecord unmarshals a []byte payload into an instance of a particular Record type.
|
||||
UnmarshalRecord([]byte) error
|
||||
}
|
||||
|
||||
// RegisterType associates a binary payload type identifier with a concrete
|
||||
// Record type. This is used to automatically unmarshal Record payloads from Envelopes
|
||||
// when using ConsumeEnvelope, and to automatically marshal Records and determine the
|
||||
// correct PayloadType when calling Seal.
|
||||
//
|
||||
// Callers must provide an instance of the record type to be registered, which must be
|
||||
// a pointer type. Registration should be done in the init function of the package
|
||||
// where the Record type is defined:
|
||||
//
|
||||
// package hello_record
|
||||
// import record "github.com/libp2p/go-libp2p-core/record"
|
||||
//
|
||||
// func init() {
|
||||
// record.RegisterType(&HelloRecord{})
|
||||
// }
|
||||
//
|
||||
// type HelloRecord struct { } // etc..
|
||||
//
|
||||
func RegisterType(prototype Record) {
|
||||
payloadTypeRegistry[string(prototype.Codec())] = getValueType(prototype)
|
||||
}
|
||||
|
||||
func unmarshalRecordPayload(payloadType []byte, payloadBytes []byte) (Record, error) {
|
||||
rec, err := blankRecordForPayloadType(payloadType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = rec.UnmarshalRecord(payloadBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rec, nil
|
||||
}
|
||||
|
||||
func blankRecordForPayloadType(payloadType []byte) (Record, error) {
|
||||
valueType, ok := payloadTypeRegistry[string(payloadType)]
|
||||
if !ok {
|
||||
return nil, ErrPayloadTypeNotRegistered
|
||||
}
|
||||
|
||||
val := reflect.New(valueType)
|
||||
asRecord := val.Interface().(Record)
|
||||
return asRecord, nil
|
||||
}
|
||||
|
||||
func getValueType(i interface{}) reflect.Type {
|
||||
valueType := reflect.TypeOf(i)
|
||||
if valueType.Kind() == reflect.Ptr {
|
||||
valueType = valueType.Elem()
|
||||
}
|
||||
return valueType
|
||||
}
|
51
record/record_test.go
Normal file
51
record/record_test.go
Normal file
@ -0,0 +1,51 @@
|
||||
package record
|
||||
|
||||
import "testing"
|
||||
|
||||
var testPayloadType = []byte("/libp2p/test/record/payload-type")
|
||||
|
||||
type testPayload struct {
|
||||
unmarshalPayloadCalled bool
|
||||
}
|
||||
|
||||
func (p *testPayload) Domain() string {
|
||||
return "testing"
|
||||
}
|
||||
|
||||
func (p *testPayload) Codec() []byte {
|
||||
return testPayloadType
|
||||
}
|
||||
|
||||
func (p *testPayload) MarshalRecord() ([]byte, error) {
|
||||
return []byte("hello"), nil
|
||||
}
|
||||
|
||||
func (p *testPayload) UnmarshalRecord(bytes []byte) error {
|
||||
p.unmarshalPayloadCalled = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestUnmarshalPayload(t *testing.T) {
|
||||
t.Run("fails if payload type is unregistered", func(t *testing.T) {
|
||||
_, err := unmarshalRecordPayload([]byte("unknown type"), []byte{})
|
||||
if err != ErrPayloadTypeNotRegistered {
|
||||
t.Error("Expected error when unmarshalling payload with unregistered payload type")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("calls UnmarshalRecord on concrete Record type", func(t *testing.T) {
|
||||
RegisterType(&testPayload{})
|
||||
|
||||
payload, err := unmarshalRecordPayload(testPayloadType, []byte{})
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error unmarshalling registered payload type: %v", err)
|
||||
}
|
||||
typedPayload, ok := payload.(*testPayload)
|
||||
if !ok {
|
||||
t.Error("expected unmarshalled payload to be of the correct type")
|
||||
}
|
||||
if !typedPayload.unmarshalPayloadCalled {
|
||||
t.Error("expected UnmarshalRecord to be called on concrete Record instance")
|
||||
}
|
||||
})
|
||||
}
|
42
test/addrs.go
Normal file
42
test/addrs.go
Normal file
@ -0,0 +1,42 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
ma "github.com/multiformats/go-multiaddr"
|
||||
)
|
||||
|
||||
func GenerateTestAddrs(n int) []ma.Multiaddr {
|
||||
out := make([]ma.Multiaddr, n)
|
||||
for i := 0; i < n; i++ {
|
||||
a, err := ma.NewMultiaddr(fmt.Sprintf("/ip4/1.2.3.4/tcp/%d", i))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
out[i] = a
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func AssertAddressesEqual(t *testing.T, exp, act []ma.Multiaddr) {
|
||||
t.Helper()
|
||||
if len(exp) != len(act) {
|
||||
t.Fatalf("lengths not the same. expected %d, got %d\n", len(exp), len(act))
|
||||
}
|
||||
|
||||
for _, a := range exp {
|
||||
found := false
|
||||
|
||||
for _, b := range act {
|
||||
if a.Equal(b) {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
t.Fatalf("expected address %s not found", a)
|
||||
}
|
||||
}
|
||||
}
|
19
test/errors.go
Normal file
19
test/errors.go
Normal file
@ -0,0 +1,19 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func AssertNilError(t *testing.T, err error) {
|
||||
t.Helper()
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func ExpectError(t *testing.T, err error, msg string) {
|
||||
t.Helper()
|
||||
if err == nil {
|
||||
t.Error(msg)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user