mithril_stm/participant/
signer.rs

1use blake2::digest::{Digest, FixedOutput};
2
3use crate::bls_multi_signature::{BlsSignature, BlsSigningKey, BlsVerificationKey};
4use crate::eligibility_check::is_lottery_won;
5use crate::key_registration::ClosedKeyRegistration;
6use crate::{Parameters, SingleSignature, Stake};
7
8/// Wrapper of the MultiSignature Verification key
9pub type VerificationKey = BlsVerificationKey;
10
11/// Participant in the protocol can sign messages.
12/// * If the signer has `closed_reg`, then it can generate Stm certificate.
13///     * This kind of signer can only be generated out of an `Initializer` and a `ClosedKeyRegistration`.
14///     * This ensures that a `MerkleTree` root is not computed before all participants have registered.
15/// * If the signer does not have `closed_reg`, then it is a core signer.
16///     * This kind of signer cannot participate certificate generation.
17///     * Signature generated can be verified by a full node verifier (core verifier).
18#[derive(Debug, Clone)]
19pub struct Signer<D: Digest> {
20    signer_index: u64,
21    stake: Stake,
22    params: Parameters,
23    sk: BlsSigningKey,
24    vk: VerificationKey,
25    closed_reg: Option<ClosedKeyRegistration<D>>,
26}
27
28impl<D: Clone + Digest + FixedOutput> Signer<D> {
29    /// Create a Signer for given input
30    pub(crate) fn set_signer(
31        signer_index: u64,
32        stake: Stake,
33        params: Parameters,
34        sk: BlsSigningKey,
35        vk: VerificationKey,
36        closed_reg: ClosedKeyRegistration<D>,
37    ) -> Signer<D> {
38        Self {
39            signer_index,
40            stake,
41            params,
42            sk,
43            vk,
44            closed_reg: Some(closed_reg),
45        }
46    }
47
48    /// Create a Signer for given input
49    #[deprecated(since = "0.4.9", note = "Use `set_signer` instead")]
50    pub fn set_stm_signer(
51        signer_index: u64,
52        stake: Stake,
53        params: Parameters,
54        sk: BlsSigningKey,
55        vk: VerificationKey,
56        closed_reg: ClosedKeyRegistration<D>,
57    ) -> Signer<D> {
58        Self::set_signer(signer_index, stake, params, sk, vk, closed_reg)
59    }
60
61    /// Create a basic signer (no registration data) for given input
62    pub(crate) fn set_basic_signer(
63        signer_index: u64,
64        stake: Stake,
65        params: Parameters,
66        sk: BlsSigningKey,
67        vk: VerificationKey,
68    ) -> Signer<D> {
69        Self {
70            signer_index,
71            stake,
72            params,
73            sk,
74            vk,
75            closed_reg: None,
76        }
77    }
78
79    /// Create a core signer (no registration data) for given input
80    #[deprecated(since = "0.4.9", note = "Use `set_basic_signer` instead")]
81    pub fn set_core_signer(
82        signer_index: u64,
83        stake: Stake,
84        params: Parameters,
85        sk: BlsSigningKey,
86        vk: VerificationKey,
87    ) -> Signer<D> {
88        Self::set_basic_signer(signer_index, stake, params, sk, vk)
89    }
90
91    /// This function produces a signature following the description of Section 2.4.
92    /// Once the signature is produced, this function checks whether any index in `[0,..,self.params.m]`
93    /// wins the lottery by evaluating the dense mapping.
94    /// It records all the winning indexes in `Self.indexes`.
95    /// If it wins at least one lottery, it stores the signer's merkle tree index. The proof of membership
96    /// will be handled by the aggregator.
97    pub fn sign(&self, msg: &[u8]) -> Option<SingleSignature> {
98        let closed_reg = self.closed_reg.as_ref().expect("Closed registration not found! Cannot produce SingleSignatures. Use core_sign to produce core signatures (not valid for an StmCertificate).");
99        let msgp = closed_reg
100            .merkle_tree
101            .to_merkle_tree_batch_commitment()
102            .concatenate_with_message(msg);
103        let signature = self.basic_sign(&msgp, closed_reg.total_stake)?;
104
105        Some(SingleSignature {
106            sigma: signature.sigma,
107            signer_index: self.signer_index,
108            indexes: signature.indexes,
109        })
110    }
111
112    /// Extract the verification key.
113    pub fn get_verification_key(&self) -> VerificationKey {
114        self.vk
115    }
116
117    /// Extract the verification key.
118    #[deprecated(since = "0.4.9", note = "Use `get_verification_key` instead")]
119    pub fn verification_key(&self) -> VerificationKey {
120        Self::get_verification_key(self)
121    }
122
123    /// Extract stake from the signer.
124    pub fn get_stake(&self) -> Stake {
125        self.stake
126    }
127
128    /// A basic signature generated without closed key registration.
129    /// The basic signature can be verified by basic verifier.
130    /// Once the signature is produced, this function checks whether any index in `[0,..,self.params.m]`
131    /// wins the lottery by evaluating the dense mapping.
132    /// It records all the winning indexes in `Self.indexes`.
133    pub fn basic_sign(&self, msg: &[u8], total_stake: Stake) -> Option<SingleSignature> {
134        let sigma = self.sk.sign(msg);
135
136        let indexes = self.check_lottery(msg, &sigma, total_stake);
137        if !indexes.is_empty() {
138            Some(SingleSignature {
139                sigma,
140                indexes,
141                signer_index: self.signer_index,
142            })
143        } else {
144            None
145        }
146    }
147
148    /// A basic signature generated without closed key registration.
149    /// The basic signature can be verified by basic verifier.
150    /// Once the signature is produced, this function checks whether any index in `[0,..,self.params.m]`
151    /// wins the lottery by evaluating the dense mapping.
152    /// It records all the winning indexes in `Self.indexes`.
153    #[deprecated(since = "0.4.9", note = "Use `basic_sign` instead")]
154    pub fn core_sign(&self, msg: &[u8], total_stake: Stake) -> Option<SingleSignature> {
155        Self::basic_sign(self, msg, total_stake)
156    }
157
158    /// Collects and returns the winning indices.
159    pub fn check_lottery(&self, msg: &[u8], sigma: &BlsSignature, total_stake: Stake) -> Vec<u64> {
160        let mut indexes = Vec::new();
161        for index in 0..self.params.m {
162            if is_lottery_won(
163                self.params.phi_f,
164                sigma.evaluate_dense_mapping(msg, index),
165                self.stake,
166                total_stake,
167            ) {
168                indexes.push(index);
169            }
170        }
171        indexes
172    }
173
174    /// Get Parameters
175    pub(crate) fn get_parameters(&self) -> Parameters {
176        self.params
177    }
178
179    /// Get Parameters
180    #[deprecated(since = "0.4.9", note = "Use `get_parameters` instead")]
181    pub fn get_params(&self) -> Parameters {
182        Self::get_parameters(self)
183    }
184
185    /// Get closed key registration
186    pub(crate) fn get_closed_key_registration(&self) -> Option<ClosedKeyRegistration<D>> {
187        self.closed_reg.clone()
188    }
189
190    /// Get closed key registration
191    #[deprecated(since = "0.4.9", note = "Use `get_closed_key_registration` instead")]
192    pub fn get_closed_reg(&self) -> Option<ClosedKeyRegistration<D>> {
193        Self::get_closed_key_registration(self)
194    }
195}