From c44c2dead50175576f8880ee8411aaf00dba4a64 Mon Sep 17 00:00:00 2001 From: Mikhail Zabaluev Date: Tue, 25 Oct 2022 17:20:34 +0300 Subject: [PATCH] Restore serialization of Block and Evidence Define hand-written Serialize/Deserialize impls for Evidence. --- proto/src/prost/v0_34/tendermint.types.rs | 3 - proto/src/prost/v0_37/tendermint.types.rs | 3 - proto/src/serializers.rs | 1 + proto/src/serializers/evidence.rs | 47 ++++++ tendermint/src/block.rs | 4 +- tendermint/src/evidence.rs | 173 ++-------------------- tools/proto-compiler/src/constants.rs | 6 +- 7 files changed, 62 insertions(+), 175 deletions(-) create mode 100644 proto/src/serializers/evidence.rs diff --git a/proto/src/prost/v0_34/tendermint.types.rs b/proto/src/prost/v0_34/tendermint.types.rs index 5e8de00a8..753c63469 100644 --- a/proto/src/prost/v0_34/tendermint.types.rs +++ b/proto/src/prost/v0_34/tendermint.types.rs @@ -389,8 +389,6 @@ pub struct EventDataRoundState { #[prost(string, tag="3")] pub step: ::prost::alloc::string::String, } -#[derive(::serde::Deserialize, ::serde::Serialize)] -#[serde(from = "crate::serializers::evidence::EvidenceVariant", into = "crate::serializers::evidence::EvidenceVariant")] #[derive(Clone, PartialEq, ::prost::Message)] pub struct Evidence { #[prost(oneof="evidence::Sum", tags="1, 2")] @@ -400,7 +398,6 @@ pub struct Evidence { pub mod evidence { #[derive(::serde::Deserialize, ::serde::Serialize)] #[serde(tag = "type", content = "value")] - #[serde(from = "crate::serializers::evidence::EvidenceVariant", into = "crate::serializers::evidence::EvidenceVariant")] #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Sum { #[prost(message, tag="1")] diff --git a/proto/src/prost/v0_37/tendermint.types.rs b/proto/src/prost/v0_37/tendermint.types.rs index 7b205cede..bb5dce6c6 100644 --- a/proto/src/prost/v0_37/tendermint.types.rs +++ b/proto/src/prost/v0_37/tendermint.types.rs @@ -383,8 +383,6 @@ pub struct EventDataRoundState { #[prost(string, tag="3")] pub step: ::prost::alloc::string::String, } -#[derive(::serde::Deserialize, ::serde::Serialize)] -#[serde(from = "crate::serializers::evidence::EvidenceVariant", into = "crate::serializers::evidence::EvidenceVariant")] #[derive(Clone, PartialEq, ::prost::Message)] pub struct Evidence { #[prost(oneof="evidence::Sum", tags="1, 2")] @@ -394,7 +392,6 @@ pub struct Evidence { pub mod evidence { #[derive(::serde::Deserialize, ::serde::Serialize)] #[serde(tag = "type", content = "value")] - #[serde(from = "crate::serializers::evidence::EvidenceVariant", into = "crate::serializers::evidence::EvidenceVariant")] #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Sum { #[prost(message, tag="1")] diff --git a/proto/src/serializers.rs b/proto/src/serializers.rs index c506cb003..161833816 100644 --- a/proto/src/serializers.rs +++ b/proto/src/serializers.rs @@ -55,6 +55,7 @@ pub mod allow_null; pub mod bytes; +mod evidence; pub mod from_str; pub mod nullable; pub mod optional; diff --git a/proto/src/serializers/evidence.rs b/proto/src/serializers/evidence.rs new file mode 100644 index 000000000..7136455c5 --- /dev/null +++ b/proto/src/serializers/evidence.rs @@ -0,0 +1,47 @@ +mod v0_34 { + use crate::v0_34::types::{evidence, Evidence}; + use serde::{Deserialize, Deserializer, Serialize, Serializer}; + + impl<'de> Deserialize<'de> for Evidence { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let sum = Option::::deserialize(deserializer)?; + Ok(Self { sum }) + } + } + + impl Serialize for Evidence { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.sum.serialize(serializer) + } + } +} + +mod v0_37 { + use crate::v0_37::types::{evidence, Evidence}; + use serde::{Deserialize, Deserializer, Serialize, Serializer}; + + impl<'de> Deserialize<'de> for Evidence { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let sum = Option::::deserialize(deserializer)?; + Ok(Self { sum }) + } + } + + impl Serialize for Evidence { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.sum.serialize(serializer) + } + } +} diff --git a/tendermint/src/block.rs b/tendermint/src/block.rs index 845fd36cd..14c27a603 100644 --- a/tendermint/src/block.rs +++ b/tendermint/src/block.rs @@ -24,7 +24,7 @@ pub use self::{ round::*, size::Size, }; -use crate::{error::Error, evidence, prelude::*, serializers}; +use crate::{error::Error, evidence, prelude::*}; /// Blocks consist of a header, transactions, votes (the commit), and a list of /// evidence of malfeasance (i.e. signing conflicting votes). @@ -33,6 +33,7 @@ use crate::{error::Error, evidence, prelude::*, serializers}; // Default serialization - all fields serialize; used by /block endpoint #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] #[non_exhaustive] +#[serde(try_from = "RawBlock", into = "RawBlock")] pub struct Block { /// Block header pub header: Header, @@ -41,7 +42,6 @@ pub struct Block { pub data: Vec>, /// Evidence of malfeasance - #[serde(with = "serializers::allow_null")] pub evidence: evidence::Data, /// Last commit diff --git a/tendermint/src/evidence.rs b/tendermint/src/evidence.rs index 6da571a53..beeb92495 100644 --- a/tendermint/src/evidence.rs +++ b/tendermint/src/evidence.rs @@ -7,7 +7,7 @@ use core::{ use serde::{Deserialize, Serialize}; use tendermint_proto::{ - google::protobuf::Duration as RawDuration, types::evidence::Sum as RawSum, Protobuf, + google::protobuf::Duration as RawDuration, types::Evidence as RawEvidence, Protobuf, }; use crate::{error::Error, prelude::*, serializers, vote::Power, Time, Vote}; @@ -18,7 +18,7 @@ use crate::{error::Error, prelude::*, serializers, vote::Power, Time, Vote}; /// /// #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] -#[serde(try_from = "RawSum", into = "Option")] // Used by RPC /broadcast_evidence endpoint +#[serde(try_from = "RawEvidence", into = "RawEvidence")] // Used by RPC /broadcast_evidence endpoint pub enum Evidence { /// Duplicate vote evidence DuplicateVote(DuplicateVoteEvidence), @@ -120,188 +120,35 @@ pub struct Params { // Protobuf conversions // ============================================================================= -mod v0_34 { - use tendermint_proto::v0_37::types::{ +tendermint_pb_modules! { + use pb::types::{ evidence::Sum as RawSum, DuplicateVoteEvidence as RawDuplicateVoteEvidence, Evidence as RawEvidence, EvidenceList as RawEvidenceList, EvidenceParams as RawEvidenceParams, }; - use tendermint_proto::Protobuf; use super::{Data, DuplicateVoteEvidence, Evidence, Params}; use crate::{error::Error, prelude::*}; - impl TryFrom for Evidence { - type Error = Error; - - fn try_from(value: RawSum) -> Result { - use RawSum::*; - match value { - DuplicateVoteEvidence(ev) => Ok(Evidence::DuplicateVote(ev.try_into()?)), - LightClientAttackEvidence(_ev) => Ok(Evidence::LightClientAttackEvidence), - } - } - } - impl TryFrom for Evidence { type Error = Error; - fn try_from(value: RawEvidence) -> Result { - value - .sum - .ok_or_else(Error::invalid_evidence) - .and_then(TryInto::try_into) - } - } - - impl From for Option { - fn from(value: Evidence) -> Self { - match value { - Evidence::DuplicateVote(ev) => Some(RawSum::DuplicateVoteEvidence(ev.into())), - Evidence::LightClientAttackEvidence => None, - } - } - } - - impl From for RawEvidence { - fn from(value: Evidence) -> Self { - RawEvidence { sum: value.into() } - } - } - - impl TryFrom for DuplicateVoteEvidence { - type Error = Error; - - fn try_from(value: RawDuplicateVoteEvidence) -> Result { - Ok(Self { - vote_a: value - .vote_a - .ok_or_else(Error::missing_evidence)? - .try_into()?, - vote_b: value - .vote_b - .ok_or_else(Error::missing_evidence)? - .try_into()?, - total_voting_power: value.total_voting_power.try_into()?, - validator_power: value.validator_power.try_into()?, - timestamp: value - .timestamp - .ok_or_else(Error::missing_timestamp)? - .try_into()?, - }) - } - } - - impl From for RawDuplicateVoteEvidence { - fn from(value: DuplicateVoteEvidence) -> Self { - RawDuplicateVoteEvidence { - vote_a: Some(value.vote_a.into()), - vote_b: Some(value.vote_b.into()), - total_voting_power: value.total_voting_power.into(), - validator_power: value.total_voting_power.into(), - timestamp: Some(value.timestamp.into()), - } - } - } - - impl TryFrom for Data { - type Error = Error; - fn try_from(value: RawEvidenceList) -> Result { - let evidence = value - .evidence - .into_iter() - .map(TryInto::try_into) - .collect::, _>>()?; - Ok(Self(evidence)) - } - } - - impl From for RawEvidenceList { - fn from(value: Data) -> Self { - RawEvidenceList { - evidence: value.0.into_iter().map(Into::into).collect(), - } - } - } - - impl Protobuf for Params {} - - impl TryFrom for Params { - type Error = Error; - - fn try_from(value: RawEvidenceParams) -> Result { - Ok(Self { - max_age_num_blocks: value - .max_age_num_blocks - .try_into() - .map_err(Error::negative_max_age_num)?, - max_age_duration: value - .max_age_duration - .ok_or_else(Error::missing_max_age_duration)? - .try_into()?, - max_bytes: value.max_bytes, - }) - } - } - - impl From for RawEvidenceParams { - fn from(value: Params) -> Self { - Self { - // Todo: Implement proper domain types so this becomes infallible - max_age_num_blocks: value.max_age_num_blocks.try_into().unwrap(), - max_age_duration: Some(value.max_age_duration.into()), - max_bytes: value.max_bytes, - } - } - } -} - -mod v0_37 { - use tendermint_proto::v0_34::types::{ - evidence::Sum as RawSum, DuplicateVoteEvidence as RawDuplicateVoteEvidence, - Evidence as RawEvidence, EvidenceList as RawEvidenceList, - EvidenceParams as RawEvidenceParams, - }; - use tendermint_proto::Protobuf; - - use super::{Data, DuplicateVoteEvidence, Evidence, Params}; - use crate::{error::Error, prelude::*}; - - impl TryFrom for Evidence { - type Error = Error; - - fn try_from(value: RawSum) -> Result { + fn try_from(message: RawEvidence) -> Result { use RawSum::*; - match value { + match message.sum.ok_or_else(Error::invalid_evidence)? { DuplicateVoteEvidence(ev) => Ok(Evidence::DuplicateVote(ev.try_into()?)), LightClientAttackEvidence(_ev) => Ok(Evidence::LightClientAttackEvidence), } } } - impl TryFrom for Evidence { - type Error = Error; - - fn try_from(value: RawEvidence) -> Result { - value - .sum - .ok_or_else(Error::invalid_evidence) - .and_then(TryInto::try_into) - } - } - - impl From for Option { + impl From for RawEvidence { fn from(value: Evidence) -> Self { - match value { + let sum = match value { Evidence::DuplicateVote(ev) => Some(RawSum::DuplicateVoteEvidence(ev.into())), Evidence::LightClientAttackEvidence => None, - } - } - } - - impl From for RawEvidence { - fn from(value: Evidence) -> Self { - RawEvidence { sum: value.into() } + }; + RawEvidence { sum } } } diff --git a/tools/proto-compiler/src/constants.rs b/tools/proto-compiler/src/constants.rs index 98be71f53..d5a7928b4 100644 --- a/tools/proto-compiler/src/constants.rs +++ b/tools/proto-compiler/src/constants.rs @@ -53,7 +53,6 @@ const RENAME_SRPUBKEY: &str = r#"#[serde(rename = "tendermint/PubKeySr25519", wi const RENAME_DUPLICATEVOTE: &str = r#"#[serde(rename = "tendermint/DuplicateVoteEvidence")]"#; const RENAME_LIGHTCLIENTATTACK: &str = r#"#[serde(rename = "tendermint/LightClientAttackEvidence")]"#; -const EVIDENCE_VARIANT: &str = r#"#[serde(from = "crate::serializers::evidence::EvidenceVariant", into = "crate::serializers::evidence::EvidenceVariant")]"#; const ALIAS_VALIDATOR_POWER_QUOTED: &str = r#"#[serde(alias = "ValidatorPower", with = "crate::serializers::from_str")]"#; const ALIAS_TOTAL_VOTING_POWER_QUOTED: &str = @@ -72,8 +71,9 @@ pub static CUSTOM_TYPE_ATTRIBUTES: &[(&str, &str)] = &[ (".tendermint.types.BlockIDFlag", PRIMITIVE_ENUM), (".tendermint.types.Block", SERIALIZED), (".tendermint.types.Data", SERIALIZED), + (".tendermint.types.Evidence.sum", SERIALIZED), + (".tendermint.types.Evidence.sum", TYPE_TAG), (".tendermint.types.EvidenceList", SERIALIZED), - (".tendermint.types.Evidence", SERIALIZED), (".tendermint.types.DuplicateVoteEvidence", SERIALIZED), (".tendermint.types.Vote", SERIALIZED), (".tendermint.types.BlockID", SERIALIZED), @@ -88,14 +88,12 @@ pub static CUSTOM_TYPE_ATTRIBUTES: &[(&str, &str)] = &[ (".tendermint.types.ValidatorSet", SERIALIZED), (".tendermint.crypto.PublicKey", SERIALIZED), (".tendermint.crypto.PublicKey.sum", TYPE_TAG), - (".tendermint.types.Evidence.sum", TYPE_TAG), (".tendermint.abci.ResponseInfo", SERIALIZED), (".tendermint.types.CanonicalBlockID", SERIALIZED), (".tendermint.types.CanonicalPartSetHeader", SERIALIZED), (".tendermint.types.Validator", SERIALIZED), (".tendermint.types.CanonicalVote", SERIALIZED), (".tendermint.types.BlockMeta", SERIALIZED), - (".tendermint.types.Evidence", EVIDENCE_VARIANT), (".tendermint.types.TxProof", SERIALIZED), (".tendermint.crypto.Proof", SERIALIZED), ];