@@ -5,6 +5,12 @@ use crate::{StdError, StdResult};
5
5
6
6
use super :: BlockRange ;
7
7
8
+ cfg_test_tools ! {
9
+ use crate :: crypto_helper:: { MKMap , MKTree , MKTreeNode , MKMapNode } ;
10
+ use crate :: entities:: BlockNumber ;
11
+ use std:: collections:: HashMap ;
12
+ }
13
+
8
14
/// A cryptographic proof of a set of Cardano transactions is included in the global Cardano transactions set
9
15
#[ derive( Clone , Debug , PartialEq ) ]
10
16
pub struct CardanoTransactionsSetProof {
@@ -50,42 +56,51 @@ impl CardanoTransactionsSetProof {
50
56
cfg_test_tools ! {
51
57
/// Retrieve a dummy proof (for test only)
52
58
pub fn dummy( ) -> Self {
53
- use crate :: crypto_helper:: { MKMap , MKTree , MKMapNode } ;
54
-
55
- let transaction_hashes_by_block_range = vec![
56
- (
57
- ( 0 ..10 ) . into( ) ,
58
- vec![ "tx-1" . to_string( ) , "tx-2" . to_string( ) , "tx-3" . to_string( ) ] ,
59
- ) ,
60
- (
61
- ( 10 ..20 ) . into( ) ,
62
- vec![ "tx-4" . to_string( ) ] ,
63
- ) ,
64
- (
65
- ( 20 ..30 ) . into( ) ,
66
- vec![ "tx-5" . to_string( ) , "tx-6" . to_string( ) ] ,
67
- ) ,
59
+ let leaves = vec![
60
+ ( 0 , "tx-1" . to_string( ) ) ,
61
+ ( 1 , "tx-2" . to_string( ) ) ,
62
+ ( 1 , "tx-3" . to_string( ) ) ,
63
+ ( 10 , "tx-4" . to_string( ) ) ,
64
+ ( 20 , "tx-5" . to_string( ) ) ,
65
+ ( 22 , "tx-6" . to_string( ) ) ,
68
66
] ;
69
- let transaction_hashes_to_certify = transaction_hashes_by_block_range
70
- . iter( )
71
- . flat_map( |( _, h) | h. to_owned( ) )
72
- . collect:: <Vec <TransactionHash >>( ) ;
73
67
74
- let mk_hash_map: MKMap <_, MKMapNode <_>> = MKMap :: new(
75
- transaction_hashes_by_block_range
68
+ Self :: from_leaves( & leaves) . unwrap( )
69
+ }
70
+
71
+ /// Helper to create a proof from a list of leaves
72
+ pub fn from_leaves( leaves: & [ ( BlockNumber , TransactionHash ) ] ) -> StdResult <Self > {
73
+ let transactions_hashes: Vec <TransactionHash > =
74
+ leaves. iter( ) . map( |( _, t) | t. into( ) ) . collect( ) ;
75
+ let mut transactions_by_block_ranges: HashMap <BlockRange , Vec <TransactionHash >> =
76
+ HashMap :: new( ) ;
77
+ for ( block_number, transaction_hash) in leaves {
78
+ let block_range = BlockRange :: from_block_number( * block_number) ;
79
+ transactions_by_block_ranges
80
+ . entry( block_range)
81
+ . or_default( )
82
+ . push( transaction_hash. to_owned( ) ) ;
83
+ }
84
+ let mk_map = MKMap :: new(
85
+ transactions_by_block_ranges
76
86
. into_iter( )
77
- . map( |( block_range, transactions) | {
78
- ( block_range, MKTree :: new( & transactions) . unwrap( ) . into( ) )
79
- } )
80
- . collect:: <Vec <_>>( )
87
+ . try_fold(
88
+ vec![ ] ,
89
+ |mut acc, ( block_range, transactions) | -> StdResult <Vec <( _, MKMapNode <_>) >> {
90
+ acc. push( ( block_range, MKTree :: new( & transactions) ?. into( ) ) ) ;
91
+ Ok ( acc)
92
+ } ,
93
+ ) ?
81
94
. as_slice( ) ,
82
- )
83
- . unwrap( ) ;
84
- let proof = mk_hash_map
85
- . compute_proof( & transaction_hashes_to_certify)
86
- . unwrap( ) ;
87
- Self :: new( transaction_hashes_to_certify, proof)
95
+ ) ?;
96
+ let mk_leaves: Vec <MKTreeNode > = transactions_hashes
97
+ . iter( )
98
+ . map( |h| h. to_owned( ) . into( ) )
99
+ . collect( ) ;
100
+ let mk_proof = mk_map. compute_proof( & mk_leaves) ?;
101
+ Ok ( Self :: new( transactions_hashes, mk_proof) )
88
102
}
103
+
89
104
}
90
105
}
91
106
@@ -117,14 +132,30 @@ mod tests {
117
132
118
133
#[ test]
119
134
fn should_verify_where_all_hashes_are_contained_in_the_proof ( ) {
120
- let proof = CardanoTransactionsSetProof :: dummy ( ) ;
135
+ let leaves = vec ! [
136
+ ( 0 , "tx-1" . to_string( ) ) ,
137
+ ( 1 , "tx-2" . to_string( ) ) ,
138
+ ( 1 , "tx-3" . to_string( ) ) ,
139
+ ( 10 , "tx-4" . to_string( ) ) ,
140
+ ( 20 , "tx-5" . to_string( ) ) ,
141
+ ( 22 , "tx-6" . to_string( ) ) ,
142
+ ] ;
143
+ let proof = CardanoTransactionsSetProof :: from_leaves ( & leaves) . unwrap ( ) ;
121
144
122
145
proof. verify ( ) . expect ( "The proof should be valid" ) ;
123
146
}
124
147
125
148
#[ test]
126
149
fn shouldnt_verify_where_at_least_one_hash_is_not_contained_in_the_proof ( ) {
127
- let proof = CardanoTransactionsSetProof :: dummy ( ) ;
150
+ let leaves = vec ! [
151
+ ( 0 , "tx-1" . to_string( ) ) ,
152
+ ( 1 , "tx-2" . to_string( ) ) ,
153
+ ( 1 , "tx-3" . to_string( ) ) ,
154
+ ( 10 , "tx-4" . to_string( ) ) ,
155
+ ( 20 , "tx-5" . to_string( ) ) ,
156
+ ( 22 , "tx-6" . to_string( ) ) ,
157
+ ] ;
158
+ let proof = CardanoTransactionsSetProof :: from_leaves ( & leaves) . unwrap ( ) ;
128
159
let mut transactions_hashes_tampered = proof. transactions_hashes ( ) . to_vec ( ) ;
129
160
transactions_hashes_tampered. push ( "tx-123" . to_string ( ) ) ;
130
161
let proof = CardanoTransactionsSetProof {
0 commit comments