mithril_stm/bls_multi_signature/
signature.rs1use std::{cmp::Ordering, iter::Sum};
2
3use blake2::{Blake2b, Blake2b512, Digest};
4use blst::{
5 blst_p1, blst_p2,
6 min_sig::{AggregateSignature, PublicKey as BlstVk, Signature as BlstSig},
7 p1_affines, p2_affines,
8};
9use digest::consts::U16;
10
11use crate::bls_multi_signature::{
12 helper::unsafe_helpers::{p1_affine_to_sig, p2_affine_to_vk, sig_to_p1, vk_from_p2_affine},
13 VerificationKey,
14};
15use crate::{
16 error::{blst_err_to_mithril, MultiSignatureError},
17 Index,
18};
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22pub struct Signature(pub BlstSig);
23
24impl Signature {
25 pub fn verify(&self, msg: &[u8], mvk: &VerificationKey) -> Result<(), MultiSignatureError> {
27 blst_err_to_mithril(
28 self.0.validate(true).map_or_else(
29 |e| e,
30 |_| {
31 self.0
32 .verify(false, msg, &[], &[], &mvk.to_blst_vk(), false)
33 },
34 ),
35 Some(*self),
36 None,
37 )
38 }
39
40 pub fn eval(&self, msg: &[u8], index: Index) -> [u8; 64] {
45 let hasher = Blake2b512::new()
46 .chain_update(b"map")
47 .chain_update(msg)
48 .chain_update(index.to_le_bytes())
49 .chain_update(self.to_bytes())
50 .finalize();
51
52 let mut output = [0u8; 64];
53 output.copy_from_slice(hasher.as_slice());
54
55 output
56 }
57
58 pub fn to_bytes(self) -> [u8; 48] {
60 self.0.to_bytes()
61 }
62
63 pub fn from_bytes(bytes: &[u8]) -> Result<Self, MultiSignatureError> {
68 let bytes = bytes
69 .get(..48)
70 .ok_or(MultiSignatureError::SerializationError)?;
71 match BlstSig::sig_validate(bytes, true) {
72 Ok(sig) => Ok(Self(sig)),
73 Err(e) => Err(blst_err_to_mithril(e, None, None)
74 .expect_err("If deserialization is not successful, blst returns and error different to SUCCESS."))
75 }
76 }
77
78 fn cmp_msp_sig(&self, other: &Self) -> Ordering {
81 let self_bytes = self.to_bytes();
82 let other_bytes = other.to_bytes();
83 let mut result = Ordering::Equal;
84
85 for (i, j) in self_bytes.iter().zip(other_bytes.iter()) {
86 result = i.cmp(j);
87 if result != Ordering::Equal {
88 return result;
89 }
90 }
91 result
92 }
93
94 pub fn aggregate(
99 vks: &[VerificationKey],
100 sigs: &[Signature],
101 ) -> Result<(VerificationKey, Signature), MultiSignatureError> {
102 if vks.len() != sigs.len() || vks.is_empty() {
103 return Err(MultiSignatureError::AggregateSignatureInvalid);
104 }
105
106 if vks.len() < 2 {
107 return Ok((vks[0], sigs[0]));
108 }
109
110 let mut hashed_sigs = Blake2b::<U16>::new();
111 for sig in sigs {
112 hashed_sigs.update(sig.to_bytes());
113 }
114
115 let mut scalars = Vec::with_capacity(vks.len() * 128);
117 let mut signatures = Vec::with_capacity(vks.len());
118 for (index, sig) in sigs.iter().enumerate() {
119 let mut hasher = hashed_sigs.clone();
120 hasher.update(index.to_be_bytes());
121 signatures.push(sig.0);
122 scalars.extend_from_slice(hasher.finalize().as_slice());
123 }
124
125 let transmuted_vks: Vec<blst_p2> = vks.iter().map(vk_from_p2_affine).collect();
126 let transmuted_sigs: Vec<blst_p1> = signatures.iter().map(sig_to_p1).collect();
127
128 let grouped_vks = p2_affines::from(transmuted_vks.as_slice());
129 let grouped_sigs = p1_affines::from(transmuted_sigs.as_slice());
130
131 let aggr_vk: BlstVk = p2_affine_to_vk(&grouped_vks.mult(&scalars, 128));
132 let aggr_sig: BlstSig = p1_affine_to_sig(&grouped_sigs.mult(&scalars, 128));
133
134 Ok((VerificationKey(aggr_vk), Signature(aggr_sig)))
135 }
136
137 pub fn verify_aggregate(
140 msg: &[u8],
141 vks: &[VerificationKey],
142 sigs: &[Signature],
143 ) -> Result<(), MultiSignatureError> {
144 let (aggr_vk, aggr_sig) = Self::aggregate(vks, sigs)?;
145
146 blst_err_to_mithril(
147 aggr_sig
148 .0
149 .verify(false, msg, &[], &[], &aggr_vk.to_blst_vk(), false),
150 Some(aggr_sig),
151 None,
152 )
153 }
154
155 #[cfg(feature = "batch-verify-aggregates")]
157 pub fn batch_verify_aggregates(
158 msgs: &[Vec<u8>],
159 vks: &[VerificationKey],
160 sigs: &[Signature],
161 ) -> Result<(), MultiSignatureError> {
162 let batched_sig: BlstSig = match AggregateSignature::aggregate(
163 &(sigs.iter().map(|sig| &sig.0).collect::<Vec<&BlstSig>>()),
164 false,
165 ) {
166 Ok(sig) => BlstSig::from_aggregate(&sig),
167 Err(e) => return blst_err_to_mithril(e, None, None),
168 };
169
170 let p2_vks: Vec<BlstVk> = vks.iter().map(|vk| vk.to_blst_vk()).collect();
171 let p2_vks_ref: Vec<&BlstVk> = p2_vks.iter().collect();
172 let slice_msgs = msgs
173 .iter()
174 .map(|msg| msg.as_slice())
175 .collect::<Vec<&[u8]>>();
176
177 blst_err_to_mithril(
178 batched_sig.aggregate_verify(false, &slice_msgs, &[], &p2_vks_ref, false),
179 None,
180 None,
181 )
182 .map_err(|_| MultiSignatureError::BatchInvalid)
183 }
184}
185
186impl<'a> Sum<&'a Self> for Signature {
187 fn sum<I>(iter: I) -> Self
188 where
189 I: Iterator<Item = &'a Self>,
190 {
191 let signatures: Vec<&BlstSig> = iter.map(|x| &x.0).collect();
192 assert!(!signatures.is_empty(), "One cannot add an empty vector");
193 let aggregate = AggregateSignature::aggregate(&signatures, false)
194 .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.")
195 .to_signature();
196
197 Self(aggregate)
198 }
199}
200
201impl PartialOrd for Signature {
202 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
203 Some(std::cmp::Ord::cmp(self, other))
204 }
205}
206
207impl Ord for Signature {
208 fn cmp(&self, other: &Self) -> Ordering {
209 self.cmp_msp_sig(other)
210 }
211}