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