mithril_stm/aggregate_signature/
clerk.rs1use blake2::digest::{Digest, FixedOutput};
2
3use crate::{
4 AggregationError, ClosedKeyReg, CoreVerifier, Index, Stake, StmAggrSig, StmAggrVerificationKey,
5 StmParameters, StmSig, StmSigRegParty, StmSigner, StmVerificationKey,
6};
7
8#[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 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 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 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 pub fn compute_avk(&self) -> StmAggrVerificationKey<D> {
85 StmAggrVerificationKey::from(&self.closed_reg)
86 }
87
88 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}