mithril_common/test/crypto_helper/
setup.rs1use std::{fs, path::PathBuf, sync::Arc};
3
4use rand_chacha::ChaCha20Rng;
5use rand_core::SeedableRng;
6
7use crate::{
8 crypto_helper::{
9 KesEvolutions, KesPeriod, KesSigner, KesSignerStandard, OpCert, ProtocolInitializer,
10 ProtocolKeyRegistration, ProtocolOpCert, ProtocolParameters, ProtocolPartyId,
11 ProtocolStakeDistribution, SerDeShelleyFileFormat, SignerRegistrationParameters,
12 },
13 entities::{ProtocolMessage, ProtocolMessagePartKey, SignerWithStake, Stake},
14 test::{
15 TempDir,
16 builder::{CertificateChainBuilder, CertificateChainFixture, SignerFixture},
17 },
18};
19
20pub fn setup_temp_directory_for_signer(
22 party_id: &ProtocolPartyId,
23 auto_create: bool,
24) -> Option<PathBuf> {
25 let temp_dir = TempDir::new("tests_setup", "mithril_crypto_helper_material")
26 .build_path()
27 .join(party_id);
28
29 if auto_create {
30 fs::create_dir_all(&temp_dir).expect("temp dir creation should not fail");
31 }
32 temp_dir.exists().then_some(temp_dir)
33}
34
35pub fn setup_message() -> ProtocolMessage {
37 let mut protocol_message = ProtocolMessage::new();
38 protocol_message.set_message_part(
39 ProtocolMessagePartKey::SnapshotDigest,
40 "message_to_sign_123".to_string(),
41 );
42 protocol_message.set_message_part(
43 ProtocolMessagePartKey::NextAggregateVerificationKey,
44 "next-avk-123".to_string(),
45 );
46 protocol_message
47}
48
49pub fn setup_protocol_parameters() -> ProtocolParameters {
51 ProtocolParameters {
52 m: 100,
53 k: 5,
54 phi_f: 0.65,
55 }
56}
57
58fn setup_protocol_initializer(
59 party_id: &str,
60 kes_secret_key_path: Option<PathBuf>,
61 operational_certificate_path: Option<PathBuf>,
62 stake: Stake,
63 protocol_parameters: &ProtocolParameters,
64) -> ProtocolInitializer {
65 let protocol_initializer_seed: [u8; 32] =
66 format!("{party_id:<032}").as_bytes()[..32].try_into().unwrap();
67 let mut protocol_initializer_rng = ChaCha20Rng::from_seed(protocol_initializer_seed);
68 let kes_period = kes_secret_key_path.as_ref().map(|_| KesPeriod(0));
69 let kes_signer = kes_secret_key_path.map(|kes_secret_key_path| {
70 Arc::new(KesSignerStandard::new(
71 kes_secret_key_path,
72 operational_certificate_path.expect(
73 "Operational certificate path must be provided when a KES secret key exists",
74 ),
75 )) as Arc<dyn KesSigner>
76 });
77 let protocol_initializer: ProtocolInitializer = ProtocolInitializer::setup(
78 *protocol_parameters,
79 kes_signer,
80 kes_period,
81 stake,
82 &mut protocol_initializer_rng,
83 )
84 .expect("protocol initializer setup should not fail");
85
86 protocol_initializer
87}
88
89fn setup_signer_with_stake(
90 party_id: &str,
91 stake: Stake,
92 protocol_initializer: &ProtocolInitializer,
93 operational_certificate: Option<ProtocolOpCert>,
94 kes_evolutions: KesEvolutions,
95) -> SignerWithStake {
96 let kes_evolutions = operational_certificate.as_ref().and(Some(kes_evolutions));
97
98 SignerWithStake {
99 party_id: party_id.to_owned(),
100 verification_key_for_concatenation: protocol_initializer
101 .verification_key_for_concatenation()
102 .into(),
103 verification_key_signature_for_concatenation: protocol_initializer
104 .verification_key_signature_for_concatenation(),
105 operational_certificate,
106 kes_evolutions,
107 stake,
108 #[cfg(feature = "future_snark")]
109 verification_key_for_snark: protocol_initializer
110 .verification_key_for_snark()
111 .map(|vk| vk.into()),
112 #[cfg(feature = "future_snark")]
113 verification_key_signature_for_snark: protocol_initializer
114 .verification_key_signature_for_snark(),
115 }
116}
117
118fn decode_op_cert_in_dir(dir: Option<PathBuf>) -> Option<ProtocolOpCert> {
119 dir.as_ref().map(|dir| {
120 OpCert::from_file(dir.join("opcert.cert"))
121 .expect("operational certificate decoding should not fail")
122 .into()
123 })
124}
125
126pub fn setup_signers_from_stake_distribution(
128 stake_distribution: &ProtocolStakeDistribution,
129 protocol_parameters: &ProtocolParameters,
130) -> Vec<SignerFixture> {
131 let mut key_registration = ProtocolKeyRegistration::init(stake_distribution);
132 let mut signers: Vec<(
133 SignerWithStake,
134 ProtocolInitializer,
135 Option<PathBuf>,
136 Option<PathBuf>,
137 )> = vec![];
138
139 for (party_id, stake) in stake_distribution {
140 let kes_evolutions = KesEvolutions(0);
141 let temp_dir = setup_temp_directory_for_signer(party_id, false);
142 let kes_secret_key_path: Option<PathBuf> = temp_dir.as_ref().map(|dir| dir.join("kes.sk"));
143 let operational_certificate_path = temp_dir.as_ref().map(|dir| dir.join("opcert.cert"));
144 let protocol_initializer = setup_protocol_initializer(
145 party_id,
146 kes_secret_key_path.clone(),
147 operational_certificate_path.clone(),
148 *stake,
149 protocol_parameters,
150 );
151 let operational_certificate = decode_op_cert_in_dir(temp_dir);
152 let signer_with_stake = setup_signer_with_stake(
153 party_id,
154 *stake,
155 &protocol_initializer,
156 operational_certificate.clone(),
157 kes_evolutions,
158 );
159
160 key_registration
161 .register(SignerRegistrationParameters {
162 party_id: Some(signer_with_stake.party_id.to_owned()),
163 operational_certificate,
164 verification_key_signature_for_concatenation: protocol_initializer
165 .verification_key_signature_for_concatenation(),
166 kes_evolutions: Some(kes_evolutions),
167 verification_key_for_concatenation: protocol_initializer
168 .verification_key_for_concatenation()
169 .into(),
170 #[cfg(feature = "future_snark")]
171 verification_key_for_snark: protocol_initializer
172 .verification_key_for_snark()
173 .map(Into::into),
174 #[cfg(feature = "future_snark")]
175 verification_key_signature_for_snark: protocol_initializer
176 .verification_key_signature_for_snark(),
177 })
178 .expect("key registration should have succeeded");
179
180 signers.push((
181 signer_with_stake,
182 protocol_initializer,
183 kes_secret_key_path,
184 operational_certificate_path,
185 ));
186 }
187
188 let closed_key_registration = key_registration.close();
189
190 signers
191 .into_iter()
192 .map(
193 |(
194 signer_with_stake,
195 protocol_initializer,
196 kes_secret_key_path,
197 operational_certificate_path,
198 )| {
199 let protocol_closed_key_registration = closed_key_registration.clone();
200 let protocol_signer = protocol_initializer
201 .clone()
202 .new_signer(protocol_closed_key_registration.clone())
203 .expect("creating a new protocol signer should not fail");
204
205 SignerFixture {
206 signer_with_stake,
207 protocol_signer,
208 protocol_initializer,
209 protocol_closed_key_registration,
210 kes_secret_key_path,
211 operational_certificate_path,
212 }
213 },
214 )
215 .collect::<_>()
216}
217
218pub fn setup_certificate_chain(
220 total_certificates: u64,
221 certificates_per_epoch: u64,
222) -> CertificateChainFixture {
223 CertificateChainBuilder::new()
224 .with_total_certificates(total_certificates)
225 .with_certificates_per_epoch(certificates_per_epoch)
226 .with_protocol_parameters(setup_protocol_parameters())
227 .build()
228}