celestia_tendermint/block/
commit_sig.rs1use crate::{account, prelude::*, Signature, Time};
4
5#[derive(Clone, Debug, PartialEq, Eq)]
8pub enum CommitSig {
9 BlockIdFlagAbsent,
11 BlockIdFlagCommit {
13 validator_address: account::Id,
15 timestamp: Time,
17 signature: Option<Signature>,
19 },
20 BlockIdFlagNil {
22 validator_address: account::Id,
24 timestamp: Time,
26 signature: Option<Signature>,
28 },
29}
30
31impl CommitSig {
32 pub fn validator_address(&self) -> Option<account::Id> {
34 match self {
35 Self::BlockIdFlagCommit {
36 validator_address, ..
37 } => Some(*validator_address),
38 Self::BlockIdFlagNil {
39 validator_address, ..
40 } => Some(*validator_address),
41 _ => None,
42 }
43 }
44
45 pub fn is_absent(&self) -> bool {
47 self == &Self::BlockIdFlagAbsent
48 }
49
50 pub fn is_commit(&self) -> bool {
52 matches!(self, Self::BlockIdFlagCommit { .. })
53 }
54
55 pub fn is_nil(&self) -> bool {
57 matches!(self, Self::BlockIdFlagNil { .. })
58 }
59}
60
61tendermint_pb_modules! {
62 use super::CommitSig;
63 use crate::{error::Error, prelude::*, Signature};
64 use num_traits::ToPrimitive;
65 use pb::types::{BlockIdFlag, CommitSig as RawCommitSig};
66
67 impl TryFrom<RawCommitSig> for CommitSig {
70 type Error = Error;
71
72 fn try_from(value: RawCommitSig) -> Result<Self, Self::Error> {
73 if value.block_id_flag == BlockIdFlag::Absent.to_i32().unwrap() {
74 if value.timestamp.is_some() {
75 let timestamp = value.timestamp.unwrap();
76 if timestamp.nanos != 0 || timestamp.seconds != -62135596800 {
78 return Err(Error::invalid_timestamp(
79 "absent commitsig has non-zero timestamp".to_string(),
80 ));
81 }
82 }
83
84 if !value.signature.is_empty() {
85 return Err(Error::invalid_signature(
86 "expected empty signature for absent commitsig".to_string(),
87 ));
88 }
89
90 return Ok(CommitSig::BlockIdFlagAbsent);
91 }
92
93 if value.block_id_flag == BlockIdFlag::Commit.to_i32().unwrap() {
94 if value.signature.is_empty() {
95 return Err(Error::invalid_signature(
96 "expected non-empty signature for regular commitsig".to_string(),
97 ));
98 }
99
100 if value.validator_address.is_empty() {
101 return Err(Error::invalid_validator_address());
102 }
103
104 let timestamp = value
105 .timestamp
106 .ok_or_else(Error::missing_timestamp)?
107 .try_into()?;
108
109 return Ok(CommitSig::BlockIdFlagCommit {
110 validator_address: value.validator_address.try_into()?,
111 timestamp,
112 signature: Signature::new(value.signature)?,
113 });
114 }
115 if value.block_id_flag == BlockIdFlag::Nil.to_i32().unwrap() {
116 if value.signature.is_empty() {
117 return Err(Error::invalid_signature(
118 "nil commitsig has no signature".to_string(),
119 ));
120 }
121 if value.validator_address.is_empty() {
122 return Err(Error::invalid_validator_address());
123 }
124 return Ok(CommitSig::BlockIdFlagNil {
125 validator_address: value.validator_address.try_into()?,
126 timestamp: value
127 .timestamp
128 .ok_or_else(Error::missing_timestamp)?
129 .try_into()?,
130 signature: Signature::new(value.signature)?,
131 });
132 }
133 Err(Error::block_id_flag())
134 }
135 }
136
137 impl From<CommitSig> for RawCommitSig {
138 fn from(commit: CommitSig) -> RawCommitSig {
139 match commit {
140 CommitSig::BlockIdFlagAbsent => RawCommitSig {
141 block_id_flag: BlockIdFlag::Absent.to_i32().unwrap(),
142 validator_address: Vec::new(),
143 timestamp: None,
144 signature: Vec::new(),
145 },
146 CommitSig::BlockIdFlagNil {
147 validator_address,
148 timestamp,
149 signature,
150 } => RawCommitSig {
151 block_id_flag: BlockIdFlag::Nil.to_i32().unwrap(),
152 validator_address: validator_address.into(),
153 timestamp: Some(timestamp.into()),
154 signature: signature.map(|s| s.to_bytes()).unwrap_or_default(),
155 },
156 CommitSig::BlockIdFlagCommit {
157 validator_address,
158 timestamp,
159 signature,
160 } => RawCommitSig {
161 block_id_flag: BlockIdFlag::Commit.to_i32().unwrap(),
162 validator_address: validator_address.into(),
163 timestamp: Some(timestamp.into()),
164 signature: signature.map(|s| s.to_bytes()).unwrap_or_default(),
165 },
166 }
167 }
168 }
169}