Skip to content

Commit

Permalink
Restore serialization of Block and Evidence
Browse files Browse the repository at this point in the history
Define hand-written Serialize/Deserialize impls for Evidence.
  • Loading branch information
mzabaluev committed Oct 27, 2022
1 parent 8dae679 commit c44c2de
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 175 deletions.
3 changes: 0 additions & 3 deletions proto/src/prost/v0_34/tendermint.types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")]
Expand All @@ -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")]
Expand Down
3 changes: 0 additions & 3 deletions proto/src/prost/v0_37/tendermint.types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")]
Expand All @@ -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")]
Expand Down
1 change: 1 addition & 0 deletions proto/src/serializers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@

pub mod allow_null;
pub mod bytes;
mod evidence;
pub mod from_str;
pub mod nullable;
pub mod optional;
Expand Down
47 changes: 47 additions & 0 deletions proto/src/serializers/evidence.rs
Original file line number Diff line number Diff line change
@@ -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<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let sum = Option::<evidence::Sum>::deserialize(deserializer)?;
Ok(Self { sum })
}
}

impl Serialize for Evidence {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
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<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let sum = Option::<evidence::Sum>::deserialize(deserializer)?;
Ok(Self { sum })
}
}

impl Serialize for Evidence {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.sum.serialize(serializer)
}
}
}
4 changes: 2 additions & 2 deletions tendermint/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand All @@ -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,
Expand All @@ -41,7 +42,6 @@ pub struct Block {
pub data: Vec<Vec<u8>>,

/// Evidence of malfeasance
#[serde(with = "serializers::allow_null")]
pub evidence: evidence::Data,

/// Last commit
Expand Down
173 changes: 10 additions & 163 deletions tendermint/src/evidence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand All @@ -18,7 +18,7 @@ use crate::{error::Error, prelude::*, serializers, vote::Power, Time, Vote};
///
/// <https://github.com/tendermint/spec/blob/d46cd7f573a2c6a2399fcab2cde981330aa63f37/spec/core/data_structures.md#evidence>
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(try_from = "RawSum", into = "Option<RawSum>")] // 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),
Expand Down Expand Up @@ -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<RawSum> for Evidence {
type Error = Error;

fn try_from(value: RawSum) -> Result<Self, Self::Error> {
use RawSum::*;
match value {
DuplicateVoteEvidence(ev) => Ok(Evidence::DuplicateVote(ev.try_into()?)),
LightClientAttackEvidence(_ev) => Ok(Evidence::LightClientAttackEvidence),
}
}
}

impl TryFrom<RawEvidence> for Evidence {
type Error = Error;

fn try_from(value: RawEvidence) -> Result<Self, Self::Error> {
value
.sum
.ok_or_else(Error::invalid_evidence)
.and_then(TryInto::try_into)
}
}

impl From<Evidence> for Option<RawSum> {
fn from(value: Evidence) -> Self {
match value {
Evidence::DuplicateVote(ev) => Some(RawSum::DuplicateVoteEvidence(ev.into())),
Evidence::LightClientAttackEvidence => None,
}
}
}

impl From<Evidence> for RawEvidence {
fn from(value: Evidence) -> Self {
RawEvidence { sum: value.into() }
}
}

impl TryFrom<RawDuplicateVoteEvidence> for DuplicateVoteEvidence {
type Error = Error;

fn try_from(value: RawDuplicateVoteEvidence) -> Result<Self, Self::Error> {
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<DuplicateVoteEvidence> 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<RawEvidenceList> for Data {
type Error = Error;
fn try_from(value: RawEvidenceList) -> Result<Self, Self::Error> {
let evidence = value
.evidence
.into_iter()
.map(TryInto::try_into)
.collect::<Result<Vec<_>, _>>()?;
Ok(Self(evidence))
}
}

impl From<Data> for RawEvidenceList {
fn from(value: Data) -> Self {
RawEvidenceList {
evidence: value.0.into_iter().map(Into::into).collect(),
}
}
}

impl Protobuf<RawEvidenceParams> for Params {}

impl TryFrom<RawEvidenceParams> for Params {
type Error = Error;

fn try_from(value: RawEvidenceParams) -> Result<Self, Self::Error> {
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<Params> 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<RawSum> for Evidence {
type Error = Error;

fn try_from(value: RawSum) -> Result<Self, Self::Error> {
fn try_from(message: RawEvidence) -> Result<Self, Self::Error> {
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<RawEvidence> for Evidence {
type Error = Error;

fn try_from(value: RawEvidence) -> Result<Self, Self::Error> {
value
.sum
.ok_or_else(Error::invalid_evidence)
.and_then(TryInto::try_into)
}
}

impl From<Evidence> for Option<RawSum> {
impl From<Evidence> 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<Evidence> for RawEvidence {
fn from(value: Evidence) -> Self {
RawEvidence { sum: value.into() }
};
RawEvidence { sum }
}
}

Expand Down
6 changes: 2 additions & 4 deletions tools/proto-compiler/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand All @@ -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),
Expand All @@ -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),
];
Expand Down

0 comments on commit c44c2de

Please sign in to comment.