-
Notifications
You must be signed in to change notification settings - Fork 982
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Migrate from protoc to rust-protobuf #3050
Changes from all commits
29e6c38
ea8a303
1d4f143
7973feb
1d3e247
8acaa31
428f86b
1f9e009
8c7a124
1e38a92
102af4c
936d646
543e7fb
d290be2
deb744e
6c27de8
e7ff68c
fb7e6db
9ae7ac1
c760fff
dfcb5f9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -147,13 +147,15 @@ impl Keypair { | |
|
||
/// Encode a private key as protobuf structure. | ||
pub fn to_protobuf_encoding(&self) -> Result<Vec<u8>, DecodingError> { | ||
use prost::Message; | ||
use protobuf::Message; | ||
|
||
let pk = match self { | ||
Self::Ed25519(data) => keys_proto::PrivateKey { | ||
r#type: keys_proto::KeyType::Ed25519.into(), | ||
data: data.encode().into(), | ||
}, | ||
Self::Ed25519(data) => { | ||
let mut key = keys_proto::PrivateKey::new(); | ||
key.set_Type(keys_proto::KeyType::Ed25519); | ||
key.set_Data(data.encode().into()); | ||
key | ||
} | ||
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))] | ||
Self::Rsa(_) => { | ||
return Err(DecodingError::new( | ||
|
@@ -174,32 +176,35 @@ impl Keypair { | |
} | ||
}; | ||
|
||
Ok(pk.encode_to_vec()) | ||
pk.write_to_bytes() | ||
.map_err(|e| DecodingError::new("Failed to decode.").source(e)) | ||
} | ||
|
||
/// 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 protobuf::Enum; | ||
use protobuf::Message; | ||
|
||
let mut private_key = keys_proto::PrivateKey::decode(bytes) | ||
let mut private_key = keys_proto::PrivateKey::parse_from_bytes(bytes) | ||
.map_err(|e| DecodingError::new("Protobuf").source(e)) | ||
.map(zeroize::Zeroizing::new)?; | ||
|
||
let key_type = keys_proto::KeyType::from_i32(private_key.r#type).ok_or_else(|| { | ||
DecodingError::new(format!("unknown key type: {}", private_key.r#type)) | ||
})?; | ||
let key_type = | ||
keys_proto::KeyType::from_i32(private_key.Type().value()).ok_or_else(|| { | ||
DecodingError::new(format!("unknown key type: {:?}", private_key.Type())) | ||
})?; | ||
Comment on lines
+192
to
+195
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This looks like another round-trip to me? Wouldn't |
||
|
||
match key_type { | ||
keys_proto::KeyType::Ed25519 => { | ||
ed25519::Keypair::decode(&mut private_key.data).map(Keypair::Ed25519) | ||
ed25519::Keypair::decode(private_key.mut_Data()).map(Keypair::Ed25519) | ||
} | ||
keys_proto::KeyType::Rsa => Err(DecodingError::new( | ||
keys_proto::KeyType::RSA => Err(DecodingError::new( | ||
"Decoding RSA key from Protobuf is unsupported.", | ||
)), | ||
keys_proto::KeyType::Secp256k1 => Err(DecodingError::new( | ||
"Decoding Secp256k1 key from Protobuf is unsupported.", | ||
)), | ||
keys_proto::KeyType::Ecdsa => Err(DecodingError::new( | ||
keys_proto::KeyType::ECDSA => Err(DecodingError::new( | ||
"Decoding ECDSA key from Protobuf is unsupported.", | ||
)), | ||
} | ||
|
@@ -208,8 +213,8 @@ impl Keypair { | |
|
||
impl zeroize::Zeroize for keys_proto::PrivateKey { | ||
fn zeroize(&mut self) { | ||
self.r#type.zeroize(); | ||
self.data.zeroize(); | ||
use protobuf::Message; | ||
self.clear() | ||
} | ||
} | ||
|
||
|
@@ -251,23 +256,21 @@ 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 protobuf::Message; | ||
|
||
let public_key = keys_proto::PublicKey::from(self); | ||
|
||
let mut buf = Vec::with_capacity(public_key.encoded_len()); | ||
public_key | ||
.encode(&mut buf) | ||
.expect("Vec<u8> provides capacity as needed"); | ||
buf | ||
.write_to_bytes() | ||
.expect("All fields to be initialized.") | ||
} | ||
|
||
/// 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 protobuf::Message; | ||
|
||
let pubkey = keys_proto::PublicKey::decode(bytes) | ||
let pubkey = keys_proto::PublicKey::parse_from_bytes(bytes) | ||
.map_err(|e| DecodingError::new("Protobuf").source(e))?; | ||
|
||
pubkey.try_into() | ||
|
@@ -282,25 +285,33 @@ impl PublicKey { | |
impl From<&PublicKey> for keys_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) => { | ||
let mut pubkey = keys_proto::PublicKey::new(); | ||
pubkey.set_Type(keys_proto::KeyType::Ed25519); | ||
pubkey.set_Data(key.encode().to_vec()); | ||
pubkey | ||
} | ||
#[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) => { | ||
let mut pubkey = keys_proto::PublicKey::new(); | ||
pubkey.set_Type(keys_proto::KeyType::RSA); | ||
pubkey.set_Data(key.encode_x509()); | ||
pubkey | ||
} | ||
#[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) => { | ||
let mut pubkey = keys_proto::PublicKey::new(); | ||
pubkey.set_Type(keys_proto::KeyType::Secp256k1); | ||
pubkey.set_Data(key.encode().to_vec()); | ||
pubkey | ||
} | ||
#[cfg(feature = "ecdsa")] | ||
PublicKey::Ecdsa(key) => keys_proto::PublicKey { | ||
r#type: keys_proto::KeyType::Ecdsa as i32, | ||
data: key.encode_der(), | ||
}, | ||
PublicKey::Ecdsa(key) => { | ||
let mut pubkey = keys_proto::PublicKey::new(); | ||
pubkey.set_Type(keys_proto::KeyType::ECDSA); | ||
pubkey.set_Data(key.encode_der()); | ||
pubkey | ||
} | ||
} | ||
} | ||
} | ||
|
@@ -309,37 +320,34 @@ impl TryFrom<keys_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::new(format!("unknown key type: {}", pubkey.r#type)))?; | ||
|
||
match key_type { | ||
match pubkey.Type() { | ||
keys_proto::KeyType::Ed25519 => { | ||
ed25519::PublicKey::decode(&pubkey.data).map(PublicKey::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) | ||
keys_proto::KeyType::RSA => { | ||
rsa::PublicKey::decode_x509(pubkey.Data()).map(PublicKey::Rsa) | ||
} | ||
#[cfg(any(not(feature = "rsa"), target_arch = "wasm32"))] | ||
keys_proto::KeyType::Rsa => { | ||
keys_proto::KeyType::RSA => { | ||
log::debug!("support for RSA was disabled at compile-time"); | ||
Err(DecodingError::new("Unsupported")) | ||
} | ||
#[cfg(feature = "secp256k1")] | ||
keys_proto::KeyType::Secp256k1 => { | ||
secp256k1::PublicKey::decode(&pubkey.data).map(PublicKey::Secp256k1) | ||
secp256k1::PublicKey::decode(pubkey.Data()).map(PublicKey::Secp256k1) | ||
} | ||
#[cfg(not(feature = "secp256k1"))] | ||
keys_proto::KeyType::Secp256k1 => { | ||
log::debug!("support for secp256k1 was disabled at compile-time"); | ||
Err(DecodingError::new("Unsupported")) | ||
} | ||
#[cfg(feature = "ecdsa")] | ||
keys_proto::KeyType::Ecdsa => { | ||
ecdsa::PublicKey::decode_der(&pubkey.data).map(PublicKey::Ecdsa) | ||
keys_proto::KeyType::ECDSA => { | ||
ecdsa::PublicKey::decode_der(pubkey.Data()).map(PublicKey::Ecdsa) | ||
} | ||
#[cfg(not(feature = "ecdsa"))] | ||
keys_proto::KeyType::Ecdsa => { | ||
keys_proto::KeyType::ECDSA => { | ||
log::debug!("support for ECDSA was disabled at compile-time"); | ||
Err(DecodingError::new("Unsupported")) | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,11 +30,12 @@ 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 protobuf::Message; | ||
|
||
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)?; | ||
let record = peer_record_proto::PeerRecord::parse_from_bytes(payload) | ||
.map_err(FromEnvelopeError::from)?; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we need the |
||
|
||
let peer_id = PeerId::from_bytes(&record.peer_id)?; | ||
|
||
|
@@ -61,7 +62,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 protobuf::Message; | ||
|
||
let seq = SystemTime::now() | ||
.duration_since(SystemTime::UNIX_EPOCH) | ||
|
@@ -70,22 +71,21 @@ impl PeerRecord { | |
let peer_id = key.public().to_peer_id(); | ||
|
||
let payload = { | ||
let record = peer_record_proto::PeerRecord { | ||
peer_id: peer_id.to_bytes(), | ||
seq, | ||
addresses: addresses | ||
.iter() | ||
.map(|m| peer_record_proto::peer_record::AddressInfo { | ||
multiaddr: m.to_vec(), | ||
}) | ||
.collect(), | ||
}; | ||
let mut record = peer_record_proto::PeerRecord::new(); | ||
record.peer_id = peer_id.to_bytes(); | ||
record.seq = seq; | ||
record.addresses = addresses | ||
.iter() | ||
.map(|m| { | ||
let mut addr_info = peer_record_proto::peer_record::AddressInfo::new(); | ||
addr_info.multiaddr = m.to_vec(); | ||
addr_info | ||
}) | ||
.collect(); | ||
|
||
let mut buf = Vec::with_capacity(record.encoded_len()); | ||
record | ||
.encode(&mut buf) | ||
.expect("Vec<u8> provides capacity as needed"); | ||
buf | ||
.write_to_bytes() | ||
.expect("All fields to be initialized.") | ||
}; | ||
|
||
let envelope = SignedEnvelope::new( | ||
|
@@ -129,7 +129,7 @@ pub enum FromEnvelopeError { | |
/// Failed to extract the payload from the envelope. | ||
BadPayload(signed_envelope::ReadPayloadError), | ||
/// Failed to decode the provided bytes as a [`PeerRecord`]. | ||
InvalidPeerRecord(prost::DecodeError), | ||
InvalidPeerRecord(protobuf::Error), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this part of the public API? If yes, then this is actually a breaking change which is unfortunate :/ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh I missed that. Yes, it is part of the public API 😞. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Damn okay. Well don't worry about it here for now, I'll send a PR that wraps the error here. That is still a breaking change but we can ship that separately! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So my idea here is to make a dedicated error like this: #[derive(thiserror::Error, Debug)]
#[error(transparent)]
pub struct DecodeError(protobuf::Error) This preserves the source chain but hides the concrete error type from the public API. It'd be nice to do this in a separate PR and then put this feature on top of that. Let me know if you'd be happy to do that otherwise I'll try to get to that next week! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
That sounds good!
If you could please do that that would be great! I'll rebase once that is merged. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I starting working on this here: #3058 |
||
/// Failed to decode the peer ID. | ||
InvalidPeerId(multihash::Error), | ||
/// The signer of the envelope is different than the peer id in the record. | ||
|
@@ -144,8 +144,8 @@ impl From<signed_envelope::ReadPayloadError> for FromEnvelopeError { | |
} | ||
} | ||
|
||
impl From<prost::DecodeError> for FromEnvelopeError { | ||
fn from(e: prost::DecodeError) -> Self { | ||
impl From<protobuf::Error> for FromEnvelopeError { | ||
fn from(e: protobuf::Error) -> Self { | ||
Self::InvalidPeerRecord(e) | ||
} | ||
} | ||
|
@@ -213,7 +213,7 @@ mod tests { | |
|
||
#[test] | ||
fn mismatched_signature() { | ||
use prost::Message; | ||
use protobuf::Message; | ||
|
||
let addr: Multiaddr = HOME.parse().unwrap(); | ||
|
||
|
@@ -227,14 +227,12 @@ mod tests { | |
seq: 0, | ||
addresses: vec![peer_record_proto::peer_record::AddressInfo { | ||
multiaddr: addr.to_vec(), | ||
..peer_record_proto::peer_record::AddressInfo::default() | ||
}], | ||
..peer_record_proto::PeerRecord::default() | ||
}; | ||
|
||
let mut buf = Vec::with_capacity(record.encoded_len()); | ||
record | ||
.encode(&mut buf) | ||
.expect("Vec<u8> provides capacity as needed"); | ||
buf | ||
record.write_to_bytes().unwrap() | ||
}; | ||
|
||
SignedEnvelope::new( | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please panic here for consistency.