mithril_stm/protocol/participant/
initializer.rs

1use anyhow::anyhow;
2use blake2::digest::Digest;
3use digest::FixedOutput;
4use rand_core::{CryptoRng, RngCore};
5use serde::{Deserialize, Serialize};
6
7use super::Signer;
8use crate::{
9    ClosedKeyRegistration, Parameters, RegisterError, RegisteredParty, Stake, StmResult,
10    signature_scheme::{BlsSigningKey, BlsVerificationKeyProofOfPossession},
11};
12
13/// Wrapper of the MultiSignature Verification key with proof of possession
14pub type VerificationKeyProofOfPossession = BlsVerificationKeyProofOfPossession;
15
16/// Initializer for `Signer`.
17/// This is the data that is used during the key registration procedure.
18/// Once the latter is finished, this instance is consumed into an `Signer`.
19#[derive(Debug, Clone, Serialize, Deserialize)]
20pub struct Initializer {
21    /// This participant's stake.
22    pub stake: Stake,
23    /// Current protocol instantiation parameters.
24    pub params: Parameters,
25    /// Secret key.
26    pub(crate) sk: BlsSigningKey,
27    /// Verification (public) key + proof of possession.
28    pub(crate) pk: VerificationKeyProofOfPossession,
29}
30
31impl Initializer {
32    /// Builds an `Initializer` that is ready to register with the key registration service.
33    /// This function generates the signing and verification key with a PoP, and initialises the structure.
34    pub fn new<R: RngCore + CryptoRng>(params: Parameters, stake: Stake, rng: &mut R) -> Self {
35        let sk = BlsSigningKey::generate(rng);
36        let pk = VerificationKeyProofOfPossession::from(&sk);
37        Self {
38            stake,
39            params,
40            sk,
41            pk,
42        }
43    }
44
45    /// Builds an `Initializer` that is ready to register with the key registration service.
46    /// This function generates the signing and verification key with a PoP, and initialises the structure.
47    #[deprecated(since = "0.5.0", note = "Use `new` instead")]
48    pub fn setup<R: RngCore + CryptoRng>(params: Parameters, stake: Stake, rng: &mut R) -> Self {
49        Self::new(params, stake, rng)
50    }
51
52    /// Extract the verification key with proof of possession.
53    pub fn get_verification_key_proof_of_possession(&self) -> VerificationKeyProofOfPossession {
54        self.pk
55    }
56
57    /// Extract the verification key.
58    #[deprecated(
59        since = "0.5.0",
60        note = "Use `get_verification_key_proof_of_possession` instead"
61    )]
62    pub fn verification_key(&self) -> VerificationKeyProofOfPossession {
63        Self::get_verification_key_proof_of_possession(self)
64    }
65
66    /// Build the `avk` for the given list of parties.
67    ///
68    /// Note that if this Initializer was modified *between* the last call to `register`,
69    /// then the resulting `Signer` may not be able to produce valid signatures.
70    ///
71    /// Returns an `Signer` specialized to
72    /// * this `Signer`'s ID and current stake
73    /// * this `Signer`'s parameter valuation
74    /// * the `avk` as built from the current registered parties (according to the registration service)
75    /// * the current total stake (according to the registration service)
76    /// # Error
77    /// This function fails if the initializer is not registered.
78    pub fn create_signer<D: Digest + Clone + FixedOutput>(
79        self,
80        closed_reg: ClosedKeyRegistration<D>,
81    ) -> StmResult<Signer<D>> {
82        let mut my_index = None;
83        for (i, rp) in closed_reg.reg_parties.iter().enumerate() {
84            if rp.0 == self.pk.vk {
85                my_index = Some(i as u64);
86                break;
87            }
88        }
89        if my_index.is_none() {
90            return Err(anyhow!(RegisterError::UnregisteredInitializer));
91        }
92
93        Ok(Signer::set_signer(
94            my_index.unwrap(),
95            self.stake,
96            self.params,
97            self.sk,
98            self.pk.vk,
99            closed_reg,
100        ))
101    }
102
103    /// Build the `avk` for the given list of parties.
104    ///
105    /// Note that if this Initializer was modified *between* the last call to `register`,
106    /// then the resulting `Signer` may not be able to produce valid signatures.
107    ///
108    /// Returns an `Signer` specialized to
109    /// * this `Signer`'s ID and current stake
110    /// * this `Signer`'s parameter valuation
111    /// * the `avk` as built from the current registered parties (according to the registration service)
112    /// * the current total stake (according to the registration service)
113    /// # Error
114    /// This function fails if the initializer is not registered.
115    #[deprecated(since = "0.5.0", note = "Use `create_signer` instead")]
116    pub fn new_signer<D: Digest + Clone + FixedOutput>(
117        self,
118        closed_reg: ClosedKeyRegistration<D>,
119    ) -> StmResult<Signer<D>> {
120        Self::create_signer(self, closed_reg)
121    }
122
123    /// Creates a new basic signer that does not include closed registration.
124    /// Takes `eligible_parties` as a parameter and determines the signer's index in the parties.
125    /// `eligible_parties` is verified and trusted which is only run by a full-node
126    /// that has already verified the parties.
127    pub fn create_basic_signer<D: Digest + Clone + FixedOutput>(
128        self,
129        eligible_parties: &[RegisteredParty],
130    ) -> Option<Signer<D>> {
131        let mut parties = eligible_parties.to_vec();
132        parties.sort_unstable();
133        let mut my_index = None;
134        for (i, rp) in parties.iter().enumerate() {
135            if rp.0 == self.pk.vk {
136                my_index = Some(i as u64);
137                break;
138            }
139        }
140        if let Some(index) = my_index {
141            Some(Signer::set_basic_signer(
142                index,
143                self.stake,
144                self.params,
145                self.sk,
146                self.pk.vk,
147            ))
148        } else {
149            None
150        }
151    }
152
153    /// Creates a new basic signer that does not include closed registration.
154    /// Takes `eligible_parties` as a parameter and determines the signer's index in the parties.
155    /// `eligible_parties` is verified and trusted which is only run by a full-node
156    /// that has already verified the parties.
157    #[deprecated(since = "0.5.0", note = "Use `create_basic_signer` instead")]
158    pub fn new_core_signer<D: Digest + Clone + FixedOutput>(
159        self,
160        eligible_parties: &[RegisteredParty],
161    ) -> Option<Signer<D>> {
162        Self::create_basic_signer(self, eligible_parties)
163    }
164
165    /// Convert to bytes
166    /// # Layout
167    /// * Stake (u64)
168    /// * Params
169    /// * Secret Key
170    /// * Public key (including PoP)
171    pub fn to_bytes(&self) -> [u8; 256] {
172        let mut out = [0u8; 256];
173        out[..8].copy_from_slice(&self.stake.to_be_bytes());
174        out[8..32].copy_from_slice(&self.params.to_bytes());
175        out[32..64].copy_from_slice(&self.sk.to_bytes());
176        out[64..].copy_from_slice(&self.pk.to_bytes());
177        out
178    }
179
180    /// Convert a slice of bytes to an `Initializer`
181    /// # Error
182    /// The function fails if the given string of bytes is not of required size.
183    pub fn from_bytes(bytes: &[u8]) -> StmResult<Initializer> {
184        let mut u64_bytes = [0u8; 8];
185        u64_bytes.copy_from_slice(bytes.get(..8).ok_or(RegisterError::SerializationError)?);
186        let stake = u64::from_be_bytes(u64_bytes);
187        let params =
188            Parameters::from_bytes(bytes.get(8..32).ok_or(RegisterError::SerializationError)?)?;
189        let sk =
190            BlsSigningKey::from_bytes(bytes.get(32..).ok_or(RegisterError::SerializationError)?)?;
191        let pk = VerificationKeyProofOfPossession::from_bytes(
192            bytes.get(64..).ok_or(RegisterError::SerializationError)?,
193        )?;
194
195        Ok(Self {
196            stake,
197            params,
198            sk,
199            pk,
200        })
201    }
202}
203
204impl PartialEq for Initializer {
205    fn eq(&self, other: &Self) -> bool {
206        self.stake == other.stake
207            && self.params == other.params
208            && self.sk.to_bytes() == other.sk.to_bytes()
209            && self.get_verification_key_proof_of_possession()
210                == other.get_verification_key_proof_of_possession()
211    }
212}
213
214#[cfg(test)]
215mod tests {
216    use super::*;
217
218    mod golden {
219        use rand_chacha::ChaCha20Rng;
220        use rand_core::SeedableRng;
221
222        use super::*;
223
224        const GOLDEN_JSON: &str = r#"
225            {
226                "stake":1,
227                "params":
228                {
229                    "m":20973,
230                    "k":2422,
231                    "phi_f":0.2
232                },
233                "sk":[64,129,87,121,27,239,221,215,2,103,45,207,207,201,157,163,81,47,156,14,168,24,137,15,203,106,183,73,88,14,242,207],
234                "pk":
235                {
236                    "vk":[143,161,255,48,78,57,204,220,25,221,164,252,248,14,56,126,186,135,228,188,145,181,52,200,97,99,213,46,0,199,193,89,187,88,29,135,173,244,86,36,83,54,67,164,6,137,94,72,6,105,128,128,93,48,176,11,4,246,138,48,180,133,90,142,192,24,193,111,142,31,76,111,110,234,153,90,208,192,31,124,95,102,49,158,99,52,220,165,94,251,68,69,121,16,224,194],
237                    "pop":[168,50,233,193,15,136,65,72,123,148,129,176,38,198,209,47,28,204,176,144,57,251,42,28,66,76,89,97,158,63,54,198,194,176,135,221,14,185,197,225,202,98,243,74,233,225,143,151,147,177,170,117,66,165,66,62,33,216,232,75,68,114,195,22,100,65,44,198,4,166,102,233,253,240,59,175,60,117,142,114,140,122,17,87,110,187,1,17,10,195,154,13,249,86,54,226]
238                }
239            }
240        "#;
241
242        fn golden_value() -> Initializer {
243            let mut rng = ChaCha20Rng::from_seed([0u8; 32]);
244            let sk = BlsSigningKey::generate(&mut rng);
245            let pk = BlsVerificationKeyProofOfPossession::from(&sk);
246            Initializer {
247                stake: 1,
248                params: Parameters {
249                    m: 20973,
250                    k: 2422,
251                    phi_f: 0.2,
252                },
253                sk,
254                pk,
255            }
256        }
257
258        #[test]
259        fn golden_conversions() {
260            let value = serde_json::from_str(GOLDEN_JSON)
261                .expect("This JSON deserialization should not fail");
262            assert_eq!(golden_value(), value);
263
264            let serialized =
265                serde_json::to_string(&value).expect("This JSON serialization should not fail");
266            let golden_serialized = serde_json::to_string(&golden_value())
267                .expect("This JSON serialization should not fail");
268            assert_eq!(golden_serialized, serialized);
269        }
270    }
271}