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::BlsSignature;
10use crate::eligibility_check::is_lottery_won;
11use crate::{
12 AggregateVerificationKey, Index, Parameters, Stake, StmSignatureError, VerificationKey,
13};
14
15#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct SingleSignature {
18 pub sigma: BlsSignature,
20 pub indexes: Vec<Index>,
22 pub signer_index: Index,
24}
25
26impl SingleSignature {
27 pub fn verify<D: Clone + Digest + FixedOutput>(
30 &self,
31 params: &Parameters,
32 pk: &VerificationKey,
33 stake: &Stake,
34 avk: &AggregateVerificationKey<D>,
35 msg: &[u8],
36 ) -> Result<(), StmSignatureError> {
37 let msgp = avk.get_merkle_tree_batch_commitment().concatenate_with_message(msg);
38 self.basic_verify(params, pk, stake, &msgp, &avk.get_total_stake())?;
39 Ok(())
40 }
41
42 pub(crate) fn check_indices(
44 &self,
45 params: &Parameters,
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.evaluate_dense_mapping(msg, index);
56
57 if !is_lottery_won(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<SingleSignature, StmSignatureError> {
92 let mut u64_bytes = [0u8; 8];
93
94 u64_bytes.copy_from_slice(bytes.get(0..8).ok_or(StmSignatureError::SerializationError)?);
95 let nr_indexes = u64::from_be_bytes(u64_bytes) as usize;
96
97 let mut indexes = Vec::new();
98 for i in 0..nr_indexes {
99 u64_bytes.copy_from_slice(
100 bytes
101 .get(8 + i * 8..16 + i * 8)
102 .ok_or(StmSignatureError::SerializationError)?,
103 );
104 indexes.push(u64::from_be_bytes(u64_bytes));
105 }
106
107 let offset = 8 + nr_indexes * 8;
108 let sigma = BlsSignature::from_bytes(
109 bytes
110 .get(offset..offset + 48)
111 .ok_or(StmSignatureError::SerializationError)?,
112 )?;
113
114 u64_bytes.copy_from_slice(
115 bytes
116 .get(offset + 48..offset + 56)
117 .ok_or(StmSignatureError::SerializationError)?,
118 );
119 let signer_index = u64::from_be_bytes(u64_bytes);
120
121 Ok(SingleSignature {
122 sigma,
123 indexes,
124 signer_index,
125 })
126 }
127
128 fn compare_signer_index(&self, other: &Self) -> Ordering {
130 self.signer_index.cmp(&other.signer_index)
131 }
132
133 #[deprecated(since = "0.4.9", note = "This function will be removed")]
135 pub fn cmp_stm_sig(&self, other: &Self) -> Ordering {
136 Self::compare_signer_index(self, other)
137 }
138
139 pub(crate) fn basic_verify(
142 &self,
143 params: &Parameters,
144 pk: &VerificationKey,
145 stake: &Stake,
146 msg: &[u8],
147 total_stake: &Stake,
148 ) -> Result<(), StmSignatureError> {
149 self.sigma.verify(msg, pk)?;
150 self.check_indices(params, stake, msg, total_stake)?;
151
152 Ok(())
153 }
154
155 #[deprecated(since = "0.4.9", note = "Use `basic_verify` instead")]
157 pub fn core_verify(
158 &self,
159 params: &Parameters,
160 pk: &VerificationKey,
161 stake: &Stake,
162 msg: &[u8],
163 total_stake: &Stake,
164 ) -> Result<(), StmSignatureError> {
165 Self::basic_verify(self, params, pk, stake, msg, total_stake)
166 }
167}
168
169impl Hash for SingleSignature {
170 fn hash<H: Hasher>(&self, state: &mut H) {
171 Hash::hash_slice(&self.sigma.to_bytes(), state)
172 }
173}
174
175impl PartialEq for SingleSignature {
176 fn eq(&self, other: &Self) -> bool {
177 self.sigma == other.sigma
178 }
179}
180
181impl Eq for SingleSignature {}
182
183impl PartialOrd for SingleSignature {
184 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
185 Some(std::cmp::Ord::cmp(self, other))
186 }
187}
188
189impl Ord for SingleSignature {
190 fn cmp(&self, other: &Self) -> Ordering {
191 self.signer_index.cmp(&other.signer_index)
192 }
193}