feat: migrate to quick-protobuf

Instead of relying on `protoc` and buildscripts, we generate the bindings using `pb-rs` and version them within our codebase. This makes for a better IDE integration, a faster build and an easier use of `rust-libp2p` because we don't force the `protoc` dependency onto them.

Resolves #3024.

Pull-Request: #3312.
This commit is contained in:
Miguel Guarniz
2023-03-02 05:45:07 -05:00
committed by GitHub
parent 4910160bea
commit db82e0210e
141 changed files with 3662 additions and 1276 deletions

View File

@ -0,0 +1,59 @@
// Automatically generated rust module for 'envelope.proto' file
#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(unused_imports)]
#![allow(unknown_lints)]
#![allow(clippy::all)]
#![cfg_attr(rustfmt, rustfmt_skip)]
use quick_protobuf::{MessageInfo, MessageRead, MessageWrite, BytesReader, Writer, WriterBackend, Result};
use quick_protobuf::sizeofs::*;
use super::*;
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Debug, Default, PartialEq, Clone)]
pub struct Envelope {
pub public_key: Option<keys_proto::PublicKey>,
pub payload_type: Vec<u8>,
pub payload: Vec<u8>,
pub signature: Vec<u8>,
}
impl<'a> MessageRead<'a> for Envelope {
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
let mut msg = Self::default();
while !r.is_eof() {
match r.next_tag(bytes) {
Ok(10) => msg.public_key = Some(r.read_message::<keys_proto::PublicKey>(bytes)?),
Ok(18) => msg.payload_type = r.read_bytes(bytes)?.to_owned(),
Ok(26) => msg.payload = r.read_bytes(bytes)?.to_owned(),
Ok(42) => msg.signature = r.read_bytes(bytes)?.to_owned(),
Ok(t) => { r.read_unknown(bytes, t)?; }
Err(e) => return Err(e),
}
}
Ok(msg)
}
}
impl MessageWrite for Envelope {
fn get_size(&self) -> usize {
0
+ self.public_key.as_ref().map_or(0, |m| 1 + sizeof_len((m).get_size()))
+ if self.payload_type.is_empty() { 0 } else { 1 + sizeof_len((&self.payload_type).len()) }
+ if self.payload.is_empty() { 0 } else { 1 + sizeof_len((&self.payload).len()) }
+ if self.signature.is_empty() { 0 } else { 1 + sizeof_len((&self.signature).len()) }
}
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
if let Some(ref s) = self.public_key { w.write_with_tag(10, |w| w.write_message(s))?; }
if !self.payload_type.is_empty() { w.write_with_tag(18, |w| w.write_bytes(&**&self.payload_type))?; }
if !self.payload.is_empty() { w.write_with_tag(26, |w| w.write_bytes(&**&self.payload))?; }
if !self.signature.is_empty() { w.write_with_tag(42, |w| w.write_bytes(&**&self.signature))?; }
Ok(())
}
}

View File

