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