Skip to content

Commit ad5d80a

Browse files
committed
feature(aggregator): implement export protocol configurations command
1 parent 8edb186 commit ad5d80a

3 files changed

Lines changed: 191 additions & 59 deletions

File tree

mithril-aggregator/src/commands/protocol_configuration_command.rs

Lines changed: 187 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use config::{ConfigBuilder, Map, Value, builder::DefaultState};
44
use serde::{Deserialize, Serialize};
55
use slog::{Logger, debug};
66
use std::{
7-
collections::{BTreeSet, HashMap},
7+
collections::{BTreeMap, BTreeSet, HashMap},
88
fs::{self, File},
99
io::Write,
1010
path::PathBuf,
@@ -14,19 +14,23 @@ use thiserror::Error;
1414

1515
use mithril_cardano_node_chain::chain_observer::ChainObserverType;
1616
use mithril_cli_helper::serde_deserialization;
17-
use mithril_common::entities::{
18-
CardanoBlocksTransactionsSigningConfig, CardanoTransactionsSigningConfig, Epoch,
19-
HexEncodedProtocolConfigurationMarkersSecretKey, ProtocolParameters,
20-
SignedEntityTypeDiscriminants::{self, CardanoBlocksTransactions},
21-
};
22-
use mithril_common::{StdResult, messages::SignedEntityTypeDiscriminantsMessage};
2317
use mithril_common::{
18+
StdResult,
2419
crypto_helper::{
2520
ProtocolConfigurationMarkersSigner, ProtocolConfigurationMarkersVerifierSecretKey,
2621
},
27-
entities::SignedEntityTypeDiscriminants::CardanoTransactions,
22+
entities::{
23+
BlockNumber, BlockNumberOffset, CardanoBlocksTransactionsSigningConfig,
24+
CardanoTransactionsSigningConfig, Epoch, HexEncodedProtocolConfigurationMarkersSecretKey,
25+
ProtocolParameters,
26+
SignedEntityTypeDiscriminants::{self, CardanoBlocksTransactions, CardanoTransactions},
27+
},
28+
messages::SignedEntityTypeDiscriminantsMessage,
2829
};
2930
use mithril_doc::{Documenter, StructDoc};
31+
use mithril_protocol_config::model::{
32+
ConfigurationComputerFromMarkers, ProtocolConfigurationForEpoch,
33+
};
3034

3135
use crate::{
3236
ConfigurationSource, ExecutionEnvironment,
@@ -86,7 +90,7 @@ impl ConfigurationSource for ProtocolConfigurationParametersConfiguration {
8690
}
8791
}
8892

89-
#[derive(Serialize, Deserialize, Clone)]
93+
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
9094
pub struct HumanReadableProtocolConfiguration {
9195
pub epoch: Epoch,
9296
pub protocol_parameters: ProtocolParameters,
@@ -177,6 +181,50 @@ impl ExportProtocolConfigurationSubCommand {
177181
root_logger: Logger,
178182
config_builder: ConfigBuilder<DefaultState>,
179183
) -> StdResult<()> {
184+
// 0 conf & dependencies
185+
let config: ProtocolConfigurationParametersConfiguration = config_builder
186+
.build()
187+
.with_context(|| "configuration build error")?
188+
.try_deserialize()
189+
.with_context(|| "configuration deserialize error")?;
190+
debug!(root_logger, "EXPORT PROTOCOL CONFIGURATION command"; "config" => format!("{config:?}"));
191+
192+
let mut dependencies_builder =
193+
DependenciesBuilder::new(root_logger.clone(), Arc::new(config.clone()));
194+
195+
let dependencies = dependencies_builder
196+
.create_protocol_configuration_container()
197+
.await
198+
.with_context(
199+
|| "Dependencies Builder can not create protocol configuration command dependencies container",
200+
)?;
201+
202+
let tools = ProtocolConfigurationTools::from_dependencies(dependencies)
203+
.await
204+
.with_context(|| "protocol-configuration-tools: initialization error")?;
205+
206+
//1: Retrieve markers from chain or fallback to default configuration
207+
let on_chain_configurations = tools.get_on_chain_configurations();
208+
let protocol_configurations_markers = if on_chain_configurations.markers.is_empty() {
209+
get_default_protocol_configurations()
210+
} else {
211+
on_chain_configurations
212+
};
213+
214+
//2: transform to human readable
215+
let protocol_configurations =
216+
to_vec_human_readable_protocol_configuration(protocol_configurations_markers);
217+
218+
//3: write human readable configurations file
219+
println!("Generating JSON protocol configurations output file...");
220+
let json_protocol_configurations = serde_json::to_string(&protocol_configurations)?;
221+
let mut target_file = File::create(&self.target_path)?;
222+
target_file.write_all(json_protocol_configurations.as_bytes())?;
223+
224+
println!(
225+
"Sucessfuly wrote JSON protocol configurations file at {}",
226+
self.target_path.to_string_lossy()
227+
);
180228
Ok(())
181229
}
182230

@@ -185,6 +233,30 @@ impl ExportProtocolConfigurationSubCommand {
185233
}
186234
}
187235

236+
pub fn get_default_protocol_configurations() -> ConfigurationComputerFromMarkers {
237+
ConfigurationComputerFromMarkers {
238+
markers: BTreeMap::from([(
239+
Epoch(42),
240+
ProtocolConfigurationForEpoch {
241+
protocol_parameters: ProtocolParameters {
242+
k: 1,
243+
m: 2,
244+
phi_f: 0.3,
245+
},
246+
enabled_signed_entity_types: SignedEntityTypeDiscriminants::all(),
247+
cardano_transactions: Some(CardanoTransactionsSigningConfig {
248+
security_parameter: BlockNumberOffset(10),
249+
step: BlockNumber(11),
250+
}),
251+
cardano_blocks_transactions: Some(CardanoBlocksTransactionsSigningConfig {
252+
security_parameter: BlockNumberOffset(20),
253+
step: BlockNumber(22),
254+
}),
255+
},
256+
)]),
257+
}
258+
}
259+
188260
/// Protocol configuration import command
189261
#[derive(Parser, Debug, Clone)]
190262
pub struct ImportProtocolConfigurationSubCommand {
@@ -213,7 +285,7 @@ impl ImportProtocolConfigurationSubCommand {
213285
.with_context(|| "configuration build error")?
214286
.try_deserialize()
215287
.with_context(|| "configuration deserialize error")?;
216-
debug!(root_logger, "EXPORT PROTOCOL CONFIGURATION command"; "config" => format!("{config:?}"));
288+
debug!(root_logger, "IMPORT PROTOCOL CONFIGURATION command"; "config" => format!("{config:?}"));
217289

218290
let mut dependencies_builder =
219291
DependenciesBuilder::new(root_logger.clone(), Arc::new(config.clone()));
@@ -228,7 +300,7 @@ impl ImportProtocolConfigurationSubCommand {
228300
//1 - Read the protocol configurations from the file
229301
println!(
230302
"Reading file content {}",
231-
&self.import_path.to_string_lossy()
303+
self.import_path.to_string_lossy()
232304
);
233305
let json_protocol_configurations = fs::read_to_string(&self.import_path);
234306

@@ -268,8 +340,8 @@ impl ImportProtocolConfigurationSubCommand {
268340
target_file.write_all(tx_datum.as_bytes())?;
269341

270342
println!(
271-
"Sucessfuly write Tx datum file at {}",
272-
&self.target_path.to_string_lossy()
343+
"Sucessfuly wrote Tx datum file at {}",
344+
self.target_path.to_string_lossy()
273345
);
274346

275347
Ok(())
@@ -332,9 +404,43 @@ impl ImportProtocolConfigurationSubCommand {
332404
}
333405
}
334406

407+
fn to_human_readable_protocol_configuration(
408+
epoch: Epoch,
409+
config: ProtocolConfigurationForEpoch,
410+
) -> HumanReadableProtocolConfiguration {
411+
HumanReadableProtocolConfiguration {
412+
epoch,
413+
protocol_parameters: config.protocol_parameters,
414+
enabled_signed_entity_types: config
415+
.enabled_signed_entity_types
416+
.into_iter()
417+
.map(Into::into)
418+
.collect(),
419+
cardano_transaction_signing_config: config.cardano_transactions,
420+
cardano_blocks_transactions_signing_config: config.cardano_blocks_transactions,
421+
}
422+
}
423+
424+
pub fn to_vec_human_readable_protocol_configuration(
425+
configs: ConfigurationComputerFromMarkers,
426+
) -> Vec<HumanReadableProtocolConfiguration> {
427+
let mut human_readable_protocol_configurations = Vec::new();
428+
for (epoch, config) in configs.markers {
429+
human_readable_protocol_configurations
430+
.push(to_human_readable_protocol_configuration(epoch, config));
431+
}
432+
human_readable_protocol_configurations
433+
}
434+
335435
#[cfg(test)]
336436
mod tests {
337-
use mithril_common::{entities::ProtocolParameters, test::double::Dummy};
437+
use mithril_common::{
438+
entities::{
439+
BlockNumber, BlockNumberOffset, ProtocolParameters,
440+
SignedEntityTypeDiscriminants::{CardanoDatabase, MithrilStakeDistribution},
441+
},
442+
test::double::Dummy,
443+
};
338444

339445
use super::*;
340446

@@ -404,6 +510,16 @@ mod tests {
404510
}
405511
}
406512

513+
#[test]
514+
fn export_subcommand_parses_flag() {
515+
ExportProtocolConfigurationSubCommand::try_parse_from([
516+
"export-markers",
517+
"--target-path",
518+
"human_readable_protocol_configuration.json",
519+
])
520+
.expect("CLI parse should succeed");
521+
}
522+
407523
#[test]
408524
fn import_subcommand_parses_flag() {
409525
let signer_secret_key = ProtocolConfigurationMarkersSigner::create_deterministic_signer()
@@ -414,12 +530,67 @@ mod tests {
414530
ImportProtocolConfigurationSubCommand::try_parse_from([
415531
"import-markers",
416532
"--import-path",
417-
"tests/human_readable_protocol_configuration_toto.json",
533+
"human_readable_protocol_configuration.json",
418534
"--target-path",
419-
"/tests/protocol_configuration_tx_datum",
535+
"protocol_configuration_tx_datum.json",
420536
"--protocol-configuration-markers-secret-key",
421537
&signer_secret_key,
422538
])
423539
.expect("CLI parse should succeed");
424540
}
541+
542+
#[test]
543+
fn to_vec_human_readable_protocol_configuration_converts_markers_to_human_readable_list() {
544+
let configuration = ProtocolConfigurationForEpoch {
545+
protocol_parameters: ProtocolParameters {
546+
k: 9,
547+
m: 77,
548+
phi_f: 0.5,
549+
},
550+
enabled_signed_entity_types: BTreeSet::from_iter(vec![
551+
SignedEntityTypeDiscriminants::MithrilStakeDistribution,
552+
SignedEntityTypeDiscriminants::CardanoDatabase,
553+
SignedEntityTypeDiscriminants::CardanoTransactions,
554+
]),
555+
cardano_transactions: Some(CardanoTransactionsSigningConfig {
556+
security_parameter: BlockNumberOffset(100),
557+
step: BlockNumber(10),
558+
}),
559+
cardano_blocks_transactions: Some(CardanoBlocksTransactionsSigningConfig {
560+
security_parameter: BlockNumberOffset(150),
561+
step: BlockNumber(20),
562+
}),
563+
};
564+
let configurations =
565+
ConfigurationComputerFromMarkers::new(BTreeMap::from([(Epoch(42), configuration)]));
566+
567+
let expected_human_readable_configurations = vec![HumanReadableProtocolConfiguration {
568+
epoch: Epoch(42),
569+
protocol_parameters: ProtocolParameters {
570+
k: 9,
571+
m: 77,
572+
phi_f: 0.5,
573+
},
574+
enabled_signed_entity_types: BTreeSet::from_iter(vec![
575+
SignedEntityTypeDiscriminantsMessage::Known(MithrilStakeDistribution),
576+
SignedEntityTypeDiscriminantsMessage::Known(CardanoDatabase),
577+
SignedEntityTypeDiscriminantsMessage::Known(CardanoTransactions),
578+
]),
579+
cardano_transaction_signing_config: Some(CardanoTransactionsSigningConfig {
580+
security_parameter: BlockNumberOffset(100),
581+
step: BlockNumber(10),
582+
}),
583+
cardano_blocks_transactions_signing_config: Some(
584+
CardanoBlocksTransactionsSigningConfig {
585+
security_parameter: BlockNumberOffset(150),
586+
step: BlockNumber(20),
587+
},
588+
),
589+
}];
590+
591+
assert_eq!(
592+
to_vec_human_readable_protocol_configuration(configurations),
593+
expected_human_readable_configurations
594+
);
595+
}
425596
}

mithril-aggregator/src/tools/protocol_configuration.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ impl ProtocolConfigurationTools {
7878
Ok(Self::new(configuration, dependencies.logger))
7979
}
8080

81+
pub fn get_on_chain_configurations(self) -> ConfigurationComputerFromMarkers {
82+
self.configuration.on_chain_configurations
83+
}
84+
8185
/// Verify if configuration to import share same windows as on chain configuration for current epoch
8286
pub fn verify_configurations_against_chain(
8387
&self,

mithril-aggregator/tests/human_readable_protocol_configuration.json

Lines changed: 0 additions & 43 deletions
This file was deleted.

0 commit comments

Comments
 (0)