1use std::{collections::HashMap, sync::Arc};
7
8use anyhow::{Context, anyhow};
9use kes_summed_ed25519::kes::Sum6KesSig;
10use rand_core::{CryptoRng, RngCore};
11use serde::{Deserialize, Serialize};
12use thiserror::Error;
13
14#[cfg(feature = "future_snark")]
15use mithril_stm::VerificationKeyForSnark;
16use mithril_stm::{
17 ClosedKeyRegistration, Initializer, KeyRegistration, MithrilMembershipDigest, Parameters,
18 RegisterError, Signer, Stake, VerificationKeyProofOfPossessionForConcatenation,
19};
20
21#[cfg(feature = "future_snark")]
22use crate::crypto_helper::types::{
23 ProtocolSignerVerificationKeyForSnark, ProtocolSignerVerificationKeySignatureForSnark,
24};
25use crate::{
26 StdError, StdResult,
27 crypto_helper::{
28 KesEvolutions, KesPeriod, ProtocolOpCert,
29 cardano::{KesSigner, KesVerifier, KesVerifierStandard},
30 types::{
31 ProtocolParameters, ProtocolPartyId, ProtocolSignerVerificationKeyForConcatenation,
32 ProtocolSignerVerificationKeySignatureForConcatenation, ProtocolStakeDistribution,
33 },
34 },
35};
36
37type D = MithrilMembershipDigest;
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: KesEvolutions={0}, StartKesPeriod={1}")]
63 KesSignatureInvalid(KesEvolutions, KesPeriod, #[source] StdError),
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 evolution {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 #[serde(rename = "kes_signature")]
110 kes_signature_for_concatenation: Option<Sum6KesSig>,
111
112 #[cfg(feature = "future_snark")]
114 #[serde(skip_serializing_if = "Option::is_none", default)]
115 kes_signature_for_snark: Option<Sum6KesSig>,
116}
117
118impl StmInitializerWrapper {
119 pub fn setup<R: RngCore + CryptoRng>(
123 params: Parameters,
124 kes_signer: Option<Arc<dyn KesSigner>>,
125 current_kes_period: Option<KesPeriod>,
126 stake: Stake,
127 rng: &mut R,
128 ) -> StdResult<Self> {
129 let stm_initializer = Initializer::new(params, stake, rng);
130 let kes_signature;
131 #[cfg(feature = "future_snark")]
132 let kes_signature_for_snark;
133
134 if let Some(kes_signer) = kes_signer {
135 let (signature, _op_cert) = kes_signer.sign(
136 &stm_initializer
137 .get_verification_key_proof_of_possession_for_concatenation()
138 .to_bytes(),
139 current_kes_period.unwrap_or_default(),
140 )?;
141 kes_signature = Some(signature);
142
143 #[cfg(feature = "future_snark")]
144 {
145 kes_signature_for_snark = if let Some(schnorr_verification_key) =
146 &stm_initializer.schnorr_verification_key
147 {
148 let (signature, _op_cert) = kes_signer.sign(
149 &schnorr_verification_key.to_bytes(),
150 current_kes_period.unwrap_or_default(),
151 )?;
152
153 Some(signature)
154 } else {
155 None
156 };
157 }
158 } else {
159 println!(
160 "WARNING: Non certified signer registration by providing only a Pool Id is decommissioned and must be used for tests only!"
161 );
162 kes_signature = None;
163 #[cfg(feature = "future_snark")]
164 {
165 kes_signature_for_snark = None;
166 }
167 };
168
169 Ok(Self {
170 stm_initializer,
171 kes_signature_for_concatenation: kes_signature,
172 #[cfg(feature = "future_snark")]
173 kes_signature_for_snark,
174 })
175 }
176
177 pub fn verification_key_for_concatenation(
179 &self,
180 ) -> VerificationKeyProofOfPossessionForConcatenation {
181 self.stm_initializer
182 .get_verification_key_proof_of_possession_for_concatenation()
183 }
184
185 pub fn verification_key_signature_for_concatenation(
187 &self,
188 ) -> Option<ProtocolSignerVerificationKeySignatureForConcatenation> {
189 self.kes_signature_for_concatenation.map(|k| k.into())
190 }
191
192 #[cfg(feature = "future_snark")]
194 pub fn verification_key_for_snark(&self) -> Option<VerificationKeyForSnark> {
195 self.stm_initializer.schnorr_verification_key
196 }
197
198 #[cfg(feature = "future_snark")]
200 pub fn verification_key_signature_for_snark(
201 &self,
202 ) -> Option<ProtocolSignerVerificationKeySignatureForSnark> {
203 self.kes_signature_for_snark.map(|k| k.into())
204 }
205
206 #[cfg(feature = "future_snark")]
213 pub fn strip_snark_keys(&mut self) {
214 self.stm_initializer.strip_snark_keys();
215 self.kes_signature_for_snark = None;
216 }
217
218 pub fn get_protocol_parameters(&self) -> ProtocolParameters {
220 self.stm_initializer.parameters
221 }
222
223 pub fn get_stake(&self) -> Stake {
225 self.stm_initializer.stake
226 }
227
228 pub fn new_signer(self, closed_reg: ClosedKeyRegistration) -> StdResult<Signer<D>> {
241 self.stm_initializer.try_create_signer(&closed_reg)
242 }
243
244 pub fn to_bytes(&self) -> StdResult<Vec<u8>> {
250 let mut out = Vec::new();
251
252 let stm_initializer_bytes = self.stm_initializer.to_bytes()?;
253 out.extend_from_slice(
254 &u64::try_from(stm_initializer_bytes.len())
255 .context("STM initializer byte length should fit in u64")?
256 .to_be_bytes(),
257 );
258 out.extend_from_slice(&stm_initializer_bytes);
259
260 if let Some(kes_signature_for_concatenation) = &self.kes_signature_for_concatenation {
261 out.extend_from_slice(&kes_signature_for_concatenation.to_bytes());
262
263 #[cfg(feature = "future_snark")]
264 if let Some(kes_signature_for_snark) = &self.kes_signature_for_snark {
265 out.extend_from_slice(&kes_signature_for_snark.to_bytes());
266 }
267 }
268
269 Ok(out)
270 }
271
272 pub fn from_bytes(bytes: &[u8]) -> StdResult<Self> {
276 let mut bytes_index = 0;
277
278 let mut u64_bytes = [0u8; 8];
279 u64_bytes.copy_from_slice(
280 bytes
281 .get(bytes_index..bytes_index + 8)
282 .ok_or(RegisterError::SerializationError)?,
283 );
284 let stm_initializer_size = usize::try_from(u64::from_be_bytes(u64_bytes))
285 .map_err(|_| RegisterError::SerializationError)?;
286
287 let stm_initializer = Initializer::from_bytes(
288 bytes
289 .get(bytes_index + 8..bytes_index + 8 + stm_initializer_size)
290 .ok_or(RegisterError::SerializationError)?,
291 )?;
292 bytes_index += 8 + stm_initializer_size;
293
294 let kes_signature_for_concatenation;
295 #[cfg(feature = "future_snark")]
296 let kes_signature_for_snark;
297 if let Some(kes_signature) = bytes.get(bytes_index..bytes_index + Sum6KesSig::SIZE) {
298 kes_signature_for_concatenation = Some(
299 Sum6KesSig::from_bytes(kes_signature)
300 .map_err(|_| RegisterError::SerializationError)?,
301 );
302
303 #[cfg(feature = "future_snark")]
304 {
305 bytes_index += Sum6KesSig::SIZE;
306 kes_signature_for_snark = if let Some(snark_kes_signature) =
307 bytes.get(bytes_index..bytes_index + Sum6KesSig::SIZE)
308 {
309 let snark_kes_signature = Sum6KesSig::from_bytes(snark_kes_signature)
310 .map_err(|_| RegisterError::SerializationError)?;
311
312 Some(snark_kes_signature)
313 } else {
314 None
315 };
316 }
317 } else {
318 kes_signature_for_concatenation = None;
319 #[cfg(feature = "future_snark")]
320 {
321 kes_signature_for_snark = None;
322 }
323 }
324
325 Ok(Self {
326 stm_initializer,
327 kes_signature_for_concatenation,
328 #[cfg(feature = "future_snark")]
329 kes_signature_for_snark,
330 })
331 }
332}
333
334#[derive(Debug, Clone)]
339pub struct SignerRegistrationParameters {
340 pub party_id: Option<ProtocolPartyId>,
344
345 pub operational_certificate: Option<ProtocolOpCert>,
349
350 pub verification_key_for_concatenation: ProtocolSignerVerificationKeyForConcatenation,
352
353 pub verification_key_signature_for_concatenation:
357 Option<ProtocolSignerVerificationKeySignatureForConcatenation>,
358
359 pub kes_evolutions: Option<KesEvolutions>,
362
363 #[cfg(feature = "future_snark")]
365 pub verification_key_for_snark: Option<ProtocolSignerVerificationKeyForSnark>,
366
367 #[cfg(feature = "future_snark")]
369 pub verification_key_signature_for_snark:
370 Option<ProtocolSignerVerificationKeySignatureForSnark>,
371}
372
373#[derive(Debug, Clone)]
380pub struct KeyRegWrapper {
381 kes_verifier: Arc<dyn KesVerifier>,
382 stm_key_reg: KeyRegistration,
383 stake_distribution: HashMap<ProtocolPartyId, Stake>,
384}
385
386impl KeyRegWrapper {
387 pub fn init(stake_dist: &ProtocolStakeDistribution) -> Self {
390 Self {
391 kes_verifier: Arc::new(KesVerifierStandard),
392 stm_key_reg: KeyRegistration::initialize(),
393 stake_distribution: HashMap::from_iter(stake_dist.to_vec()),
394 }
395 }
396
397 fn verify_kes_signature(
401 &self,
402 message: &[u8],
403 kes_sig: Option<Sum6KesSig>,
404 opcert: &ProtocolOpCert,
405 kes_evolutions: KesEvolutions,
406 ) -> Result<(), ProtocolRegistrationErrorWrapper> {
407 let signature = kes_sig.ok_or(ProtocolRegistrationErrorWrapper::KesSignatureMissing)?;
408 self.kes_verifier
409 .verify(message, &signature, opcert, kes_evolutions)
410 .map_err(|e| {
411 ProtocolRegistrationErrorWrapper::KesSignatureInvalid(
412 kes_evolutions,
413 opcert.get_start_kes_period(),
414 e,
415 )
416 })
417 }
418
419 pub fn register(
426 &mut self,
427 parameters: SignerRegistrationParameters,
428 ) -> StdResult<ProtocolPartyId> {
429 let pool_id_bech32: ProtocolPartyId =
430 if let Some(opcert) = ¶meters.operational_certificate {
431 let kes_evolutions = parameters
432 .kes_evolutions
433 .ok_or(ProtocolRegistrationErrorWrapper::KesPeriodMissing)?;
434
435 self.verify_kes_signature(
436 ¶meters.verification_key_for_concatenation.to_bytes(),
437 parameters
438 .verification_key_signature_for_concatenation
439 .map(|s| s.into_inner()),
440 opcert,
441 kes_evolutions,
442 )
443 .with_context(|| "invalid KES signature for Concatenation")?;
444
445 #[cfg(feature = "future_snark")]
446 if let Some(verification_key_for_snark) = ¶meters.verification_key_for_snark {
447 self.verify_kes_signature(
448 &verification_key_for_snark.to_bytes(),
449 parameters
450 .verification_key_signature_for_snark
451 .map(|s| s.into_inner()),
452 opcert,
453 kes_evolutions,
454 )
455 .with_context(|| "invalid KES signature for SNARK")?;
456 }
457
458 opcert
459 .compute_protocol_party_id()
460 .map_err(|_| ProtocolRegistrationErrorWrapper::PoolAddressEncoding)?
461 } else {
462 if cfg!(not(feature = "allow_skip_signer_certification")) {
463 Err(ProtocolRegistrationErrorWrapper::OpCertMissing)?
464 }
465 parameters
466 .party_id
467 .ok_or(ProtocolRegistrationErrorWrapper::PartyIdMissing)?
468 };
469
470 if let Some(&stake) = self.stake_distribution.get(&pool_id_bech32) {
471 self.stm_key_reg.register(
472 stake,
473 ¶meters.verification_key_for_concatenation.into(),
474 #[cfg(feature = "future_snark")]
475 parameters.verification_key_for_snark.map(|k| k.into()),
476 )?;
477 return Ok(pool_id_bech32);
478 }
479 Err(anyhow!(
480 ProtocolRegistrationErrorWrapper::PartyIdNonExisting
481 ))
482 }
483
484 pub fn close(self, protocol_params: &ProtocolParameters) -> StdResult<ClosedKeyRegistration> {
487 self.stm_key_reg.close_registration(protocol_params)
488 }
489}
490
491mod test_extensions {
492 use crate::test::crypto_helper::ProtocolInitializerTestExtension;
493
494 use super::*;
495
496 impl ProtocolInitializerTestExtension for StmInitializerWrapper {
497 fn override_protocol_parameters(&mut self, protocol_parameters: &ProtocolParameters) {
498 self.stm_initializer.parameters = protocol_parameters.to_owned();
499 }
500 }
501}
502
503#[cfg(test)]
504mod test {
505 use crate::crypto_helper::cardano::kes::KesSignerStandard;
506 use crate::crypto_helper::{OpCert, SerDeShelleyFileFormat};
507 use crate::test::crypto_helper::{
508 KesCryptographicMaterialForTest, KesPartyIndexForTest, create_kes_cryptographic_material,
509 };
510
511 use rand_chacha::ChaCha20Rng;
512 use rand_core::SeedableRng;
513
514 use super::*;
515
516 #[test]
517 fn test_vector_key_reg() {
518 let params = Parameters {
519 m: 5,
520 k: 5,
521 phi_f: 1.0,
522 };
523 let mut rng = ChaCha20Rng::from_seed([0u8; 32]);
524 let KesCryptographicMaterialForTest {
525 party_id: party_id_1,
526 operational_certificate_file: operational_certificate_file_1,
527 kes_secret_key_file: kes_secret_key_file_1,
528 } = create_kes_cryptographic_material(
529 1 as KesPartyIndexForTest,
530 KesPeriod(0),
531 "test_vector_key_reg",
532 );
533 let KesCryptographicMaterialForTest {
534 party_id: party_id_2,
535 operational_certificate_file: operational_certificate_file_2,
536 kes_secret_key_file: kes_secret_key_file_2,
537 } = create_kes_cryptographic_material(
538 2 as KesPartyIndexForTest,
539 KesPeriod(0),
540 "test_vector_key_reg",
541 );
542
543 let mut key_reg = KeyRegWrapper::init(&vec![(party_id_1, 10), (party_id_2, 3)]);
544
545 let initializer_1 = StmInitializerWrapper::setup(
546 params,
547 Some(Arc::new(KesSignerStandard::new(
548 kes_secret_key_file_1,
549 operational_certificate_file_1.clone(),
550 ))),
551 Some(KesPeriod(0)),
552 10,
553 &mut rng,
554 )
555 .unwrap();
556
557 let opcert1 = OpCert::from_file(operational_certificate_file_1)
558 .expect("opcert deserialization should not fail")
559 .into();
560
561 let key_registration_1 = key_reg.register(SignerRegistrationParameters {
562 party_id: None,
563 operational_certificate: Some(opcert1),
564 verification_key_signature_for_concatenation: initializer_1
565 .verification_key_signature_for_concatenation(),
566 kes_evolutions: Some(KesEvolutions(0)),
567 verification_key_for_concatenation: initializer_1
568 .stm_initializer
569 .get_verification_key_proof_of_possession_for_concatenation()
570 .into(),
571 #[cfg(feature = "future_snark")]
572 verification_key_for_snark: initializer_1.verification_key_for_snark().map(Into::into),
573 #[cfg(feature = "future_snark")]
574 verification_key_signature_for_snark: initializer_1
575 .verification_key_signature_for_snark(),
576 });
577 assert!(key_registration_1.is_ok());
578
579 let initializer_2 = StmInitializerWrapper::setup(
580 params,
581 Some(Arc::new(KesSignerStandard::new(
582 kes_secret_key_file_2,
583 operational_certificate_file_2.clone(),
584 ))),
585 Some(KesPeriod(0)),
586 10,
587 &mut rng,
588 )
589 .unwrap();
590
591 let opcert2 = OpCert::from_file(operational_certificate_file_2)
592 .expect("opcert deserialization should not fail")
593 .into();
594
595 let key_registration_2 = key_reg.register(SignerRegistrationParameters {
596 party_id: None,
597 operational_certificate: Some(opcert2),
598 verification_key_signature_for_concatenation: initializer_2
599 .verification_key_signature_for_concatenation(),
600 kes_evolutions: Some(KesEvolutions(0)),
601 verification_key_for_concatenation: initializer_2
602 .stm_initializer
603 .get_verification_key_proof_of_possession_for_concatenation()
604 .into(),
605 #[cfg(feature = "future_snark")]
606 verification_key_for_snark: initializer_2.verification_key_for_snark().map(Into::into),
607 #[cfg(feature = "future_snark")]
608 verification_key_signature_for_snark: initializer_2
609 .verification_key_signature_for_snark(),
610 });
611 assert!(key_registration_2.is_ok())
612 }
613
614 const GOLDEN_STM_INITIALIZER_WRAPPER_JSON: &str = r#"
615 {
616 "stm_initializer": {
617 "stake": 9497432569,
618 "params": {
619 "m": 20973,
620 "k": 2422,
621 "phi_f": 0.2
622 },
623 "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],
624 "pk": {
625 "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],
626 "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]
627 }
628 },
629 "kes_signature": {
630 "sigma": {
631 "sigma": {
632 "sigma": {
633 "sigma": {
634 "sigma": {
635 "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],
636 "lhs_pk": [
637 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],
638 "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]
639 },
640 "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],
641 "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]
642 },
643 "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],
644 "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]
645 },
646 "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],
647 "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]
648 },
649 "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],
650 "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]
651 },
652 "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],
653 "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]
654 }
655 }
656 "#;
657
658 #[test]
659 fn golden_initializer_deserialization() {
660 let _: StmInitializerWrapper = serde_json::from_str(GOLDEN_STM_INITIALIZER_WRAPPER_JSON)
661 .expect("Deserializing a StmInitializerWrapper should not fail");
662 }
663
664 #[test]
665 fn test_initializer_wrapper_conversions() {
666 let stm_initializer_wrapper_json = GOLDEN_STM_INITIALIZER_WRAPPER_JSON;
667
668 let stm_initializer_wrapper_from_json: StmInitializerWrapper =
669 serde_json::from_str(stm_initializer_wrapper_json)
670 .expect("Deserializing a StmInitializerWrapper should not fail");
671 let stm_initializer_wrapper_from_json_to_json =
672 serde_json::to_string(&stm_initializer_wrapper_from_json)
673 .expect("Serializing a StmInitializerWrapper to json should not fail");
674
675 let stm_initializer_wrapper_bytes = stm_initializer_wrapper_from_json
676 .to_bytes()
677 .expect("Serializing a StmInitializerWrapper to bytes should not fail");
678 let stm_initializer_wrapper_from_bytes =
679 StmInitializerWrapper::from_bytes(&stm_initializer_wrapper_bytes)
680 .expect("Deserializing a StmInitializerWrapper from bytes should not fail");
681 let stm_initializer_wrapper_from_bytes_to_json =
682 serde_json::to_string(&stm_initializer_wrapper_from_bytes)
683 .expect("Serializing a StmInitializerWrapper to json should not fail");
684
685 assert_eq!(
686 stm_initializer_wrapper_from_json_to_json,
687 stm_initializer_wrapper_from_bytes_to_json
688 );
689
690 let mut stm_initializer_wrapper_from_json = stm_initializer_wrapper_from_json;
691 stm_initializer_wrapper_from_json.kes_signature_for_concatenation = None;
692
693 let stm_initializer_wrapper_bytes = stm_initializer_wrapper_from_json
694 .to_bytes()
695 .expect("Serializing a StmInitializerWrapper to bytes should not fail");
696 let stm_initializer_wrapper_from_bytes =
697 StmInitializerWrapper::from_bytes(&stm_initializer_wrapper_bytes)
698 .expect("Deserializing a StmInitializerWrapper from bytes should not fail");
699 assert_eq!(
700 None,
701 stm_initializer_wrapper_from_bytes.kes_signature_for_concatenation
702 );
703 }
704}