1use anyhow::anyhow;
2use rand_core::{CryptoRng, RngCore};
3use serde::{Deserialize, Serialize};
4
5use crate::{
6 ClosedKeyRegistration, MembershipDigest, Parameters, RegisterError, Stake, StmResult,
7 signature_scheme::{BlsSigningKey, BlsVerificationKeyProofOfPossession},
8};
9
10use super::Signer;
11
12pub type VerificationKeyProofOfPossession = BlsVerificationKeyProofOfPossession;
14
15#[derive(Debug, Clone, Serialize, Deserialize)]
19pub struct Initializer {
20 pub stake: Stake,
22 pub params: Parameters,
24 pub(crate) sk: BlsSigningKey,
26 pub(crate) pk: VerificationKeyProofOfPossession,
28}
29
30impl Initializer {
31 pub fn new<R: RngCore + CryptoRng>(params: Parameters, stake: Stake, rng: &mut R) -> Self {
34 let sk = BlsSigningKey::generate(rng);
35 let pk = VerificationKeyProofOfPossession::from(&sk);
36 Self {
37 stake,
38 params,
39 sk,
40 pk,
41 }
42 }
43
44 pub fn get_verification_key_proof_of_possession(&self) -> VerificationKeyProofOfPossession {
46 self.pk
47 }
48
49 pub fn create_signer<D: MembershipDigest>(
62 self,
63 closed_reg: ClosedKeyRegistration<D>,
64 ) -> StmResult<Signer<D>> {
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(anyhow!(RegisterError::UnregisteredInitializer));
74 }
75
76 Ok(Signer::set_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 pub fn to_bytes(&self) -> [u8; 256] {
93 let mut out = [0u8; 256];
94 out[..8].copy_from_slice(&self.stake.to_be_bytes());
95 out[8..32].copy_from_slice(&self.params.to_bytes());
96 out[32..64].copy_from_slice(&self.sk.to_bytes());
97 out[64..].copy_from_slice(&self.pk.to_bytes());
98 out
99 }
100
101 pub fn from_bytes(bytes: &[u8]) -> StmResult<Initializer> {
105 let mut u64_bytes = [0u8; 8];
106 u64_bytes.copy_from_slice(bytes.get(..8).ok_or(RegisterError::SerializationError)?);
107 let stake = u64::from_be_bytes(u64_bytes);
108 let params =
109 Parameters::from_bytes(bytes.get(8..32).ok_or(RegisterError::SerializationError)?)?;
110 let sk =
111 BlsSigningKey::from_bytes(bytes.get(32..).ok_or(RegisterError::SerializationError)?)?;
112 let pk = VerificationKeyProofOfPossession::from_bytes(
113 bytes.get(64..).ok_or(RegisterError::SerializationError)?,
114 )?;
115
116 Ok(Self {
117 stake,
118 params,
119 sk,
120 pk,
121 })
122 }
123}
124
125impl PartialEq for Initializer {
126 fn eq(&self, other: &Self) -> bool {
127 self.stake == other.stake
128 && self.params == other.params
129 && self.sk.to_bytes() == other.sk.to_bytes()
130 && self.get_verification_key_proof_of_possession()
131 == other.get_verification_key_proof_of_possession()
132 }
133}
134
135#[cfg(test)]
136mod tests {
137 use super::*;
138
139 mod golden {
140 use rand_chacha::ChaCha20Rng;
141 use rand_core::SeedableRng;
142
143 use super::*;
144
145 const GOLDEN_JSON: &str = r#"
146 {
147 "stake":1,
148 "params":
149 {
150 "m":20973,
151 "k":2422,
152 "phi_f":0.2
153 },
154 "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],
155 "pk":
156 {
157 "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],
158 "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]
159 }
160 }
161 "#;
162
163 fn golden_value() -> Initializer {
164 let mut rng = ChaCha20Rng::from_seed([0u8; 32]);
165 let sk = BlsSigningKey::generate(&mut rng);
166 let pk = BlsVerificationKeyProofOfPossession::from(&sk);
167 Initializer {
168 stake: 1,
169 params: Parameters {
170 m: 20973,
171 k: 2422,
172 phi_f: 0.2,
173 },
174 sk,
175 pk,
176 }
177 }
178
179 #[test]
180 fn golden_conversions() {
181 let value = serde_json::from_str(GOLDEN_JSON)
182 .expect("This JSON deserialization should not fail");
183 assert_eq!(golden_value(), value);
184
185 let serialized =
186 serde_json::to_string(&value).expect("This JSON serialization should not fail");
187 let golden_serialized = serde_json::to_string(&golden_value())
188 .expect("This JSON serialization should not fail");
189 assert_eq!(golden_serialized, serialized);
190 }
191 }
192}