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