Skip to content

Commit

Permalink
tendermint: support 0.38 extensions for VoteInfo
Browse files Browse the repository at this point in the history
Add members to VoteInfo to be able to convert from and to
the ExtendedVoteInfo message type as defined in 0.38 proto.
Define conversions from and to the proto type, as well as
conversions between CommitInfo and ExtendedCommitInfo in the
proto.

As a helper to the above, provide Bytes conversions for the
Signature domain type.
  • Loading branch information
mzabaluev committed May 4, 2023
1 parent 7a6ff78 commit 3ff8e06
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 13 deletions.
98 changes: 85 additions & 13 deletions tendermint/src/abci/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

use bytes::Bytes;

use crate::{block, prelude::*, vote, Time};
use crate::{block, prelude::*, vote, Signature, Time};

/// A validator address with voting power.
///
Expand All @@ -29,6 +29,10 @@ pub struct VoteInfo {
pub validator: Validator,
/// Whether or not the validator signed the last block.
pub sig_info: BlockSignatureInfo,
/// Non-deterministic extension provided by the sending validator's application.
pub vote_extension: Bytes,
/// Signature for the vote extension.
pub extension_signature: Option<Signature>,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
Expand Down Expand Up @@ -101,6 +105,9 @@ pub struct Misbehavior {

/// Information on a block commit.
///
/// The `CommitInfo` domain type represents both `CommitInfo` and `ExtendedCommitInfo`
/// messages defined in protobuf.
///
/// [ABCI documentation](https://github.com/tendermint/tendermint/blob/main/spec/abci/abci++_methods.md#extendedcommitinfo)
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct CommitInfo {
Expand Down Expand Up @@ -208,6 +215,8 @@ mod v0_34 {
.ok_or_else(Error::missing_validator)?
.try_into()?,
sig_info,
vote_extension: Default::default(),
extension_signature: None,
})
}
}
Expand Down Expand Up @@ -374,14 +383,16 @@ mod v0_37 {
.ok_or_else(Error::missing_validator)?
.try_into()?,
sig_info,
vote_extension: Default::default(),
extension_signature: None,
})
}
}

impl Protobuf<pb::VoteInfo> for VoteInfo {}

// ExtendedVoteInfo is defined in 0.37, but the vote_extension field is always nil,
// so we can omit it from VoteInfo for the time being.
// ExtendedVoteInfo is defined in 0.37, but the vote_extension field
// should be always nil and is ignored.