@ -0,0 +1,125 @@
// Automatically generated rust module for 'keys.proto' file
#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(unused_imports)]
#![allow(unknown_lints)]
#![allow(clippy::all)]
#![cfg_attr(rustfmt, rustfmt_skip)]
use quick_protobuf::{MessageInfo, MessageRead, MessageWrite, BytesReader, Writer, WriterBackend, Result};
use quick_protobuf::sizeofs::*;
use super::*;
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum KeyType {
RSA = 0,
Ed25519 = 1,
Secp256k1 = 2,
ECDSA = 3,
}
impl Default for KeyType {
fn default() -> Self {
KeyType::RSA
}
}
impl From<i32> for KeyType {
fn from(i: i32) -> Self {
match i {
0 => KeyType::RSA,
1 => KeyType::Ed25519,
2 => KeyType::Secp256k1,
3 => KeyType::ECDSA,
_ => Self::default(),
}
}
}
impl<'a> From<&'a str> for KeyType {
fn from(s: &'a str) -> Self {
match s {
"RSA" => KeyType::RSA,
"Ed25519" => KeyType::Ed25519,
"Secp256k1" => KeyType::Secp256k1,
"ECDSA" => KeyType::ECDSA,
_ => Self::default(),
}
}
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Debug, Default, PartialEq, Clone)]
pub struct PublicKey {
pub Type: keys_proto::KeyType,
pub Data: Vec<u8>,
}
impl<'a> MessageRead<'a> for PublicKey {
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
let mut msg = Self::default();
while !r.is_eof() {
match r.next_tag(bytes) {
Ok(8) => msg.Type = r.read_enum(bytes)?,
Ok(18) => msg.Data = r.read_bytes(bytes)?.to_owned(),
Ok(t) => { r.read_unknown(bytes, t)?; }
Err(e) => return Err(e),
}
}
Ok(msg)
}
}
impl MessageWrite for PublicKey {
fn get_size(&self) -> usize {
0
+ 1 + sizeof_varint(*(&self.Type) as u64)
+ 1 + sizeof_len((&self.Data).len())
}
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
w.write_with_tag(8, |w| w.write_enum(*&self.Type as i32))?;
w.write_with_tag(18, |w| w.write_bytes(&**&self.Data))?;
Ok(())
}
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Debug, Default, PartialEq, Clone)]
pub struct PrivateKey {
pub Type: keys_proto::KeyType,
pub Data: Vec<u8>,
}
impl<'a> MessageRead<'a> for PrivateKey {
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
let mut msg = Self::default();
while !r.is_eof() {
match r.next_tag(bytes) {
Ok(8) => msg.Type = r.read_enum(bytes)?,
Ok(18) => msg.Data = r.read_bytes(bytes)?.to_owned(),
Ok(t) => { r.read_unknown(bytes, t)?; }
Err(e) => return Err(e),
}
}
Ok(msg)
}
}
impl MessageWrite for PrivateKey {
fn get_size(&self) -> usize {
0
+ 1 + sizeof_varint(*(&self.Type) as u64)
+ 1 + sizeof_len((&self.Data).len())
}
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
w.write_with_tag(8, |w| w.write_enum(*&self.Type as i32))?;
w.write_with_tag(18, |w| w.write_bytes(&**&self.Data))?;
Ok(())
}
}

View File

@ -0,0 +1,4 @@
// Automatically generated mod.rs
pub mod envelope_proto;
pub mod keys_proto;
pub mod peer_record_proto;

View File

@ -0,0 +1,93 @@
// Automatically generated rust module for 'peer_record.proto' file
#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(unused_imports)]
#![allow(unknown_lints)]
#![allow(clippy::all)]
#![cfg_attr(rustfmt, rustfmt_skip)]
use quick_protobuf::{MessageInfo, MessageRead, MessageWrite, BytesReader, Writer, WriterBackend, Result};
use quick_protobuf::sizeofs::*;
use super::*;
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Debug, Default, PartialEq, Clone)]
pub struct PeerRecord {
pub peer_id: Vec<u8>,
pub seq: u64,
pub addresses: Vec<peer_record_proto::mod_PeerRecord::AddressInfo>,
}
impl<'a> MessageRead<'a> for PeerRecord {
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
let mut msg = Self::default();
while !r.is_eof() {
match r.next_tag(bytes) {
Ok(10) => msg.peer_id = r.read_bytes(bytes)?.to_owned(),
Ok(16) => msg.seq = r.read_uint64(bytes)?,
Ok(26) => msg.addresses.push(r.read_message::<peer_record_proto::mod_PeerRecord::AddressInfo>(bytes)?),
Ok(t) => { r.read_unknown(bytes, t)?; }
Err(e) => return Err(e),
}
}
Ok(msg)
}
}
impl MessageWrite for PeerRecord {
fn get_size(&self) -> usize {
0
+ if self.peer_id.is_empty() { 0 } else { 1 + sizeof_len((&self.peer_id).len()) }
+ if self.seq == 0u64 { 0 } else { 1 + sizeof_varint(*(&self.seq) as u64) }
+ self.addresses.iter().map(|s| 1 + sizeof_len((s).get_size())).sum::<usize>()
}
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
if !self.peer_id.is_empty() { w.write_with_tag(10, |w| w.write_bytes(&**&self.peer_id))?; }
if self.seq != 0u64 { w.write_with_tag(16, |w| w.write_uint64(*&self.seq))?; }
for s in &self.addresses { w.write_with_tag(26, |w| w.write_message(s))?; }
Ok(())
}
}
pub mod mod_PeerRecord {
use super::*;
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Debug, Default, PartialEq, Clone)]
pub struct AddressInfo {
pub multiaddr: Vec<u8>,
}
impl<'a> MessageRead<'a> for AddressInfo {
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
let mut msg = Self::default();
while !r.is_eof() {
match r.next_tag(bytes) {
Ok(10) => msg.multiaddr = r.read_bytes(bytes)?.to_owned(),
Ok(t) => { r.read_unknown(bytes, t)?; }
Err(e) => return Err(e),
}
}
Ok(msg)
}
}
impl MessageWrite for AddressInfo {
fn get_size(&self) -> usize {
0
+ if self.multiaddr.is_empty() { 0 } else { 1 + sizeof_len((&self.multiaddr).len()) }
}
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
if !self.multiaddr.is_empty() { w.write_with_tag(10, |w| w.write_bytes(&**&self.multiaddr))?; }
Ok(())
}
}
}

