mithril_common/test/builder/
mithril_fixture.rs1use rayon::prelude::*;
2use serde::{Deserialize, Serialize};
3use std::{
4 collections::HashMap,
5 path::{Path, PathBuf},
6 sync::Arc,
7};
8
9#[cfg(feature = "future_snark")]
10use crate::crypto_helper::{
11 ProtocolKey, ProtocolSignerVerificationKeyForSnark,
12 ProtocolSignerVerificationKeySignatureForSnark,
13};
14use crate::{
15 StdResult,
16 certificate_chain::CertificateGenesisProducer,
17 crypto_helper::{
18 ProtocolAggregateVerificationKey, ProtocolAggregateVerificationKeyForConcatenation,
19 ProtocolClosedKeyRegistration, ProtocolGenesisSigner, ProtocolInitializer, ProtocolOpCert,
20 ProtocolSigner, ProtocolSignerVerificationKeyForConcatenation,
21 ProtocolSignerVerificationKeySignatureForConcatenation, ProtocolStakeDistribution,
22 },
23 entities::{
24 Certificate, Epoch, HexEncodedAggregateVerificationKey, PartyId, ProtocolParameters,
25 Signer, SignerWithStake, SingleSignature, Stake, StakeDistribution, StakeDistributionParty,
26 SupportedEra,
27 },
28 protocol::{SignerBuilder, ToMessage},
29 test::crypto_helper::ProtocolInitializerTestExtension,
30};
31
32#[derive(Debug, Clone)]
34pub struct MithrilFixture {
35 protocol_parameters: ProtocolParameters,
36 signers: Vec<SignerFixture>,
37 stake_distribution: ProtocolStakeDistribution,
38}
39
40#[derive(Debug, Clone)]
44pub struct SignerFixture {
45 pub signer_with_stake: SignerWithStake,
47 pub protocol_signer: ProtocolSigner,
49 pub protocol_initializer: ProtocolInitializer,
51 pub protocol_closed_key_registration: ProtocolClosedKeyRegistration,
53 pub kes_secret_key_path: Option<PathBuf>,
55 pub operational_certificate_path: Option<PathBuf>,
57}
58
59impl SignerFixture {
60 pub fn try_new_with_protocol_parameters(
63 self,
64 protocol_parameters: ProtocolParameters,
65 ) -> StdResult<Self> {
66 let mut protocol_initializer = self.protocol_initializer.clone();
67 protocol_initializer.override_protocol_parameters(&protocol_parameters.into());
68 let protocol_signer =
69 protocol_initializer.new_signer(self.protocol_closed_key_registration.clone())?;
70 Ok(Self {
71 protocol_signer,
72 ..self
73 })
74 }
75}
76
77impl From<SignerFixture> for SignerWithStake {
78 fn from(fixture: SignerFixture) -> Self {
79 fixture.signer_with_stake
80 }
81}
82
83impl From<&SignerFixture> for SignerWithStake {
84 fn from(fixture: &SignerFixture) -> Self {
85 fixture.signer_with_stake.clone()
86 }
87}
88
89#[derive(Debug, Clone, Serialize, Deserialize)]
91pub struct CardanoCliStakeDistribution {
92 #[serde(rename = "pools")]
93 pub signers: HashMap<String, CardanoCliSignerStake>,
94}
95
96#[derive(Debug, Clone, Serialize, Deserialize)]
99pub struct CardanoCliSignerStake {
100 #[serde(rename = "stakeMark")]
101 actual_stake: Stake,
102 #[serde(rename = "stakeSet")]
103 previous_stake: Stake,
104 #[serde(rename = "stakeGo")]
105 penultimate_stake: Stake,
106}
107
108impl MithrilFixture {
109 pub fn new(
111 protocol_parameters: ProtocolParameters,
112 signers: Vec<SignerFixture>,
113 stake_distribution: ProtocolStakeDistribution,
114 ) -> Self {
115 Self {
116 protocol_parameters,
117 signers,
118 stake_distribution,
119 }
120 }
121
122 pub fn protocol_parameters(&self) -> ProtocolParameters {
124 self.protocol_parameters.clone()
125 }
126
127 pub fn signers_fixture(&self) -> Vec<SignerFixture> {
129 self.signers.clone()
130 }
131
132 pub fn signers(&self) -> Vec<Signer> {
134 self.signers
135 .clone()
136 .into_iter()
137 .map(|s| s.signer_with_stake.into())
138 .collect()
139 }
140
141 pub fn signers_with_stake(&self) -> Vec<SignerWithStake> {
143 self.signers.iter().map(|s| &s.signer_with_stake).cloned().collect()
144 }
145
146 pub fn stake_distribution_parties(&self) -> Vec<StakeDistributionParty> {
148 self.signers
149 .iter()
150 .map(|s| StakeDistributionParty {
151 party_id: s.signer_with_stake.party_id.clone(),
152 stake: s.signer_with_stake.stake,
153 })
154 .collect()
155 }
156
157 pub fn stake_distribution(&self) -> StakeDistribution {
159 StakeDistribution::from_iter(self.stake_distribution.clone())
160 }
161
162 pub fn protocol_stake_distribution(&self) -> ProtocolStakeDistribution {
164 self.stake_distribution.clone()
165 }
166
167 pub fn cardano_cli_stake_distribution(&self) -> CardanoCliStakeDistribution {
171 let signers = HashMap::from_iter(self.signers_fixture().into_iter().map(|signer| {
172 (
173 signer.compute_protocol_party_id_as_hash(),
174 CardanoCliSignerStake {
175 actual_stake: signer.signer_with_stake.stake,
176 previous_stake: signer.signer_with_stake.stake,
177 penultimate_stake: signer.signer_with_stake.stake,
178 },
179 )
180 }));
181
182 CardanoCliStakeDistribution { signers }
183 }
184
185 pub fn compute_aggregate_verification_key(&self) -> ProtocolAggregateVerificationKey {
187 SignerBuilder::new(&self.signers_with_stake(), &self.protocol_parameters)
188 .unwrap()
189 .compute_aggregate_verification_key()
190 }
191
192 pub fn compute_concatenation_aggregate_verification_key(
194 &self,
195 ) -> ProtocolAggregateVerificationKeyForConcatenation {
196 self.compute_aggregate_verification_key()
197 .to_concatenation_aggregate_verification_key()
198 .to_owned()
199 .into()
200 }
201
202 pub fn compute_and_encode_concatenation_aggregate_verification_key(
204 &self,
205 ) -> HexEncodedAggregateVerificationKey {
206 let aggregate_verification_key = self.compute_concatenation_aggregate_verification_key();
207 aggregate_verification_key.to_json_hex().unwrap()
208 }
209
210 #[cfg(feature = "future_snark")]
212 pub fn compute_snark_aggregate_verification_key(
213 &self,
214 ) -> Option<crate::crypto_helper::ProtocolAggregateVerificationKeyForSnark> {
215 self.compute_aggregate_verification_key()
216 .to_snark_aggregate_verification_key()
217 .map(|key| ProtocolKey::new(key.to_owned()))
218 }
219
220 #[cfg(feature = "future_snark")]
222 pub fn compute_and_encode_snark_aggregate_verification_key(&self) -> Option<String> {
223 self.compute_snark_aggregate_verification_key()
224 .map(|avk| avk.to_bytes_hex().unwrap())
225 }
226
227 pub fn create_genesis_certificate<T: Into<String>>(
229 &self,
230 network: T,
231 epoch: Epoch,
232 ) -> Certificate {
233 let genesis_avk = self.compute_aggregate_verification_key();
234 let genesis_signer = ProtocolGenesisSigner::create_deterministic_signer();
235 let genesis_producer = CertificateGenesisProducer::new(Some(Arc::new(genesis_signer)));
236 let mithril_era = SupportedEra::Pythagoras;
237 let genesis_protocol_message = genesis_producer
238 .create_genesis_protocol_message(
239 &self.protocol_parameters,
240 &genesis_avk,
241 &epoch,
242 mithril_era,
243 )
244 .unwrap();
245 let genesis_signature = genesis_producer
246 .sign_genesis_protocol_message(genesis_protocol_message)
247 .unwrap();
248
249 genesis_producer
250 .create_genesis_certificate(
251 self.protocol_parameters.clone(),
252 network,
253 epoch,
254 genesis_avk,
255 genesis_signature,
256 mithril_era,
257 )
258 .unwrap()
259 }
260
261 pub fn sign_all<T: ToMessage>(&self, message: &T) -> Vec<SingleSignature> {
264 self.signers.par_iter().filter_map(|s| s.sign(message)).collect()
265 }
266}
267
268impl From<MithrilFixture> for Vec<Signer> {
269 fn from(fixture: MithrilFixture) -> Self {
270 fixture.signers()
271 }
272}
273
274impl From<MithrilFixture> for Vec<SignerWithStake> {
275 fn from(fixture: MithrilFixture) -> Self {
276 fixture.signers_with_stake()
277 }
278}
279
280impl From<MithrilFixture> for Vec<SignerFixture> {
281 fn from(fixture: MithrilFixture) -> Self {
282 fixture.signers_fixture()
283 }
284}
285
286impl SignerFixture {
287 pub fn sign<T: ToMessage>(&self, message: &T) -> Option<SingleSignature> {
289 let message = message.to_message();
290 self.protocol_signer.sign(message.as_bytes()).map(|signature| {
291 let won_indexes = signature.get_concatenation_signature_indices();
292
293 SingleSignature::new(
294 self.signer_with_stake.party_id.to_owned(),
295 signature.into(),
296 won_indexes,
297 )
298 })
299 }
300
301 pub fn party_id(&self) -> PartyId {
303 self.signer_with_stake.party_id.clone()
304 }
305
306 pub fn operational_certificate(&self) -> Option<ProtocolOpCert> {
308 self.signer_with_stake.operational_certificate.clone()
309 }
310
311 pub fn compute_protocol_party_id_as_hash(&self) -> String {
315 self.operational_certificate()
316 .unwrap()
317 .compute_protocol_party_id_as_hash()
318 }
319
320 pub fn verification_key_for_concatenation(
322 &self,
323 ) -> ProtocolSignerVerificationKeyForConcatenation {
324 self.signer_with_stake.verification_key_for_concatenation
325 }
326
327 pub fn verification_key_signature_for_concatenation(
329 &self,
330 ) -> Option<ProtocolSignerVerificationKeySignatureForConcatenation> {
331 self.signer_with_stake.verification_key_signature_for_concatenation
332 }
333
334 #[cfg(feature = "future_snark")]
336 pub fn verification_key_for_snark(&self) -> Option<ProtocolSignerVerificationKeyForSnark> {
337 self.signer_with_stake.verification_key_for_snark
338 }
339
340 #[cfg(feature = "future_snark")]
342 pub fn verification_key_signature_for_snark(
343 &self,
344 ) -> Option<ProtocolSignerVerificationKeySignatureForSnark> {
345 self.signer_with_stake.verification_key_signature_for_snark
346 }
347
348 pub fn kes_secret_key_path(&self) -> Option<&Path> {
350 self.kes_secret_key_path.as_deref()
351 }
352
353 pub fn operational_certificate_path(&self) -> Option<&Path> {
355 self.operational_certificate_path.as_deref()
356 }
357}