Skip to content

Commit

Permalink
Create a trait for with a blanket impl instead of new type
Browse files Browse the repository at this point in the history
Thanks for the suggestion @tarcieri :-)
  • Loading branch information
liamsi committed Nov 11, 2019
1 parent 23ed2dc commit 5071ede
Show file tree
Hide file tree
Showing 5 changed files with 21 additions and 40 deletions.
42 changes: 12 additions & 30 deletions tendermint/src/amino_types/message.rs
Original file line number Diff line number Diff line change
@@ -1,39 +1,21 @@
/// A wrapper whose sole purpose is to extend the original
/// prost::Message trait with a few helper functions in order to reduce boiler-plate code
/// (and without modifying the prost-amino dependency).
pub struct AminoMessage<M>(M); // Note: we have to introduce a new type in order to add methods like bytes_vec or impl Into<Vec<u8>>

impl<M> AminoMessage<M>
where
M: prost_amino::Message,
{
/// Returns a wrapper for the given prost-amino message
pub fn new(m: M) -> AminoMessage<M> {
AminoMessage(m)
}
/// Extend the original prost::Message trait with a few helper functions in order to
/// reduce boiler-plate code (and without modifying the prost-amino dependency).
pub trait AminoMessage: prost_amino::Message {
/// Directly amino encode a prost-amino message into a freshly created Vec<u8>.
/// This can be useful when passing those bytes directly to a hasher, or,
/// to reduce boiler plate code when working with the encoded bytes.
///
/// Warning: Only use this method, if you are in control what will be encoded.
/// If there is an encoding error, this method will panic.
pub fn bytes_vec(m: M) -> Vec<u8> {
AminoMessage(m).into()
}
}

impl<M> Into<Vec<u8>> for AminoMessage<M>
where
M: prost_amino::Message,
{
/// Convert a wrapped prost-amino message directly into a byte vector which contains the amino
/// encoding.
///
/// Warning: Only use this method, if you are in control what will be encoded. If there is an
/// encoding error, this method will panic.
fn into(self) -> Vec<u8> {
let mut res = Vec::with_capacity(self.0.encoded_len());
self.0.encode(&mut res).unwrap();
fn bytes_vec(&self) -> Vec<u8>
where
Self: Sized,
{
let mut res = Vec::with_capacity(self.encoded_len());
self.encode(&mut res).unwrap();
res
}
}
impl<M: prost_amino::Message> AminoMessage for M {
// blanket impl
}
9 changes: 4 additions & 5 deletions tendermint/src/amino_types/vote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,6 @@ mod tests {
use crate::amino_types::message::AminoMessage;
use crate::amino_types::SignedMsgType;
use chrono::{DateTime, Utc};
use prost::Message;

#[test]
fn test_vote_serialization() {
Expand Down Expand Up @@ -334,7 +333,7 @@ mod tests {
vt_precommit.vote_type = SignedMsgType::PreCommit.to_u32(); // precommit
println!("{:?}", vt_precommit);
let cv_precommit = CanonicalVote::new(vt_precommit, "");
let got = AminoMessage::bytes_vec(cv_precommit);
let got = AminoMessage::bytes_vec(&cv_precommit);
let want = vec![
0x8, // (field_number << 3) | wire_type
0x2, // PrecommitType
Expand All @@ -357,7 +356,7 @@ mod tests {

let cv_prevote = CanonicalVote::new(vt_prevote, "");

let got = AminoMessage::bytes_vec(cv_prevote);
let got = AminoMessage::bytes_vec(&cv_prevote);

let want = vec![
0x8, // (field_number << 3) | wire_type
Expand All @@ -379,7 +378,7 @@ mod tests {
vt_no_type.round = 1;

let cv = CanonicalVote::new(vt_no_type, "");
let got = AminoMessage::bytes_vec(cv);
let got = AminoMessage::bytes_vec(&cv);

let want = vec![
0x11, // (field_number << 3) | wire_type
Expand All @@ -398,7 +397,7 @@ mod tests {
no_vote_type2.round = 1;

let with_chain_id = CanonicalVote::new(no_vote_type2, "test_chain_id");
got = AminoMessage::bytes_vec(with_chain_id);
got = AminoMessage::bytes_vec(&with_chain_id);
let want = vec![
0x11, // (field_number << 3) | wire_type
0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // height
Expand Down
6 changes: 3 additions & 3 deletions tendermint/src/block/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,15 +95,15 @@ impl lite::Header for Header {
// https://github.com/tendermint/tendermint/blob/134fe2896275bb926b49743c1e25493f6b24cc31/types/encoding_helper.go#L9:6

let mut byteslices: Vec<Vec<u8>> = Vec::with_capacity(16);
byteslices.push(AminoMessage::bytes_vec(ConsensusVersion::from(
byteslices.push(AminoMessage::bytes_vec(&ConsensusVersion::from(
&self.version,
)));
byteslices.push(bytes_enc(self.chain_id.as_bytes()));
byteslices.push(encode_varint(self.height.value()));
byteslices.push(AminoMessage::bytes_vec(TimeMsg::from(self.time)));
byteslices.push(AminoMessage::bytes_vec(&TimeMsg::from(self.time)));
byteslices.push(encode_varint(self.num_txs));
byteslices.push(encode_varint(self.total_txs));
byteslices.push(AminoMessage::bytes_vec(BlockId::from(&self.last_block_id)));
byteslices.push(AminoMessage::bytes_vec(&BlockId::from(&self.last_block_id)));
byteslices.push(encode_hash(self.last_commit_hash));
byteslices.push(encode_hash(self.data_hash));
byteslices.push(encode_hash(self.validators_hash));
Expand Down
2 changes: 1 addition & 1 deletion tendermint/src/validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ impl From<&Info> for InfoHashable {
// pubkey and voting power, so it includes the pubkey's amino prefix.
impl Info {
fn hash_bytes(&self) -> Vec<u8> {
AminoMessage::bytes_vec(InfoHashable::from(self))
AminoMessage::bytes_vec(&InfoHashable::from(self))
}
}

Expand Down
2 changes: 1 addition & 1 deletion tendermint/src/vote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ impl lite::Vote for SignedVote {
}

fn sign_bytes(&self) -> Vec<u8> {
AminoMessage::bytes_vec(self.vote.to_owned())
AminoMessage::bytes_vec(&self.vote.to_owned())
}
fn signature(&self) -> &[u8] {
match &self.signature {
Expand Down

0 comments on commit 5071ede

Please sign in to comment.