mithril_common/test/
entities_extensions.rs1use std::collections::HashMap;
4
5use crate::StdResult;
6use crate::crypto_helper::MKTreeStorer;
7use crate::entities::{
8 BlockNumber, BlockRange, CardanoBlock, CardanoTransaction, CardanoTransactionsSetProof,
9 IntoMKTreeNode, MkSetProof, ProtocolParameters, SingleSignature,
10 SingleSignatureAuthenticationStatus, TransactionHash,
11};
12use crate::test::builder::{MithrilFixtureBuilder, StakeDistributionGenerationMethod};
13use crate::test::crypto_helper::mkmap_helpers;
14
15pub trait BlockRangeTestExtension {
17 fn new(start: u64, end: u64) -> Self;
19
20 fn try_add(&self, other: &BlockRange) -> StdResult<BlockRange>;
22}
23
24pub trait BlockNumberTestExtension {
26 fn group_items_by_block_range<N, I>(iter: I) -> HashMap<BlockRange, Vec<N>>
28 where
29 I: Iterator<Item = (BlockNumber, N)>;
30}
31
32impl BlockNumberTestExtension for BlockNumber {
33 fn group_items_by_block_range<N, I>(iter: I) -> HashMap<BlockRange, Vec<N>>
34 where
35 I: Iterator<Item = (BlockNumber, N)>,
36 {
37 let mut result: HashMap<BlockRange, Vec<N>> = HashMap::new();
38
39 for (block_number, item) in iter.into_iter() {
40 let block_range = BlockRange::from_block_number(block_number);
41 result.entry(block_range).or_default().push(item);
42 }
43
44 result
45 }
46}
47
48pub trait CardanoTransactionsSetProofTestExtension {
50 fn from_leaves<S: MKTreeStorer>(
52 leaves: &[(BlockNumber, TransactionHash)],
53 ) -> StdResult<CardanoTransactionsSetProof>;
54}
55
56impl CardanoTransactionsSetProofTestExtension for CardanoTransactionsSetProof {
57 fn from_leaves<S: MKTreeStorer>(
58 leaves: &[(BlockNumber, TransactionHash)],
59 ) -> StdResult<CardanoTransactionsSetProof> {
60 let transactions_hashes: Vec<TransactionHash> =
61 leaves.iter().map(|(_, t)| t.into()).collect();
62 let transactions_by_block_ranges =
63 BlockNumber::group_items_by_block_range(leaves.iter().cloned());
64 let mk_map = mkmap_helpers::fold_nodes_per_block_range_into_mkmap::<_, _, S>(
65 transactions_by_block_ranges,
66 )?;
67 let mk_proof = mk_map.compute_proof(&transactions_hashes)?;
68 Ok(Self::new(transactions_hashes, mk_proof))
69 }
70}
71
72pub trait MkSetProofTestExtension<L: IntoMKTreeNode + Clone> {
74 fn from_leaves<S: MKTreeStorer>(leaves: &[L]) -> StdResult<MkSetProof<L>>;
76}
77
78impl MkSetProofTestExtension<CardanoBlock> for MkSetProof<CardanoBlock> {
79 fn from_leaves<S: MKTreeStorer>(
80 leaves: &[CardanoBlock],
81 ) -> StdResult<MkSetProof<CardanoBlock>> {
82 let node_per_block_range = BlockNumber::group_items_by_block_range(
83 leaves.iter().map(|l| (l.block_number, l.clone().into_mk_tree_node())),
84 );
85 let all_nodes = node_per_block_range.values().flatten().cloned().collect::<Vec<_>>();
86 let mk_map =
87 mkmap_helpers::fold_nodes_per_block_range_into_mkmap::<_, _, S>(node_per_block_range)?;
88 let proof = mk_map.compute_proof(&all_nodes)?;
89
90 Ok(MkSetProof::new(leaves.to_vec(), proof))
91 }
92}
93
94impl MkSetProofTestExtension<CardanoTransaction> for MkSetProof<CardanoTransaction> {
95 fn from_leaves<S: MKTreeStorer>(
96 leaves: &[CardanoTransaction],
97 ) -> StdResult<MkSetProof<CardanoTransaction>> {
98 let node_per_block_range = BlockNumber::group_items_by_block_range(
99 leaves.iter().map(|l| (l.block_number, l.clone().into_mk_tree_node())),
100 );
101 let all_nodes = node_per_block_range.values().flatten().cloned().collect::<Vec<_>>();
102 let mk_map =
103 mkmap_helpers::fold_nodes_per_block_range_into_mkmap::<_, _, S>(node_per_block_range)?;
104 let proof = mk_map.compute_proof(&all_nodes)?;
105
106 Ok(MkSetProof::new(leaves.to_vec(), proof))
107 }
108}
109
110pub trait SingleSignatureTestExtension {
112 fn fake<TPartyId: Into<String>, TMessage: Into<String>>(
114 party_id: TPartyId,
115 message: TMessage,
116 ) -> SingleSignature;
117}
118
119impl SingleSignatureTestExtension for SingleSignature {
120 fn fake<TPartyId: Into<String>, TMessage: Into<String>>(
121 party_id: TPartyId,
122 message: TMessage,
123 ) -> SingleSignature {
124 let party_id = party_id.into();
125 let message = message.into();
126
127 let fixture = MithrilFixtureBuilder::default()
128 .with_stake_distribution(StakeDistributionGenerationMethod::Custom(
129 std::collections::BTreeMap::from([(party_id.to_string(), 100)]),
130 ))
131 .with_protocol_parameters(ProtocolParameters::new(1, 1, 1.0))
132 .build();
133 let signature = fixture.signers_fixture()[0].sign(&message).unwrap();
134
135 Self {
136 party_id,
137 signature: signature.signature,
138 won_indexes: vec![10, 15],
139 authentication_status: SingleSignatureAuthenticationStatus::Unauthenticated,
140 }
141 }
142}
143
144#[cfg(test)]
145mod tests {
146 use super::*;
147
148 #[test]
149 fn group_list_of_blocknumber_and_string_tuple_by_block_range() {
150 let input = [
151 (BlockNumber(1), "item_1"),
152 (BlockNumber(2), "item_2"),
153 (BlockNumber(3), "item_3"),
154 (BlockNumber(16), "item_16"),
155 (BlockNumber(17), "item_17"),
156 ];
157
158 let grouped_items = BlockNumber::group_items_by_block_range(input.iter().cloned());
159
160 assert_eq!(
161 HashMap::from([
162 (
163 BlockRange::from_block_number(BlockNumber(1)),
164 vec!["item_1", "item_2", "item_3"]
165 ),
166 (
167 BlockRange::from_block_number(BlockNumber(16)),
168 vec!["item_16", "item_17"]
169 ),
170 ]),
171 grouped_items
172 );
173 }
174}