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::{SigningKey, VerificationKeyPoP};
7use crate::key_reg::{ClosedKeyReg, RegParty};
8use crate::participant::StmSigner;
9use crate::stm::{Stake, StmParameters};
10use crate::RegisterError;
11
12/// Wrapper of the MultiSignature Verification key with proof of possession
13pub type StmVerificationKeyPoP = VerificationKeyPoP;
14
15/// Initializer for `StmSigner`.
16/// This is the data that is used during the key registration procedure.
17/// Once the latter is finished, this instance is consumed into an `StmSigner`.
18#[derive(Debug, Clone, Serialize, Deserialize)]
19pub struct StmInitializer {
20    /// This participant's stake.
21    pub stake: Stake,
22    /// Current protocol instantiation parameters.
23    pub params: StmParameters,
24    /// Secret key.
25    pub(crate) sk: SigningKey,
26    /// Verification (public) key + proof of possession.
27    pub(crate) pk: StmVerificationKeyPoP,
28}
29
30impl StmInitializer {
31    /// Builds an `StmInitializer` that is ready to register with the key registration service.
32    /// This function generates the signing and verification key with a PoP, and initialises the structure.
33    pub fn setup<R: RngCore + CryptoRng>(params: StmParameters, stake: Stake, rng: &mut R) -> Self {
34        let sk = SigningKey::gen(rng);
35        let pk = StmVerificationKeyPoP::from(&sk);
36        Self {
37            stake,
38            params,
39            sk,
40            pk,
41        }
42    }
43
44    /// Extract the verification key.
45    pub fn verification_key(&self) -> StmVerificationKeyPoP {
46        self.pk
47    }
48
49    /// Build the `avk` for the given list of parties.
50    ///
51    /// Note that if this StmInitializer was modified *between* the last call to `register`,
52    /// then the resulting `StmSigner` may not be able to produce valid signatures.
53    ///
54    /// Returns an `StmSigner` specialized to
55    /// * this `StmSigner`'s ID and current stake
56    /// * this `StmSigner`'s parameter valuation
57    /// * the `avk` as built from the current registered parties (according to the registration service)
58    /// * the current total stake (according to the registration service)
59    /// # Error
60    /// This function fails if the initializer is not registered.
61    pub fn new_signer<D: Digest + Clone + FixedOutput>(
62        self,
63        closed_reg: ClosedKeyReg<D>,
64    ) -> Result<StmSigner<D>, RegisterError> {
65        let mut my_index = None;
66        for (i, rp) in closed_reg.reg_parties.iter().enumerate() {
67            if rp.0 == self.pk.vk {
68                my_index = Some(i as u64);
69                break;
70            }
71        }
72        if my_index.is_none() {
73            return Err(RegisterError::UnregisteredInitializer);
74        }
75
76        Ok(StmSigner::set_stm_signer(
77            my_index.unwrap(),
78            self.stake,
79            self.params,
80            self.sk,
81            self.pk.vk,
82            closed_reg,
83        ))
84    }
85
86    /// Creates a new core signer that does not include closed registration.
87    /// Takes `eligible_parties` as a parameter and determines the signer's index in the parties.
88    /// `eligible_parties` is verified and trusted which is only run by a full-node
89    /// that has already verified the parties.
90    pub fn new_core_signer<D: Digest + Clone + FixedOutput>(
91        self,
92        eligible_parties: &[RegParty],
93    ) -> Option<StmSigner<D>> {
94        let mut parties = eligible_parties.to_vec();
95        parties.sort_unstable();
96        let mut my_index = None;
97        for (i, rp) in parties.iter().enumerate() {
98            if rp.0 == self.pk.vk {
99                my_index = Some(i as u64);
100                break;
101            }
102        }
103        if let Some(index) = my_index {
104            Some(StmSigner::set_core_signer(
105                index,
106                self.stake,
107                self.params,
108                self.sk,
109                self.pk.vk,
110            ))
111        } else {
112            None
113        }
114    }
115
116    /// Convert to bytes
117    /// # Layout
118    /// * Stake (u64)
119    /// * Params
120    /// * Secret Key
121    /// * Public key (including PoP)
122    pub fn to_bytes(&self) -> [u8; 256] {
123        let mut out = [0u8; 256];
124        out[..8].copy_from_slice(&self.stake.to_be_bytes());
125        out[8..32].copy_from_slice(&self.params.to_bytes());
126        out[32..64].copy_from_slice(&self.sk.to_bytes());
127        out[64..].copy_from_slice(&self.pk.to_bytes());
128        out
129    }
130
131    /// Convert a slice of bytes to an `StmInitializer`
132    /// # Error
133    /// The function fails if the given string of bytes is not of required size.
134    pub fn from_bytes(bytes: &[u8]) -> Result<StmInitializer, RegisterError> {
135        let mut u64_bytes = [0u8; 8];
136        u64_bytes.copy_from_slice(&bytes[..8]);
137        let stake = u64::from_be_bytes(u64_bytes);
138        let params = StmParameters::from_bytes(&bytes[8..32])?;
139        let sk = SigningKey::from_bytes(&bytes[32..])?;
140        let pk = StmVerificationKeyPoP::from_bytes(&bytes[64..])?;
141
142        Ok(Self {
143            stake,
144            params,
145            sk,
146            pk,
147        })
148    }
149}