-
Notifications
You must be signed in to change notification settings - Fork 128
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Vendors all Amino types from the `tendermint` crate, so we can continue supporting Amino even though it's been removed from the upstream crate in favor of Protobufs.
- Loading branch information
1 parent
77fbc00
commit c2bb765
Showing
17 changed files
with
1,535 additions
and
129 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
//! Legacy message types serialized using the Amino serialization format | ||
//! <https://github.com/tendermint/amino_rs> | ||
#![allow(missing_docs)] | ||
|
||
pub mod block_id; | ||
pub mod ed25519; | ||
pub mod message; | ||
pub mod ping; | ||
pub mod proposal; | ||
pub mod remote_error; | ||
pub mod signature; | ||
pub mod time; | ||
pub mod validate; | ||
pub mod version; | ||
pub mod vote; | ||
|
||
pub use self::{ | ||
block_id::{BlockId, CanonicalBlockId, CanonicalPartSetHeader, PartsSetHeader}, | ||
ed25519::{ | ||
PubKeyRequest, PubKeyResponse, AMINO_NAME as PUBKEY_AMINO_NAME, | ||
AMINO_PREFIX as PUBKEY_PREFIX, | ||
}, | ||
ping::{PingRequest, PingResponse, AMINO_NAME as PING_AMINO_NAME, AMINO_PREFIX as PING_PREFIX}, | ||
proposal::{ | ||
Proposal, SignProposalRequest, SignedProposalResponse, AMINO_NAME as PROPOSAL_AMINO_NAME, | ||
AMINO_PREFIX as PROPOSAL_PREFIX, | ||
}, | ||
remote_error::RemoteError, | ||
signature::{SignableMsg, SignedMsgType}, | ||
time::TimeMsg, | ||
validate::ConsensusMessage, | ||
version::ConsensusVersion, | ||
vote::{ | ||
SignVoteRequest, SignedVoteResponse, Vote, AMINO_NAME as VOTE_AMINO_NAME, | ||
AMINO_PREFIX as VOTE_PREFIX, | ||
}, | ||
}; | ||
|
||
use crate::rpc; | ||
use sha2::{Digest, Sha256}; | ||
|
||
/// Tendermint requests | ||
pub trait TendermintRequest: SignableMsg { | ||
fn build_response(self, error: Option<RemoteError>) -> rpc::Response; | ||
} | ||
|
||
/// Compute the Amino prefix for the given registered type name | ||
pub fn compute_prefix(name: &str) -> Vec<u8> { | ||
let mut sh = Sha256::default(); | ||
sh.update(name.as_bytes()); | ||
let output = sh.finalize(); | ||
|
||
output | ||
.iter() | ||
.filter(|&x| *x != 0x00) | ||
.skip(3) | ||
.filter(|&x| *x != 0x00) | ||
.cloned() | ||
.take(4) | ||
.collect() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
use super::validate::{self, ConsensusMessage, Error::*}; | ||
use crate::proto_types; | ||
use prost_amino_derive::Message; | ||
use tendermint::{ | ||
block::{self, parts}, | ||
error::Error, | ||
hash, | ||
hash::{Hash, SHA256_HASH_SIZE}, | ||
}; | ||
|
||
#[derive(Clone, PartialEq, Message)] | ||
pub struct BlockId { | ||
#[prost_amino(bytes, tag = "1")] | ||
pub hash: Vec<u8>, | ||
#[prost_amino(message, tag = "2")] | ||
pub parts_header: Option<PartsSetHeader>, | ||
} | ||
|
||
impl BlockId { | ||
pub fn new(hash: Vec<u8>, parts_header: Option<PartsSetHeader>) -> Self { | ||
BlockId { hash, parts_header } | ||
} | ||
} | ||
|
||
impl block::ParseId for BlockId { | ||
fn parse_block_id(&self) -> Result<block::Id, Error> { | ||
let hash = Hash::new(hash::Algorithm::Sha256, &self.hash)?; | ||
let parts_header = self | ||
.parts_header | ||
.as_ref() | ||
.and_then(PartsSetHeader::parse_parts_header); | ||
Ok(block::Id::new(hash, parts_header)) | ||
} | ||
} | ||
|
||
impl From<&block::Id> for BlockId { | ||
fn from(bid: &block::Id) -> Self { | ||
let bid_hash = bid.hash.as_bytes(); | ||
BlockId::new( | ||
bid_hash.to_vec(), | ||
bid.parts.as_ref().map(PartsSetHeader::from), | ||
) | ||
} | ||
} | ||
|
||
impl From<proto_types::BlockId> for BlockId { | ||
fn from(block_id: proto_types::BlockId) -> BlockId { | ||
BlockId::new( | ||
block_id.hash, | ||
block_id.part_set_header.map(|psh| PartsSetHeader { | ||
total: psh.total as i64, | ||
hash: psh.hash, | ||
}), | ||
) | ||
} | ||
} | ||
|
||
impl From<BlockId> for proto_types::BlockId { | ||
fn from(block_id: BlockId) -> proto_types::BlockId { | ||
proto_types::BlockId { | ||
hash: block_id.hash, | ||
part_set_header: block_id.parts_header.map(|psh| proto_types::PartSetHeader { | ||
total: psh.total as u32, | ||
hash: psh.hash, | ||
}), | ||
} | ||
} | ||
} | ||
|
||
impl ConsensusMessage for BlockId { | ||
fn validate_basic(&self) -> Result<(), validate::Error> { | ||
// Hash can be empty in case of POLBlockID in Proposal. | ||
if !self.hash.is_empty() && self.hash.len() != SHA256_HASH_SIZE { | ||
return Err(InvalidHashSize); | ||
} | ||
self.parts_header | ||
.as_ref() | ||
.map_or(Ok(()), ConsensusMessage::validate_basic) | ||
} | ||
} | ||
|
||
#[derive(Clone, PartialEq, Message)] | ||
pub struct CanonicalBlockId { | ||
#[prost_amino(bytes, tag = "1")] | ||
pub hash: Vec<u8>, | ||
#[prost_amino(message, tag = "2")] | ||
pub parts_header: Option<CanonicalPartSetHeader>, | ||
} | ||
|
||
impl block::ParseId for CanonicalBlockId { | ||
fn parse_block_id(&self) -> Result<block::Id, Error> { | ||
let hash = Hash::new(hash::Algorithm::Sha256, &self.hash)?; | ||
let parts_header = self | ||
.parts_header | ||
.as_ref() | ||
.and_then(CanonicalPartSetHeader::parse_parts_header); | ||
Ok(block::Id::new(hash, parts_header)) | ||
} | ||
} | ||
|
||
#[derive(Clone, PartialEq, Message)] | ||
pub struct PartsSetHeader { | ||
#[prost_amino(int64, tag = "1")] | ||
pub total: i64, | ||
#[prost_amino(bytes, tag = "2")] | ||
pub hash: Vec<u8>, | ||
} | ||
|
||
impl PartsSetHeader { | ||
pub fn new(total: i64, hash: Vec<u8>) -> Self { | ||
PartsSetHeader { total, hash } | ||
} | ||
} | ||
|
||
impl From<&parts::Header> for PartsSetHeader { | ||
fn from(parts: &parts::Header) -> Self { | ||
PartsSetHeader::new(parts.total as i64, parts.hash.as_bytes().to_vec()) | ||
} | ||
} | ||
|
||
impl PartsSetHeader { | ||
fn parse_parts_header(&self) -> Option<block::parts::Header> { | ||
Hash::new(hash::Algorithm::Sha256, &self.hash) | ||
.map(|hash| block::parts::Header::new(self.total as u64, hash)) | ||
.ok() | ||
} | ||
} | ||
|
||
impl ConsensusMessage for PartsSetHeader { | ||
fn validate_basic(&self) -> Result<(), validate::Error> { | ||
if self.total < 0 { | ||
return Err(NegativeTotal); | ||
} | ||
// Hash can be empty in case of POLBlockID.PartsHeader in Proposal. | ||
if !self.hash.is_empty() && self.hash.len() != SHA256_HASH_SIZE { | ||
return Err(InvalidHashSize); | ||
} | ||
Ok(()) | ||
} | ||
} | ||
|
||
#[derive(Clone, PartialEq, Message)] | ||
pub struct CanonicalPartSetHeader { | ||
#[prost_amino(bytes, tag = "1")] | ||
pub hash: Vec<u8>, | ||
#[prost_amino(int64, tag = "2")] | ||
pub total: i64, | ||
} | ||
|
||
impl CanonicalPartSetHeader { | ||
fn parse_parts_header(&self) -> Option<block::parts::Header> { | ||
Hash::new(hash::Algorithm::Sha256, &self.hash) | ||
.map(|hash| block::parts::Header::new(self.total as u64, hash)) | ||
.ok() | ||
} | ||
} |
Oops, something went wrong.