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