mithril_stm/protocol/participant/
signer.rs

1use crate::{
2    ClosedKeyRegistration, MembershipDigest, Parameters, SingleSignature, Stake, is_lottery_won,
3    proof_system::SingleSignatureForConcatenation,
4    signature_scheme::{BlsSignature, BlsSigningKey, BlsVerificationKey},
5};
6
7/// Wrapper of the MultiSignature Verification key
8pub type VerificationKey = BlsVerificationKey;
9
10/// Participant in the protocol can sign messages.
11/// * If the signer has `closed_reg`, then it can generate Stm certificate.
12///     * This kind of signer can only be generated out of an `Initializer` and a `ClosedKeyRegistration`.
13///     * This ensures that a `MerkleTree` root is not computed before all participants have registered.
14/// * If the signer does not have `closed_reg`, then it is a core signer.
15///     * This kind of signer cannot participate certificate generation.
16///     * Signature generated can be verified by a full node verifier (core verifier).
17#[derive(Debug, Clone)]
18pub struct Signer<D: MembershipDigest> {
19    signer_index: u64,
20    stake: Stake,
21    params: Parameters,
22    sk: BlsSigningKey,
23    vk: VerificationKey,
24    closed_reg: Option<ClosedKeyRegistration<D>>,
25}
26
27impl<D: MembershipDigest> Signer<D> {
28    /// Create a Signer for given input
29    pub(crate) fn set_signer(
30        signer_index: u64,
31        stake: Stake,
32        params: Parameters,
33        sk: BlsSigningKey,
34        vk: VerificationKey,
35        closed_reg: ClosedKeyRegistration<D>,
36    ) -> Signer<D> {
37        Self {
38            signer_index,
39            stake,
40            params,
41            sk,
42            vk,
43            closed_reg: Some(closed_reg),
44        }
45    }
46
47    /// This function produces a signature following the description of Section 2.4.
48    /// Once the signature is produced, this function checks whether any index in `[0,..,self.params.m]`
49    /// wins the lottery by evaluating the dense mapping.
50    /// It records all the winning indexes in `Self.indexes`.
51    /// If it wins at least one lottery, it stores the signer's merkle tree index. The proof of membership
52    /// will be handled by the aggregator.
53    pub fn sign(&self, msg: &[u8]) -> Option<SingleSignature> {
54        let closed_reg = self
55            .closed_reg
56            .as_ref()
57            .expect("Closed registration not found! Cannot produce SingleSignatures.");
58        let msgp = closed_reg
59            .merkle_tree
60            .to_merkle_tree_batch_commitment()
61            .concatenate_with_message(msg);
62        let sigma = self.sk.sign(&msgp);
63
64        let indexes = self.check_lottery(&msgp, &sigma, closed_reg.total_stake);
65
66        if !indexes.is_empty() {
67            Some(SingleSignature {
68                concatenation_signature: SingleSignatureForConcatenation::new(sigma, indexes),
69                signer_index: self.signer_index,
70            })
71        } else {
72            None
73        }
74    }
75
76    /// Extract the verification key.
77    pub fn get_verification_key(&self) -> VerificationKey {
78        self.vk
79    }
80
81    /// Extract stake from the signer.
82    pub fn get_stake(&self) -> Stake {
83        self.stake
84    }
85
86    /// Collects and returns the winning indices.
87    pub fn check_lottery(&self, msg: &[u8], sigma: &BlsSignature, total_stake: Stake) -> Vec<u64> {
88        let mut indexes = Vec::new();
89        for index in 0..self.params.m {
90            if is_lottery_won(
91                self.params.phi_f,
92                sigma.evaluate_dense_mapping(msg, index),
93                self.stake,
94                total_stake,
95            ) {
96                indexes.push(index);
97            }
98        }
99        indexes
100    }
101
102    /// Get Parameters
103    pub(crate) fn get_parameters(&self) -> Parameters {
104        self.params
105    }
106
107    /// Get closed key registration
108    pub(crate) fn get_closed_key_registration(&self) -> Option<ClosedKeyRegistration<D>> {
109        self.closed_reg.clone()
110    }
111}