use bytes::Bytes;
use serde::{Deserialize, Serialize};
use super::{Code, Event};
use crate::{
block::{self, BlockIdFlag},
prelude::*,
serializers, vote, Signature, Time,
};
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Validator {
pub address: [u8; 20],
pub power: vote::Power,
}
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct VoteInfo {
pub validator: Validator,
pub sig_info: BlockSignatureInfo,
}
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct ExtendedVoteInfo {
pub validator: Validator,
pub sig_info: BlockSignatureInfo,
pub vote_extension: Bytes,
pub extension_signature: Option<Signature>,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum BlockSignatureInfo {
Flag(BlockIdFlag),
LegacySigned,
}
impl BlockSignatureInfo {
pub fn is_signed(&self) -> bool {
use BlockIdFlag::*;
match self {
BlockSignatureInfo::Flag(Commit) | BlockSignatureInfo::Flag(Nil) => true,
BlockSignatureInfo::Flag(Absent) => false,
BlockSignatureInfo::LegacySigned => true,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[repr(i32)]
pub enum MisbehaviorKind {
Unknown = 0,
DuplicateVote = 1,
LightClientAttack = 2,
}
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Misbehavior {
pub kind: MisbehaviorKind,
pub validator: Validator,
pub height: block::Height,
pub time: Time,
pub total_voting_power: vote::Power,
}
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct CommitInfo {
pub round: block::Round,
pub votes: Vec<VoteInfo>,
}
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct ExtendedCommitInfo {
pub round: block::Round,
pub votes: Vec<ExtendedVoteInfo>,
}
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Snapshot {
pub height: block::Height,
pub format: u32,
pub chunks: u32,
pub hash: Bytes,
pub metadata: Bytes,
}
#[derive(Clone, PartialEq, Eq, Debug, Default, Serialize, Deserialize)]
pub struct ExecTxResult {
#[serde(default)]
pub code: Code,
#[serde(default, with = "serializers::nullable")]
pub data: Bytes,
#[serde(default)]
pub log: String,
#[serde(default)]
pub info: String,
#[serde(default, with = "serializers::from_str")]
pub gas_wanted: i64,
#[serde(default, with = "serializers::from_str")]
pub gas_used: i64,
#[serde(default)]
pub events: Vec<Event>,
#[serde(default)]
pub codespace: String,
}
mod v0_34 {
use super::{
BlockSignatureInfo, CommitInfo, Misbehavior, MisbehaviorKind, Snapshot, Validator, VoteInfo,
};
use crate::{block::BlockIdFlag, prelude::*, Error};
use tendermint_proto::v0_34::abci as pb;
use tendermint_proto::Protobuf;
use bytes::Bytes;
impl From<Validator> for pb::Validator {
fn from(v: Validator) -> Self {
Self {
address: Bytes::copy_from_slice(&v.address[..]),
power: v.power.into(),
}
}
}
impl TryFrom<pb::Validator> for Validator {
type Error = Error;
fn try_from(vu: pb::Validator) -> Result<Self, Self::Error> {
let address = if vu.address.len() == 20 {
let mut bytes = [0u8; 20];
bytes.copy_from_slice(&vu.address);
bytes
} else {
return Err(Error::invalid_account_id_length());
};
Ok(Self {
address,
power: vu.power.try_into()?,
})
}
}
impl Protobuf<pb::Validator> for Validator {}
impl From<VoteInfo> for pb::VoteInfo {
fn from(vi: VoteInfo) -> Self {
Self {
validator: Some(vi.validator.into()),
signed_last_block: vi.sig_info.is_signed(),
}
}
}
impl TryFrom<pb::VoteInfo> for VoteInfo {
type Error = Error;
fn try_from(vi: pb::VoteInfo) -> Result<Self, Self::Error> {
let sig_info = if vi.signed_last_block {
BlockSignatureInfo::LegacySigned
} else {
BlockSignatureInfo::Flag(BlockIdFlag::Absent)
};
Ok(Self {
validator: vi
.validator
.ok_or_else(Error::missing_validator)?
.try_into()?,
sig_info,
})
}
}
impl Protobuf<pb::VoteInfo> for VoteInfo {}
impl From<Misbehavior> for pb::Evidence {
fn from(evidence: Misbehavior) -> Self {
Self {
r#type: evidence.kind as i32,
validator: Some(evidence.validator.into()),
height: evidence.height.into(),
time: Some(evidence.time.into()),
total_voting_power: evidence.total_voting_power.into(),
}
}
}
impl TryFrom<pb::Evidence> for Misbehavior {
type Error = Error;
fn try_from(evidence: pb::Evidence) -> Result<Self, Self::Error> {
let kind = match evidence.r#type {
0 => MisbehaviorKind::Unknown,
1 => MisbehaviorKind::DuplicateVote,
2 => MisbehaviorKind::LightClientAttack,
_ => return Err(Error::invalid_evidence()),
};
Ok(Self {
kind,
validator: evidence
.validator
.ok_or_else(Error::missing_validator)?
.try_into()?,
height: evidence.height.try_into()?,
time: evidence
.time
.ok_or_else(Error::missing_timestamp)?
.try_into()?,
total_voting_power: evidence.total_voting_power.try_into()?,
})
}
}
impl Protobuf<pb::Evidence> for Misbehavior {}
impl From<CommitInfo> for pb::LastCommitInfo {
fn from(lci: CommitInfo) -> Self {
Self {
round: lci.round.into(),
votes: lci.votes.into_iter().map(Into::into).collect(),
}
}
}
impl TryFrom<pb::LastCommitInfo> for CommitInfo {
type Error = Error;
fn try_from(lci: pb::LastCommitInfo) -> 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::LastCommitInfo> for CommitInfo {}
impl From<Snapshot> for pb::Snapshot {
fn from(snapshot: Snapshot) -> Self {
Self {
height: snapshot.height.into(),
format: snapshot.format,
chunks: snapshot.chunks,
hash: snapshot.hash,
metadata: snapshot.metadata,
}
}
}
impl TryFrom<pb::Snapshot> for Snapshot {
type Error = Error;
fn try_from(snapshot: pb::Snapshot) -> Result<Self, Self::Error> {
Ok(Self {
height: snapshot.height.try_into()?,
format: snapshot.format,
chunks: snapshot.chunks,
hash: snapshot.hash,
metadata: snapshot.metadata,
})
}
}
impl Protobuf<pb::Snapshot> for Snapshot {}
}
mod v0_37 {
use super::{
BlockSignatureInfo, CommitInfo, ExtendedCommitInfo, ExtendedVoteInfo, Misbehavior,
MisbehaviorKind, Snapshot, Validator, VoteInfo,
};
use crate::{block::BlockIdFlag, prelude::*, Error};
use tendermint_proto::v0_37::abci as pb;
use tendermint_proto::Protobuf;
use bytes::Bytes;
impl From<Validator> for pb::Validator {
fn from(v: Validator) -> Self {
Self {
address: Bytes::copy_from_slice(&v.address[..]),
power: v.power.into(),
}
}
}
impl TryFrom<pb::Validator> for Validator {
type Error = Error;
fn try_from(vu: pb::Validator) -> Result<Self, Self::Error> {
let address = if vu.address.len() == 20 {
let mut bytes = [0u8; 20];
bytes.copy_from_slice(&vu.address);
bytes
} else {
return Err(Error::invalid_account_id_length());
};
Ok(Self {
address,
power: vu.power.try_into()?,
})
}
}
impl Protobuf<pb::Validator> for Validator {}
impl From<VoteInfo> for pb::VoteInfo {
fn from(vi: VoteInfo) -> Self {
Self {
validator: Some(vi.validator.into()),
signed_last_block: vi.sig_info.is_signed(),
}
}
}
impl TryFrom<pb::VoteInfo> for VoteInfo {
type Error = Error;
fn try_from(vi: pb::VoteInfo) -> Result<Self, Self::Error> {
let sig_info = if vi.signed_last_block {
BlockSignatureInfo::LegacySigned
} else {
BlockSignatureInfo::Flag(BlockIdFlag::Absent)
};
Ok(Self {
validator: vi
.validator
.ok_or_else(Error::missing_validator)?
.try_into()?,
sig_info,
})
}
}
impl Protobuf<pb::VoteInfo> for VoteInfo {}
impl From<ExtendedVoteInfo> for pb::ExtendedVoteInfo {
fn from(vi: ExtendedVoteInfo) -> Self {
Self {
validator: Some(vi.validator.into()),
signed_last_block: vi.sig_info.is_signed(),
vote_extension: Default::default(),
}
}
}
impl TryFrom<pb::ExtendedVoteInfo> for ExtendedVoteInfo {
type Error = Error;
fn try_from(vi: pb::ExtendedVoteInfo) -> Result<Self, Self::Error> {
let sig_info = if vi.signed_last_block {
BlockSignatureInfo::LegacySigned
} else {
BlockSignatureInfo::Flag(BlockIdFlag::Absent)
};
Ok(Self {
validator: vi
.validator
.ok_or_else(Error::missing_validator)?
.try_into()?,
sig_info,
vote_extension: Default::default(),
extension_signature: None,
})
}
}
impl Protobuf<pb::ExtendedVoteInfo> for ExtendedVoteInfo {}
impl From<Misbehavior> for pb::Misbehavior {
fn from(evidence: Misbehavior) -> Self {
Self {
r#type: evidence.kind as i32,
validator: Some(evidence.validator.into()),
height: evidence.height.into(),
time: Some(evidence.time.into()),
total_voting_power: evidence.total_voting_power.into(),
}
}
}
impl TryFrom<pb::Misbehavior> for Misbehavior {
type Error = Error;
fn try_from(evidence: pb::Misbehavior) -> Result<Self, Self::Error> {
let kind = match evidence.r#type {
0 => MisbehaviorKind::Unknown,
1 => MisbehaviorKind::DuplicateVote,
2 => MisbehaviorKind::LightClientAttack,
_ => return Err(Error::invalid_evidence()),
};
Ok(Self {
kind,
validator: evidence
.validator
.ok_or_else(Error::missing_validator)?
.try_into()?,
height: evidence.height.try_into()?,
time: evidence
.time
.ok_or_else(Error::missing_timestamp)?
.try_into()?,
total_voting_power: evidence.total_voting_power.try_into()?,
})
}
}
impl Protobuf<pb::Misbehavior> for Misbehavior {}
impl From<CommitInfo> for pb::CommitInfo {
fn from(lci: CommitInfo) -> Self {
Self {
round: lci.round.into(),
votes: lci.votes.into_iter().map(Into::into).collect(),
}
}
}
impl TryFrom<pb::CommitInfo> for CommitInfo {
type Error = Error;
fn try_from(lci: pb::CommitInfo) -> 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::CommitInfo> for CommitInfo {}
impl From<ExtendedCommitInfo> for pb::ExtendedCommitInfo {
fn from(lci: ExtendedCommitInfo) -> Self {
Self {
round: lci.round.into(),
votes: lci.votes.into_iter().map(Into::into).collect(),
}
}
}
impl TryFrom<pb::ExtendedCommitInfo> for ExtendedCommitInfo {
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 ExtendedCommitInfo {}
impl From<Snapshot> for pb::Snapshot {
fn from(snapshot: Snapshot) -> Self {
Self {
height: snapshot.height.into(),
format: snapshot.format,
chunks: snapshot.chunks,
hash: snapshot.hash,
metadata: snapshot.metadata,
}
}
}
impl TryFrom<pb::Snapshot> for Snapshot {
type Error = Error;
fn try_from(snapshot: pb::Snapshot) -> Result<Self, Self::Error> {
Ok(Self {
height: snapshot.height.try_into()?,
format: snapshot.format,
chunks: snapshot.chunks,
hash: snapshot.hash,
metadata: snapshot.metadata,
})
}
}
impl Protobuf<pb::Snapshot> for Snapshot {}
}
mod v0_38 {
use super::{
BlockSignatureInfo, CommitInfo, ExecTxResult, ExtendedCommitInfo, ExtendedVoteInfo,
Misbehavior, MisbehaviorKind, Snapshot, Validator, VoteInfo,
};
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;
use bytes::Bytes;
impl From<Validator> for pb::Validator {
fn from(v: Validator) -> Self {
Self {
address: Bytes::copy_from_slice(&v.address[..]),
power: v.power.into(),
}
}
}
impl TryFrom<pb::Validator> for Validator {
type Error = Error;
fn try_from(vu: pb::Validator) -> Result<Self, Self::Error> {
let address = if vu.address.len() == 20 {
let mut bytes = [0u8; 20];
bytes.copy_from_slice(&vu.address);
bytes
} else {
return Err(Error::invalid_account_id_length());
};
Ok(Self {
address,
power: vu.power.try_into()?,
})
}
}
impl Protobuf<pb::Validator> for Validator {}
impl From<BlockSignatureInfo> for RawBlockIdFlag {
fn from(value: BlockSignatureInfo) -> Self {
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,
}
}
}
impl TryFrom<pb::VoteInfo> for VoteInfo {
type Error = Error;
fn try_from(vi: pb::VoteInfo) -> Result<Self, Self::Error> {
let block_id_flag: RawBlockIdFlag = vi
.block_id_flag
.try_into()
.map_err(|_| 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()?),
})
}
}
impl Protobuf<pb::VoteInfo> for VoteInfo {}
impl From<ExtendedVoteInfo> for pb::ExtendedVoteInfo {
fn from(vi: ExtendedVoteInfo) -> 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 ExtendedVoteInfo {
type Error = Error;
fn try_from(vi: pb::ExtendedVoteInfo) -> Result<Self, Self::Error> {
let block_id_flag: RawBlockIdFlag = vi
.block_id_flag
.try_into()
.map_err(|_| 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 ExtendedVoteInfo {}
impl From<Misbehavior> for pb::Misbehavior {
fn from(evidence: Misbehavior) -> Self {
Self {
r#type: evidence.kind as i32,
validator: Some(evidence.validator.into()),
height: evidence.height.into(),
time: Some(evidence.time.into()),
total_voting_power: evidence.total_voting_power.into(),
}
}
}
impl TryFrom<pb::Misbehavior> for Misbehavior {
type Error = Error;
fn try_from(evidence: pb::Misbehavior) -> Result<Self, Self::Error> {
let kind = match evidence.r#type {
0 => MisbehaviorKind::Unknown,
1 => MisbehaviorKind::DuplicateVote,
2 => MisbehaviorKind::LightClientAttack,
_ => return Err(Error::invalid_evidence()),
};
Ok(Self {
kind,
validator: evidence
.validator
.ok_or_else(Error::missing_validator)?
.try_into()?,
height: evidence.height.try_into()?,
time: evidence
.time
.ok_or_else(Error::missing_timestamp)?
.try_into()?,
total_voting_power: evidence.total_voting_power.try_into()?,
})
}
}
impl Protobuf<pb::Misbehavior> for Misbehavior {}
impl From<CommitInfo> for pb::CommitInfo {
fn from(lci: CommitInfo) -> Self {
Self {
round: lci.round.into(),
votes: lci.votes.into_iter().map(Into::into).collect(),
}
}
}
impl TryFrom<pb::CommitInfo> for CommitInfo {
type Error = Error;
fn try_from(lci: pb::CommitInfo) -> 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::CommitInfo> for CommitInfo {}
impl From<ExtendedCommitInfo> for pb::ExtendedCommitInfo {
fn from(lci: ExtendedCommitInfo) -> Self {
Self {
round: lci.round.into(),
votes: lci.votes.into_iter().map(Into::into).collect(),
}
}
}
impl TryFrom<pb::ExtendedCommitInfo> for ExtendedCommitInfo {
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 ExtendedCommitInfo {}
impl From<Snapshot> for pb::Snapshot {
fn from(snapshot: Snapshot) -> Self {
Self {
height: snapshot.height.into(),
format: snapshot.format,
chunks: snapshot.chunks,
hash: snapshot.hash,
metadata: snapshot.metadata,
}
}
}
impl TryFrom<pb::Snapshot> for Snapshot {
type Error = Error;
fn try_from(snapshot: pb::Snapshot) -> Result<Self, Self::Error> {
Ok(Self {
height: snapshot.height.try_into()?,
format: snapshot.format,
chunks: snapshot.chunks,
hash: snapshot.hash,
metadata: snapshot.metadata,
})
}
}
impl Protobuf<pb::Snapshot> for Snapshot {}
impl From<ExecTxResult> for pb::ExecTxResult {
fn from(deliver_tx: ExecTxResult) -> Self {
Self {
code: deliver_tx.code.into(),
data: deliver_tx.data,
log: deliver_tx.log,
info: deliver_tx.info,
gas_wanted: deliver_tx.gas_wanted,
gas_used: deliver_tx.gas_used,
events: deliver_tx.events.into_iter().map(Into::into).collect(),
codespace: deliver_tx.codespace,
}
}
}
impl TryFrom<pb::ExecTxResult> for ExecTxResult {
type Error = Error;
fn try_from(deliver_tx: pb::ExecTxResult) -> Result<Self, Self::Error> {
Ok(Self {
code: deliver_tx.code.into(),
data: deliver_tx.data,
log: deliver_tx.log,
info: deliver_tx.info,
gas_wanted: deliver_tx.gas_wanted,
gas_used: deliver_tx.gas_used,
events: deliver_tx
.events
.into_iter()
.map(TryInto::try_into)
.collect::<Result<_, _>>()?,
codespace: deliver_tx.codespace,
})
}
}
impl Protobuf<pb::ExecTxResult> for ExecTxResult {}
}