tendermint/abci/
types.rs

1//! ABCI-specific data types used in requests and responses.
2//!
3//! These types have changes from the core data structures to better accommodate
4//! ABCI applications.
5//!
6//! [ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#data-types)
7
8use bytes::Bytes;
9use serde::{Deserialize, Serialize};
10
11use super::{Code, Event};
12use crate::{
13    block::{self, BlockIdFlag},
14    prelude::*,
15    serializers, vote, Signature, Time,
16};
17
18/// A validator address with voting power.
19///
20/// [ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#validator)
21#[derive(Clone, PartialEq, Eq, Debug)]
22pub struct Validator {
23    /// The validator's address (the first 20 bytes of `SHA256(public_key)`).
24    pub address: [u8; 20],
25    /// The voting power of the validator.
26    pub power: vote::Power,
27}
28
29/// Information about a whether a validator signed the last block.
30///
31/// [ABCI documentation](https://github.com/cometbft/cometbft/blob/v0.38.x/spec/abci/abci%2B%2B_methods.md#voteinfo)
32#[derive(Clone, PartialEq, Eq, Debug)]
33pub struct VoteInfo {
34    /// Identifies the validator.
35    pub validator: Validator,
36    /// Whether or not the validator signed the last block.
37    pub sig_info: BlockSignatureInfo,
38}
39
40/// Information about a whether a validator signed the last block,
41/// together with vote extensions.
42///
43/// [ABCI documentation](https://github.com/cometbft/cometbft/blob/v0.38.x/spec/abci/abci%2B%2B_methods.md#extendedvoteinfo)
44#[derive(Clone, PartialEq, Eq, Debug)]
45pub struct ExtendedVoteInfo {
46    /// Identifies the validator.
47    pub validator: Validator,
48    /// Whether or not the validator signed the last block.
49    pub sig_info: BlockSignatureInfo,
50    /// Non-deterministic extension provided by the sending validator's application.
51    ///
52    /// This field is only used since CometBFT 0.38. It will be ignored when
53    /// encoding into earlier protocol versions.
54    pub vote_extension: Bytes,
55    /// Signature for the vote extension.
56    ///
57    /// This field has been added in CometBFT 0.38 and will be ignored when
58    /// encoding into earlier protocol versions.
59    pub extension_signature: Option<Signature>,
60}
61
62#[derive(Copy, Clone, Debug, PartialEq, Eq)]
63/// Information on how the validator voted for a block.
64pub enum BlockSignatureInfo {
65    /// Full information available, as determined by the [`BlockIdFlag`] value.
66    ///
67    /// In CometBFT versions before 0.38, both [`Commit`] and [`Nil`] values
68    /// are encoded as the true value of the `signed_last_block` field,
69    /// losing information on whether the vote was for the block or nil.
70    ///
71    /// [`Commit`]: BlockIdFlag::Commit
72    /// [`Nil`]: BlockIdFlag::Nil
73    Flag(BlockIdFlag),
74    /// In the message encoded in a CometBFT version before 0.38,
75    /// the `signed_last_block` field has the value of true.
76    ///
77    /// This variant should not be used in CometBFT 0.38 or later
78    /// and will result in the "undefined" encoding in protobuf.
79    LegacySigned,
80}
81
82impl BlockSignatureInfo {
83    /// Whether the validator has signed the block accordingly to this information.
84    pub fn is_signed(&self) -> bool {
85        use BlockIdFlag::*;
86
87        match self {
88            BlockSignatureInfo::Flag(Commit) | BlockSignatureInfo::Flag(Nil) => true,
89            BlockSignatureInfo::Flag(Absent) => false,
90            BlockSignatureInfo::LegacySigned => true,
91        }
92    }
93}
94
95/// The possible kinds of [`Misbehavior`].
96///
97/// Note: the
98/// [ABCI documentation](https://github.com/tendermint/tendermint/blob/main/spec/abci/abci++_methods.md#misbehaviortype)
99/// calls this `MisbehaviorType`, but we follow the Rust convention and name it `MisbehaviorKind`
100/// to avoid confusion with Rust types.
101#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
102#[repr(i32)]
103pub enum MisbehaviorKind {
104    /// Unknown evidence type (proto default value).
105    Unknown = 0,
106    /// Evidence that the validator voted for two different blocks in the same
107    /// round of the same height.
108    DuplicateVote = 1,
109    /// Evidence that a validator attacked a light client.
110    LightClientAttack = 2,
111}
112
113/// Evidence of validator misbehavior.
114///
115/// [ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#evidence)
116#[derive(Clone, PartialEq, Eq, Debug)]
117pub struct Misbehavior {
118    /// The kind of evidence.
119    ///
120    /// Note: this field is called `type` in the protobuf, but we call it `kind`
121    /// to avoid the Rust keyword.
122    pub kind: MisbehaviorKind,
123    /// The offending validator.
124    pub validator: Validator,
125    /// The height when the offense occurred.
126    pub height: block::Height,
127    /// The corresponding time when the offense occurred.
128    pub time: Time,
129    /// Total voting power of the validator set at `height`.
130    ///
131    /// This is included in case the ABCI application does not store historical
132    /// validators, cf.
133    /// [#4581](https://github.com/tendermint/tendermint/issues/4581)
134    pub total_voting_power: vote::Power,
135}
136
137/// Information on a block commit.
138///
139/// [ABCI documentation](https://github.com/cometbft/cometbft/blob/v0.38.x/spec/abci/abci%2B%2B_methods.md#commitinfo)
140#[derive(Clone, PartialEq, Eq, Debug)]
141pub struct CommitInfo {
142    /// The commit round.
143    ///
144    /// Reflects the total number of rounds it took to come to consensus for the
145    /// current block.
146    pub round: block::Round,
147    /// The list of validator addresses in the last validator set, with their
148    /// voting power and whether or not they signed a vote.
149    pub votes: Vec<VoteInfo>,
150}
151
152/// Information on a block commit with provided vote extensions.
153///
154/// [ABCI documentation](https://github.com/cometbft/cometbft/blob/v0.38.x/spec/abci/abci%2B%2B_methods.md#extendedcommitinfo)
155#[derive(Clone, PartialEq, Eq, Debug)]
156pub struct ExtendedCommitInfo {
157    /// The commit round.
158    ///
159    /// Reflects the total number of rounds it took to come to consensus for the
160    /// current block.
161    pub round: block::Round,
162    /// The list of validator addresses in the last validator set, with their
163    /// voting power and whether or not they signed a vote.
164    pub votes: Vec<ExtendedVoteInfo>,
165}
166
167/// Used for state sync snapshots.
168///
169/// When sent across the network, a `Snapshot` can be at most 4 MB.
170///
171/// [ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#snapshot)
172#[derive(Clone, PartialEq, Eq, Debug)]
173pub struct Snapshot {
174    /// The height at which the snapshot was taken
175    pub height: block::Height,
176    /// The application-specific snapshot format identifier.
177    ///
178    /// This allows applications to version their snapshot data format and make
179    /// backwards-incompatible changes. Tendermint does not interpret this field.
180    pub format: u32,
181    /// The number of chunks in the snapshot. Must be at least 1.
182    pub chunks: u32,
183    /// An arbitrary snapshot hash.
184    ///
185    /// This hash must be equal only for identical snapshots across nodes.
186    /// Tendermint does not interpret the hash, only compares it with other
187    /// hashes.
188    pub hash: Bytes,
189    /// Arbitrary application metadata, e.g., chunk hashes or other verification data.
190    pub metadata: Bytes,
191}
192
193/// Results of executing one individual transaction.
194///
195/// This structure is equivalent to [`response::DeliverTx`] which will be
196/// deprecated and removed.
197///
198/// [`response::DeliverTx`]: super::response::DeliverTx
199#[derive(Clone, PartialEq, Eq, Debug, Default, Serialize, Deserialize)]
200pub struct ExecTxResult {
201    /// The response code.
202    ///
203    /// This code should be `Ok` only if the transaction is fully valid. However,
204    /// invalid transactions included in a block will still be executed against
205    /// the application state.
206    #[serde(default)]
207    pub code: Code,
208
209    /// Result bytes, if any.
210    #[serde(default, with = "serializers::nullable")]
211    pub data: Bytes,
212
213    /// The output of the application's logger.
214    ///
215    /// **May be non-deterministic**.
216    #[serde(default)]
217    pub log: String,
218
219    /// Additional information.
220    ///
221    /// **May be non-deterministic**.
222    #[serde(default)]
223    pub info: String,
224    /// Amount of gas requested for the transaction.
225    #[serde(default, with = "serializers::from_str")]
226    pub gas_wanted: i64,
227
228    /// Amount of gas consumed by the transaction.
229    #[serde(default, with = "serializers::from_str")]
230    pub gas_used: i64,
231
232    /// Events that occurred while executing the transaction.
233    #[serde(default)]
234    pub events: Vec<Event>,
235
236    /// The namespace for the `code`.
237    #[serde(default)]
238    pub codespace: String,
239}
240
241// =============================================================================
242// Protobuf conversions
243// =============================================================================
244
245mod v0_34 {
246    use super::{
247        BlockSignatureInfo, CommitInfo, Misbehavior, MisbehaviorKind, Snapshot, Validator, VoteInfo,
248    };
249    use crate::{block::BlockIdFlag, prelude::*, Error};
250    use tendermint_proto::v0_34::abci as pb;
251    use tendermint_proto::Protobuf;
252
253    use bytes::Bytes;
254
255    impl From<Validator> for pb::Validator {
256        fn from(v: Validator) -> Self {
257            Self {
258                address: Bytes::copy_from_slice(&v.address[..]),
259                power: v.power.into(),
260            }
261        }
262    }
263
264    impl TryFrom<pb::Validator> for Validator {
265        type Error = Error;
266
267        fn try_from(vu: pb::Validator) -> Result<Self, Self::Error> {
268            let address = if vu.address.len() == 20 {
269                let mut bytes = [0u8; 20];
270                bytes.copy_from_slice(&vu.address);
271                bytes
272            } else {
273                return Err(Error::invalid_account_id_length());
274            };
275
276            Ok(Self {
277                address,
278                power: vu.power.try_into()?,
279            })
280        }
281    }
282
283    impl Protobuf<pb::Validator> for Validator {}
284
285    impl From<VoteInfo> for pb::VoteInfo {
286        fn from(vi: VoteInfo) -> Self {
287            Self {
288                validator: Some(vi.validator.into()),
289                signed_last_block: vi.sig_info.is_signed(),
290            }
291        }
292    }
293
294    impl TryFrom<pb::VoteInfo> for VoteInfo {
295        type Error = Error;
296
297        fn try_from(vi: pb::VoteInfo) -> Result<Self, Self::Error> {
298            let sig_info = if vi.signed_last_block {
299                BlockSignatureInfo::LegacySigned
300            } else {
301                BlockSignatureInfo::Flag(BlockIdFlag::Absent)
302            };
303            Ok(Self {
304                validator: vi
305                    .validator
306                    .ok_or_else(Error::missing_validator)?
307                    .try_into()?,
308                sig_info,
309            })
310        }
311    }
312
313    impl Protobuf<pb::VoteInfo> for VoteInfo {}
314
315    impl From<Misbehavior> for pb::Evidence {
316        fn from(evidence: Misbehavior) -> Self {
317            Self {
318                r#type: evidence.kind as i32,
319                validator: Some(evidence.validator.into()),
320                height: evidence.height.into(),
321                time: Some(evidence.time.into()),
322                total_voting_power: evidence.total_voting_power.into(),
323            }
324        }
325    }
326
327    impl TryFrom<pb::Evidence> for Misbehavior {
328        type Error = Error;
329
330        fn try_from(evidence: pb::Evidence) -> Result<Self, Self::Error> {
331            let kind = match evidence.r#type {
332                0 => MisbehaviorKind::Unknown,
333                1 => MisbehaviorKind::DuplicateVote,
334                2 => MisbehaviorKind::LightClientAttack,
335                _ => return Err(Error::invalid_evidence()),
336            };
337
338            Ok(Self {
339                kind,
340                validator: evidence
341                    .validator
342                    .ok_or_else(Error::missing_validator)?
343                    .try_into()?,
344                height: evidence.height.try_into()?,
345                time: evidence
346                    .time
347                    .ok_or_else(Error::missing_timestamp)?
348                    .try_into()?,
349                total_voting_power: evidence.total_voting_power.try_into()?,
350            })
351        }
352    }
353
354    impl Protobuf<pb::Evidence> for Misbehavior {}
355
356    impl From<CommitInfo> for pb::LastCommitInfo {
357        fn from(lci: CommitInfo) -> Self {
358            Self {
359                round: lci.round.into(),
360                votes: lci.votes.into_iter().map(Into::into).collect(),
361            }
362        }
363    }
364
365    impl TryFrom<pb::LastCommitInfo> for CommitInfo {
366        type Error = Error;
367
368        fn try_from(lci: pb::LastCommitInfo) -> Result<Self, Self::Error> {
369            Ok(Self {
370                round: lci.round.try_into()?,
371                votes: lci
372                    .votes
373                    .into_iter()
374                    .map(TryInto::try_into)
375                    .collect::<Result<_, _>>()?,
376            })
377        }
378    }
379
380    impl Protobuf<pb::LastCommitInfo> for CommitInfo {}
381
382    impl From<Snapshot> for pb::Snapshot {
383        fn from(snapshot: Snapshot) -> Self {
384            Self {
385                height: snapshot.height.into(),
386                format: snapshot.format,
387                chunks: snapshot.chunks,
388                hash: snapshot.hash,
389                metadata: snapshot.metadata,
390            }
391        }
392    }
393
394    impl TryFrom<pb::Snapshot> for Snapshot {
395        type Error = Error;
396
397        fn try_from(snapshot: pb::Snapshot) -> Result<Self, Self::Error> {
398            Ok(Self {
399                height: snapshot.height.try_into()?,
400                format: snapshot.format,
401                chunks: snapshot.chunks,
402                hash: snapshot.hash,
403                metadata: snapshot.metadata,
404            })
405        }
406    }
407
408    impl Protobuf<pb::Snapshot> for Snapshot {}
409}
410
411mod v0_37 {
412    use super::{
413        BlockSignatureInfo, CommitInfo, ExtendedCommitInfo, ExtendedVoteInfo, Misbehavior,
414        MisbehaviorKind, Snapshot, Validator, VoteInfo,
415    };
416    use crate::{block::BlockIdFlag, prelude::*, Error};
417    use tendermint_proto::v0_37::abci as pb;
418    use tendermint_proto::Protobuf;
419
420    use bytes::Bytes;
421
422    impl From<Validator> for pb::Validator {
423        fn from(v: Validator) -> Self {
424            Self {
425                address: Bytes::copy_from_slice(&v.address[..]),
426                power: v.power.into(),
427            }
428        }
429    }
430
431    impl TryFrom<pb::Validator> for Validator {
432        type Error = Error;
433
434        fn try_from(vu: pb::Validator) -> Result<Self, Self::Error> {
435            let address = if vu.address.len() == 20 {
436                let mut bytes = [0u8; 20];
437                bytes.copy_from_slice(&vu.address);
438                bytes
439            } else {
440                return Err(Error::invalid_account_id_length());
441            };
442
443            Ok(Self {
444                address,
445                power: vu.power.try_into()?,
446            })
447        }
448    }
449
450    impl Protobuf<pb::Validator> for Validator {}
451
452    impl From<VoteInfo> for pb::VoteInfo {
453        fn from(vi: VoteInfo) -> Self {
454            Self {
455                validator: Some(vi.validator.into()),
456                signed_last_block: vi.sig_info.is_signed(),
457            }
458        }
459    }
460
461    impl TryFrom<pb::VoteInfo> for VoteInfo {
462        type Error = Error;
463
464        fn try_from(vi: pb::VoteInfo) -> Result<Self, Self::Error> {
465            let sig_info = if vi.signed_last_block {
466                BlockSignatureInfo::LegacySigned
467            } else {
468                BlockSignatureInfo::Flag(BlockIdFlag::Absent)
469            };
470            Ok(Self {
471                validator: vi
472                    .validator
473                    .ok_or_else(Error::missing_validator)?
474                    .try_into()?,
475                sig_info,
476            })
477        }
478    }
479
480    impl Protobuf<pb::VoteInfo> for VoteInfo {}
481
482    // ExtendedVoteInfo is defined in 0.37, but the vote_extension field
483    // should be always nil and is ignored.
484
485    impl From<ExtendedVoteInfo> for pb::ExtendedVoteInfo {
486        fn from(vi: ExtendedVoteInfo) -> Self {
487            Self {
488                validator: Some(vi.validator.into()),
489                signed_last_block: vi.sig_info.is_signed(),
490                vote_extension: Default::default(),
491            }
492        }
493    }
494
495    impl TryFrom<pb::ExtendedVoteInfo> for ExtendedVoteInfo {
496        type Error = Error;
497
498        fn try_from(vi: pb::ExtendedVoteInfo) -> Result<Self, Self::Error> {
499            let sig_info = if vi.signed_last_block {
500                BlockSignatureInfo::LegacySigned
501            } else {
502                BlockSignatureInfo::Flag(BlockIdFlag::Absent)
503            };
504            Ok(Self {
505                validator: vi
506                    .validator
507                    .ok_or_else(Error::missing_validator)?
508                    .try_into()?,
509                sig_info,
510                vote_extension: Default::default(),
511                extension_signature: None,
512            })
513        }
514    }
515
516    impl Protobuf<pb::ExtendedVoteInfo> for ExtendedVoteInfo {}
517
518    impl From<Misbehavior> for pb::Misbehavior {
519        fn from(evidence: Misbehavior) -> Self {
520            Self {
521                r#type: evidence.kind as i32,
522                validator: Some(evidence.validator.into()),
523                height: evidence.height.into(),
524                time: Some(evidence.time.into()),
525                total_voting_power: evidence.total_voting_power.into(),
526            }
527        }
528    }
529
530    impl TryFrom<pb::Misbehavior> for Misbehavior {
531        type Error = Error;
532
533        fn try_from(evidence: pb::Misbehavior) -> Result<Self, Self::Error> {
534            let kind = match evidence.r#type {
535                0 => MisbehaviorKind::Unknown,
536                1 => MisbehaviorKind::DuplicateVote,
537                2 => MisbehaviorKind::LightClientAttack,
538                _ => return Err(Error::invalid_evidence()),
539            };
540
541            Ok(Self {
542                kind,
543                validator: evidence
544                    .validator
545                    .ok_or_else(Error::missing_validator)?
546                    .try_into()?,
547                height: evidence.height.try_into()?,
548                time: evidence
549                    .time
550                    .ok_or_else(Error::missing_timestamp)?
551                    .try_into()?,
552                total_voting_power: evidence.total_voting_power.try_into()?,
553            })
554        }
555    }
556
557    impl Protobuf<pb::Misbehavior> for Misbehavior {}
558
559    impl From<CommitInfo> for pb::CommitInfo {
560        fn from(lci: CommitInfo) -> Self {
561            Self {
562                round: lci.round.into(),
563                votes: lci.votes.into_iter().map(Into::into).collect(),
564            }
565        }
566    }
567
568    impl TryFrom<pb::CommitInfo> for CommitInfo {
569        type Error = Error;
570
571        fn try_from(lci: pb::CommitInfo) -> Result<Self, Self::Error> {
572            Ok(Self {
573                round: lci.round.try_into()?,
574                votes: lci
575                    .votes
576                    .into_iter()
577                    .map(TryInto::try_into)
578                    .collect::<Result<_, _>>()?,
579            })
580        }
581    }
582
583    impl Protobuf<pb::CommitInfo> for CommitInfo {}
584
585    impl From<ExtendedCommitInfo> for pb::ExtendedCommitInfo {
586        fn from(lci: ExtendedCommitInfo) -> Self {
587            Self {
588                round: lci.round.into(),
589                votes: lci.votes.into_iter().map(Into::into).collect(),
590            }
591        }
592    }
593
594    impl TryFrom<pb::ExtendedCommitInfo> for ExtendedCommitInfo {
595        type Error = Error;
596
597        fn try_from(lci: pb::ExtendedCommitInfo) -> Result<Self, Self::Error> {
598            Ok(Self {
599                round: lci.round.try_into()?,
600                votes: lci
601                    .votes
602                    .into_iter()
603                    .map(TryInto::try_into)
604                    .collect::<Result<_, _>>()?,
605            })
606        }
607    }
608
609    impl Protobuf<pb::ExtendedCommitInfo> for ExtendedCommitInfo {}
610
611    impl From<Snapshot> for pb::Snapshot {
612        fn from(snapshot: Snapshot) -> Self {
613            Self {
614                height: snapshot.height.into(),
615                format: snapshot.format,
616                chunks: snapshot.chunks,
617                hash: snapshot.hash,
618                metadata: snapshot.metadata,
619            }
620        }
621    }
622
623    impl TryFrom<pb::Snapshot> for Snapshot {
624        type Error = Error;
625
626        fn try_from(snapshot: pb::Snapshot) -> Result<Self, Self::Error> {
627            Ok(Self {
628                height: snapshot.height.try_into()?,
629                format: snapshot.format,
630                chunks: snapshot.chunks,
631                hash: snapshot.hash,
632                metadata: snapshot.metadata,
633            })
634        }
635    }
636
637    impl Protobuf<pb::Snapshot> for Snapshot {}
638}
639
640mod v0_38 {
641    use super::{
642        BlockSignatureInfo, CommitInfo, ExecTxResult, ExtendedCommitInfo, ExtendedVoteInfo,
643        Misbehavior, MisbehaviorKind, Snapshot, Validator, VoteInfo,
644    };
645    use crate::{prelude::*, Error, Signature};
646    use tendermint_proto::v0_38::abci as pb;
647    use tendermint_proto::v0_38::types::BlockIdFlag as RawBlockIdFlag;
648    use tendermint_proto::Protobuf;
649
650    use bytes::Bytes;
651
652    impl From<Validator> for pb::Validator {
653        fn from(v: Validator) -> Self {
654            Self {
655                address: Bytes::copy_from_slice(&v.address[..]),
656                power: v.power.into(),
657            }
658        }
659    }
660
661    impl TryFrom<pb::Validator> for Validator {
662        type Error = Error;
663
664        fn try_from(vu: pb::Validator) -> Result<Self, Self::Error> {
665            let address = if vu.address.len() == 20 {
666                let mut bytes = [0u8; 20];
667                bytes.copy_from_slice(&vu.address);
668                bytes
669            } else {
670                return Err(Error::invalid_account_id_length());
671            };
672
673            Ok(Self {
674                address,
675                power: vu.power.try_into()?,
676            })
677        }
678    }
679
680    impl Protobuf<pb::Validator> for Validator {}
681
682    impl From<BlockSignatureInfo> for RawBlockIdFlag {
683        fn from(value: BlockSignatureInfo) -> Self {
684            // The API user should not use the LegacySigned flag in
685            // values for 0.38-based chains. As this conversion is infallible,
686            // silently convert it to the undefined value.
687            match value {
688                BlockSignatureInfo::Flag(flag) => flag.into(),
689                BlockSignatureInfo::LegacySigned => RawBlockIdFlag::Unknown,
690            }
691        }
692    }
693
694    impl From<VoteInfo> for pb::VoteInfo {
695        fn from(vi: VoteInfo) -> Self {
696            let block_id_flag: RawBlockIdFlag = vi.sig_info.into();
697            Self {
698                validator: Some(vi.validator.into()),
699                block_id_flag: block_id_flag as i32,
700            }
701        }
702    }
703
704    impl TryFrom<pb::VoteInfo> for VoteInfo {
705        type Error = Error;
706
707        fn try_from(vi: pb::VoteInfo) -> Result<Self, Self::Error> {
708            let block_id_flag: RawBlockIdFlag = vi
709                .block_id_flag
710                .try_into()
711                .map_err(|_| Error::block_id_flag())?;
712            Ok(Self {
713                validator: vi
714                    .validator
715                    .ok_or_else(Error::missing_validator)?
716                    .try_into()?,
717                sig_info: BlockSignatureInfo::Flag(block_id_flag.try_into()?),
718            })
719        }
720    }
721
722    impl Protobuf<pb::VoteInfo> for VoteInfo {}
723
724    impl From<ExtendedVoteInfo> for pb::ExtendedVoteInfo {
725        fn from(vi: ExtendedVoteInfo) -> Self {
726            let block_id_flag: RawBlockIdFlag = vi.sig_info.into();
727            Self {
728                validator: Some(vi.validator.into()),
729                vote_extension: vi.vote_extension,
730                extension_signature: vi.extension_signature.map(Into::into).unwrap_or_default(),
731                block_id_flag: block_id_flag as i32,
732            }
733        }
734    }
735
736    impl TryFrom<pb::ExtendedVoteInfo> for ExtendedVoteInfo {
737        type Error = Error;
738
739        fn try_from(vi: pb::ExtendedVoteInfo) -> Result<Self, Self::Error> {
740            let block_id_flag: RawBlockIdFlag = vi
741                .block_id_flag
742                .try_into()
743                .map_err(|_| Error::block_id_flag())?;
744            Ok(Self {
745                validator: vi
746                    .validator
747                    .ok_or_else(Error::missing_validator)?
748                    .try_into()?,
749                sig_info: BlockSignatureInfo::Flag(block_id_flag.try_into()?),
750                vote_extension: vi.vote_extension,
751                extension_signature: Signature::new(vi.extension_signature)?,
752            })
753        }
754    }
755
756    impl Protobuf<pb::ExtendedVoteInfo> for ExtendedVoteInfo {}
757
758    impl From<Misbehavior> for pb::Misbehavior {
759        fn from(evidence: Misbehavior) -> Self {
760            Self {
761                r#type: evidence.kind as i32,
762                validator: Some(evidence.validator.into()),
763                height: evidence.height.into(),
764                time: Some(evidence.time.into()),
765                total_voting_power: evidence.total_voting_power.into(),
766            }
767        }
768    }
769
770    impl TryFrom<pb::Misbehavior> for Misbehavior {
771        type Error = Error;
772
773        fn try_from(evidence: pb::Misbehavior) -> Result<Self, Self::Error> {
774            let kind = match evidence.r#type {
775                0 => MisbehaviorKind::Unknown,
776                1 => MisbehaviorKind::DuplicateVote,
777                2 => MisbehaviorKind::LightClientAttack,
778                _ => return Err(Error::invalid_evidence()),
779            };
780
781            Ok(Self {
782                kind,
783                validator: evidence
784                    .validator
785                    .ok_or_else(Error::missing_validator)?
786                    .try_into()?,
787                height: evidence.height.try_into()?,
788                time: evidence
789                    .time
790                    .ok_or_else(Error::missing_timestamp)?
791                    .try_into()?,
792                total_voting_power: evidence.total_voting_power.try_into()?,
793            })
794        }
795    }
796
797    impl Protobuf<pb::Misbehavior> for Misbehavior {}
798
799    impl From<CommitInfo> for pb::CommitInfo {
800        fn from(lci: CommitInfo) -> Self {
801            Self {
802                round: lci.round.into(),
803                votes: lci.votes.into_iter().map(Into::into).collect(),
804            }
805        }
806    }
807
808    impl TryFrom<pb::CommitInfo> for CommitInfo {
809        type Error = Error;
810
811        fn try_from(lci: pb::CommitInfo) -> Result<Self, Self::Error> {
812            Ok(Self {
813                round: lci.round.try_into()?,
814                votes: lci
815                    .votes
816                    .into_iter()
817                    .map(TryInto::try_into)
818                    .collect::<Result<_, _>>()?,
819            })
820        }
821    }
822
823    impl Protobuf<pb::CommitInfo> for CommitInfo {}
824
825    impl From<ExtendedCommitInfo> for pb::ExtendedCommitInfo {
826        fn from(lci: ExtendedCommitInfo) -> Self {
827            Self {
828                round: lci.round.into(),
829                votes: lci.votes.into_iter().map(Into::into).collect(),
830            }
831        }
832    }
833
834    impl TryFrom<pb::ExtendedCommitInfo> for ExtendedCommitInfo {
835        type Error = Error;
836
837        fn try_from(lci: pb::ExtendedCommitInfo) -> Result<Self, Self::Error> {
838            Ok(Self {
839                round: lci.round.try_into()?,
840                votes: lci
841                    .votes
842                    .into_iter()
843                    .map(TryInto::try_into)
844                    .collect::<Result<_, _>>()?,
845            })
846        }
847    }
848
849    impl Protobuf<pb::ExtendedCommitInfo> for ExtendedCommitInfo {}
850
851    impl From<Snapshot> for pb::Snapshot {
852        fn from(snapshot: Snapshot) -> Self {
853            Self {
854                height: snapshot.height.into(),
855                format: snapshot.format,
856                chunks: snapshot.chunks,
857                hash: snapshot.hash,
858                metadata: snapshot.metadata,
859            }
860        }
861    }
862
863    impl TryFrom<pb::Snapshot> for Snapshot {
864        type Error = Error;
865
866        fn try_from(snapshot: pb::Snapshot) -> Result<Self, Self::Error> {
867            Ok(Self {
868                height: snapshot.height.try_into()?,
869                format: snapshot.format,
870                chunks: snapshot.chunks,
871                hash: snapshot.hash,
872                metadata: snapshot.metadata,
873            })
874        }
875    }
876
877    impl Protobuf<pb::Snapshot> for Snapshot {}
878
879    impl From<ExecTxResult> for pb::ExecTxResult {
880        fn from(deliver_tx: ExecTxResult) -> Self {
881            Self {
882                code: deliver_tx.code.into(),
883                data: deliver_tx.data,
884                log: deliver_tx.log,
885                info: deliver_tx.info,
886                gas_wanted: deliver_tx.gas_wanted,
887                gas_used: deliver_tx.gas_used,
888                events: deliver_tx.events.into_iter().map(Into::into).collect(),
889                codespace: deliver_tx.codespace,
890            }
891        }
892    }
893
894    impl TryFrom<pb::ExecTxResult> for ExecTxResult {
895        type Error = Error;
896
897        fn try_from(deliver_tx: pb::ExecTxResult) -> Result<Self, Self::Error> {
898            Ok(Self {
899                code: deliver_tx.code.into(),
900                data: deliver_tx.data,
901                log: deliver_tx.log,
902                info: deliver_tx.info,
903                gas_wanted: deliver_tx.gas_wanted,
904                gas_used: deliver_tx.gas_used,
905                events: deliver_tx
906                    .events
907                    .into_iter()
908                    .map(TryInto::try_into)
909                    .collect::<Result<_, _>>()?,
910                codespace: deliver_tx.codespace,
911            })
912        }
913    }
914
915    impl Protobuf<pb::ExecTxResult> for ExecTxResult {}
916}