mithril_aggregator/tools/
era.rs1use std::path::{Path, PathBuf};
2
3use anyhow::anyhow;
4use mithril_common::{
5 chain_observer::{TxDatumBuilder, TxDatumFieldValue},
6 crypto_helper::EraMarkersSigner,
7 entities::Epoch,
8 era::{adapters::EraMarkersPayloadCardanoChain, EraMarker, SupportedEra},
9 StdResult,
10};
11
12type EraToolsResult<R> = StdResult<R>;
13
14pub struct EraTools {}
15
16impl EraTools {
17 pub fn new() -> Self {
18 Self {}
19 }
20
21 pub fn get_supported_eras_list(&self) -> EraToolsResult<Vec<SupportedEra>> {
23 Ok(SupportedEra::eras())
24 }
25
26 pub fn generate_tx_datum(
28 &self,
29 current_era_epoch: Epoch,
30 maybe_next_era_epoch: Option<Epoch>,
31 era_markers_signer: &EraMarkersSigner,
32 ) -> EraToolsResult<String> {
33 if maybe_next_era_epoch.is_some()
34 && maybe_next_era_epoch.unwrap_or_default() <= current_era_epoch
35 {
36 Err(anyhow!(
37 "next era epoch must be strictly greater than the current era epoch"
38 ))?;
39 }
40
41 let mut era_markers = Vec::new();
42 for (index, era) in SupportedEra::eras().iter().enumerate() {
43 let era_marker = match index {
44 0 => EraMarker::new(&era.to_string(), Some(current_era_epoch)),
45 1 => EraMarker::new(&era.to_string(), maybe_next_era_epoch),
46 _ => Err(anyhow!("too many eras retrieved, can't generate tx datum"))?,
47 };
48 era_markers.push(era_marker);
49 }
50 let era_markers_payload = EraMarkersPayloadCardanoChain {
51 markers: era_markers,
52 signature: None,
53 }
54 .sign(era_markers_signer)?;
55
56 let tx_datum = TxDatumBuilder::new()
57 .add_field(TxDatumFieldValue::Bytes(era_markers_payload.to_json_hex()?))
58 .build()?;
59 Ok(tx_datum.0)
60 }
61
62 pub fn create_and_save_era_keypair(keypair_path: &Path) -> StdResult<(PathBuf, PathBuf)> {
64 let era_signer = EraMarkersSigner::create_non_deterministic_signer();
65 let era_secret_key_path = keypair_path.join("era.sk");
66 era_signer
67 .secret_key()
68 .write_json_hex_to_file(&era_secret_key_path)?;
69 let era_verification_key_path = keypair_path.join("era.vk");
70 era_signer
71 .verification_key()
72 .write_json_hex_to_file(&era_verification_key_path)?;
73
74 Ok((era_secret_key_path, era_verification_key_path))
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 use mithril_common::{
81 crypto_helper::{EraMarkersVerifierSecretKey, EraMarkersVerifierVerificationKey},
82 test_utils::TempDir,
83 };
84 use std::fs::read_to_string;
85
86 use super::*;
87
88 fn build_tools() -> EraTools {
89 EraTools {}
90 }
91
92 fn get_temp_dir(dir_name: &str) -> PathBuf {
93 TempDir::create("era", dir_name)
94 }
95
96 #[test]
97 fn get_supported_eras_list() {
98 let era_tools = build_tools();
99 let supported_eras_list = era_tools
100 .get_supported_eras_list()
101 .expect("get_supported_eras_list should not fail");
102 assert_eq!(supported_eras_list, SupportedEra::eras());
103 }
104
105 #[test]
106 fn generate_tx_datum_ok() {
107 let era_markers_signer = EraMarkersSigner::create_deterministic_signer();
108 let era_tools = build_tools();
109 let _ = era_tools
110 .generate_tx_datum(Epoch(1), None, &era_markers_signer)
111 .expect("generate_tx_datum should not fail");
112 }
113
114 #[test]
115 fn generate_tx_datum_wrong_epochs() {
116 let era_markers_signer = EraMarkersSigner::create_deterministic_signer();
117 let era_tools = build_tools();
118 let _ = era_tools
119 .generate_tx_datum(Epoch(3), Some(Epoch(2)), &era_markers_signer)
120 .expect_err("generate_tx_datum should have failed");
121 }
122
123 #[test]
124 fn test_create_and_save_era_keypair() {
125 let temp_dir = get_temp_dir("test_create_and_save_era_keypair");
126 let (era_secret_key_path, era_verification_key_path) =
127 EraTools::create_and_save_era_keypair(&temp_dir)
128 .expect("Failed to create and save era keypair");
129 let era_secret_key = EraMarkersVerifierSecretKey::from_json_hex(
130 &read_to_string(&era_secret_key_path).expect("Failed to read era secret key file"),
131 )
132 .expect("Failed to parse era secret key");
133 let era_verification_key = EraMarkersVerifierVerificationKey::from_json_hex(
134 &read_to_string(&era_verification_key_path)
135 .expect("Failed to read era verification key file"),
136 )
137 .expect("Failed to parse era verification key");
138 let era_verifier = EraMarkersSigner::from_secret_key(era_secret_key).create_verifier();
139
140 let expected_era_verification_key = era_verifier.to_verification_key();
141 assert_eq!(expected_era_verification_key, era_verification_key);
142 }
143}