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