1use std::{collections::HashMap, sync::Arc};
7
8use anyhow::anyhow;
9use kes_summed_ed25519::kes::Sum6KesSig;
10use rand_core::{CryptoRng, RngCore};
11use serde::{Deserialize, Serialize};
12use thiserror::Error;
13
14use mithril_stm::{
15 ClosedKeyRegistration, Initializer, KeyRegistration, MembershipDigest, MithrilMembershipDigest,
16 Parameters, RegisterError, Signer, Stake, VerificationKeyProofOfPossession,
17};
18
19use crate::{
20 StdError, StdResult,
21 crypto_helper::{
22 ProtocolOpCert,
23 cardano::{KesSigner, KesVerifier, KesVerifierStandard},
24 types::{
25 ProtocolParameters, ProtocolPartyId, ProtocolSignerVerificationKey,
26 ProtocolSignerVerificationKeySignature, ProtocolStakeDistribution,
27 },
28 },
29};
30
31type D = MithrilMembershipDigest;
33
34pub type KesPeriod = u32;
36
37#[derive(Error, Debug)]
39pub enum ProtocolRegistrationErrorWrapper {
40 #[error("missing party id")]
44 PartyIdMissing,
45
46 #[error("party id does not exist in the stake distribution")]
48 PartyIdNonExisting,
49
50 #[error("missing operational certificate")]
52 OpCertMissing,
53
54 #[error("invalid operational certificate")]
56 OpCertInvalid,
57
58 #[error("KES signature verification error: CurrentKesPeriod={0}, StartKesPeriod={1}")]
60 KesSignatureInvalid(u32, u64),
61
62 #[error("missing KES signature")]
64 KesSignatureMissing,
65
66 #[error("missing KES period")]
68 KesPeriodMissing,
69
70 #[error("pool address encoding error")]
72 PoolAddressEncoding,
73
74 #[error("core registration error")]
76 CoreRegister(#[source] RegisterError),
77}
78
79#[derive(Error, Debug)]
81pub enum ProtocolInitializerErrorWrapper {
82 #[error("protocol initializer error")]
84 ProtocolInitializer(#[source] StdError),
85
86 #[error("KES key cannot be updated for evolution {0}")]
88 KesUpdate(KesPeriod),
89
90 #[error("Period of key file, {0}, does not match with period provided by user, {1}")]
92 KesMismatch(KesPeriod, KesPeriod),
93}
94
95#[derive(Debug, Clone, Serialize, Deserialize)]
99pub struct StmInitializerWrapper {
100 stm_initializer: Initializer,
102
103 kes_signature: Option<Sum6KesSig>,
107}
108
109impl StmInitializerWrapper {
110 pub fn setup<R: RngCore + CryptoRng>(
114 params: Parameters,
115 kes_signer: Option<Arc<dyn KesSigner>>,
116 current_kes_period: Option<KesPeriod>,
117 stake: Stake,
118 rng: &mut R,
119 ) -> StdResult<Self> {
120 let stm_initializer = Initializer::new(params, stake, rng);
121 let kes_signature = if let Some(kes_signer) = kes_signer {
122 let (signature, _op_cert) = kes_signer.sign(
123 &stm_initializer.get_verification_key_proof_of_possession().to_bytes(),
124 current_kes_period.unwrap_or_default(),
125 )?;
126
127 Some(signature)
128 } else {
129 println!(
130 "WARNING: Non certified signer registration by providing only a Pool Id is decommissioned and must be used for tests only!"
131 );
132 None
133 };
134
135 Ok(Self {
136 stm_initializer,
137 kes_signature,
138 })
139 }
140
141 pub fn verification_key(&self) -> VerificationKeyProofOfPossession {
143 self.stm_initializer.get_verification_key_proof_of_possession()
144 }
145
146 pub fn verification_key_signature(&self) -> Option<ProtocolSignerVerificationKeySignature> {
148 self.kes_signature.map(|k| k.into())
149 }
150
151 pub fn get_protocol_parameters(&self) -> ProtocolParameters {
153 self.stm_initializer.params
154 }
155
156 pub fn get_stake(&self) -> Stake {
158 self.stm_initializer.stake
159 }
160
161 pub fn new_signer(self, closed_reg: ClosedKeyRegistration<D>) -> StdResult<Signer<D>> {
174 self.stm_initializer.create_signer(closed_reg)
175 }
176
177 pub fn to_bytes(&self) -> Vec<u8> {
182 let mut out = Vec::new();
183 out.extend_from_slice(&self.stm_initializer.to_bytes());
184 if let Some(kes_signature) = &self.kes_signature {
185 out.extend_from_slice(&kes_signature.to_bytes());
186 }
187
188 out
189 }
190
191 pub fn from_bytes(bytes: &[u8]) -> StdResult<Self> {
195 let stm_initializer =
196 Initializer::from_bytes(bytes.get(..256).ok_or(RegisterError::SerializationError)?)?;
197 let bytes = bytes.get(256..).ok_or(RegisterError::SerializationError)?;
198 let kes_signature = if bytes.is_empty() {
199 None
200 } else {
201 Some(Sum6KesSig::from_bytes(bytes).map_err(|_| RegisterError::SerializationError)?)
202 };
203
204 Ok(Self {
205 stm_initializer,
206 kes_signature,
207 })
208 }
209}
210
211#[derive(Debug, Clone)]
218pub struct KeyRegWrapper {
219 kes_verifier: Arc<dyn KesVerifier>,
220 stm_key_reg: KeyRegistration,
221 stake_distribution: HashMap<ProtocolPartyId, Stake>,
222}
223
224impl KeyRegWrapper {
225 pub fn init(stake_dist: &ProtocolStakeDistribution) -> Self {
228 Self {
229 kes_verifier: Arc::new(KesVerifierStandard),
230 stm_key_reg: KeyRegistration::init(),
231 stake_distribution: HashMap::from_iter(stake_dist.to_vec()),
232 }
233 }
234
235 pub fn register(
241 &mut self,
242 party_id: Option<ProtocolPartyId>, opcert: Option<ProtocolOpCert>, kes_sig: Option<ProtocolSignerVerificationKeySignature>, kes_evolutions: Option<KesPeriod>,
246 pk: ProtocolSignerVerificationKey,
247 ) -> StdResult<ProtocolPartyId> {
248 let pool_id_bech32: ProtocolPartyId = if let Some(opcert) = opcert {
249 let signature = kes_sig.ok_or(ProtocolRegistrationErrorWrapper::KesSignatureMissing)?;
250 let kes_evolutions =
251 kes_evolutions.ok_or(ProtocolRegistrationErrorWrapper::KesPeriodMissing)?;
252 if self
253 .kes_verifier
254 .verify(&pk.to_bytes(), &signature, &opcert, kes_evolutions)
255 .is_ok()
256 {
257 opcert
258 .compute_protocol_party_id()
259 .map_err(|_| ProtocolRegistrationErrorWrapper::PoolAddressEncoding)?
260 } else {
261 return Err(anyhow!(
262 ProtocolRegistrationErrorWrapper::KesSignatureInvalid(
263 kes_evolutions,
264 opcert.get_start_kes_period(),
265 )
266 ));
267 }
268 } else {
269 if cfg!(not(feature = "allow_skip_signer_certification")) {
270 Err(ProtocolRegistrationErrorWrapper::OpCertMissing)?
271 }
272 party_id.ok_or(ProtocolRegistrationErrorWrapper::PartyIdMissing)?
273 };
274
275 if let Some(&stake) = self.stake_distribution.get(&pool_id_bech32) {
276 self.stm_key_reg.register(stake, pk.into())?;
277 return Ok(pool_id_bech32);
278 }
279 Err(anyhow!(
280 ProtocolRegistrationErrorWrapper::PartyIdNonExisting
281 ))
282 }
283
284 pub fn close<D: MembershipDigest>(self) -> ClosedKeyRegistration<D> {
287 self.stm_key_reg.close()
288 }
289}
290
291mod test_extensions {
292 use crate::test::crypto_helper::ProtocolInitializerTestExtension;
293
294 use super::*;
295
296 impl ProtocolInitializerTestExtension for StmInitializerWrapper {
297 fn override_protocol_parameters(&mut self, protocol_parameters: &ProtocolParameters) {
298 self.stm_initializer.params = protocol_parameters.to_owned();
299 }
300 }
301}
302
303#[cfg(test)]
304mod test {
305 use crate::crypto_helper::cardano::kes::KesSignerStandard;
306 use crate::crypto_helper::{OpCert, SerDeShelleyFileFormat};
307 use crate::test::crypto_helper::{
308 KesCryptographicMaterialForTest, KesPartyIndexForTest, create_kes_cryptographic_material,
309 };
310
311 use rand_chacha::ChaCha20Rng;
312 use rand_core::SeedableRng;
313
314 use super::*;
315
316 #[test]
317 fn test_vector_key_reg() {
318 let params = Parameters {
319 m: 5,
320 k: 5,
321 phi_f: 1.0,
322 };
323 let mut rng = ChaCha20Rng::from_seed([0u8; 32]);
324 let KesCryptographicMaterialForTest {
325 party_id: party_id_1,
326 operational_certificate_file: operational_certificate_file_1,
327 kes_secret_key_file: kes_secret_key_file_1,
328 } = create_kes_cryptographic_material(
329 1 as KesPartyIndexForTest,
330 0 as KesPeriod,
331 "test_vector_key_reg",
332 );
333 let KesCryptographicMaterialForTest {
334 party_id: party_id_2,
335 operational_certificate_file: operational_certificate_file_2,
336 kes_secret_key_file: kes_secret_key_file_2,
337 } = create_kes_cryptographic_material(
338 2 as KesPartyIndexForTest,
339 0 as KesPeriod,
340 "test_vector_key_reg",
341 );
342
343 let mut key_reg = KeyRegWrapper::init(&vec![(party_id_1, 10), (party_id_2, 3)]);
344
345 let initializer_1 = StmInitializerWrapper::setup(
346 params,
347 Some(Arc::new(KesSignerStandard::new(
348 kes_secret_key_file_1,
349 operational_certificate_file_1.clone(),
350 ))),
351 Some(0),
352 10,
353 &mut rng,
354 )
355 .unwrap();
356
357 let opcert1 = OpCert::from_file(operational_certificate_file_1)
358 .expect("opcert deserialization should not fail")
359 .into();
360
361 let key_registration_1 = key_reg.register(
362 None,
363 Some(opcert1),
364 initializer_1.verification_key_signature(),
365 Some(0),
366 initializer_1
367 .stm_initializer
368 .get_verification_key_proof_of_possession()
369 .into(),
370 );
371 assert!(key_registration_1.is_ok());
372
373 let initializer_2 = StmInitializerWrapper::setup(
374 params,
375 Some(Arc::new(KesSignerStandard::new(
376 kes_secret_key_file_2,
377 operational_certificate_file_2.clone(),
378 ))),
379 Some(0),
380 10,
381 &mut rng,
382 )
383 .unwrap();
384
385 let opcert2 = OpCert::from_file(operational_certificate_file_2)
386 .expect("opcert deserialization should not fail")
387 .into();
388
389 let key_registration_2 = key_reg.register(
390 None,
391 Some(opcert2),
392 initializer_2.verification_key_signature(),
393 Some(0),
394 initializer_2
395 .stm_initializer
396 .get_verification_key_proof_of_possession()
397 .into(),
398 );
399 assert!(key_registration_2.is_ok())
400 }
401
402 const GOLDEN_STM_INITIALIZER_WRAPPER_JSON: &str = r#"
403 {
404 "stm_initializer": {
405 "stake": 9497432569,
406 "params": {
407 "m": 20973,
408 "k": 2422,
409 "phi_f": 0.2
410 },
411 "sk": [49, 181, 118, 110, 190, 161, 107, 218, 165, 20, 147, 129, 193, 79, 160, 0, 37, 23, 102, 223, 88, 174, 208, 70, 97, 79, 174, 51, 28, 0, 192, 210],
412 "pk": {
413 "vk": [173, 149, 133, 21, 100, 254, 36, 74, 165, 174, 56, 9, 145, 190, 48, 14, 12, 193, 243, 3, 200, 148, 221, 124, 170, 143, 89, 5, 168, 0, 226, 125, 61, 181, 190, 80, 62, 199, 99, 161, 117, 49, 65, 34, 81, 96, 34, 81, 2, 235, 173, 57, 58, 128, 49, 22, 242, 42, 30, 137, 6, 51, 77, 57, 142, 192, 140, 161, 206, 206, 213, 114, 156, 191, 127, 167, 167, 9, 39, 29, 97, 166, 134, 76, 55, 179, 72, 29, 41, 251, 14, 71, 89, 181, 31, 115],
414 "pop": [171, 0, 214, 91, 37, 208, 228, 71, 228, 31, 138, 0, 237, 175, 24, 45, 160, 117, 14, 210, 23, 46, 235, 83, 45, 9, 58, 207, 18, 36, 31, 160, 252, 111, 69, 102, 248, 205, 46, 71, 24, 38, 41, 77, 29, 129, 95, 16, 136, 114, 250, 44, 230, 184, 222, 122, 120, 58, 249, 103, 48, 121, 141, 244, 243, 26, 252, 60, 230, 64, 75, 3, 86, 107, 198, 198, 117, 242, 107, 104, 219, 209, 211, 255, 174, 203, 43, 141, 34, 146, 25, 181, 212, 38, 194, 99]
415 }
416 },
417 "kes_signature": {
418 "sigma": {
419 "sigma": {
420 "sigma": {
421 "sigma": {
422 "sigma": {
423 "sigma": [71, 225, 146, 98, 81, 62, 28, 21, 7, 157, 88, 4, 226, 126, 27, 133, 146, 171, 216, 170, 77, 17, 38, 146, 98, 202, 35, 87, 166, 162, 25, 207, 105, 174, 48, 225, 152, 68, 19, 109, 72, 241, 69, 111, 22, 214, 72, 20, 81, 56, 181, 104, 69, 121, 173, 194, 37, 60, 16, 155, 86, 99, 253, 7],
424 "lhs_pk": [
425 91, 82, 235, 39, 167, 29, 141, 253, 163, 163, 55, 185, 162, 191, 52, 8, 245, 7, 104, 22, 182, 239, 133, 138, 131, 15, 233, 116, 147, 251, 182, 140],
426 "rhs_pk": [189, 26, 9, 118, 59, 34, 225, 34, 104, 202, 192, 7, 66, 150, 137, 75, 106, 7, 22, 234, 42, 94, 139, 65, 241, 65, 1, 190, 153, 16, 221, 87]
427 },
428 "lhs_pk": [206, 50, 185, 93, 20, 234, 100, 168, 163, 125, 95, 201, 162, 104, 35, 2, 205, 41, 180, 73, 107, 140, 79, 182, 173, 17, 172, 49, 51, 85, 180, 5],
429 "rhs_pk": [68, 40, 90, 110, 254, 68, 87, 12, 19, 21, 252, 197, 69, 255, 33, 172, 140, 70, 79, 39, 71, 217, 12, 254, 82, 125, 123, 148, 221, 217, 141, 194]
430 },
431 "lhs_pk": [155, 2, 30, 71, 52, 89, 112, 247, 108, 177, 144, 212, 206, 254, 87, 126, 180, 207, 146, 223, 164, 246, 178, 62, 148, 96, 39, 136, 106, 36, 253, 56],
432 "rhs_pk": [155, 140, 124, 154, 235, 97, 51, 77, 208, 24, 45, 219, 199, 232, 222, 26, 160, 62, 38, 253, 121, 241, 219, 233, 36, 50, 60, 182, 127, 255, 132, 245]
433 },
434 "lhs_pk": [172, 176, 18, 228, 203, 85, 44, 151, 221, 13, 91, 250, 67, 232, 114, 16, 251, 13, 115, 233, 214, 194, 102, 199, 200, 124, 30, 190, 143, 18, 85, 75],
435 "rhs_pk": [100, 192, 98, 123, 150, 116, 55, 42, 207, 44, 181, 31, 203, 65, 237, 13, 55, 246, 185, 211, 149, 245, 245, 219, 183, 41, 237, 253, 128, 231, 161, 226]
436 },
437 "lhs_pk": [112, 16, 177, 142, 158, 1, 36, 210, 87, 165, 5, 195, 199, 61, 13, 195, 219, 26, 231, 103, 163, 223, 54, 16, 106, 0, 252, 69, 242, 31, 210, 167],
438 "rhs_pk": [15, 246, 81, 72, 172, 15, 170, 235, 10, 64, 229, 233, 169, 140, 179, 209, 244, 183, 3, 59, 2, 252, 233, 229, 13, 190, 196, 208, 109, 30, 73, 113]
439 },
440 "lhs_pk": [114, 238, 75, 184, 228, 147, 37, 72, 134, 65, 139, 64, 81, 114, 157, 148, 197, 108, 80, 89, 30, 235, 75, 108, 193, 53, 185, 15, 57, 61, 181, 119],
441 "rhs_pk": [82, 28, 113, 114, 168, 192, 222, 110, 96, 15, 28, 179, 164, 180, 76, 87, 254, 72, 48, 154, 167, 102, 220, 74, 76, 136, 45, 105, 243, 87, 165, 212]
442 }
443 }
444 "#;
445
446 #[test]
447 fn golden_initializer_deserialization() {
448 let _: StmInitializerWrapper = serde_json::from_str(GOLDEN_STM_INITIALIZER_WRAPPER_JSON)
449 .expect("Deserializing a StmInitializerWrapper should not fail");
450 }
451
452 #[test]
453 fn test_initializer_wrapper_conversions() {
454 let stm_initializer_wrapper_json = GOLDEN_STM_INITIALIZER_WRAPPER_JSON;
455
456 let stm_initializer_wrapper_from_json: StmInitializerWrapper =
457 serde_json::from_str(stm_initializer_wrapper_json)
458 .expect("Deserializing a StmInitializerWrapper should not fail");
459 let stm_initializer_wrapper_from_json_to_json =
460 serde_json::to_string(&stm_initializer_wrapper_from_json)
461 .expect("Serializing a StmInitializerWrapper to json should not fail");
462
463 let stm_initializer_wrapper_from_bytes =
464 StmInitializerWrapper::from_bytes(&stm_initializer_wrapper_from_json.to_bytes())
465 .expect("Deserializing a StmInitializerWrapper from bytes should not fail");
466 let stm_initializer_wrapper_from_bytes_to_json =
467 serde_json::to_string(&stm_initializer_wrapper_from_bytes)
468 .expect("Serializing a StmInitializerWrapper to json should not fail");
469
470 assert_eq!(
471 stm_initializer_wrapper_from_json_to_json,
472 stm_initializer_wrapper_from_bytes_to_json
473 );
474
475 let mut stm_initializer_wrapper_from_json = stm_initializer_wrapper_from_json;
476 stm_initializer_wrapper_from_json.kes_signature = None;
477
478 let stm_initializer_wrapper_from_bytes =
479 StmInitializerWrapper::from_bytes(&stm_initializer_wrapper_from_json.to_bytes())
480 .expect("Deserializing a StmInitializerWrapper from bytes should not fail");
481 assert_eq!(None, stm_initializer_wrapper_from_bytes.kes_signature);
482 }
483}