mithril_stm/participant/
initializer.rs

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