From 90ac60facb3b2a95745a76b7cd7c526dc69723ab Mon Sep 17 00:00:00 2001 From: Greg Szabo Date: Tue, 13 Oct 2020 19:41:08 -0400 Subject: [PATCH] Header domain type --- tendermint/src/block/header.rs | 73 ++++++++++++++++++++++++++- tendermint/src/block/signed_header.rs | 30 +++++++++++ tendermint/src/error.rs | 8 +++ 3 files changed, 110 insertions(+), 1 deletion(-) diff --git a/tendermint/src/block/header.rs b/tendermint/src/block/header.rs index 7b9431cbf..cb2de2c7e 100644 --- a/tendermint/src/block/header.rs +++ b/tendermint/src/block/header.rs @@ -3,8 +3,10 @@ use crate::merkle::simple_hash_from_byte_vectors; use crate::serializers; use crate::{account, block, chain, AppHash, Hash, Time}; +use crate::{Error, Kind}; use serde::{Deserialize, Serialize}; -use std::convert::TryFrom; +use std::convert::{TryFrom, TryInto}; +use tendermint_proto::types::Header as RawHeader; use tendermint_proto::version::Consensus as RawConsensusVersion; use tendermint_proto::DomainType; @@ -63,6 +65,75 @@ pub struct Header { pub proposer_address: account::Id, } +impl DomainType for Header {} + +impl TryFrom for Header { + type Error = Error; + + fn try_from(value: RawHeader) -> Result { + if value.version.is_none() { + return Err(Kind::InvalidHeader.into()); + } + if value.time.is_none() { + return Err(Kind::InvalidHeader.into()); + } + + Ok(Self { + version: value.version.unwrap().try_into()?, + chain_id: value.chain_id.try_into()?, + height: value.height.try_into()?, + time: value.time.unwrap().try_into()?, + last_block_id: value.last_block_id.map(TryInto::try_into).transpose()?, + last_commit_hash: if value.last_commit_hash.is_empty() { + None + } else { + Some(value.last_commit_hash.try_into()?) + }, + data_hash: if value.data_hash.is_empty() { + None + } else { + Some(value.data_hash.try_into()?) + }, + validators_hash: value.validators_hash.try_into()?, + next_validators_hash: value.next_validators_hash.try_into()?, + consensus_hash: value.consensus_hash.try_into()?, + app_hash: value.app_hash.try_into()?, + last_results_hash: if value.last_results_hash.is_empty() { + None + } else { + Some(value.last_results_hash.try_into()?) + }, + evidence_hash: if value.evidence_hash.is_empty() { + None + } else { + Some(value.evidence_hash.try_into()?) + }, + proposer_address: value.proposer_address.try_into()?, + }) + } +} + +impl From
for RawHeader { + fn from(value: Header) -> Self { + Self { + version: Some(value.version.into()), + chain_id: value.chain_id.into(), + height: value.height.into(), + time: Some(value.time.into()), + last_block_id: value.last_block_id.map(Into::into), + last_commit_hash: value.last_commit_hash.map(Into::into).unwrap_or(vec![]), + data_hash: value.data_hash.map(Into::into).unwrap_or(vec![]), + validators_hash: value.validators_hash.into(), + next_validators_hash: value.next_validators_hash.into(), + consensus_hash: value.consensus_hash.into(), + app_hash: value.app_hash.into(), + last_results_hash: value.last_results_hash.map(Into::into).unwrap_or(vec![]), + evidence_hash: value.evidence_hash.map(Into::into).unwrap_or(vec![]), + proposer_address: value.proposer_address.into(), + } + } +} + impl Header { /// Hash this header pub fn hash(&self) -> Hash { diff --git a/tendermint/src/block/signed_header.rs b/tendermint/src/block/signed_header.rs index 5d4813d89..0d3f1a2ba 100644 --- a/tendermint/src/block/signed_header.rs +++ b/tendermint/src/block/signed_header.rs @@ -4,6 +4,11 @@ use serde::{Deserialize, Serialize}; use crate::block; +use crate::{Error, Kind}; +use anomaly::format_err; +use std::convert::TryFrom; +use tendermint_proto::types::SignedHeader as RawSignedHeader; +use tendermint_proto::DomainType; /// Signed block headers #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] @@ -13,3 +18,28 @@ pub struct SignedHeader { /// Commit containing signatures for the header pub commit: block::Commit, } + +impl DomainType for SignedHeader {} + +impl TryFrom for SignedHeader { + type Error = Error; + + fn try_from(value: RawSignedHeader) -> Result { + if value.header.is_none() { + return Err(format_err!(Kind::InvalidSignedHeader, "empty header field").into()); + } + if value.commit.is_none() { + return Err(format_err!(Kind::InvalidSignedHeader, "empty commit field").into()); + } + unimplemented!("Greg implement it using the fields' implementations") + } +} + +impl From for RawSignedHeader { + fn from(value: SignedHeader) -> Self { + RawSignedHeader { + header: Some(value.header.into()), + commit: Some(value.commit.into()), + } + } +} diff --git a/tendermint/src/error.rs b/tendermint/src/error.rs index 68a5323ab..b2af567a8 100644 --- a/tendermint/src/error.rs +++ b/tendermint/src/error.rs @@ -96,6 +96,14 @@ pub enum Kind { /// Invalid PartSetHeader #[error("invalid part set header")] InvalidPartSetHeader, + + /// Invalid SignedHeader + #[error("invalid signed header")] + InvalidSignedHeader, + + /// Invalid Header + #[error("invalid header")] + InvalidHeader, } impl Kind {