mithril_common/certificate_chain/
certificate_genesis.rs1use std::sync::Arc;
4
5use chrono::prelude::*;
6use thiserror::Error;
7
8use crate::{
9 StdResult,
10 crypto_helper::{
11 PROTOCOL_VERSION, ProtocolAggregateVerificationKey, ProtocolGenesisSignature,
12 ProtocolGenesisSigner, ProtocolKey,
13 },
14 entities::{
15 Certificate, CertificateMetadata, CertificateSignature, Epoch, ProtocolMessage,
16 ProtocolMessagePartKey, ProtocolParameters,
17 },
18 protocol::ToMessage,
19};
20
21#[derive(Error, Debug)]
23pub enum CertificateGenesisProducerError {
24 #[error("missing genesis signer error")]
26 MissingGenesisSigner(),
27}
28
29#[derive(Debug)]
31pub struct CertificateGenesisProducer {
32 genesis_signer: Option<Arc<ProtocolGenesisSigner>>,
33}
34
35impl CertificateGenesisProducer {
36 pub fn new(genesis_signer: Option<Arc<ProtocolGenesisSigner>>) -> Self {
38 Self { genesis_signer }
39 }
40
41 pub fn create_genesis_protocol_message(
43 genesis_protocol_parameters: &ProtocolParameters,
44 genesis_avk: &ProtocolAggregateVerificationKey,
45 genesis_epoch: &Epoch,
46 ) -> StdResult<ProtocolMessage> {
47 let genesis_aggregate_verification_key_for_concatenation =
48 ProtocolKey::new(genesis_avk.to_concatenation_aggregate_verification_key().to_owned());
49 let genesis_avk = genesis_aggregate_verification_key_for_concatenation.to_json_hex()?;
50 let mut protocol_message = ProtocolMessage::new();
51 protocol_message.set_message_part(
52 ProtocolMessagePartKey::NextAggregateVerificationKey,
53 genesis_avk,
54 );
55 protocol_message.set_message_part(
56 ProtocolMessagePartKey::NextProtocolParameters,
57 genesis_protocol_parameters.compute_hash(),
58 );
59 protocol_message.set_message_part(
60 ProtocolMessagePartKey::CurrentEpoch,
61 genesis_epoch.to_string(),
62 );
63 Ok(protocol_message)
64 }
65
66 pub fn sign_genesis_protocol_message<T: ToMessage>(
68 &self,
69 genesis_message: T,
70 ) -> Result<ProtocolGenesisSignature, CertificateGenesisProducerError> {
71 Ok(self
72 .genesis_signer
73 .as_ref()
74 .ok_or_else(CertificateGenesisProducerError::MissingGenesisSigner)?
75 .sign(genesis_message.to_message().as_bytes()))
76 }
77
78 pub fn create_genesis_certificate<T: Into<String>>(
80 protocol_parameters: ProtocolParameters,
81 network: T,
82 epoch: Epoch,
83 genesis_avk: ProtocolAggregateVerificationKey,
84 genesis_signature: ProtocolGenesisSignature,
85 ) -> StdResult<Certificate> {
86 let protocol_version = PROTOCOL_VERSION.to_string();
87 let initiated_at = Utc::now();
88 let sealed_at = Utc::now();
89 let signers = vec![];
90 let metadata = CertificateMetadata::new(
91 network,
92 protocol_version,
93 protocol_parameters.clone(),
94 initiated_at,
95 sealed_at,
96 signers,
97 );
98 let previous_hash = "".to_string();
99 let genesis_protocol_message =
100 Self::create_genesis_protocol_message(&protocol_parameters, &genesis_avk, &epoch)?;
101 Ok(Certificate::new(
102 previous_hash,
103 epoch,
104 metadata,
105 genesis_protocol_message,
106 genesis_avk,
107 CertificateSignature::GenesisSignature(genesis_signature),
108 ))
109 }
110}
111
112#[cfg(test)]
113mod tests {
114 use super::*;
115
116 use crate::{entities::ProtocolMessagePartKey, test::builder::MithrilFixtureBuilder};
117
118 #[test]
119 fn test_create_genesis_protocol_message_has_expected_keys_and_values() {
120 let fixture = MithrilFixtureBuilder::default().with_signers(5).build();
121 let genesis_protocol_parameters = fixture.protocol_parameters();
122 let genesis_avk = fixture.compute_aggregate_verification_key();
123 let genesis_epoch = Epoch(123);
124 let protocol_message = CertificateGenesisProducer::create_genesis_protocol_message(
125 &genesis_protocol_parameters,
126 &genesis_avk,
127 &genesis_epoch,
128 )
129 .unwrap();
130
131 let expected_genesis_avk_value =
132 fixture.compute_and_encode_concatenation_aggregate_verification_key();
133 assert_eq!(
134 protocol_message
135 .get_message_part(&ProtocolMessagePartKey::NextAggregateVerificationKey),
136 Some(&expected_genesis_avk_value)
137 );
138
139 let expected_genesis_protocol_parameters_value = genesis_protocol_parameters.compute_hash();
140 assert_eq!(
141 protocol_message.get_message_part(&ProtocolMessagePartKey::NextProtocolParameters),
142 Some(&expected_genesis_protocol_parameters_value)
143 );
144
145 let expected_genesis_epoch = genesis_epoch.to_string();
146 assert_eq!(
147 protocol_message.get_message_part(&ProtocolMessagePartKey::CurrentEpoch),
148 Some(&expected_genesis_epoch)
149 );
150 }
151}