mithril_client/
message.rs1use anyhow::Context;
2use slog::{Logger, o};
3#[cfg(feature = "fs")]
4use std::{path::Path, sync::Arc};
5
6#[cfg(feature = "fs")]
7use mithril_cardano_node_internal_database::digesters::{
8 CardanoImmutableDigester, ImmutableDigester,
9};
10#[cfg(feature = "fs")]
11use mithril_common::entities::SignedEntityType;
12use mithril_common::{
13 crypto_helper::ProtocolKey, logging::LoggerExtensions, protocol::SignerBuilder,
14 signable_builder::CardanoStakeDistributionSignableBuilder,
15};
16
17#[cfg(feature = "fs")]
18use mithril_common::crypto_helper::MKProof;
19
20use crate::{
21 CardanoStakeDistribution, MithrilCertificate, MithrilResult, MithrilSigner,
22 MithrilStakeDistribution, VerifiedCardanoTransactions,
23 common::{ProtocolMessage, ProtocolMessagePartKey},
24};
25
26#[cfg(feature = "unstable")]
27use crate::{VerifiedCardanoBlocks, VerifiedCardanoTransactionsV2};
28
29pub struct MessageBuilder {
31 #[cfg(feature = "fs")]
32 immutable_digester: Option<Arc<dyn ImmutableDigester>>,
33 logger: Logger,
34}
35
36impl MessageBuilder {
37 pub fn new() -> MessageBuilder {
39 let logger = Logger::root(slog::Discard, o!());
40 Self {
41 #[cfg(feature = "fs")]
42 immutable_digester: None,
43 logger,
44 }
45 }
46
47 pub fn with_logger(mut self, logger: Logger) -> Self {
49 self.logger = logger.new_with_component_name::<Self>();
50 self
51 }
52
53 cfg_fs! {
54 fn get_immutable_digester(&self, network: &str) -> Arc<dyn ImmutableDigester> {
55 match self.immutable_digester.as_ref() {
56 None => Arc::new(CardanoImmutableDigester::new(network.to_owned(),None, self.logger.clone())),
57 Some(digester) => digester.clone(),
58 }
59 }
60
61 pub fn with_immutable_digester(
65 mut self,
66 immutable_digester: Arc<dyn ImmutableDigester>,
67 ) -> Self {
68 self.immutable_digester = Some(immutable_digester);
69 self
70 }
71
72 pub async fn compute_snapshot_message(
76 &self,
77 snapshot_certificate: &MithrilCertificate,
78 unpacked_snapshot_directory: &Path,
79 ) -> MithrilResult<ProtocolMessage> {
80 let digester = self.get_immutable_digester(&snapshot_certificate.metadata.network);
81 let beacon =
82 match &snapshot_certificate.signed_entity_type {
83 SignedEntityType::CardanoImmutableFilesFull(beacon) => {Ok(beacon)},
84 other => {
85 Err(anyhow::anyhow!(
86 "Can't compute message: Given certificate `{}` does not certify a snapshot, certificate signed entity: {:?}",
87 snapshot_certificate.hash,
88 other
89 )
90 )},
91 }?;
92
93 let mut message = snapshot_certificate.protocol_message.clone();
94
95 let digest = digester
96 .compute_digest(unpacked_snapshot_directory, &beacon.clone())
97 .await
98 .with_context(|| {
99 format!(
100 "Snapshot digest computation failed: unpacked_dir: '{}'",
101 unpacked_snapshot_directory.display()
102 )
103 })?;
104 message.set_message_part(ProtocolMessagePartKey::SnapshotDigest, digest);
105
106 Ok(message)
107 }
108
109 pub async fn compute_cardano_database_message(
111 &self,
112 certificate: &MithrilCertificate,
113 merkle_proof: &MKProof,
114 ) -> MithrilResult<ProtocolMessage> {
115 let mut message = certificate.protocol_message.clone();
116 message.set_message_part(
117 ProtocolMessagePartKey::CardanoDatabaseMerkleRoot,
118 merkle_proof.root().to_hex(),
119 );
120 Ok(message)
121 }
122 }
123
124 pub fn compute_mithril_stake_distribution_message(
126 &self,
127 certificate: &MithrilCertificate,
128 mithril_stake_distribution: &MithrilStakeDistribution,
129 ) -> MithrilResult<ProtocolMessage> {
130 let signers =
131 MithrilSigner::try_into_signers(mithril_stake_distribution.signers_with_stake.clone())
132 .with_context(|| "Could not compute message: conversion failure")?;
133
134 let signer_builder =
135 SignerBuilder::new(&signers, &mithril_stake_distribution.protocol_parameters)
136 .with_context(
137 || "Could not compute message: aggregate verification key computation failed",
138 )?;
139
140 let aggregate_verification_key = signer_builder.compute_aggregate_verification_key();
141
142 let avk = ProtocolKey::new(
143 aggregate_verification_key
144 .to_concatenation_aggregate_verification_key()
145 .to_owned(),
146 )
147 .to_json_hex()
148 .with_context(|| "Could not compute message: aggregate verification key encoding failed")?;
149
150 let mut message = certificate.protocol_message.clone();
151 message.set_message_part(ProtocolMessagePartKey::NextAggregateVerificationKey, avk);
152
153 #[cfg(feature = "future_snark")]
154 if certificate
155 .protocol_message
156 .get_message_part(&ProtocolMessagePartKey::NextSnarkAggregateVerificationKey)
157 .is_some()
158 {
159 let snark_avk = aggregate_verification_key
160 .to_snark_aggregate_verification_key()
161 .ok_or_else(|| {
162 anyhow::anyhow!(
163 "Could not compute message: SNARK aggregate verification key is unavailable"
164 )
165 })?;
166 let snark_avk_encoded = ProtocolKey::new(snark_avk.to_owned())
167 .to_bytes_hex()
168 .with_context(|| {
169 "Could not compute message: SNARK aggregate verification key encoding failed"
170 })?;
171 message.set_message_part(
172 ProtocolMessagePartKey::NextSnarkAggregateVerificationKey,
173 snark_avk_encoded,
174 );
175 }
176
177 Ok(message)
178 }
179
180 pub fn compute_cardano_transactions_proofs_message(
182 &self,
183 transactions_proofs_certificate: &MithrilCertificate,
184 verified_transactions: &VerifiedCardanoTransactions,
185 ) -> ProtocolMessage {
186 let mut message = transactions_proofs_certificate.protocol_message.clone();
187 verified_transactions.fill_protocol_message(&mut message);
188 message
189 }
190
191 cfg_unstable! {
192 pub fn compute_cardano_blocks_proofs_message(
194 &self,
195 blocks_proofs_certificate: &MithrilCertificate,
196 verified_blocks: &VerifiedCardanoBlocks,
197 ) -> ProtocolMessage {
198 let mut message = blocks_proofs_certificate.protocol_message.clone();
199 message.set_message_part(
200 ProtocolMessagePartKey::CardanoBlocksTransactionsMerkleRoot,
201 verified_blocks.certified_merkle_root().to_string(),
202 );
203 message.set_message_part(
204 ProtocolMessagePartKey::LatestBlockNumber,
205 verified_blocks.latest_certified_block_number().to_string(),
206 );
207 message.set_message_part(
208 ProtocolMessagePartKey::CardanoBlocksTransactionsBlockNumberOffset,
209 verified_blocks.security_parameter().to_string(),
210 );
211 message
212 }
213
214 pub fn compute_cardano_transactions_proofs_v2_message(
216 &self,
217 transactions_proofs_certificate: &MithrilCertificate,
218 verified_transactions: &VerifiedCardanoTransactionsV2,
219 ) -> ProtocolMessage {
220 let mut message = transactions_proofs_certificate.protocol_message.clone();
221 message.set_message_part(
222 ProtocolMessagePartKey::CardanoBlocksTransactionsMerkleRoot,
223 verified_transactions.certified_merkle_root().to_string(),
224 );
225 message.set_message_part(
226 ProtocolMessagePartKey::LatestBlockNumber,
227 verified_transactions.latest_certified_block_number().to_string(),
228 );
229 message.set_message_part(
230 ProtocolMessagePartKey::CardanoBlocksTransactionsBlockNumberOffset,
231 verified_transactions.security_parameter().to_string(),
232 );
233 message
234 }
235 }
236
237 pub fn compute_cardano_stake_distribution_message(
239 &self,
240 certificate: &MithrilCertificate,
241 cardano_stake_distribution: &CardanoStakeDistribution,
242 ) -> MithrilResult<ProtocolMessage> {
243 let mk_tree =
244 CardanoStakeDistributionSignableBuilder::compute_merkle_tree_from_stake_distribution(
245 cardano_stake_distribution.stake_distribution.clone(),
246 )?;
247
248 let mut message = certificate.protocol_message.clone();
249 message.set_message_part(
250 ProtocolMessagePartKey::CardanoStakeDistributionEpoch,
251 cardano_stake_distribution.epoch.to_string(),
252 );
253 message.set_message_part(
254 ProtocolMessagePartKey::CardanoStakeDistributionMerkleRoot,
255 mk_tree.compute_root()?.to_hex(),
256 );
257
258 Ok(message)
259 }
260}
261
262impl Default for MessageBuilder {
263 fn default() -> Self {
264 Self::new()
265 }
266}