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
9use crate::{
10 StdResult,
11 certificate_chain::CertificateGenesisProducer,
12 crypto_helper::{
13 ProtocolAggregateVerificationKey, ProtocolAggregateVerificationKeyForConcatenation,
14 ProtocolClosedKeyRegistration, ProtocolGenesisSigner, ProtocolInitializer, ProtocolOpCert,
15 ProtocolSigner, ProtocolSignerVerificationKey, ProtocolSignerVerificationKeySignature,
16 ProtocolStakeDistribution,
17 },
18 entities::{
19 Certificate, Epoch, HexEncodedAggregateVerificationKey, PartyId, ProtocolParameters,
20 Signer, SignerWithStake, SingleSignature, Stake, StakeDistribution, StakeDistributionParty,
21 },
22 protocol::{SignerBuilder, ToMessage},
23 test::crypto_helper::ProtocolInitializerTestExtension,
24};
25
26#[derive(Debug, Clone)]
28pub struct MithrilFixture {
29 protocol_parameters: ProtocolParameters,
30 signers: Vec<SignerFixture>,
31 stake_distribution: ProtocolStakeDistribution,
32}
33
34#[derive(Debug, Clone)]
38pub struct SignerFixture {
39 pub signer_with_stake: SignerWithStake,
41 pub protocol_signer: ProtocolSigner,
43 pub protocol_initializer: ProtocolInitializer,
45 pub protocol_closed_key_registration: ProtocolClosedKeyRegistration,
47 pub kes_secret_key_path: Option<PathBuf>,
49 pub operational_certificate_path: Option<PathBuf>,
51}
52
53impl SignerFixture {
54 pub fn try_new_with_protocol_parameters(
57 self,
58 protocol_parameters: ProtocolParameters,
59 ) -> StdResult<Self> {
60 let mut protocol_initializer = self.protocol_initializer.clone();
61 protocol_initializer.override_protocol_parameters(&protocol_parameters.into());
62 let protocol_signer =
63 protocol_initializer.new_signer(self.protocol_closed_key_registration.clone())?;
64 Ok(Self {
65 protocol_signer,
66 ..self
67 })
68 }
69}
70
71impl From<SignerFixture> for SignerWithStake {
72 fn from(fixture: SignerFixture) -> Self {
73 fixture.signer_with_stake
74 }
75}
76
77impl From<&SignerFixture> for SignerWithStake {
78 fn from(fixture: &SignerFixture) -> Self {
79 fixture.signer_with_stake.clone()
80 }
81}
82
83#[derive(Debug, Clone, Serialize, Deserialize)]
85pub struct CardanoCliStakeDistribution {
86 #[serde(rename = "pools")]
87 pub signers: HashMap<String, CardanoCliSignerStake>,
88}
89
90#[derive(Debug, Clone, Serialize, Deserialize)]
93pub struct CardanoCliSignerStake {
94 #[serde(rename = "stakeMark")]
95 actual_stake: Stake,
96 #[serde(rename = "stakeSet")]
97 previous_stake: Stake,
98 #[serde(rename = "stakeGo")]
99 penultimate_stake: Stake,
100}
101
102impl MithrilFixture {
103 pub fn new(
105 protocol_parameters: ProtocolParameters,
106 signers: Vec<SignerFixture>,
107 stake_distribution: ProtocolStakeDistribution,
108 ) -> Self {
109 Self {
110 protocol_parameters,
111 signers,
112 stake_distribution,
113 }
114 }
115
116 pub fn protocol_parameters(&self) -> ProtocolParameters {
118 self.protocol_parameters.clone()
119 }
120
121 pub fn signers_fixture(&self) -> Vec<SignerFixture> {
123 self.signers.clone()
124 }
125
126 pub fn signers(&self) -> Vec<Signer> {
128 self.signers
129 .clone()
130 .into_iter()
131 .map(|s| s.signer_with_stake.into())
132 .collect()
133 }
134
135 pub fn signers_with_stake(&self) -> Vec<SignerWithStake> {
137 self.signers.iter().map(|s| &s.signer_with_stake).cloned().collect()
138 }
139
140 pub fn stake_distribution_parties(&self) -> Vec<StakeDistributionParty> {
142 self.signers
143 .iter()
144 .map(|s| StakeDistributionParty {
145 party_id: s.signer_with_stake.party_id.clone(),
146 stake: s.signer_with_stake.stake,
147 })
148 .collect()
149 }
150
151 pub fn stake_distribution(&self) -> StakeDistribution {
153 StakeDistribution::from_iter(self.stake_distribution.clone())
154 }
155
156 pub fn protocol_stake_distribution(&self) -> ProtocolStakeDistribution {
158 self.stake_distribution.clone()
159 }
160
161 pub fn cardano_cli_stake_distribution(&self) -> CardanoCliStakeDistribution {
165 let signers = HashMap::from_iter(self.signers_fixture().into_iter().map(|signer| {
166 (
167 signer.compute_protocol_party_id_as_hash(),
168 CardanoCliSignerStake {
169 actual_stake: signer.signer_with_stake.stake,
170 previous_stake: signer.signer_with_stake.stake,
171 penultimate_stake: signer.signer_with_stake.stake,
172 },
173 )
174 }));
175
176 CardanoCliStakeDistribution { signers }
177 }
178
179 pub fn compute_aggregate_verification_key(&self) -> ProtocolAggregateVerificationKey {
181 SignerBuilder::new(&self.signers_with_stake(), &self.protocol_parameters)
182 .unwrap()
183 .compute_aggregate_verification_key()
184 }
185
186 pub fn compute_concatenation_aggregate_verification_key(
188 &self,
189 ) -> ProtocolAggregateVerificationKeyForConcatenation {
190 self.compute_aggregate_verification_key()
191 .to_concatenation_aggregate_verification_key()
192 .to_owned()
193 .into()
194 }
195
196 pub fn compute_and_encode_concatenation_aggregate_verification_key(
198 &self,
199 ) -> HexEncodedAggregateVerificationKey {
200 let aggregate_verification_key = self.compute_concatenation_aggregate_verification_key();
201 aggregate_verification_key.to_json_hex().unwrap()
202 }
203
204 pub fn create_genesis_certificate<T: Into<String>>(
206 &self,
207 network: T,
208 epoch: Epoch,
209 ) -> Certificate {
210 let genesis_avk = self.compute_aggregate_verification_key();
211 let genesis_signer = ProtocolGenesisSigner::create_deterministic_signer();
212 let genesis_producer = CertificateGenesisProducer::new(Some(Arc::new(genesis_signer)));
213 let genesis_protocol_message = CertificateGenesisProducer::create_genesis_protocol_message(
214 &self.protocol_parameters,
215 &genesis_avk,
216 &epoch,
217 )
218 .unwrap();
219 let genesis_signature = genesis_producer
220 .sign_genesis_protocol_message(genesis_protocol_message)
221 .unwrap();
222
223 CertificateGenesisProducer::create_genesis_certificate(
224 self.protocol_parameters.clone(),
225 network,
226 epoch,
227 genesis_avk,
228 genesis_signature,
229 )
230 .unwrap()
231 }
232
233 pub fn sign_all<T: ToMessage>(&self, message: &T) -> Vec<SingleSignature> {
236 self.signers.par_iter().filter_map(|s| s.sign(message)).collect()
237 }
238}
239
240impl From<MithrilFixture> for Vec<Signer> {
241 fn from(fixture: MithrilFixture) -> Self {
242 fixture.signers()
243 }
244}
245
246impl From<MithrilFixture> for Vec<SignerWithStake> {
247 fn from(fixture: MithrilFixture) -> Self {
248 fixture.signers_with_stake()
249 }
250}
251
252impl From<MithrilFixture> for Vec<SignerFixture> {
253 fn from(fixture: MithrilFixture) -> Self {
254 fixture.signers_fixture()
255 }
256}
257
258impl SignerFixture {
259 pub fn sign<T: ToMessage>(&self, message: &T) -> Option<SingleSignature> {
261 let message = message.to_message();
262 self.protocol_signer.sign(message.as_bytes()).map(|signature| {
263 let won_indexes = signature.get_concatenation_signature_indices();
264
265 SingleSignature::new(
266 self.signer_with_stake.party_id.to_owned(),
267 signature.into(),
268 won_indexes,
269 )
270 })
271 }
272
273 pub fn party_id(&self) -> PartyId {
275 self.signer_with_stake.party_id.clone()
276 }
277
278 pub fn operational_certificate(&self) -> Option<ProtocolOpCert> {
280 self.signer_with_stake.operational_certificate.clone()
281 }
282
283 pub fn compute_protocol_party_id_as_hash(&self) -> String {
287 self.operational_certificate()
288 .unwrap()
289 .compute_protocol_party_id_as_hash()
290 }
291
292 pub fn verification_key(&self) -> ProtocolSignerVerificationKey {
294 self.signer_with_stake.verification_key
295 }
296
297 pub fn verification_key_signature(&self) -> Option<ProtocolSignerVerificationKeySignature> {
299 self.signer_with_stake.verification_key_signature
300 }
301
302 pub fn kes_secret_key_path(&self) -> Option<&Path> {
304 self.kes_secret_key_path.as_deref()
305 }
306
307 pub fn operational_certificate_path(&self) -> Option<&Path> {
309 self.operational_certificate_path.as_deref()
310 }
311}