mithril_stm/signature_scheme/bls_multi_signature/
signature.rs1use std::{cmp::Ordering, iter::Sum};
2
3use anyhow::{Context, anyhow};
4use blake2::{Blake2b, Blake2b512, Digest};
5use blst::{
6 blst_p1, blst_p2,
7 min_sig::{AggregateSignature, PublicKey as BlstVk, Signature as BlstSig},
8 p1_affines, p2_affines,
9};
10use digest::consts::U16;
11
12use crate::{Index, StmResult};
13
14use super::{
15 BlsSignatureError, BlsVerificationKey, blst_error_to_stm_error,
16 helper::unsafe_helpers::{p1_affine_to_sig, p2_affine_to_vk, sig_to_p1, vk_from_p2_affine},
17};
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq)]
21pub struct BlsSignature(pub BlstSig);
22
23impl BlsSignature {
24 pub fn verify(&self, msg: &[u8], mvk: &BlsVerificationKey) -> StmResult<()> {
26 blst_error_to_stm_error(
27 self.0.validate(true).map_or_else(
28 |e| e,
29 |_| {
30 self.0
31 .verify(false, msg, &[], &[], &mvk.to_blst_verification_key(), false)
32 },
33 ),
34 Some(*self),
35 None,
36 )
37 }
38
39 pub(crate) fn evaluate_dense_mapping(&self, msg: &[u8], index: Index) -> [u8; 64] {
44 let hasher = Blake2b512::new()
45 .chain_update(b"map")
46 .chain_update(msg)
47 .chain_update(index.to_le_bytes())
48 .chain_update(self.to_bytes())
49 .finalize();
50
51 let mut output = [0u8; 64];
52 output.copy_from_slice(&hasher);
53
54 output
55 }
56
57 pub fn to_bytes(self) -> [u8; 48] {
59 self.0.to_bytes()
60 }
61
62 pub fn from_bytes(bytes: &[u8]) -> StmResult<Self> {
67 let bytes = bytes.get(..48).ok_or(BlsSignatureError::SerializationError)?;
68 match BlstSig::sig_validate(bytes, true) {
69 Ok(sig) => Ok(Self(sig)),
70 Err(e) => Err(blst_error_to_stm_error(e, None, None)
71 .expect_err("If deserialization is not successful, blst returns and error different to SUCCESS."))
72 }
73 }
74
75 fn compare_signatures(&self, other: &Self) -> Ordering {
78 let self_bytes = self.to_bytes();
79 let other_bytes = other.to_bytes();
80 let mut result = Ordering::Equal;
81
82 for (i, j) in self_bytes.iter().zip(other_bytes.iter()) {
83 result = i.cmp(j);
84 if result != Ordering::Equal {
85 return result;
86 }
87 }
88 result
89 }
90
91 pub fn aggregate(
96 vks: &[BlsVerificationKey],
97 sigs: &[BlsSignature],
98 ) -> StmResult<(BlsVerificationKey, BlsSignature)> {
99 if vks.len() != sigs.len() || vks.is_empty() {
100 return Err(anyhow!(BlsSignatureError::AggregateSignatureInvalid));
101 }
102
103 if vks.len() < 2 {
104 return Ok((vks[0], sigs[0]));
105 }
106
107 let mut hashed_sigs = Blake2b::<U16>::new();
108 for sig in sigs {
109 hashed_sigs.update(sig.to_bytes());
110 }
111
112 let mut scalars = Vec::with_capacity(vks.len() * 128);
114 let mut signatures = Vec::with_capacity(vks.len());
115 for (index, sig) in sigs.iter().enumerate() {
116 let mut hasher = hashed_sigs.clone();
117 hasher.update(index.to_be_bytes());
118 signatures.push(sig.0);
119 scalars.extend_from_slice(&hasher.finalize());
120 }
121
122 let transmuted_vks: Vec<blst_p2> = vks.iter().map(vk_from_p2_affine).collect();
123 let transmuted_sigs: Vec<blst_p1> = signatures.iter().map(sig_to_p1).collect();
124
125 let grouped_vks = p2_affines::from(transmuted_vks.as_slice());
126 let grouped_sigs = p1_affines::from(transmuted_sigs.as_slice());
127
128 let aggr_vk: BlstVk = p2_affine_to_vk(&grouped_vks.mult(&scalars, 128));
129 let aggr_sig: BlstSig = p1_affine_to_sig(&grouped_sigs.mult(&scalars, 128));
130
131 Ok((BlsVerificationKey(aggr_vk), BlsSignature(aggr_sig)))
132 }
133
134 pub fn verify_aggregate(
137 msg: &[u8],
138 vks: &[BlsVerificationKey],
139 sigs: &[BlsSignature],
140 ) -> StmResult<()> {
141 let (aggr_vk, aggr_sig) = Self::aggregate(vks, sigs).with_context(|| "Multi signature verification failed in aggregation of verification keys and signatures.")?;
142
143 blst_error_to_stm_error(
144 aggr_sig.0.verify(
145 false,
146 msg,
147 &[],
148 &[],
149 &aggr_vk.to_blst_verification_key(),
150 false,
151 ),
152 Some(aggr_sig),
153 None,
154 )
155 }
156
157 pub fn batch_verify_aggregates(
159 msgs: &[Vec<u8>],
160 vks: &[BlsVerificationKey],
161 sigs: &[BlsSignature],
162 ) -> StmResult<()> {
163 let batched_sig: BlstSig = match AggregateSignature::aggregate(
164 &(sigs.iter().map(|sig| &sig.0).collect::<Vec<&BlstSig>>()),
165 false,
166 ) {
167 Ok(sig) => BlstSig::from_aggregate(&sig),
168 Err(e) => return blst_error_to_stm_error(e, None, None),
169 };
170
171 let p2_vks: Vec<BlstVk> = vks.iter().map(|vk| vk.to_blst_verification_key()).collect();
172 let p2_vks_ref: Vec<&BlstVk> = p2_vks.iter().collect();
173 let slice_msgs = msgs.iter().map(|msg| msg.as_slice()).collect::<Vec<&[u8]>>();
174
175 blst_error_to_stm_error(
176 batched_sig.aggregate_verify(false, &slice_msgs, &[], &p2_vks_ref, false),
177 None,
178 None,
179 )
180 .map_err(|_| anyhow!(BlsSignatureError::BatchInvalid))
181 }
182}
183
184impl<'a> Sum<&'a Self> for BlsSignature {
185 fn sum<I>(iter: I) -> Self
186 where
187 I: Iterator<Item = &'a Self>,
188 {
189 let signatures: Vec<&BlstSig> = iter.map(|x| &x.0).collect();
190 assert!(!signatures.is_empty(), "One cannot add an empty vector");
191 let aggregate = AggregateSignature::aggregate(&signatures, false)
192 .expect("An MspSig is always a valid signature. This function only fails if signatures is empty or if the signatures are invalid, none of which can happen.")
193 .to_signature();
194
195 Self(aggregate)
196 }
197}
198
199impl PartialOrd for BlsSignature {
200 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
201 Some(std::cmp::Ord::cmp(self, other))
202 }
203}
204
205impl Ord for BlsSignature {
206 fn cmp(&self, other: &Self) -> Ordering {
207 self.compare_signatures(other)
208 }
209}
210
211#[cfg(test)]
212mod tests {
213 mod golden {
214
215 use rand_chacha::ChaCha20Rng;
216 use rand_core::SeedableRng;
217
218 use crate::signature_scheme::{BlsSignature, BlsSigningKey};
219
220 const GOLDEN_JSON: &str = r#"[132,95,124,197,185,105,193,171,114,182,52,171,205,119,202,188,2,213,61,125,219,242,10,131,53,219,53,197,157,42,152,194,234,161,244,204,2,134,47,179,176,49,200,232,120,241,180,246]"#;
221
222 fn golden_value() -> BlsSignature {
223 let mut rng = ChaCha20Rng::from_seed([0u8; 32]);
224 let sk = BlsSigningKey::generate(&mut rng);
225 let msg = [0u8; 32];
226 sk.sign(&msg)
227 }
228
229 #[test]
230 fn golden_conversions() {
231 let value = serde_json::from_str(GOLDEN_JSON)
232 .expect("This JSON deserialization should not fail");
233 assert_eq!(golden_value(), value);
234
235 let serialized =
236 serde_json::to_string(&value).expect("This JSON serialization should not fail");
237 let golden_serialized = serde_json::to_string(&golden_value())
238 .expect("This JSON serialization should not fail");
239 assert_eq!(golden_serialized, serialized);
240 }
241 }
242}