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
295#[cfg(any(test, feature = "test_tools"))]
296mod test_extensions {
297 use crate::test::crypto_helper::ProtocolInitializerTestExtension;
298
299 use super::*;
300
301 impl ProtocolInitializerTestExtension for StmInitializerWrapper {
302 fn override_protocol_parameters(&mut self, protocol_parameters: &ProtocolParameters) {
303 self.stm_initializer.params = protocol_parameters.to_owned();
304 }
305 }
306}
307
308#[cfg(test)]
309mod test {
310 use crate::crypto_helper::cardano::kes::KesSignerStandard;
311 use crate::crypto_helper::{OpCert, SerDeShelleyFileFormat};
312 use crate::test::crypto_helper::{
313 KesCryptographicMaterialForTest, KesPartyIndexForTest, create_kes_cryptographic_material,
314 };
315
316 use rand_chacha::ChaCha20Rng;
317 use rand_core::SeedableRng;
318
319 use super::*;
320
321 #[test]
322 fn test_vector_key_reg() {
323 let params = Parameters {
324 m: 5,
325 k: 5,
326 phi_f: 1.0,
327 };
328 let mut rng = ChaCha20Rng::from_seed([0u8; 32]);
329 let KesCryptographicMaterialForTest {
330 party_id: party_id_1,
331 operational_certificate_file: operational_certificate_file_1,
332 kes_secret_key_file: kes_secret_key_file_1,
333 } = create_kes_cryptographic_material(
334 1 as KesPartyIndexForTest,
335 0 as KesPeriod,
336 "test_vector_key_reg",
337 );
338 let KesCryptographicMaterialForTest {
339 party_id: party_id_2,
340 operational_certificate_file: operational_certificate_file_2,
341 kes_secret_key_file: kes_secret_key_file_2,
342 } = create_kes_cryptographic_material(
343 2 as KesPartyIndexForTest,
344 0 as KesPeriod,
345 "test_vector_key_reg",
346 );
347
348 let mut key_reg = KeyRegWrapper::init(&vec![(party_id_1, 10), (party_id_2, 3)]);
349
350 let initializer_1 = StmInitializerWrapper::setup(
351 params,
352 Some(Arc::new(KesSignerStandard::new(
353 kes_secret_key_file_1,
354 operational_certificate_file_1.clone(),
355 ))),
356 Some(0),
357 10,
358 &mut rng,
359 )
360 .unwrap();
361
362 let opcert1 = OpCert::from_file(operational_certificate_file_1)
363 .expect("opcert deserialization should not fail")
364 .into();
365
366 let key_registration_1 = key_reg.register(
367 None,
368 Some(opcert1),
369 initializer_1.verification_key_signature(),
370 Some(0),
371 initializer_1
372 .stm_initializer
373 .get_verification_key_proof_of_possession()
374 .into(),
375 );
376 assert!(key_registration_1.is_ok());
377
378 let initializer_2 = StmInitializerWrapper::setup(
379 params,
380 Some(Arc::new(KesSignerStandard::new(
381 kes_secret_key_file_2,
382 operational_certificate_file_2.clone(),
383 ))),
384 Some(0),
385 10,
386 &mut rng,
387 )
388 .unwrap();
389
390 let opcert2 = OpCert::from_file(operational_certificate_file_2)
391 .expect("opcert deserialization should not fail")
392 .into();
393
394 let key_registration_2 = key_reg.register(
395 None,
396 Some(opcert2),
397 initializer_2.verification_key_signature(),
398 Some(0),
399 initializer_2
400 .stm_initializer
401 .get_verification_key_proof_of_possession()
402 .into(),
403 );
404 assert!(key_registration_2.is_ok())
405 }
406
407 const GOLDEN_STM_INITIALIZER_WRAPPER_JSON: &str = r#"
408 {
409 "stm_initializer": {
410 "stake": 9497432569,
411 "params": {
412 "m": 20973,
413 "k": 2422,
414 "phi_f": 0.2
415 },
416 "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],
417 "pk": {
418 "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],
419 "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]
420 }
421 },
422 "kes_signature": {
423 "sigma": {
424 "sigma": {
425 "sigma": {
426 "sigma": {
427 "sigma": {
428 "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],
429 "lhs_pk": [
430 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],
431 "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]
432 },
433 "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],
434 "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]
435 },
436 "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],
437 "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]
438 },
439 "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],
440 "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]
441 },
442 "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],
443 "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]
444 },
445 "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],
446 "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]
447 }
448 }
449 "#;
450
451 #[test]
452 fn golden_initializer_deserialization() {
453 let _: StmInitializerWrapper = serde_json::from_str(GOLDEN_STM_INITIALIZER_WRAPPER_JSON)
454 .expect("Deserializing a StmInitializerWrapper should not fail");
455 }
456
457 #[test]
458 fn test_initializer_wrapper_conversions() {
459 let stm_initializer_wrapper_json = GOLDEN_STM_INITIALIZER_WRAPPER_JSON;
460
461 let stm_initializer_wrapper_from_json: StmInitializerWrapper =
462 serde_json::from_str(stm_initializer_wrapper_json)
463 .expect("Deserializing a StmInitializerWrapper should not fail");
464 let stm_initializer_wrapper_from_json_to_json =
465 serde_json::to_string(&stm_initializer_wrapper_from_json)
466 .expect("Serializing a StmInitializerWrapper to json should not fail");
467
468 let stm_initializer_wrapper_from_bytes =
469 StmInitializerWrapper::from_bytes(&stm_initializer_wrapper_from_json.to_bytes())
470 .expect("Deserializing a StmInitializerWrapper from bytes should not fail");
471 let stm_initializer_wrapper_from_bytes_to_json =
472 serde_json::to_string(&stm_initializer_wrapper_from_bytes)
473 .expect("Serializing a StmInitializerWrapper to json should not fail");
474
475 assert_eq!(
476 stm_initializer_wrapper_from_json_to_json,
477 stm_initializer_wrapper_from_bytes_to_json
478 );
479
480 let mut stm_initializer_wrapper_from_json = stm_initializer_wrapper_from_json;
481 stm_initializer_wrapper_from_json.kes_signature = None;
482
483 let stm_initializer_wrapper_from_bytes =
484 StmInitializerWrapper::from_bytes(&stm_initializer_wrapper_from_json.to_bytes())
485 .expect("Deserializing a StmInitializerWrapper from bytes should not fail");
486 assert_eq!(None, stm_initializer_wrapper_from_bytes.kes_signature);
487 }
488}