mithril_stm/single_signature/
signature.rs1use std::{
2 cmp::Ordering,
3 hash::{Hash, Hasher},
4};
5
6use blake2::digest::{Digest, FixedOutput};
7use serde::{Deserialize, Serialize};
8
9use crate::bls_multi_signature::Signature;
10use crate::eligibility_check::ev_lt_phi;
11use crate::{
12 Index, Stake, StmAggrVerificationKey, StmParameters, StmSignatureError, StmVerificationKey,
13};
14
15#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct StmSig {
18 pub sigma: Signature,
20 pub indexes: Vec<Index>,
22 pub signer_index: Index,
24}
25
26impl StmSig {
27 pub fn verify<D: Clone + Digest + FixedOutput>(
30 &self,
31 params: &StmParameters,
32 pk: &StmVerificationKey,
33 stake: &Stake,
34 avk: &StmAggrVerificationKey<D>,
35 msg: &[u8],
36 ) -> Result<(), StmSignatureError> {
37 let msgp = avk.get_mt_commitment().concat_with_msg(msg);
38 self.verify_core(params, pk, stake, &msgp, &avk.get_total_stake())?;
39 Ok(())
40 }
41
42 pub(crate) fn check_indices(
44 &self,
45 params: &StmParameters,
46 stake: &Stake,
47 msg: &[u8],
48 total_stake: &Stake,
49 ) -> Result<(), StmSignatureError> {
50 for &index in &self.indexes {
51 if index > params.m {
52 return Err(StmSignatureError::IndexBoundFailed(index, params.m));
53 }
54
55 let ev = self.sigma.eval(msg, index);
56
57 if !ev_lt_phi(params.phi_f, ev, *stake, *total_stake) {
58 return Err(StmSignatureError::LotteryLost);
59 }
60 }
61
62 Ok(())
63 }
64
65 pub fn to_bytes(&self) -> Vec<u8> {
75 let mut output = Vec::new();
76 output.extend_from_slice(&(self.indexes.len() as u64).to_be_bytes());
77
78 for index in &self.indexes {
79 output.extend_from_slice(&index.to_be_bytes());
80 }
81
82 output.extend_from_slice(&self.sigma.to_bytes());
83
84 output.extend_from_slice(&self.signer_index.to_be_bytes());
85 output
86 }
87
88 pub fn from_bytes<D: Clone + Digest + FixedOutput>(
90 bytes: &[u8],
91 ) -> Result<StmSig, StmSignatureError> {
92 let mut u64_bytes = [0u8; 8];
93
94 u64_bytes.copy_from_slice(
95 bytes
96 .get(0..8)
97 .ok_or(StmSignatureError::SerializationError)?,
98 );
99 let nr_indexes = u64::from_be_bytes(u64_bytes) as usize;
100
101 let mut indexes = Vec::new();
102 for i in 0..nr_indexes {
103 u64_bytes.copy_from_slice(
104 bytes
105 .get(8 + i * 8..16 + i * 8)
106 .ok_or(StmSignatureError::SerializationError)?,
107 );
108 indexes.push(u64::from_be_bytes(u64_bytes));
109 }
110
111 let offset = 8 + nr_indexes * 8;
112 let sigma = Signature::from_bytes(
113 bytes
114 .get(offset..offset + 48)
115 .ok_or(StmSignatureError::SerializationError)?,
116 )?;
117
118 u64_bytes.copy_from_slice(
119 bytes
120 .get(offset + 48..offset + 56)
121 .ok_or(StmSignatureError::SerializationError)?,
122 );
123 let signer_index = u64::from_be_bytes(u64_bytes);
124
125 Ok(StmSig {
126 sigma,
127 indexes,
128 signer_index,
129 })
130 }
131
132 pub fn cmp_stm_sig(&self, other: &Self) -> Ordering {
134 self.signer_index.cmp(&other.signer_index)
135 }
136
137 pub fn verify_core(
140 &self,
141 params: &StmParameters,
142 pk: &StmVerificationKey,
143 stake: &Stake,
144 msg: &[u8],
145 total_stake: &Stake,
146 ) -> Result<(), StmSignatureError> {
147 self.sigma.verify(msg, pk)?;
148 self.check_indices(params, stake, msg, total_stake)?;
149
150 Ok(())
151 }
152}
153
154impl Hash for StmSig {
155 fn hash<H: Hasher>(&self, state: &mut H) {
156 Hash::hash_slice(&self.sigma.to_bytes(), state)
157 }
158}
159
160impl PartialEq for StmSig {
161 fn eq(&self, other: &Self) -> bool {
162 self.sigma == other.sigma
163 }
164}
165
166impl Eq for StmSig {}
167
168impl PartialOrd for StmSig {
169 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
170 Some(std::cmp::Ord::cmp(self, other))
171 }
172}
173
174impl Ord for StmSig {
175 fn cmp(&self, other: &Self) -> Ordering {
176 self.cmp_stm_sig(other)
177 }
178}