mithril_common/test_utils/
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, ProtocolClosedKeyRegistration, ProtocolGenesisSigner,
14 ProtocolInitializer, ProtocolOpCert, ProtocolSigner, ProtocolSignerVerificationKey,
15 ProtocolSignerVerificationKeySignature, ProtocolStakeDistribution,
16 },
17 entities::{
18 Certificate, Epoch, HexEncodedAggregateVerificationKey, PartyId, ProtocolParameters,
19 Signer, SignerWithStake, SingleSignature, Stake, StakeDistribution, StakeDistributionParty,
20 },
21 protocol::{SignerBuilder, ToMessage},
22};
23
24#[derive(Debug, Clone)]
26pub struct MithrilFixture {
27 protocol_parameters: ProtocolParameters,
28 signers: Vec<SignerFixture>,
29 stake_distribution: ProtocolStakeDistribution,
30}
31
32#[derive(Debug, Clone)]
36pub struct SignerFixture {
37 pub signer_with_stake: SignerWithStake,
39 pub protocol_signer: ProtocolSigner,
41 pub protocol_initializer: ProtocolInitializer,
43 pub protocol_closed_key_registration: ProtocolClosedKeyRegistration,
45 pub kes_secret_key_path: Option<PathBuf>,
47 pub operational_certificate_path: Option<PathBuf>,
49}
50
51impl SignerFixture {
52 pub fn try_new_with_protocol_parameters(
55 self,
56 protocol_parameters: ProtocolParameters,
57 ) -> StdResult<Self> {
58 let mut protocol_initializer = self.protocol_initializer.clone();
59 protocol_initializer.override_protocol_parameters(&protocol_parameters.into());
60 let protocol_signer =
61 protocol_initializer.new_signer(self.protocol_closed_key_registration.clone())?;
62 Ok(Self {
63 protocol_signer,
64 ..self
65 })
66 }
67}
68
69impl From<SignerFixture> for SignerWithStake {
70 fn from(fixture: SignerFixture) -> Self {
71 fixture.signer_with_stake
72 }
73}
74
75impl From<&SignerFixture> for SignerWithStake {
76 fn from(fixture: &SignerFixture) -> Self {
77 fixture.signer_with_stake.clone()
78 }
79}
80
81#[derive(Debug, Clone, Serialize, Deserialize)]
83pub struct CardanoCliStakeDistribution {
84 #[serde(rename = "pools")]
85 pub signers: HashMap<String, CardanoCliSignerStake>,
86}
87
88#[derive(Debug, Clone, Serialize, Deserialize)]
91pub struct CardanoCliSignerStake {
92 #[serde(rename = "stakeMark")]
93 actual_stake: Stake,
94 #[serde(rename = "stakeSet")]
95 previous_stake: Stake,
96 #[serde(rename = "stakeGo")]
97 penultimate_stake: Stake,
98}
99
100impl MithrilFixture {
101 pub fn new(
103 protocol_parameters: ProtocolParameters,
104 signers: Vec<SignerFixture>,
105 stake_distribution: ProtocolStakeDistribution,
106 ) -> Self {
107 Self {
108 protocol_parameters,
109 signers,
110 stake_distribution,
111 }
112 }
113
114 pub fn protocol_parameters(&self) -> ProtocolParameters {
116 self.protocol_parameters.clone()
117 }
118
119 pub fn signers_fixture(&self) -> Vec<SignerFixture> {
121 self.signers.clone()
122 }
123
124 pub fn signers(&self) -> Vec<Signer> {
126 self.signers
127 .clone()
128 .into_iter()
129 .map(|s| s.signer_with_stake.into())
130 .collect()
131 }
132
133 pub fn signers_with_stake(&self) -> Vec<SignerWithStake> {
135 self.signers.iter().map(|s| &s.signer_with_stake).cloned().collect()
136 }
137
138 pub fn stake_distribution_parties(&self) -> Vec<StakeDistributionParty> {
140 self.signers
141 .iter()
142 .map(|s| StakeDistributionParty {
143 party_id: s.signer_with_stake.party_id.clone(),
144 stake: s.signer_with_stake.stake,
145 })
146 .collect()
147 }
148
149 pub fn stake_distribution(&self) -> StakeDistribution {
151 StakeDistribution::from_iter(self.stake_distribution.clone())
152 }
153
154 pub fn protocol_stake_distribution(&self) -> ProtocolStakeDistribution {
156 self.stake_distribution.clone()
157 }
158
159 pub fn cardano_cli_stake_distribution(&self) -> CardanoCliStakeDistribution {
163 let signers = HashMap::from_iter(self.signers_fixture().into_iter().map(|signer| {
164 (
165 signer.compute_protocol_party_id_as_hash(),
166 CardanoCliSignerStake {
167 actual_stake: signer.signer_with_stake.stake,
168 previous_stake: signer.signer_with_stake.stake,
169 penultimate_stake: signer.signer_with_stake.stake,
170 },
171 )
172 }));
173
174 CardanoCliStakeDistribution { signers }
175 }
176
177 pub fn compute_avk(&self) -> ProtocolAggregateVerificationKey {
179 SignerBuilder::new(&self.signers_with_stake(), &self.protocol_parameters)
180 .unwrap()
181 .compute_aggregate_verification_key()
182 }
183
184 pub fn compute_and_encode_avk(&self) -> HexEncodedAggregateVerificationKey {
186 let avk = self.compute_avk();
187 avk.to_json_hex().unwrap()
188 }
189
190 pub fn create_genesis_certificate<T: Into<String>>(
192 &self,
193 network: T,
194 epoch: Epoch,
195 ) -> Certificate {
196 let genesis_avk = self.compute_avk();
197 let genesis_signer = ProtocolGenesisSigner::create_deterministic_signer();
198 let genesis_producer = CertificateGenesisProducer::new(Some(Arc::new(genesis_signer)));
199 let genesis_protocol_message = CertificateGenesisProducer::create_genesis_protocol_message(
200 &self.protocol_parameters,
201 &genesis_avk,
202 &epoch,
203 )
204 .unwrap();
205 let genesis_signature = genesis_producer
206 .sign_genesis_protocol_message(genesis_protocol_message)
207 .unwrap();
208
209 CertificateGenesisProducer::create_genesis_certificate(
210 self.protocol_parameters.clone(),
211 network,
212 epoch,
213 genesis_avk,
214 genesis_signature,
215 )
216 .unwrap()
217 }
218
219 pub fn sign_all<T: ToMessage>(&self, message: &T) -> Vec<SingleSignature> {
222 self.signers.par_iter().filter_map(|s| s.sign(message)).collect()
223 }
224}
225
226impl From<MithrilFixture> for Vec<Signer> {
227 fn from(fixture: MithrilFixture) -> Self {
228 fixture.signers()
229 }
230}
231
232impl From<MithrilFixture> for Vec<SignerWithStake> {
233 fn from(fixture: MithrilFixture) -> Self {
234 fixture.signers_with_stake()
235 }
236}
237
238impl From<MithrilFixture> for Vec<SignerFixture> {
239 fn from(fixture: MithrilFixture) -> Self {
240 fixture.signers_fixture()
241 }
242}
243
244impl SignerFixture {
245 pub fn sign<T: ToMessage>(&self, message: &T) -> Option<SingleSignature> {
247 let message = message.to_message();
248 self.protocol_signer.sign(message.as_bytes()).map(|signature| {
249 let won_indexes = signature.indexes.clone();
250
251 SingleSignature::new(
252 self.signer_with_stake.party_id.to_owned(),
253 signature.into(),
254 won_indexes,
255 )
256 })
257 }
258
259 pub fn party_id(&self) -> PartyId {
261 self.signer_with_stake.party_id.clone()
262 }
263
264 pub fn operational_certificate(&self) -> Option<ProtocolOpCert> {
266 self.signer_with_stake.operational_certificate.clone()
267 }
268
269 pub fn compute_protocol_party_id_as_hash(&self) -> String {
273 self.operational_certificate()
274 .unwrap()
275 .compute_protocol_party_id_as_hash()
276 }
277
278 pub fn verification_key(&self) -> ProtocolSignerVerificationKey {
280 self.signer_with_stake.verification_key
281 }
282
283 pub fn verification_key_signature(&self) -> Option<ProtocolSignerVerificationKeySignature> {
285 self.signer_with_stake.verification_key_signature
286 }
287
288 pub fn kes_secret_key_path(&self) -> Option<&Path> {
290 self.kes_secret_key_path.as_deref()
291 }
292
293 pub fn operational_certificate_path(&self) -> Option<&Path> {
295 self.operational_certificate_path.as_deref()
296 }
297}