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
13pub type VerificationKeyProofOfPossession = BlsVerificationKeyProofOfPossession;
15
16#[derive(Debug, Clone, Serialize, Deserialize)]
20pub struct Initializer {
21 pub stake: Stake,
23 pub params: Parameters,
25 pub(crate) sk: BlsSigningKey,
27 pub(crate) pk: VerificationKeyProofOfPossession,
29}
30
31impl Initializer {
32 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 #[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 pub fn get_verification_key_proof_of_possession(&self) -> VerificationKeyProofOfPossession {
54 self.pk
55 }
56
57 #[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 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 #[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 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 #[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 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 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}