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 ProtocolSignerVerificationKeyForSnark, ProtocolSignerVerificationKeySignatureForSnark,
12};
13use crate::{
14 StdResult,
15 certificate_chain::CertificateGenesisProducer,
16 crypto_helper::{
17 ProtocolAggregateVerificationKey, ProtocolAggregateVerificationKeyForConcatenation,
18 ProtocolClosedKeyRegistration, ProtocolGenesisSigner, ProtocolInitializer, ProtocolOpCert,
19 ProtocolSigner, ProtocolSignerVerificationKeyForConcatenation,
20 ProtocolSignerVerificationKeySignatureForConcatenation, ProtocolStakeDistribution,
21 },
22 entities::{
23 Certificate, Epoch, HexEncodedAggregateVerificationKey, PartyId, ProtocolParameters,
24 Signer, SignerWithStake, SingleSignature, Stake, StakeDistribution, StakeDistributionParty,
25 },
26 protocol::{SignerBuilder, ToMessage},
27 test::crypto_helper::ProtocolInitializerTestExtension,
28};
29
30#[derive(Debug, Clone)]
32pub struct MithrilFixture {
33 protocol_parameters: ProtocolParameters,
34 signers: Vec<SignerFixture>,
35 stake_distribution: ProtocolStakeDistribution,
36}
37
38#[derive(Debug, Clone)]
42pub struct SignerFixture {
43 pub signer_with_stake: SignerWithStake,
45 pub protocol_signer: ProtocolSigner,
47 pub protocol_initializer: ProtocolInitializer,
49 pub protocol_closed_key_registration: ProtocolClosedKeyRegistration,
51 pub kes_secret_key_path: Option<PathBuf>,
53 pub operational_certificate_path: Option<PathBuf>,
55}
56
57impl SignerFixture {
58 pub fn try_new_with_protocol_parameters(
61 self,
62 protocol_parameters: ProtocolParameters,
63 ) -> StdResult<Self> {
64 let mut protocol_initializer = self.protocol_initializer.clone();
65 protocol_initializer.override_protocol_parameters(&protocol_parameters.into());
66 let protocol_signer =
67 protocol_initializer.new_signer(self.protocol_closed_key_registration.clone())?;
68 Ok(Self {
69 protocol_signer,
70 ..self
71 })
72 }
73}
74
75impl From<SignerFixture> for SignerWithStake {
76 fn from(fixture: SignerFixture) -> Self {
77 fixture.signer_with_stake
78 }
79}
80
81impl From<&SignerFixture> for SignerWithStake {
82 fn from(fixture: &SignerFixture) -> Self {
83 fixture.signer_with_stake.clone()
84 }
85}
86
87#[derive(Debug, Clone, Serialize, Deserialize)]
89pub struct CardanoCliStakeDistribution {
90 #[serde(rename = "pools")]
91 pub signers: HashMap<String, CardanoCliSignerStake>,
92}
93
94#[derive(Debug, Clone, Serialize, Deserialize)]
97pub struct CardanoCliSignerStake {
98 #[serde(rename = "stakeMark")]
99 actual_stake: Stake,
100 #[serde(rename = "stakeSet")]
101 previous_stake: Stake,
102 #[serde(rename = "stakeGo")]
103 penultimate_stake: Stake,
104}
105
106impl MithrilFixture {
107 pub fn new(
109 protocol_parameters: ProtocolParameters,
110 signers: Vec<SignerFixture>,
111 stake_distribution: ProtocolStakeDistribution,
112 ) -> Self {
113 Self {
114 protocol_parameters,
115 signers,
116 stake_distribution,
117 }
118 }
119
120 pub fn protocol_parameters(&self) -> ProtocolParameters {
122 self.protocol_parameters.clone()
123 }
124
125 pub fn signers_fixture(&self) -> Vec<SignerFixture> {
127 self.signers.clone()
128 }
129
130 pub fn signers(&self) -> Vec<Signer> {
132 self.signers
133 .clone()
134 .into_iter()
135 .map(|s| s.signer_with_stake.into())
136 .collect()
137 }
138
139 pub fn signers_with_stake(&self) -> Vec<SignerWithStake> {
141 self.signers.iter().map(|s| &s.signer_with_stake).cloned().collect()
142 }
143
144 pub fn stake_distribution_parties(&self) -> Vec<StakeDistributionParty> {
146 self.signers
147 .iter()
148 .map(|s| StakeDistributionParty {
149 party_id: s.signer_with_stake.party_id.clone(),
150 stake: s.signer_with_stake.stake,
151 })
152 .collect()
153 }
154
155 pub fn stake_distribution(&self) -> StakeDistribution {
157 StakeDistribution::from_iter(self.stake_distribution.clone())
158 }
159
160 pub fn protocol_stake_distribution(&self) -> ProtocolStakeDistribution {
162 self.stake_distribution.clone()
163 }
164
165 pub fn cardano_cli_stake_distribution(&self) -> CardanoCliStakeDistribution {
169 let signers = HashMap::from_iter(self.signers_fixture().into_iter().map(|signer| {
170 (
171 signer.compute_protocol_party_id_as_hash(),
172 CardanoCliSignerStake {
173 actual_stake: signer.signer_with_stake.stake,
174 previous_stake: signer.signer_with_stake.stake,
175 penultimate_stake: signer.signer_with_stake.stake,
176 },
177 )
178 }));
179
180 CardanoCliStakeDistribution { signers }
181 }
182
183 pub fn compute_aggregate_verification_key(&self) -> ProtocolAggregateVerificationKey {
185 SignerBuilder::new(&self.signers_with_stake(), &self.protocol_parameters)
186 .unwrap()
187 .compute_aggregate_verification_key()
188 }
189
190 pub fn compute_concatenation_aggregate_verification_key(
192 &self,
193 ) -> ProtocolAggregateVerificationKeyForConcatenation {
194 self.compute_aggregate_verification_key()
195 .to_concatenation_aggregate_verification_key()
196 .to_owned()
197 .into()
198 }
199
200 pub fn compute_and_encode_concatenation_aggregate_verification_key(
202 &self,
203 ) -> HexEncodedAggregateVerificationKey {
204 let aggregate_verification_key = self.compute_concatenation_aggregate_verification_key();
205 aggregate_verification_key.to_json_hex().unwrap()
206 }
207
208 pub fn create_genesis_certificate<T: Into<String>>(
210 &self,
211 network: T,
212 epoch: Epoch,
213 ) -> Certificate {
214 let genesis_avk = self.compute_aggregate_verification_key();
215 let genesis_signer = ProtocolGenesisSigner::create_deterministic_signer();
216 let genesis_producer = CertificateGenesisProducer::new(Some(Arc::new(genesis_signer)));
217 let genesis_protocol_message = CertificateGenesisProducer::create_genesis_protocol_message(
218 &self.protocol_parameters,
219 &genesis_avk,
220 &epoch,
221 )
222 .unwrap();
223 let genesis_signature = genesis_producer
224 .sign_genesis_protocol_message(genesis_protocol_message)
225 .unwrap();
226
227 CertificateGenesisProducer::create_genesis_certificate(
228 self.protocol_parameters.clone(),
229 network,
230 epoch,
231 genesis_avk,
232 genesis_signature,
233 )
234 .unwrap()
235 }
236
237 pub fn sign_all<T: ToMessage>(&self, message: &T) -> Vec<SingleSignature> {
240 self.signers.par_iter().filter_map(|s| s.sign(message)).collect()
241 }
242}
243
244impl From<MithrilFixture> for Vec<Signer> {
245 fn from(fixture: MithrilFixture) -> Self {
246 fixture.signers()
247 }
248}
249
250impl From<MithrilFixture> for Vec<SignerWithStake> {
251 fn from(fixture: MithrilFixture) -> Self {
252 fixture.signers_with_stake()
253 }
254}
255
256impl From<MithrilFixture> for Vec<SignerFixture> {
257 fn from(fixture: MithrilFixture) -> Self {
258 fixture.signers_fixture()
259 }
260}
261
262impl SignerFixture {
263 pub fn sign<T: ToMessage>(&self, message: &T) -> Option<SingleSignature> {
265 let message = message.to_message();
266 self.protocol_signer.sign(message.as_bytes()).map(|signature| {
267 let won_indexes = signature.get_concatenation_signature_indices();
268
269 SingleSignature::new(
270 self.signer_with_stake.party_id.to_owned(),
271 signature.into(),
272 won_indexes,
273 )
274 })
275 }
276
277 pub fn party_id(&self) -> PartyId {
279 self.signer_with_stake.party_id.clone()
280 }
281
282 pub fn operational_certificate(&self) -> Option<ProtocolOpCert> {
284 self.signer_with_stake.operational_certificate.clone()
285 }
286
287 pub fn compute_protocol_party_id_as_hash(&self) -> String {
291 self.operational_certificate()
292 .unwrap()
293 .compute_protocol_party_id_as_hash()
294 }
295
296 pub fn verification_key_for_concatenation(
298 &self,
299 ) -> ProtocolSignerVerificationKeyForConcatenation {
300 self.signer_with_stake.verification_key_for_concatenation
301 }
302
303 pub fn verification_key_signature_for_concatenation(
305 &self,
306 ) -> Option<ProtocolSignerVerificationKeySignatureForConcatenation> {
307 self.signer_with_stake.verification_key_signature_for_concatenation
308 }
309
310 #[cfg(feature = "future_snark")]
312 pub fn verification_key_for_snark(&self) -> Option<ProtocolSignerVerificationKeyForSnark> {
313 self.signer_with_stake.verification_key_for_snark
314 }
315
316 #[cfg(feature = "future_snark")]
318 pub fn verification_key_signature_for_snark(
319 &self,
320 ) -> Option<ProtocolSignerVerificationKeySignatureForSnark> {
321 self.signer_with_stake.verification_key_signature_for_snark
322 }
323
324 pub fn kes_secret_key_path(&self) -> Option<&Path> {
326 self.kes_secret_key_path.as_deref()
327 }
328
329 pub fn operational_certificate_path(&self) -> Option<&Path> {
331 self.operational_certificate_path.as_deref()
332 }
333}