View File

@ -43,7 +43,8 @@ pub mod secp256k1;
pub mod error;
use self::error::*;
use crate::{keys_proto, PeerId};
use crate::{proto, PeerId};
use quick_protobuf::{BytesReader, Writer};
use std::convert::{TryFrom, TryInto};
/// Identity keypair of a node.
@ -147,12 +148,12 @@ impl Keypair {
/// Encode a private key as protobuf structure.
pub fn to_protobuf_encoding(&self) -> Result<Vec<u8>, DecodingError> {
use prost::Message;
use quick_protobuf::MessageWrite;
let pk = match self {
Self::Ed25519(data) => keys_proto::PrivateKey {
r#type: keys_proto::KeyType::Ed25519.into(),
data: data.encode().into(),
Self::Ed25519(data) => proto::PrivateKey {
Type: proto::KeyType::Ed25519,
Data: data.encode().to_vec(),
},
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
Self::Rsa(_) => return Err(DecodingError::encoding_unsupported("RSA")),
@ -162,35 +163,38 @@ impl Keypair {
Self::Ecdsa(_) => return Err(DecodingError::encoding_unsupported("ECDSA")),
};
Ok(pk.encode_to_vec())
let mut buf = Vec::with_capacity(pk.get_size());
let mut writer = Writer::new(&mut buf);
pk.write_message(&mut writer).expect("Encoding to succeed");
Ok(buf)
}
/// Decode a private key from a protobuf structure and parse it as a [`Keypair`].
pub fn from_protobuf_encoding(bytes: &[u8]) -> Result<Keypair, DecodingError> {
use prost::Message;
use quick_protobuf::MessageRead;
let mut private_key = keys_proto::PrivateKey::decode(bytes)
let mut reader = BytesReader::from_bytes(bytes);
let mut private_key = proto::PrivateKey::from_reader(&mut reader, bytes)
.map_err(|e| DecodingError::bad_protobuf("private key bytes", e))
.map(zeroize::Zeroizing::new)?;
let key_type = keys_proto::KeyType::from_i32(private_key.r#type)
.ok_or_else(|| DecodingError::unknown_key_type(private_key.r#type))?;
match key_type {
keys_proto::KeyType::Ed25519 => {
ed25519::Keypair::decode(&mut private_key.data).map(Keypair::Ed25519)
match private_key.Type {
proto::KeyType::Ed25519 => {
ed25519::Keypair::decode(&mut private_key.Data).map(Keypair::Ed25519)
}
keys_proto::KeyType::Rsa => Err(DecodingError::decoding_unsupported("RSA")),
keys_proto::KeyType::Secp256k1 => Err(DecodingError::decoding_unsupported("secp256k1")),
keys_proto::KeyType::Ecdsa => Err(DecodingError::decoding_unsupported("ECDSA")),
proto::KeyType::RSA => Err(DecodingError::decoding_unsupported("RSA")),
proto::KeyType::Secp256k1 => Err(DecodingError::decoding_unsupported("secp256k1")),
proto::KeyType::ECDSA => Err(DecodingError::decoding_unsupported("ECDSA")),
}
}
}
impl zeroize::Zeroize for keys_proto::PrivateKey {
impl zeroize::Zeroize for proto::PrivateKey {
fn zeroize(&mut self) {
self.r#type.zeroize();
self.data.zeroize();
// KeyType cannot be zeroized.
self.Type = proto::KeyType::default();
self.Data.zeroize();
}
}
@ -232,23 +236,27 @@ impl PublicKey {
/// Encode the public key into a protobuf structure for storage or
/// exchange with other nodes.
pub fn to_protobuf_encoding(&self) -> Vec<u8> {
use prost::Message;
use quick_protobuf::MessageWrite;
let public_key = keys_proto::PublicKey::from(self);
let public_key = proto::PublicKey::from(self);
let mut buf = Vec::with_capacity(public_key.encoded_len());
let mut buf = Vec::with_capacity(public_key.get_size());
let mut writer = Writer::new(&mut buf);
public_key
.encode(&mut buf)
.expect("Vec<u8> provides capacity as needed");
.write_message(&mut writer)
.expect("Encoding to succeed");
buf
}
/// Decode a public key from a protobuf structure, e.g. read from storage
/// or received from another node.
pub fn from_protobuf_encoding(bytes: &[u8]) -> Result<PublicKey, DecodingError> {
use prost::Message;
use quick_protobuf::MessageRead;
let pubkey = keys_proto::PublicKey::decode(bytes)
let mut reader = BytesReader::from_bytes(bytes);
let pubkey = proto::PublicKey::from_reader(&mut reader, bytes)
.map_err(|e| DecodingError::bad_protobuf("public key bytes", e))?;
pubkey.try_into()
@ -260,67 +268,62 @@ impl PublicKey {
}
}
impl From<&PublicKey> for keys_proto::PublicKey {
impl From<&PublicKey> for proto::PublicKey {
fn from(key: &PublicKey) -> Self {
match key {
PublicKey::Ed25519(key) => keys_proto::PublicKey {
r#type: keys_proto::KeyType::Ed25519 as i32,
data: key.encode().to_vec(),
PublicKey::Ed25519(key) => proto::PublicKey {
Type: proto::KeyType::Ed25519,
Data: key.encode().to_vec(),
},
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
PublicKey::Rsa(key) => keys_proto::PublicKey {
r#type: keys_proto::KeyType::Rsa as i32,
data: key.encode_x509(),
PublicKey::Rsa(key) => proto::PublicKey {
Type: proto::KeyType::RSA,
Data: key.encode_x509(),
},
#[cfg(feature = "secp256k1")]
PublicKey::Secp256k1(key) => keys_proto::PublicKey {
r#type: keys_proto::KeyType::Secp256k1 as i32,
data: key.encode().to_vec(),
PublicKey::Secp256k1(key) => proto::PublicKey {
Type: proto::KeyType::Secp256k1,
Data: key.encode().to_vec(),
},
#[cfg(feature = "ecdsa")]
PublicKey::Ecdsa(key) => keys_proto::PublicKey {
r#type: keys_proto::KeyType::Ecdsa as i32,
data: key.encode_der(),
PublicKey::Ecdsa(key) => proto::PublicKey {
Type: proto::KeyType::ECDSA,
Data: key.encode_der(),
},
}
}
}
impl TryFrom<keys_proto::PublicKey> for PublicKey {
impl TryFrom<proto::PublicKey> for PublicKey {
type Error = DecodingError;
fn try_from(pubkey: keys_proto::PublicKey) -> Result<Self, Self::Error> {
let key_type = keys_proto::KeyType::from_i32(pubkey.r#type)
.ok_or_else(|| DecodingError::unknown_key_type(pubkey.r#type))?;
match key_type {
keys_proto::KeyType::Ed25519 => {
ed25519::PublicKey::decode(&pubkey.data).map(PublicKey::Ed25519)
fn try_from(pubkey: proto::PublicKey) -> Result<Self, Self::Error> {
match pubkey.Type {
proto::KeyType::Ed25519 => {
ed25519::PublicKey::decode(&pubkey.Data).map(PublicKey::Ed25519)
}
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
keys_proto::KeyType::Rsa => {
rsa::PublicKey::decode_x509(&pubkey.data).map(PublicKey::Rsa)
}
proto::KeyType::RSA => rsa::PublicKey::decode_x509(&pubkey.Data).map(PublicKey::Rsa),
#[cfg(any(not(feature = "rsa"), target_arch = "wasm32"))]
keys_proto::KeyType::Rsa => {
proto::KeyType::RSA => {
log::debug!("support for RSA was disabled at compile-time");
Err(DecodingError::missing_feature("rsa"))
}
#[cfg(feature = "secp256k1")]
keys_proto::KeyType::Secp256k1 => {
secp256k1::PublicKey::decode(&pubkey.data).map(PublicKey::Secp256k1)
proto::KeyType::Secp256k1 => {
secp256k1::PublicKey::decode(&pubkey.Data).map(PublicKey::Secp256k1)
}
#[cfg(not(feature = "secp256k1"))]
keys_proto::KeyType::Secp256k1 => {
proto::KeyType::Secp256k1 => {
log::debug!("support for secp256k1 was disabled at compile-time");
Err(DecodingError::missing_feature("secp256k1"))
}
#[cfg(feature = "ecdsa")]
keys_proto::KeyType::Ecdsa => {
ecdsa::PublicKey::decode_der(&pubkey.data).map(PublicKey::Ecdsa)
proto::KeyType::ECDSA => {
ecdsa::PublicKey::decode_der(&pubkey.Data).map(PublicKey::Ecdsa)
}
#[cfg(not(feature = "ecdsa"))]
keys_proto::KeyType::Ecdsa => {
proto::KeyType::ECDSA => {
log::debug!("support for ECDSA was disabled at compile-time");
Err(DecodingError::missing_feature("ecdsa"))
}

View File

@ -68,13 +68,6 @@ impl DecodingError {
}
}
pub(crate) fn unknown_key_type(key_type: i32) -> Self {
Self {
msg: format!("unknown key-type {key_type}"),
source: None,
}
}
pub(crate) fn decoding_unsupported(key_type: &'static str) -> Self {
Self {
msg: format!("decoding {key_type} key from Protobuf is unsupported"),

View File

@ -37,22 +37,18 @@
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
#[allow(clippy::derive_partial_eq_without_eq)]
mod keys_proto {
include!(concat!(env!("OUT_DIR"), "/keys_proto.rs"));
}
mod envelope_proto {
include!(concat!(env!("OUT_DIR"), "/envelope_proto.rs"));
}
#[allow(clippy::derive_partial_eq_without_eq)]
mod peer_record_proto {
include!(concat!(env!("OUT_DIR"), "/peer_record_proto.rs"));
mod proto {
include!("generated/mod.rs");
pub use self::{
envelope_proto::*, keys_proto::*, peer_record_proto::mod_PeerRecord::*,
peer_record_proto::PeerRecord,
};
}
/// Multi-address re-export.
pub use multiaddr;
use std::fmt;
use std::fmt::Formatter;
pub type Negotiated<T> = multistream_select::Negotiated<T>;
mod peer_id;
@ -80,6 +76,17 @@ pub use translation::address_translation;
pub use transport::Transport;
pub use upgrade::{InboundUpgrade, OutboundUpgrade, ProtocolName, UpgradeError, UpgradeInfo};
#[derive(thiserror::Error, Debug)]
#[error(transparent)]
pub struct DecodeError(prost::DecodeError);
#[derive(Debug, thiserror::Error)]
pub struct DecodeError(String);
impl From<quick_protobuf::Error> for DecodeError {
fn from(e: quick_protobuf::Error) -> Self {
Self(e.to_string())
}
}
impl fmt::Display for DecodeError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}

View File

@ -1,8 +1,10 @@
use crate::identity::error::SigningError;
use crate::identity::Keypair;
use crate::proto;
use crate::signed_envelope::SignedEnvelope;
use crate::{peer_record_proto, signed_envelope, DecodeError, Multiaddr, PeerId};
use crate::{signed_envelope, DecodeError, Multiaddr, PeerId};
use instant::SystemTime;
use quick_protobuf::{BytesReader, Writer};
use std::convert::TryInto;
const PAYLOAD_TYPE: &str = "/libp2p/routing-state-record";
@ -29,11 +31,13 @@ impl PeerRecord {
///
/// If this function succeeds, the [`SignedEnvelope`] contained a peer record with a valid signature and can hence be considered authenticated.
pub fn from_signed_envelope(envelope: SignedEnvelope) -> Result<Self, FromEnvelopeError> {
use prost::Message;
use quick_protobuf::MessageRead;
let (payload, signing_key) =
envelope.payload_and_signing_key(String::from(DOMAIN_SEP), PAYLOAD_TYPE.as_bytes())?;
let record = peer_record_proto::PeerRecord::decode(payload).map_err(DecodeError)?;
let mut reader = BytesReader::from_bytes(payload);
let record =
proto::PeerRecord::from_reader(&mut reader, payload).map_err(DecodeError::from)?;
let peer_id = PeerId::from_bytes(&record.peer_id)?;
@ -45,7 +49,7 @@ impl PeerRecord {
let addresses = record
.addresses
.into_iter()
.map(|a| a.multiaddr.try_into())
.map(|a| a.multiaddr.to_vec().try_into())
.collect::<Result<Vec<_>, _>>()?;
Ok(Self {
@ -60,7 +64,7 @@ impl PeerRecord {
///
/// This is the same key that is used for authenticating every libp2p connection of your application, i.e. what you use when setting up your [`crate::transport::Transport`].
pub fn new(key: &Keypair, addresses: Vec<Multiaddr>) -> Result<Self, SigningError> {
use prost::Message;
use quick_protobuf::MessageWrite;
let seq = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
@ -69,21 +73,23 @@ impl PeerRecord {
let peer_id = key.public().to_peer_id();
let payload = {
let record = peer_record_proto::PeerRecord {
let record = proto::PeerRecord {
peer_id: peer_id.to_bytes(),
seq,
addresses: addresses
.iter()
.map(|m| peer_record_proto::peer_record::AddressInfo {
.map(|m| proto::AddressInfo {
multiaddr: m.to_vec(),
})
.collect(),
};
let mut buf = Vec::with_capacity(record.encoded_len());
let mut buf = Vec::with_capacity(record.get_size());
let mut writer = Writer::new(&mut buf);
record
.encode(&mut buf)
.expect("Vec<u8> provides capacity as needed");
.write_message(&mut writer)
.expect("Encoding to succeed");
buf
};
@ -162,7 +168,7 @@ mod tests {
#[test]
fn mismatched_signature() {
use prost::Message;
use quick_protobuf::MessageWrite;
let addr: Multiaddr = HOME.parse().unwrap();
@ -171,18 +177,20 @@ mod tests {
let identity_b = Keypair::generate_ed25519();
let payload = {
let record = peer_record_proto::PeerRecord {
let record = proto::PeerRecord {
peer_id: identity_a.public().to_peer_id().to_bytes(),
seq: 0,
addresses: vec![peer_record_proto::peer_record::AddressInfo {
addresses: vec![proto::AddressInfo {
multiaddr: addr.to_vec(),
}],
};
let mut buf = Vec::with_capacity(record.encoded_len());
let mut buf = Vec::with_capacity(record.get_size());
let mut writer = Writer::new(&mut buf);
record
.encode(&mut buf)
.expect("Vec<u8> provides capacity as needed");
.write_message(&mut writer)
.expect("Encoding to succeed");
buf
};

View File

@ -1,6 +1,7 @@
use crate::identity::error::SigningError;
use crate::identity::Keypair;
use crate::{identity, DecodeError, PublicKey};
use crate::{identity, proto, DecodeError, PublicKey};
use quick_protobuf::{BytesReader, Writer};
use std::convert::TryInto;
use std::fmt;
use unsigned_varint::encode::usize_buffer;
@ -73,37 +74,41 @@ impl SignedEnvelope {
/// Encode this [`SignedEnvelope`] using the protobuf encoding specified in the RFC.
pub fn into_protobuf_encoding(self) -> Vec<u8> {
use prost::Message;
use quick_protobuf::MessageWrite;
let envelope = crate::envelope_proto::Envelope {
let envelope = proto::Envelope {
public_key: Some((&self.key).into()),
payload_type: self.payload_type,
payload: self.payload,
signature: self.signature,
};
let mut buf = Vec::with_capacity(envelope.encoded_len());
let mut buf = Vec::with_capacity(envelope.get_size());
let mut writer = Writer::new(&mut buf);
envelope
.encode(&mut buf)
.expect("Vec<u8> provides capacity as needed");
.write_message(&mut writer)
.expect("Encoding to succeed");
buf
}
/// Decode a [`SignedEnvelope`] using the protobuf encoding specified in the RFC.
pub fn from_protobuf_encoding(bytes: &[u8]) -> Result<Self, DecodingError> {
use prost::Message;
use quick_protobuf::MessageRead;
let envelope = crate::envelope_proto::Envelope::decode(bytes).map_err(DecodeError)?;
let mut reader = BytesReader::from_bytes(bytes);
let envelope =
proto::Envelope::from_reader(&mut reader, bytes).map_err(DecodeError::from)?;
Ok(Self {
key: envelope
.public_key
.ok_or(DecodingError::MissingPublicKey)?
.try_into()?,
payload_type: envelope.payload_type,
payload: envelope.payload,
signature: envelope.signature,
payload_type: envelope.payload_type.to_vec(),
payload: envelope.payload.to_vec(),
signature: envelope.signature.to_vec(),
})
}
}