mithril_stm/aggregate_signature/
signature.rs

1use blake2::digest::{Digest, FixedOutput};
2
3use serde::{Deserialize, Serialize};
4
5use crate::bls_multi_signature::{BlsSignature, BlsVerificationKey};
6use crate::key_registration::RegisteredParty;
7use crate::merkle_tree::MerkleBatchPath;
8use crate::{
9    AggregateVerificationKey, BasicVerifier, Parameters, SingleSignatureWithRegisteredParty,
10    StmAggregateSignatureError,
11};
12
13/// `AggregateSignature` uses the "concatenation" proving system (as described in Section 4.3 of the original paper.)
14/// This means that the aggregated signature contains a vector with all individual signatures.
15/// BatchPath is also a part of the aggregate signature which covers path for all signatures.
16#[derive(Debug, Clone, Serialize, Deserialize)]
17#[serde(bound(
18    serialize = "MerkleBatchPath<D>: Serialize",
19    deserialize = "MerkleBatchPath<D>: Deserialize<'de>"
20))]
21pub struct AggregateSignature<D: Clone + Digest + FixedOutput> {
22    pub(crate) signatures: Vec<SingleSignatureWithRegisteredParty>,
23    /// The list of unique merkle tree nodes that covers path for all signatures.
24    pub batch_proof: MerkleBatchPath<D>,
25}
26
27impl<D: Clone + Digest + FixedOutput + Send + Sync> AggregateSignature<D> {
28    /// Verify all checks from signatures, except for the signature verification itself.
29    ///
30    /// Indices and quorum are checked by `BasicVerifier::preliminary_verify` with `msgp`.
31    /// It collects leaves from signatures and checks the batch proof.
32    /// After batch proof is checked, it collects and returns the signatures and
33    /// verification keys to be used by aggregate verification.
34    fn preliminary_verify(
35        &self,
36        msg: &[u8],
37        avk: &AggregateVerificationKey<D>,
38        parameters: &Parameters,
39    ) -> Result<(Vec<BlsSignature>, Vec<BlsVerificationKey>), StmAggregateSignatureError<D>> {
40        let msgp = avk.get_merkle_tree_batch_commitment().concatenate_with_message(msg);
41        BasicVerifier::preliminary_verify(
42            &avk.get_total_stake(),
43            &self.signatures,
44            parameters,
45            &msgp,
46        )?;
47
48        let leaves = self
49            .signatures
50            .iter()
51            .map(|r| r.reg_party)
52            .collect::<Vec<RegisteredParty>>();
53
54        avk.get_merkle_tree_batch_commitment()
55            .verify_leaves_membership_from_batch_path(&leaves, &self.batch_proof)?;
56
57        Ok(BasicVerifier::collect_signatures_verification_keys(
58            &self.signatures,
59        ))
60    }
61
62    /// Verify aggregate signature, by checking that
63    /// * each signature contains only valid indices,
64    /// * the lottery is indeed won by each one of them,
65    /// * the merkle tree path is valid,
66    /// * the aggregate signature validates with respect to the aggregate verification key
67    ///   (aggregation is computed using functions `MSP.BKey` and `MSP.BSig` as described in Section 2.4 of the paper).
68    pub fn verify(
69        &self,
70        msg: &[u8],
71        avk: &AggregateVerificationKey<D>,
72        parameters: &Parameters,
73    ) -> Result<(), StmAggregateSignatureError<D>> {
74        let msgp = avk.get_merkle_tree_batch_commitment().concatenate_with_message(msg);
75        let (sigs, vks) = self.preliminary_verify(msg, avk, parameters)?;
76
77        BlsSignature::verify_aggregate(msgp.as_slice(), &vks, &sigs)?;
78        Ok(())
79    }
80
81    /// Batch verify a set of signatures, with different messages and avks.
82    pub fn batch_verify(
83        stm_signatures: &[Self],
84        msgs: &[Vec<u8>],
85        avks: &[AggregateVerificationKey<D>],
86        parameters: &[Parameters],
87    ) -> Result<(), StmAggregateSignatureError<D>> {
88        let batch_size = stm_signatures.len();
89        assert_eq!(
90            batch_size,
91            msgs.len(),
92            "Number of messages should correspond to size of the batch"
93        );
94        assert_eq!(
95            batch_size,
96            avks.len(),
97            "Number of avks should correspond to size of the batch"
98        );
99        assert_eq!(
100            batch_size,
101            parameters.len(),
102            "Number of parameters should correspond to size of the batch"
103        );
104
105        let mut aggr_sigs = Vec::with_capacity(batch_size);
106        let mut aggr_vks = Vec::with_capacity(batch_size);
107        for (idx, sig_group) in stm_signatures.iter().enumerate() {
108            sig_group.preliminary_verify(&msgs[idx], &avks[idx], &parameters[idx])?;
109            let grouped_sigs: Vec<BlsSignature> =
110                sig_group.signatures.iter().map(|sig_reg| sig_reg.sig.sigma).collect();
111            let grouped_vks: Vec<BlsVerificationKey> = sig_group
112                .signatures
113                .iter()
114                .map(|sig_reg| sig_reg.reg_party.0)
115                .collect();
116
117            let (aggr_vk, aggr_sig) = BlsSignature::aggregate(&grouped_vks, &grouped_sigs).unwrap();
118            aggr_sigs.push(aggr_sig);
119            aggr_vks.push(aggr_vk);
120        }
121
122        let concat_msgs: Vec<Vec<u8>> = msgs
123            .iter()
124            .zip(avks.iter())
125            .map(|(msg, avk)| avk.get_merkle_tree_batch_commitment().concatenate_with_message(msg))
126            .collect();
127
128        BlsSignature::batch_verify_aggregates(&concat_msgs, &aggr_vks, &aggr_sigs)?;
129        Ok(())
130    }
131
132    /// Convert multi signature to bytes
133    /// # Layout
134    /// * Aggregate signature type (u8)
135    /// * Number of the pairs of Signatures and Registered Parties (SigRegParty) (as u64)
136    /// * Pairs of Signatures and Registered Parties (prefixed with their size as u64)
137    /// * Batch proof
138    pub fn to_bytes(&self) -> Vec<u8> {
139        let mut out = Vec::new();
140        // This proof type is not strictly necessary, but it will help to identify
141        // the type of the proof used to aggregate when implementing multiple aggregation proof systems.
142        // We use '0' for concatenation proof.
143        let proof_type: u8 = 0;
144        out.extend_from_slice(&proof_type.to_be_bytes());
145        out.extend_from_slice(&u64::try_from(self.signatures.len()).unwrap().to_be_bytes());
146        for sig_reg in &self.signatures {
147            out.extend_from_slice(&u64::try_from(sig_reg.to_bytes().len()).unwrap().to_be_bytes());
148            out.extend_from_slice(&sig_reg.to_bytes());
149        }
150        let proof = &self.batch_proof;
151        out.extend_from_slice(&proof.to_bytes());
152
153        out
154    }
155
156    ///Extract a `AggregateSignature` from a byte slice.
157    pub fn from_bytes(
158        bytes: &[u8],
159    ) -> Result<AggregateSignature<D>, StmAggregateSignatureError<D>> {
160        let mut u8_bytes = [0u8; 1];
161        let mut bytes_index = 0;
162
163        u8_bytes
164            .copy_from_slice(bytes.get(..1).ok_or(StmAggregateSignatureError::SerializationError)?);
165        bytes_index += 1;
166        let proof_type = u8::from_be_bytes(u8_bytes);
167        if proof_type != 0 {
168            return Err(StmAggregateSignatureError::SerializationError);
169        }
170
171        let mut u64_bytes = [0u8; 8];
172        u64_bytes.copy_from_slice(
173            bytes
174                .get(bytes_index..bytes_index + 8)
175                .ok_or(StmAggregateSignatureError::SerializationError)?,
176        );
177        let total_sigs = usize::try_from(u64::from_be_bytes(u64_bytes))
178            .map_err(|_| StmAggregateSignatureError::SerializationError)?;
179        bytes_index += 8;
180
181        let mut sig_reg_list = Vec::with_capacity(total_sigs);
182        for _ in 0..total_sigs {
183            u64_bytes.copy_from_slice(
184                bytes
185                    .get(bytes_index..bytes_index + 8)
186                    .ok_or(StmAggregateSignatureError::SerializationError)?,
187            );
188            let sig_reg_size = usize::try_from(u64::from_be_bytes(u64_bytes))
189                .map_err(|_| StmAggregateSignatureError::SerializationError)?;
190            let sig_reg = SingleSignatureWithRegisteredParty::from_bytes::<D>(
191                bytes
192                    .get(bytes_index + 8..bytes_index + 8 + sig_reg_size)
193                    .ok_or(StmAggregateSignatureError::SerializationError)?,
194            )?;
195            bytes_index += 8 + sig_reg_size;
196            sig_reg_list.push(sig_reg);
197        }
198
199        let batch_proof = MerkleBatchPath::from_bytes(
200            bytes
201                .get(bytes_index..)
202                .ok_or(StmAggregateSignatureError::SerializationError)?,
203        )?;
204
205        Ok(AggregateSignature {
206            signatures: sig_reg_list,
207            batch_proof,
208        })
209    }
210}