Skip to content
This repository has been archived by the owner on Feb 25, 2021. It is now read-only.

Commit

Permalink
Update crypto-com-chain branch for the new PR request (#3)
Browse files Browse the repository at this point in the history
* build(deps): update tai64 requirement from 2 to 3 (informalsystems#22)

Updates the requirements on [tai64](https://github.com/iqlusioninc/crates) to permit the latest version.
- [Release notes](https://github.com/iqlusioninc/crates/releases)
- [Commits](iqlusioninc/crates@canonical-path/v2.0.0...tai64/3.0.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

* simple_hash_from_byte_slices takes a Vec instead of slice

* cargo fmt

* WIP: pass in Vec<Vec<u8> instead of &Vec<Vec<u8>

 - work in progress as we might want to let an inner function for the
   recursion
 - also we might simply want to use From to consume (or create a Vec)
   instead of changing the method signature (as suggested here:
   informalsystems#57 (comment))

* use Vec<Vec<u8>> with inner recursion method

* merge in changes of informalsystems#59 and simplify Header::hash

* simplify tests:
 direct vector initialization instead of going through &[&[u8]]

* remove obsolete comment

* Further reduce boilerplate code by leveraging generics

* max_gas should be i64, can be -1

* remove unneed clones

* remove secret_connection

* Create a trait for with a blanket impl instead of new type

Thanks for the suggestion @tarcieri :-)

* impl lite::Commit for commit::SignedHeader

* Parse validators field in genesis api

* Modify lite::Commit impl for SignedHeader to not include amino dep:

 - SignedVote can now be constructed without going through CanoncialVote
   (which is an amino-type)
 - modify impl to match new constructor and remove amino dep
 - make explicit where which types are amino_types (in vote.rs)

* impl lite::ValidatorSetLookup

* Add a few methods to tests and deduplicate code for fn hash of
lite::ValidatorSet:: & Set

- tests for  lite::ValidatorSetLookup lite::ValidatorSet impl
- delete `fn hash(self) -> merkle::Hash` from Set and only keep the impl
  of lite::ValidatorSet

* implement utility traits for tendermint data types

* Signing bytes need to encoded with encode_length_delimited

* utilities
  • Loading branch information
yihuang authored and tomtau committed Nov 19, 2019
1 parent bb27fdc commit fb56737
Show file tree
Hide file tree
Showing 12 changed files with 162 additions and 110 deletions.
1 change: 1 addition & 0 deletions tendermint/src/amino_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

pub mod block_id;
pub mod ed25519;
pub mod message;
pub mod ping;
pub mod proposal;
pub mod remote_error;
Expand Down
37 changes: 37 additions & 0 deletions tendermint/src/amino_types/message.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use prost_amino::encoding::encoded_len_varint;

/// 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.
fn bytes_vec(&self) -> Vec<u8>
where
Self: Sized,
{
let mut res = Vec::with_capacity(self.encoded_len());
self.encode(&mut res).unwrap();
res
}

/// Encode prost-amino message as length delimited.
///
/// 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 bytes_vec_length_delimited(&self) -> Vec<u8>
where
Self: Sized,
{
let len = self.encoded_len();
let mut res = Vec::with_capacity(len + encoded_len_varint(len as u64));
self.encode_length_delimited(&mut res).unwrap();
res
}
}
impl<M: prost_amino::Message> AminoMessage for M {
// blanket impl
}
14 changes: 5 additions & 9 deletions tendermint/src/amino_types/vote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,9 +245,9 @@ impl ConsensusMessage for Vote {
mod tests {
use super::super::PartsSetHeader;
use super::*;
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 @@ -333,8 +333,7 @@ mod tests {
vt_precommit.vote_type = SignedMsgType::PreCommit.to_u32(); // precommit
println!("{:?}", vt_precommit);
let cv_precommit = CanonicalVote::new(vt_precommit, "");
got = vec![];
cv_precommit.encode(&mut got).unwrap();
let got = AminoMessage::bytes_vec(&cv_precommit);
let want = vec![
0x8, // (field_number << 3) | wire_type
0x2, // PrecommitType
Expand All @@ -355,10 +354,9 @@ mod tests {
vt_prevote.round = 1;
vt_prevote.vote_type = SignedMsgType::PreVote.to_u32();

got = vec![];
let cv_prevote = CanonicalVote::new(vt_prevote, "");

cv_prevote.encode(&mut got).unwrap();
let got = AminoMessage::bytes_vec(&cv_prevote);

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

got = vec![];
let cv = CanonicalVote::new(vt_no_type, "");
cv.encode(&mut got).unwrap();
let got = AminoMessage::bytes_vec(&cv);

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

let with_chain_id = CanonicalVote::new(no_vote_type2, "test_chain_id");
got = vec![];
with_chain_id.encode(&mut got).unwrap();
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
74 changes: 24 additions & 50 deletions tendermint/src/block/header.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Block headers
use crate::merkle::simple_hash_from_byte_slices;
use crate::{account, amino_types, block, chain, lite, Hash, Time};
use prost::Message;
use amino_types::{message::AminoMessage, BlockId, ConsensusVersion, TimeMsg};
use {
crate::serializers,
serde::{Deserialize, Serialize},
Expand Down Expand Up @@ -89,58 +89,32 @@ impl lite::Header for Header {
}

fn hash(&self) -> Hash {
let mut version_enc = vec![];
// TODO: if there is an encoding problem this will
// Note that if there is an encoding problem this will
// panic (as the golang code would):
// https://github.com/tendermint/tendermint/blob/134fe2896275bb926b49743c1e25493f6b24cc31/types/block.go#L393
// https://github.com/tendermint/tendermint/blob/134fe2896275bb926b49743c1e25493f6b24cc31/types/encoding_helper.go#L9:6
// Instead, handle errors gracefully here.
amino_types::ConsensusVersion::from(&self.version)
.encode(&mut version_enc)
.unwrap();
let height_enc = encode_varint(self.height.value());
let mut time_enc = vec![];
amino_types::TimeMsg::from(self.time)
.encode(&mut time_enc)
.unwrap();
let chain_id_bytes = self.chain_id.as_bytes();
let chain_id_enc = bytes_enc(&chain_id_bytes);
let num_tx_enc = encode_varint(self.num_txs);
let total_tx_enc = encode_varint(self.total_txs);
let mut last_block_id_enc = vec![];
amino_types::BlockId::from(&self.last_block_id)
.encode(&mut last_block_id_enc)
.unwrap();
let last_commit_hash_enc = encode_hash(self.last_commit_hash);
let data_hash_enc = encode_hash(self.data_hash);
let validator_hash_enc = encode_hash(self.validators_hash);
let next_validator_hash_enc = encode_hash(self.next_validators_hash);
let consensus_hash_enc = encode_hash(self.consensus_hash);
let app_hash_enc = encode_hash(self.app_hash);
let last_result_hash_enc = encode_hash(self.last_results_hash);
let evidence_hash_enc = encode_hash(self.evidence_hash);
let proposer_address_bytes = self.proposer_address.as_bytes();
let proposer_address_enc = bytes_enc(&proposer_address_bytes);

let mut byteslices: Vec<&[u8]> = vec![];
byteslices.push(version_enc.as_slice());
byteslices.push(chain_id_enc.as_slice());
byteslices.push(height_enc.as_slice());
byteslices.push(time_enc.as_slice());
byteslices.push(num_tx_enc.as_slice());
byteslices.push(total_tx_enc.as_slice());
byteslices.push(last_block_id_enc.as_slice());
byteslices.push(last_commit_hash_enc.as_slice());
byteslices.push(data_hash_enc.as_slice());
byteslices.push(validator_hash_enc.as_slice());
byteslices.push(next_validator_hash_enc.as_slice());
byteslices.push(consensus_hash_enc.as_slice());
byteslices.push(app_hash_enc.as_slice());
byteslices.push(last_result_hash_enc.as_slice());
byteslices.push(evidence_hash_enc.as_slice());
byteslices.push(proposer_address_enc.as_slice());

Hash::Sha256(simple_hash_from_byte_slices(byteslices.as_slice()))

let mut byteslices: Vec<Vec<u8>> = Vec::with_capacity(16);
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(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(encode_hash(self.last_commit_hash));
byteslices.push(encode_hash(self.data_hash));
byteslices.push(encode_hash(self.validators_hash));
byteslices.push(encode_hash(self.next_validators_hash));
byteslices.push(encode_hash(self.consensus_hash));
byteslices.push(encode_hash(self.app_hash));
byteslices.push(encode_hash(self.last_results_hash));
byteslices.push(encode_hash(self.evidence_hash));
byteslices.push(bytes_enc(self.proposer_address.as_bytes()));

Hash::Sha256(simple_hash_from_byte_slices(byteslices))
}
}

Expand Down
5 changes: 4 additions & 1 deletion tendermint/src/genesis.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Genesis data

use crate::{chain, consensus, Hash, Time};
use crate::{chain, consensus, validator, Hash, Time};
use serde::{Deserialize, Serialize};

/// Genesis data
Expand All @@ -15,6 +15,9 @@ pub struct Genesis<AppState = serde_json::Value> {
/// Consensus parameters
pub consensus_params: consensus::Params,

/// Validators
pub validators: Vec<validator::Info>,

/// App hash
pub app_hash: Hash,

Expand Down
1 change: 1 addition & 0 deletions tendermint/src/lite/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ pub trait Vote {
fn signature(&self) -> &[u8];
}

#[derive(Debug)]
pub enum Error {
Expired,
NonSequentialHeight,
Expand Down
21 changes: 14 additions & 7 deletions tendermint/src/merkle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,21 @@ pub const HASH_SIZE: usize = 32;
/// Hash is the output of the cryptographic digest function
pub type Hash = [u8; HASH_SIZE];

/// Compute a simple Merkle root from the arbitrary sized byte slices
pub fn simple_hash_from_byte_slices(byte_slices: &[&[u8]]) -> Hash {
/// Compute a simple Merkle root from the arbitrary byte arrays
pub fn simple_hash_from_byte_slices(byte_slices: Vec<Vec<u8>>) -> Hash {
simple_hash_from_byte_slices_inner(byte_slices.as_slice())
}

// recurse into subtrees
fn simple_hash_from_byte_slices_inner(byte_slices: &[Vec<u8>]) -> Hash {
let length = byte_slices.len();
match length {
0 => [0; HASH_SIZE],
1 => leaf_hash(byte_slices[0]),
1 => leaf_hash(byte_slices[0].as_slice()),
_ => {
let k = get_split_point(length);
let left = simple_hash_from_byte_slices(&byte_slices[..k]);
let right = simple_hash_from_byte_slices(&byte_slices[k..]);
let left = simple_hash_from_byte_slices_inner(&byte_slices[..k]);
let right = simple_hash_from_byte_slices_inner(&byte_slices[k..]);
inner_hash(&left, &right)
}
}
Expand Down Expand Up @@ -90,7 +95,8 @@ mod tests {
let empty_leaf_root_hex =
"6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d";
let empty_leaf_root = &hex::decode(empty_leaf_root_hex).unwrap();
let empty_tree: &[&[u8]] = &[&[]];
let empty_tree: Vec<Vec<u8>> = vec![vec![]; 1];

let root = simple_hash_from_byte_slices(empty_tree);
assert_eq!(empty_leaf_root, &root);
}
Expand All @@ -101,7 +107,8 @@ mod tests {
let leaf_string = "L123456";

let leaf_root = &hex::decode(leaf_root_hex).unwrap();
let leaf_tree: &[&[u8]] = &[leaf_string.as_bytes()];
let leaf_tree: Vec<Vec<u8>> = vec![leaf_string.as_bytes().to_vec(); 1];

let root = simple_hash_from_byte_slices(leaf_tree);
assert_eq!(leaf_root, &root);
}
Expand Down
27 changes: 26 additions & 1 deletion tendermint/src/rpc/endpoint/commit.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! `/commit` endpoint JSONRPC wrapper

use crate::{block, rpc};
use crate::vote::SignedVote;
use crate::{block, lite, rpc, Hash};
use serde::{Deserialize, Serialize};

/// Get commit information about a specific block
Expand Down Expand Up @@ -46,3 +47,27 @@ pub struct SignedHeader {
/// Commit containing signatures for the header
pub commit: block::Commit,
}

impl lite::Commit for SignedHeader {
type Vote = SignedVote;
fn header_hash(&self) -> Hash {
self.commit.block_id.hash
}
fn into_vec(&self) -> Vec<Option<Self::Vote>> {
let chain_id = self.header.chain_id.to_string();
let mut votes = self.commit.precommits.clone().into_vec();
votes
.drain(..)
.map(|opt| {
opt.map(|vote| {
SignedVote::new(
(&vote).into(),
&chain_id,
vote.validator_address,
vote.signature,
)
})
})
.collect()
}
}
6 changes: 3 additions & 3 deletions tendermint/src/time.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Timestamps used by Tendermint blockchains

use crate::error::{Error, ErrorKind};
use chrono::{DateTime, Utc};
use chrono::{DateTime, SecondsFormat, Utc};
use serde::{Deserialize, Serialize};
use std::fmt;
use std::str::FromStr;
Expand Down Expand Up @@ -38,9 +38,9 @@ impl Time {
Ok(Time(DateTime::parse_from_rfc3339(s)?.with_timezone(&Utc)))
}

/// Returns an RFC 3339 string, such as 1996-12-19T16:39:57-08:00.
/// Return an RFC 3339 and ISO 8601 date and time string with 6 subseconds digits and Z.
pub fn to_rfc3339(&self) -> String {
self.0.to_rfc3339()
self.0.to_rfc3339_opts(SecondsFormat::Micros, true)
}

/// Convert this timestamp to a `SystemTime`
Expand Down
Loading

0 comments on commit fb56737

Please sign in to comment.