1
- use std:: sync:: Arc ;
1
+ use std:: { collections :: HashMap , sync:: Arc } ;
2
2
3
3
use anyhow:: Context ;
4
4
use async_trait:: async_trait;
5
5
6
6
use mithril_common:: {
7
- crypto_helper:: { MKTree , MKTreeNode , MKTreeStore } ,
8
- entities:: { Beacon , CardanoTransaction , CardanoTransactionsSetProof , TransactionHash } ,
7
+ crypto_helper:: { MKMap , MKMapNode , MKTree , MKTreeNode } ,
8
+ entities:: {
9
+ Beacon , BlockRange , CardanoTransaction , CardanoTransactionsSetProof , TransactionHash ,
10
+ } ,
9
11
StdResult ,
10
12
} ;
11
13
@@ -44,6 +46,36 @@ impl MithrilProverService {
44
46
transaction_retriever,
45
47
}
46
48
}
49
+
50
+ fn compute_merkle_map_from_transactions (
51
+ & self ,
52
+ transactions : & [ CardanoTransaction ] ,
53
+ ) -> StdResult < MKMap < BlockRange , MKMapNode < BlockRange > > > {
54
+ let mut transactions_by_block_ranges: HashMap < BlockRange , Vec < TransactionHash > > =
55
+ HashMap :: new ( ) ;
56
+ for transaction in transactions {
57
+ let block_range = BlockRange :: from_block_number ( transaction. block_number ) ;
58
+ transactions_by_block_ranges
59
+ . entry ( block_range)
60
+ . or_default ( )
61
+ . push ( transaction. transaction_hash . to_owned ( ) ) ;
62
+ }
63
+ let mk_hash_map = MKMap :: new (
64
+ transactions_by_block_ranges
65
+ . into_iter ( )
66
+ . try_fold (
67
+ vec ! [ ] ,
68
+ |mut acc, ( block_range, transactions) | -> StdResult < Vec < ( _ , MKMapNode < _ > ) > > {
69
+ acc. push ( ( block_range, MKTree :: new ( & transactions) ?. into ( ) ) ) ;
70
+ Ok ( acc)
71
+ } ,
72
+ ) ?
73
+ . as_slice ( ) ,
74
+ )
75
+ . with_context ( || "ProverService failed to compute the merkelized structure that proves ownership of the transaction" ) ?;
76
+
77
+ Ok ( mk_hash_map)
78
+ }
47
79
}
48
80
49
81
#[ async_trait]
@@ -54,26 +86,33 @@ impl ProverService for MithrilProverService {
54
86
transaction_hashes : & [ TransactionHash ] ,
55
87
) -> StdResult < Vec < CardanoTransactionsSetProof > > {
56
88
let transactions = self . transaction_retriever . get_up_to ( up_to) . await ?;
57
- let mk_leaves_all: Vec < MKTreeNode > =
58
- transactions. iter ( ) . map ( |t| t. to_owned ( ) . into ( ) ) . collect ( ) ;
59
- let store = MKTreeStore :: default ( ) ;
60
- let mktree = MKTree :: new ( & mk_leaves_all, & store)
61
- . with_context ( || "MKTree creation should not fail" ) ?;
62
-
89
+ let mk_map = self . compute_merkle_map_from_transactions ( & transactions) ?;
90
+ let transactions_to_prove = transactions
91
+ . iter ( )
92
+ . filter_map ( |transaction| {
93
+ let block_range = BlockRange :: from_block_number ( transaction. block_number ) ;
94
+ transaction_hashes
95
+ . contains ( & transaction. transaction_hash )
96
+ . then ( || ( block_range, transaction. to_owned ( ) ) )
97
+ } )
98
+ . collect :: < Vec < _ > > ( ) ;
63
99
let mut transaction_hashes_certified = vec ! [ ] ;
64
- for transaction_hash in transaction_hashes {
65
- let mk_leaf = transaction_hash. to_string ( ) . into ( ) ;
66
- if mktree. compute_proof ( & [ mk_leaf] ) . is_ok ( ) {
67
- transaction_hashes_certified. push ( transaction_hash. to_string ( ) ) ;
100
+ for ( _block_range, transaction) in transactions_to_prove {
101
+ let mk_tree_node_transaction_hash: MKTreeNode =
102
+ transaction. transaction_hash . to_owned ( ) . into ( ) ;
103
+ if mk_map
104
+ . compute_proof ( & [ mk_tree_node_transaction_hash] )
105
+ . is_ok ( )
106
+ {
107
+ transaction_hashes_certified. push ( transaction. transaction_hash . to_string ( ) ) ;
68
108
}
69
109
}
70
-
71
110
if !transaction_hashes_certified. is_empty ( ) {
72
111
let mk_leaves: Vec < MKTreeNode > = transaction_hashes_certified
73
112
. iter ( )
74
113
. map ( |h| h. to_owned ( ) . into ( ) )
75
114
. collect ( ) ;
76
- let mk_proof = mktree . compute_proof ( & mk_leaves) ?;
115
+ let mk_proof = mk_map . compute_proof ( & mk_leaves) ?;
77
116
let transactions_set_proof_batch =
78
117
CardanoTransactionsSetProof :: new ( transaction_hashes_certified, mk_proof) ;
79
118
@@ -171,9 +210,6 @@ mod tests {
171
210
transactions_set_proof[ 0 ] . verify ( ) . unwrap ( ) ;
172
211
}
173
212
174
- // this one can't be done right now because we don't have a merkle tree of merkle tree yet
175
- // todo: compute_proof_for_multiple_set_with_multiple_transactions
176
-
177
213
#[ tokio:: test]
178
214
async fn cant_compute_proof_if_retriever_fail ( ) {
179
215
let ( transaction_hashes, _transactions) = generate_transactions ( 3 ) ;
0 commit comments