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