iq_cometbft/block/
commit.rs

1//! Commits to a CometBFT blockchain
2
3use cometbft_proto::types::v1::Commit as RawCommit;
4use serde::{Deserialize, Serialize};
5
6use crate::{
7    block::{commit_sig::CommitSig, Height, Id, Round},
8    prelude::*,
9};
10
11/// Commit contains the justification (ie. a set of signatures) that a block was committed by a set
12/// of validators.
13/// TODO: Update links below!
14/// <https://github.com/cometbft/cometbft/blob/51dc810d041eaac78320adc6d53ad8b160b06601/types/block.go#L486-L502>
15/// <https://github.com/tendermint/spec/blob/d46cd7f573a2c6a2399fcab2cde981330aa63f37/spec/core/data_structures.md#lastcommit>
16#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
17#[serde(try_from = "RawCommit", into = "RawCommit")] // Used by testgen Generator trait
18pub struct Commit {
19    /// Block height
20    pub height: Height,
21
22    /// Round
23    pub round: Round,
24
25    /// Block ID
26    pub block_id: Id,
27
28    /// Signatures
29    pub signatures: Vec<CommitSig>,
30}
31
32cometbft_old_pb_modules! {
33    use super::Commit;
34    use crate::{block::commit_sig::CommitSig, error::Error, prelude::*};
35    use pb::types::Commit as RawCommit;
36
37    impl TryFrom<RawCommit> for Commit {
38        type Error = Error;
39
40        fn try_from(value: RawCommit) -> Result<Self, Self::Error> {
41            let signatures: Result<Vec<CommitSig>, Error> = value
42                .signatures
43                .into_iter()
44                .map(TryFrom::try_from)
45                .collect();
46            Ok(Self {
47                height: value.height.try_into()?,
48                round: value.round.try_into()?,
49                block_id: value
50                    .block_id
51                    .ok_or_else(|| Error::invalid_block("missing block id".to_string()))?
52                    .try_into()?, // gogoproto.nullable = false
53                signatures: signatures?,
54            })
55        }
56    }
57
58    impl From<Commit> for RawCommit {
59        fn from(value: Commit) -> Self {
60            RawCommit {
61                height: value.height.into(),
62                round: value.round.into(),
63                block_id: Some(value.block_id.into()),
64                signatures: value.signatures.into_iter().map(Into::into).collect(),
65            }
66        }
67    }
68}
69
70mod v1 {
71    use super::Commit;
72    use crate::{block::commit_sig::CommitSig, error::Error, prelude::*};
73    use cometbft_proto::types::v1 as pb;
74
75    impl TryFrom<pb::Commit> for Commit {
76        type Error = Error;
77
78        fn try_from(value: pb::Commit) -> Result<Self, Self::Error> {
79            let signatures: Result<Vec<CommitSig>, Error> = value
80                .signatures
81                .into_iter()
82                .map(TryFrom::try_from)
83                .collect();
84            Ok(Self {
85                height: value.height.try_into()?,
86                round: value.round.try_into()?,
87                block_id: value
88                    .block_id
89                    .ok_or_else(|| Error::invalid_block("missing block id".to_string()))?
90                    .try_into()?, // gogoproto.nullable = false
91                signatures: signatures?,
92            })
93        }
94    }
95
96    impl From<Commit> for pb::Commit {
97        fn from(value: Commit) -> Self {
98            pb::Commit {
99                height: value.height.into(),
100                round: value.round.into(),
101                block_id: Some(value.block_id.into()),
102                signatures: value.signatures.into_iter().map(Into::into).collect(),
103            }
104        }
105    }
106}
107
108mod v1beta1 {
109    use super::Commit;
110    use crate::{block::commit_sig::CommitSig, error::Error, prelude::*};
111    use cometbft_proto::types::v1beta1 as pb;
112
113    impl TryFrom<pb::Commit> for Commit {
114        type Error = Error;
115
116        fn try_from(value: pb::Commit) -> Result<Self, Self::Error> {
117            let signatures: Result<Vec<CommitSig>, Error> = value
118                .signatures
119                .into_iter()
120                .map(TryFrom::try_from)
121                .collect();
122            Ok(Self {
123                height: value.height.try_into()?,
124                round: value.round.try_into()?,
125                block_id: value
126                    .block_id
127                    .ok_or_else(|| Error::invalid_block("missing block id".to_string()))?
128                    .try_into()?, // gogoproto.nullable = false
129                signatures: signatures?,
130            })
131        }
132    }
133
134    impl From<Commit> for pb::Commit {
135        fn from(value: Commit) -> Self {
136            pb::Commit {
137                height: value.height.into(),
138                round: value.round.into(),
139                block_id: Some(value.block_id.into()),
140                signatures: value.signatures.into_iter().map(Into::into).collect(),
141            }
142        }
143    }
144}
145
146impl Default for Commit {
147    fn default() -> Self {
148        Commit {
149            // The default Height is 1, but the default commit is an empty commit with height = 0.
150            height: Height::from(0_u32),
151            round: Default::default(),
152            block_id: Default::default(),
153            signatures: vec![],
154        }
155    }
156}