Skip to content

Commit adcfdc0

Browse files
thomaseizingerrishflabda-kami
authored
protocols/rendezvous: Implement protocol (#2107)
Implement the libp2p rendezvous protocol. > A lightweight mechanism for generalized peer discovery. It can be used for bootstrap purposes, real time peer discovery, application specific routing, and so on. Co-authored-by: rishflab <[email protected]> Co-authored-by: Daniel Karzel <[email protected]>
1 parent c1ae8a0 commit adcfdc0

32 files changed

+4463
-25
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
- [`libp2p-ping` CHANGELOG](protocols/ping/CHANGELOG.md)
1717
- [`libp2p-relay` CHANGELOG](protocols/relay/CHANGELOG.md)
1818
- [`libp2p-request-response` CHANGELOG](protocols/request-response/CHANGELOG.md)
19+
- [`libp2p-rendezvous` CHANGELOG](protocols/rendezvous/CHANGELOG.md)
1920

2021
## Transport Protocols & Upgrades
2122

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ default = [
2525
"pnet",
2626
"relay",
2727
"request-response",
28+
"rendezvous",
2829
"secp256k1",
2930
"tcp-async-io",
3031
"uds",
@@ -48,6 +49,7 @@ plaintext = ["libp2p-plaintext"]
4849
pnet = ["libp2p-pnet"]
4950
relay = ["libp2p-relay"]
5051
request-response = ["libp2p-request-response"]
52+
rendezvous = ["libp2p-rendezvous"]
5153
tcp-async-io = ["libp2p-tcp", "libp2p-tcp/async-io"]
5254
tcp-tokio = ["libp2p-tcp", "libp2p-tcp/tokio"]
5355
uds = ["libp2p-uds"]
@@ -78,6 +80,7 @@ libp2p-ping = { version = "0.31.0", path = "protocols/ping", optional = true }
7880
libp2p-plaintext = { version = "0.30.0", path = "transports/plaintext", optional = true }
7981
libp2p-pnet = { version = "0.22.0", path = "transports/pnet", optional = true }
8082
libp2p-relay = { version = "0.4.0", path = "protocols/relay", optional = true }
83+
libp2p-rendezvous = { version = "0.1.0", path = "protocols/rendezvous", optional = true }
8184
libp2p-request-response = { version = "0.13.0", path = "protocols/request-response", optional = true }
8285
libp2p-swarm = { version = "0.31.0", path = "swarm" }
8386
libp2p-swarm-derive = { version = "0.25.0", path = "swarm-derive" }
@@ -115,6 +118,7 @@ members = [
115118
"muxers/yamux",
116119
"protocols/floodsub",
117120
"protocols/gossipsub",
121+
"protocols/rendezvous",
118122
"protocols/identify",
119123
"protocols/kad",
120124
"protocols/mdns",

core/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,19 @@
3333
- Remove deprecated functions `upgrade::write_one`, `upgrade::write_with_len_prefix`
3434
and `upgrade::read_one` (see [PR 2213]).
3535

36+
- Add `SignedEnvelope` and `PeerRecord` according to [RFC0002] and [RFC0003]
37+
(see [PR 2107]).
38+
3639
[PR 2145]: https://github.com/libp2p/rust-libp2p/pull/2145
3740
[PR 2213]: https://github.com/libp2p/rust-libp2p/pull/2213
3841
[PR 2142]: https://github.com/libp2p/rust-libp2p/pull/2142
3942
[PR 2137]: https://github.com/libp2p/rust-libp2p/pull/2137
4043
[PR 2183]: https://github.com/libp2p/rust-libp2p/pull/2183
4144
[PR 2191]: https://github.com/libp2p/rust-libp2p/pull/2191
4245
[PR 2195]: https://github.com/libp2p/rust-libp2p/pull/2195
46+
[PR 2107]: https://github.com/libp2p/rust-libp2p/pull/2107
47+
[RFC0002]: https://github.com/libp2p/specs/blob/master/RFC/0002-signed-envelopes.md
48+
[RFC0003]: https://github.com/libp2p/specs/blob/master/RFC/0003-routing-records.md
4349

4450
# 0.29.0 [2021-07-12]
4551

core/build.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,13 @@
1919
// DEALINGS IN THE SOFTWARE.
2020

2121
fn main() {
22-
prost_build::compile_protos(&["src/keys.proto"], &["src"]).unwrap();
22+
prost_build::compile_protos(
23+
&[
24+
"src/keys.proto",
25+
"src/envelope.proto",
26+
"src/peer_record.proto",
27+
],
28+
&["src"],
29+
)
30+
.unwrap();
2331
}

core/src/envelope.proto

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
syntax = "proto3";
2+
3+
package envelope_proto;
4+
5+
import "keys.proto";
6+
7+
// Envelope encloses a signed payload produced by a peer, along with the public
8+
// key of the keypair it was signed with so that it can be statelessly validated
9+
// by the receiver.
10+
//
11+
// The payload is prefixed with a byte string that determines the type, so it
12+
// can be deserialized deterministically. Often, this byte string is a
13+
// multicodec.
14+
message Envelope {
15+
// public_key is the public key of the keypair the enclosed payload was
16+
// signed with.
17+
keys_proto.PublicKey public_key = 1;
18+
19+
// payload_type encodes the type of payload, so that it can be deserialized
20+
// deterministically.
21+
bytes payload_type = 2;
22+
23+
// payload is the actual payload carried inside this envelope.
24+
bytes payload = 3;
25+
26+
// signature is the signature produced by the private key corresponding to
27+
// the enclosed public key, over the payload, prefixing a domain string for
28+
// additional security.
29+
bytes signature = 5;
30+
}

core/src/identity.rs

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ pub mod error;
4242

4343
use self::error::*;
4444
use crate::{keys_proto, PeerId};
45+
use std::convert::{TryFrom, TryInto};
4546

4647
/// Identity keypair of a node.
4748
///
@@ -205,6 +206,7 @@ impl PublicKey {
205206
/// that the signature has been produced by the corresponding
206207
/// private key (authenticity), and that the message has not been
207208
/// tampered with (integrity).
209+
#[must_use]
208210
pub fn verify(&self, msg: &[u8], sig: &[u8]) -> bool {
209211
use PublicKey::*;
210212
match self {
@@ -221,7 +223,35 @@ impl PublicKey {
221223
pub fn to_protobuf_encoding(&self) -> Vec<u8> {
222224
use prost::Message;
223225

224-
let public_key = match self {
226+
let public_key = keys_proto::PublicKey::from(self);
227+
228+
let mut buf = Vec::with_capacity(public_key.encoded_len());
229+
public_key
230+
.encode(&mut buf)
231+
.expect("Vec<u8> provides capacity as needed");
232+
buf
233+
}
234+
235+
/// Decode a public key from a protobuf structure, e.g. read from storage
236+
/// or received from another node.
237+
pub fn from_protobuf_encoding(bytes: &[u8]) -> Result<PublicKey, DecodingError> {
238+
use prost::Message;
239+
240+
let pubkey = keys_proto::PublicKey::decode(bytes)
241+
.map_err(|e| DecodingError::new("Protobuf").source(e))?;
242+
243+
pubkey.try_into()
244+
}
245+
246+
/// Convert the `PublicKey` into the corresponding `PeerId`.
247+
pub fn to_peer_id(&self) -> PeerId {
248+
self.into()
249+
}
250+
}
251+
252+
impl From<&PublicKey> for keys_proto::PublicKey {
253+
fn from(key: &PublicKey) -> Self {
254+
match key {
225255
PublicKey::Ed25519(key) => keys_proto::PublicKey {
226256
r#type: keys_proto::KeyType::Ed25519 as i32,
227257
data: key.encode().to_vec(),
@@ -236,24 +266,14 @@ impl PublicKey {
236266
r#type: keys_proto::KeyType::Secp256k1 as i32,
237267
data: key.encode().to_vec(),
238268
},
239-
};
240-
241-
let mut buf = Vec::with_capacity(public_key.encoded_len());
242-
public_key
243-
.encode(&mut buf)
244-
.expect("Vec<u8> provides capacity as needed");
245-
buf
269+
}
246270
}
271+
}
247272

248-
/// Decode a public key from a protobuf structure, e.g. read from storage
249-
/// or received from another node.
250-
pub fn from_protobuf_encoding(bytes: &[u8]) -> Result<PublicKey, DecodingError> {
251-
use prost::Message;
252-
253-
#[allow(unused_mut)] // Due to conditional compilation.
254-
let mut pubkey = keys_proto::PublicKey::decode(bytes)
255-
.map_err(|e| DecodingError::new("Protobuf").source(e))?;
273+
impl TryFrom<keys_proto::PublicKey> for PublicKey {
274+
type Error = DecodingError;
256275

276+
fn try_from(pubkey: keys_proto::PublicKey) -> Result<Self, Self::Error> {
257277
let key_type = keys_proto::KeyType::from_i32(pubkey.r#type)
258278
.ok_or_else(|| DecodingError::new(format!("unknown key type: {}", pubkey.r#type)))?;
259279

@@ -281,11 +301,6 @@ impl PublicKey {
281301
}
282302
}
283303
}
284-
285-
/// Convert the `PublicKey` into the corresponding `PeerId`.
286-
pub fn to_peer_id(&self) -> PeerId {
287-
self.into()
288-
}
289304
}
290305

291306
#[cfg(test)]

core/src/lib.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,14 @@ mod keys_proto {
3939
include!(concat!(env!("OUT_DIR"), "/keys_proto.rs"));
4040
}
4141

42+
mod envelope_proto {
43+
include!(concat!(env!("OUT_DIR"), "/envelope_proto.rs"));
44+
}
45+
46+
mod peer_record_proto {
47+
include!(concat!(env!("OUT_DIR"), "/peer_record_proto.rs"));
48+
}
49+
4250
/// Multi-address re-export.
4351
pub use multiaddr;
4452
pub type Negotiated<T> = multistream_select::Negotiated<T>;
@@ -51,6 +59,8 @@ pub mod either;
5159
pub mod identity;
5260
pub mod muxing;
5361
pub mod network;
62+
pub mod peer_record;
63+
pub mod signed_envelope;
5464
pub mod transport;
5565
pub mod upgrade;
5666

@@ -61,6 +71,8 @@ pub use multihash;
6171
pub use muxing::StreamMuxer;
6272
pub use network::Network;
6373
pub use peer_id::PeerId;
74+
pub use peer_record::PeerRecord;
75+
pub use signed_envelope::SignedEnvelope;
6476
pub use translation::address_translation;
6577
pub use transport::Transport;
6678
pub use upgrade::{InboundUpgrade, OutboundUpgrade, ProtocolName, UpgradeError, UpgradeInfo};

core/src/network/event.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ where
109109
/// A connection may close if
110110
///
111111
/// * it encounters an error, which includes the connection being
112-
/// closed by the remote. In this case `error` is `Some`.
112+
/// closed by the remote. In this case `error` is `ome`.
113113
/// * it was actively closed by [`EstablishedConnection::start_close`],
114114
/// i.e. a successful, orderly close. In this case `error` is `None`.
115115
/// * it was actively closed by [`super::peer::ConnectedPeer::disconnect`] or

core/src/peer_record.proto

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
syntax = "proto3";
2+
3+
package peer_record_proto;
4+
5+
// PeerRecord messages contain information that is useful to share with other peers.
6+
// Currently, a PeerRecord contains the public listen addresses for a peer, but this
7+
// is expected to expand to include other information in the future.
8+
//
9+
// PeerRecords are designed to be serialized to bytes and placed inside of
10+
// SignedEnvelopes before sharing with other peers.
11+
message PeerRecord {
12+
13+
// AddressInfo is a wrapper around a binary multiaddr. It is defined as a
14+
// separate message to allow us to add per-address metadata in the future.
15+
message AddressInfo {
16+
bytes multiaddr = 1;
17+
}
18+
19+
// peer_id contains a libp2p peer id in its binary representation.
20+
bytes peer_id = 1;
21+
22+
// seq contains a monotonically-increasing sequence counter to order PeerRecords in time.
23+
uint64 seq = 2;
24+
25+
// addresses is a list of public listen addresses for the peer.
26+
repeated AddressInfo addresses = 3;
27+
}

0 commit comments

Comments
 (0)