mithril_stm/aggregate_signature/
clerk.rs

1use blake2::digest::{Digest, FixedOutput};
2
3use crate::{
4    AggregationError, ClosedKeyReg, CoreVerifier, Index, Stake, StmAggrSig, StmAggrVerificationKey,
5    StmParameters, StmSig, StmSigRegParty, StmSigner, StmVerificationKey,
6};
7
8/// `StmClerk` can verify and aggregate `StmSig`s and verify `StmMultiSig`s.
9/// Clerks can only be generated with the registration closed.
10/// This avoids that a Merkle Tree is computed before all parties have registered.
11#[derive(Debug, Clone)]
12pub struct StmClerk<D: Clone + Digest> {
13    pub(crate) closed_reg: ClosedKeyReg<D>,
14    pub(crate) params: StmParameters,
15}
16
17impl<D: Digest + Clone + FixedOutput> StmClerk<D> {
18    /// Create a new `Clerk` from a closed registration instance.
19    pub fn from_registration(params: &StmParameters, closed_reg: &ClosedKeyReg<D>) -> Self {
20        Self {
21            params: *params,
22            closed_reg: closed_reg.clone(),
23        }
24    }
25
26    /// Create a Clerk from a signer.
27    pub fn from_signer(signer: &StmSigner<D>) -> Self {
28        let closed_reg = signer
29            .get_closed_reg()
30            .clone()
31            .expect("Core signer does not include closed registration. StmClerk, and so, the Stm certificate cannot be built without closed registration!")
32            ;
33
34        Self {
35            params: signer.get_params(),
36            closed_reg,
37        }
38    }
39
40    /// Aggregate a set of signatures for their corresponding indices.
41    ///
42    /// This function first deduplicates the repeated signatures, and if there are enough signatures, it collects the merkle tree indexes of unique signatures.
43    /// The list of merkle tree indexes is used to create a batch proof, to prove that all signatures are from eligible signers.
44    ///
45    /// It returns an instance of `StmAggrSig`.
46    pub fn aggregate(
47        &self,
48        sigs: &[StmSig],
49        msg: &[u8],
50    ) -> Result<StmAggrSig<D>, AggregationError> {
51        let sig_reg_list = sigs
52            .iter()
53            .map(|sig| StmSigRegParty {
54                sig: sig.clone(),
55                reg_party: self.closed_reg.reg_parties[sig.signer_index as usize],
56            })
57            .collect::<Vec<StmSigRegParty>>();
58
59        let avk = StmAggrVerificationKey::from(&self.closed_reg);
60        let msgp = avk.get_mt_commitment().concat_with_msg(msg);
61        let mut unique_sigs = CoreVerifier::dedup_sigs_for_indices(
62            &self.closed_reg.total_stake,
63            &self.params,
64            &msgp,
65            &sig_reg_list,
66        )?;
67
68        unique_sigs.sort_unstable();
69
70        let mt_index_list = unique_sigs
71            .iter()
72            .map(|sig_reg| sig_reg.sig.signer_index as usize)
73            .collect::<Vec<usize>>();
74
75        let batch_proof = self.closed_reg.merkle_tree.get_batched_path(mt_index_list);
76
77        Ok(StmAggrSig {
78            signatures: unique_sigs,
79            batch_proof,
80        })
81    }
82
83    /// Compute the `StmAggrVerificationKey` related to the used registration.
84    pub fn compute_avk(&self) -> StmAggrVerificationKey<D> {
85        StmAggrVerificationKey::from(&self.closed_reg)
86    }
87
88    /// Get the (VK, stake) of a party given its index.
89    pub fn get_reg_party(&self, party_index: &Index) -> Option<(StmVerificationKey, Stake)> {
90        self.closed_reg
91            .reg_parties
92            .get(*party_index as usize)
93            .map(|&r| r.into())
94    }
95}