impl From<VoteInfo> for pb::ExtendedVoteInfo {
fn from(vi: VoteInfo) -> Self {
Expand All @@ -408,6 +419,8 @@ mod v0_37 {
.ok_or_else(Error::missing_validator)?
.try_into()?,
sig_info,
vote_extension: vi.vote_extension,
extension_signature: None,
})
}
}
Expand Down Expand Up @@ -455,9 +468,6 @@ mod v0_37 {

impl Protobuf<pb::Misbehavior> for Misbehavior {}

// The CommitInfo domain type represents both CommitInfo and ExtendedCommitInfo
// as defined in protobuf for 0.37.

impl From<CommitInfo> for pb::CommitInfo {
fn from(lci: CommitInfo) -> Self {
Self {
Expand Down Expand Up @@ -543,7 +553,7 @@ mod v0_38 {
use super::{
BlockSignatureInfo, CommitInfo, Misbehavior, MisbehaviorKind, Snapshot, Validator, VoteInfo,
};
use crate::{prelude::*, Error};
use crate::{prelude::*, Error, Signature};
use tendermint_proto::v0_38::abci as pb;
use tendermint_proto::v0_38::types::BlockIdFlag as RawBlockIdFlag;
use tendermint_proto::Protobuf;
Expand Down Expand Up @@ -580,15 +590,21 @@ mod v0_38 {

impl Protobuf<pb::Validator> for Validator {}

impl From<VoteInfo> for pb::VoteInfo {
fn from(vi: VoteInfo) -> Self {
impl From<BlockSignatureInfo> for RawBlockIdFlag {
fn from(value: BlockSignatureInfo) -> Self {
// The API user should not use the LegacySigned flag in
// values for 0.38-based chains. As this conversion is infallible,
// silently convert it to the undefined value.
let block_id_flag = match vi.sig_info {
match value {
BlockSignatureInfo::Flag(flag) => flag.into(),
BlockSignatureInfo::LegacySigned => RawBlockIdFlag::Unknown,
};
}
}
}

impl From<VoteInfo> for pb::VoteInfo {
fn from(vi: VoteInfo) -> Self {
let block_id_flag: RawBlockIdFlag = vi.sig_info.into();
Self {
validator: Some(vi.validator.into()),
block_id_flag: block_id_flag as i32,
Expand All @@ -608,13 +624,45 @@ mod v0_38 {
.ok_or_else(Error::missing_validator)?
.try_into()?,
sig_info: BlockSignatureInfo::Flag(block_id_flag.try_into()?),
vote_extension: Default::default(),
extension_signature: None,
})
}
}

impl Protobuf<pb::VoteInfo> for VoteInfo {}

// TODO: introduce ExtendedVoteInfo domain type.
impl From<VoteInfo> for pb::ExtendedVoteInfo {
fn from(vi: VoteInfo) -> Self {
let block_id_flag: RawBlockIdFlag = vi.sig_info.into();
Self {
validator: Some(vi.validator.into()),
vote_extension: vi.vote_extension,
extension_signature: vi.extension_signature.map(Into::into).unwrap_or_default(),
block_id_flag: block_id_flag as i32,
}
}
}

impl TryFrom<pb::ExtendedVoteInfo> for VoteInfo {
type Error = Error;

fn try_from(vi: pb::ExtendedVoteInfo) -> Result<Self, Self::Error> {
let block_id_flag =
RawBlockIdFlag::from_i32(vi.block_id_flag).ok_or_else(Error::block_id_flag)?;
Ok(Self {
validator: vi
.validator
.ok_or_else(Error::missing_validator)?
.try_into()?,
sig_info: BlockSignatureInfo::Flag(block_id_flag.try_into()?),
vote_extension: vi.vote_extension,
extension_signature: Signature::new(vi.extension_signature)?,
})
}
}

impl Protobuf<pb::ExtendedVoteInfo> for VoteInfo {}

impl From<Misbehavior> for pb::Misbehavior {
fn from(evidence: Misbehavior) -> Self {
Expand Down Expand Up @@ -683,7 +731,31 @@ mod v0_38 {

impl Protobuf<pb::CommitInfo> for CommitInfo {}

// TODO: introduce the ExtendedCommitInfo domain type.
impl From<CommitInfo> for pb::ExtendedCommitInfo {
fn from(lci: CommitInfo) -> Self {
Self {
round: lci.round.into(),
votes: lci.votes.into_iter().map(Into::into).collect(),
}
}
}

impl TryFrom<pb::ExtendedCommitInfo> for CommitInfo {
type Error = Error;

fn try_from(lci: pb::ExtendedCommitInfo) -> Result<Self, Self::Error> {
Ok(Self {
round: lci.round.try_into()?,
votes: lci
.votes
.into_iter()
.map(TryInto::try_into)
.collect::<Result<_, _>>()?,
})
}
}

impl Protobuf<pb::ExtendedCommitInfo> for CommitInfo {}

impl From<Snapshot> for pb::Snapshot {
fn from(snapshot: Snapshot) -> Self {
Expand Down
16 changes: 16 additions & 0 deletions tendermint/src/signature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ pub use ed25519::Signature as Ed25519Signature;
#[cfg(feature = "secp256k1")]
pub use k256::ecdsa::Signature as Secp256k1Signature;

use bytes::Bytes;

use tendermint_proto::Protobuf;

use crate::{error::Error, prelude::*};
Expand Down Expand Up @@ -39,6 +41,20 @@ impl From<Signature> for Vec<u8> {
}
}

impl TryFrom<Bytes> for Signature {
type Error = Error;

fn try_from(bytes: Bytes) -> Result<Self, Self::Error> {
Self::new_non_empty(bytes)
}
}

impl From<Signature> for Bytes {
fn from(value: Signature) -> Self {
value.0.into()
}
}

impl Signature {
/// Create a new signature from the given byte array, if non-empty.
///
Expand Down

0 comments on commit 3ff8e06

Please sign in to comment.