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, 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 test::crypto_helper::ProtocolInitializerTestExtension,
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 pub operational_certificate_path: Option<PathBuf>,
50}
51
52impl SignerFixture {
53 pub fn try_new_with_protocol_parameters(
56 self,
57 protocol_parameters: ProtocolParameters,
58 ) -> StdResult<Self> {
59 let mut protocol_initializer = self.protocol_initializer.clone();
60 protocol_initializer.override_protocol_parameters(&protocol_parameters.into());
61 let protocol_signer =
62 protocol_initializer.new_signer(self.protocol_closed_key_registration.clone())?;
63 Ok(Self {
64 protocol_signer,
65 ..self
66 })
67 }
68}
69
70impl From<SignerFixture> for SignerWithStake {
71 fn from(fixture: SignerFixture) -> Self {
72 fixture.signer_with_stake
73 }
74}
75
76impl From<&SignerFixture> for SignerWithStake {
77 fn from(fixture: &SignerFixture) -> Self {
78 fixture.signer_with_stake.clone()
79 }
80}
81
82#[derive(Debug, Clone, Serialize, Deserialize)]
84pub struct CardanoCliStakeDistribution {
85 #[serde(rename = "pools")]
86 pub signers: HashMap<String, CardanoCliSignerStake>,
87}
88
89#[derive(Debug, Clone, Serialize, Deserialize)]
92pub struct CardanoCliSignerStake {
93 #[serde(rename = "stakeMark")]
94 actual_stake: Stake,
95 #[serde(rename = "stakeSet")]
96 previous_stake: Stake,
97 #[serde(rename = "stakeGo")]
98 penultimate_stake: Stake,
99}
100
101impl MithrilFixture {
102 pub fn new(
104 protocol_parameters: ProtocolParameters,
105 signers: Vec<SignerFixture>,
106 stake_distribution: ProtocolStakeDistribution,
107 ) -> Self {
108 Self {
109 protocol_parameters,
110 signers,
111 stake_distribution,
112 }
113 }
114
115 pub fn protocol_parameters(&self) -> ProtocolParameters {
117 self.protocol_parameters.clone()
118 }
119
120 pub fn signers_fixture(&self) -> Vec<SignerFixture> {
122 self.signers.clone()
123 }
124
125 pub fn signers(&self) -> Vec<Signer> {
127 self.signers
128 .clone()
129 .into_iter()
130 .map(|s| s.signer_with_stake.into())
131 .collect()
132 }
133
134 pub fn signers_with_stake(&self) -> Vec<SignerWithStake> {
136 self.signers.iter().map(|s| &s.signer_with_stake).cloned().collect()
137 }
138
139 pub fn stake_distribution_parties(&self) -> Vec<StakeDistributionParty> {
141 self.signers
142 .iter()
143 .map(|s| StakeDistributionParty {
144 party_id: s.signer_with_stake.party_id.clone(),
145 stake: s.signer_with_stake.stake,
146 })
147 .collect()
148 }
149
150 pub fn stake_distribution(&self) -> StakeDistribution {
152 StakeDistribution::from_iter(self.stake_distribution.clone())
153 }
154
155 pub fn protocol_stake_distribution(&self) -> ProtocolStakeDistribution {
157 self.stake_distribution.clone()
158 }
159
160 pub fn cardano_cli_stake_distribution(&self) -> CardanoCliStakeDistribution {
164 let signers = HashMap::from_iter(self.signers_fixture().into_iter().map(|signer| {
165 (
166 signer.compute_protocol_party_id_as_hash(),
167 CardanoCliSignerStake {
168 actual_stake: signer.signer_with_stake.stake,
169 previous_stake: signer.signer_with_stake.stake,
170 penultimate_stake: signer.signer_with_stake.stake,
171 },
172 )
173 }));
174
175 CardanoCliStakeDistribution { signers }
176 }
177
178 pub fn compute_avk(&self) -> ProtocolAggregateVerificationKey {
180 SignerBuilder::new(&self.signers_with_stake(), &self.protocol_parameters)
181 .unwrap()
182 .compute_aggregate_verification_key()
183 }
184
185 pub fn compute_and_encode_avk(&self) -> HexEncodedAggregateVerificationKey {
187 let avk = self.compute_avk();
188 avk.to_json_hex().unwrap()
189 }
190
191 pub fn create_genesis_certificate<T: Into<String>>(
193 &self,
194 network: T,
195 epoch: Epoch,
196 ) -> Certificate {
197 let genesis_avk = self.compute_avk();
198 let genesis_signer = ProtocolGenesisSigner::create_deterministic_signer();
199 let genesis_producer = CertificateGenesisProducer::new(Some(Arc::new(genesis_signer)));
200 let genesis_protocol_message = CertificateGenesisProducer::create_genesis_protocol_message(
201 &self.protocol_parameters,
202 &genesis_avk,
203 &epoch,
204 )
205 .unwrap();
206 let genesis_signature = genesis_producer
207 .sign_genesis_protocol_message(genesis_protocol_message)
208 .unwrap();
209
210 CertificateGenesisProducer::create_genesis_certificate(
211 self.protocol_parameters.clone(),
212 network,
213 epoch,
214 genesis_avk,
215 genesis_signature,
216 )
217 .unwrap()
218 }
219
220 pub fn sign_all<T: ToMessage>(&self, message: &T) -> Vec<SingleSignature> {
223 self.signers.par_iter().filter_map(|s| s.sign(message)).collect()
224 }
225}
226
227impl From<MithrilFixture> for Vec<Signer> {
228 fn from(fixture: MithrilFixture) -> Self {
229 fixture.signers()
230 }
231}
232
233impl From<MithrilFixture> for Vec<SignerWithStake> {
234 fn from(fixture: MithrilFixture) -> Self {
235 fixture.signers_with_stake()
236 }
237}
238
239impl From<MithrilFixture> for Vec<SignerFixture> {
240 fn from(fixture: MithrilFixture) -> Self {
241 fixture.signers_fixture()
242 }
243}
244
245impl SignerFixture {
246 pub fn sign<T: ToMessage>(&self, message: &T) -> Option<SingleSignature> {
248 let message = message.to_message();
249 self.protocol_signer.sign(message.as_bytes()).map(|signature| {
250 let won_indexes = signature.indexes.clone();
251
252 SingleSignature::new(
253 self.signer_with_stake.party_id.to_owned(),
254 signature.into(),
255 won_indexes,
256 )
257 })
258 }
259
260 pub fn party_id(&self) -> PartyId {
262 self.signer_with_stake.party_id.clone()
263 }
264
265 pub fn operational_certificate(&self) -> Option<ProtocolOpCert> {
267 self.signer_with_stake.operational_certificate.clone()
268 }
269
270 pub fn compute_protocol_party_id_as_hash(&self) -> String {
274 self.operational_certificate()
275 .unwrap()
276 .compute_protocol_party_id_as_hash()
277 }
278
279 pub fn verification_key(&self) -> ProtocolSignerVerificationKey {
281 self.signer_with_stake.verification_key
282 }
283
284 pub fn verification_key_signature(&self) -> Option<ProtocolSignerVerificationKeySignature> {
286 self.signer_with_stake.verification_key_signature
287 }
288
289 pub fn kes_secret_key_path(&self) -> Option<&Path> {
291 self.kes_secret_key_path.as_deref()
292 }
293
294 pub fn operational_certificate_path(&self) -> Option<&Path> {
296 self.operational_certificate_path.as_deref()
297 }
298}