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