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 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
26pub struct MessageBuilder {
28 #[cfg(feature = "fs")]
29 immutable_digester: Option<Arc<dyn ImmutableDigester>>,
30 logger: Logger,
31}
32
33impl MessageBuilder {
34 pub fn new() -> MessageBuilder {
36 let logger = Logger::root(slog::Discard, o!());
37 Self {
38 #[cfg(feature = "fs")]
39 immutable_digester: None,
40 logger,
41 }
42 }
43
44 pub fn with_logger(mut self, logger: Logger) -> Self {
46 self.logger = logger.new_with_component_name::<Self>();
47 self
48 }
49
50 cfg_fs! {
51 fn get_immutable_digester(&self, network: &str) -> Arc<dyn ImmutableDigester> {
52 match self.immutable_digester.as_ref() {
53 None => Arc::new(CardanoImmutableDigester::new(network.to_owned(),None, self.logger.clone())),
54 Some(digester) => digester.clone(),
55 }
56 }
57
58 pub fn with_immutable_digester(
62 mut self,
63 immutable_digester: Arc<dyn ImmutableDigester>,
64 ) -> Self {
65 self.immutable_digester = Some(immutable_digester);
66 self
67 }
68
69 pub async fn compute_snapshot_message(
73 &self,
74 snapshot_certificate: &MithrilCertificate,
75 unpacked_snapshot_directory: &Path,
76 ) -> MithrilResult<ProtocolMessage> {
77 let digester = self.get_immutable_digester(&snapshot_certificate.metadata.network);
78 let beacon =
79 match &snapshot_certificate.signed_entity_type {
80 SignedEntityType::CardanoImmutableFilesFull(beacon) => {Ok(beacon)},
81 other => {
82 Err(anyhow::anyhow!(
83 "Can't compute message: Given certificate `{}` does not certify a snapshot, certificate signed entity: {:?}",
84 snapshot_certificate.hash,
85 other
86 )
87 )},
88 }?;
89
90 let mut message = snapshot_certificate.protocol_message.clone();
91
92 let digest = digester
93 .compute_digest(unpacked_snapshot_directory, &beacon.clone())
94 .await
95 .with_context(|| {
96 format!(
97 "Snapshot digest computation failed: unpacked_dir: '{}'",
98 unpacked_snapshot_directory.display()
99 )
100 })?;
101 message.set_message_part(ProtocolMessagePartKey::SnapshotDigest, digest);
102
103 Ok(message)
104 }
105
106 pub async fn compute_cardano_database_message(
108 &self,
109 certificate: &MithrilCertificate,
110 merkle_proof: &MKProof,
111 ) -> MithrilResult<ProtocolMessage> {
112 let mut message = certificate.protocol_message.clone();
113 message.set_message_part(
114 ProtocolMessagePartKey::CardanoDatabaseMerkleRoot,
115 merkle_proof.root().to_hex(),
116 );
117 Ok(message)
118 }
119 }
120
121 pub fn compute_mithril_stake_distribution_message(
123 &self,
124 certificate: &MithrilCertificate,
125 mithril_stake_distribution: &MithrilStakeDistribution,
126 ) -> MithrilResult<ProtocolMessage> {
127 let signers =
128 MithrilSigner::try_into_signers(mithril_stake_distribution.signers_with_stake.clone())
129 .with_context(|| "Could not compute message: conversion failure")?;
130
131 let signer_builder =
132 SignerBuilder::new(&signers, &mithril_stake_distribution.protocol_parameters)
133 .with_context(
134 || "Could not compute message: aggregate verification key computation failed",
135 )?;
136
137 let avk = signer_builder
138 .compute_aggregate_verification_key()
139 .to_json_hex()
140 .with_context(
141 || "Could not compute message: aggregate verification key encoding failed",
142 )?;
143
144 let mut message = certificate.protocol_message.clone();
145 message.set_message_part(ProtocolMessagePartKey::NextAggregateVerificationKey, avk);
146
147 Ok(message)
148 }
149
150 pub fn compute_cardano_transactions_proofs_message(
152 &self,
153 transactions_proofs_certificate: &MithrilCertificate,
154 verified_transactions: &VerifiedCardanoTransactions,
155 ) -> ProtocolMessage {
156 let mut message = transactions_proofs_certificate.protocol_message.clone();
157 verified_transactions.fill_protocol_message(&mut message);
158 message
159 }
160
161 pub fn compute_cardano_stake_distribution_message(
163 &self,
164 certificate: &MithrilCertificate,
165 cardano_stake_distribution: &CardanoStakeDistribution,
166 ) -> MithrilResult<ProtocolMessage> {
167 let mk_tree =
168 CardanoStakeDistributionSignableBuilder::compute_merkle_tree_from_stake_distribution(
169 cardano_stake_distribution.stake_distribution.clone(),
170 )?;
171
172 let mut message = certificate.protocol_message.clone();
173 message.set_message_part(
174 ProtocolMessagePartKey::CardanoStakeDistributionEpoch,
175 cardano_stake_distribution.epoch.to_string(),
176 );
177 message.set_message_part(
178 ProtocolMessagePartKey::CardanoStakeDistributionMerkleRoot,
179 mk_tree.compute_root()?.to_hex(),
180 );
181
182 Ok(message)
183 }
184}
185
186impl Default for MessageBuilder {
187 fn default() -> Self {
188 Self::new()
189 }
190}