@@ -9,12 +9,15 @@ use mithril_common::entities::{
9
9
BlockHash , BlockNumber , BlockRange , CardanoDbBeacon , CardanoTransaction , ImmutableFileNumber ,
10
10
SlotNumber , TransactionHash ,
11
11
} ;
12
+ use mithril_common:: signable_builder:: BlockRangeRootRetriever ;
12
13
use mithril_common:: StdResult ;
13
14
use mithril_persistence:: sqlite:: { Provider , SqliteConnection , WhereCondition } ;
15
+ use sqlite:: Value ;
14
16
15
17
use crate :: database:: provider:: {
16
- GetCardanoTransactionProvider , GetIntervalWithoutBlockRangeRootProvider ,
17
- InsertBlockRangeRootProvider , InsertCardanoTransactionProvider ,
18
+ GetBlockRangeRootProvider , GetCardanoTransactionProvider ,
19
+ GetIntervalWithoutBlockRangeRootProvider , InsertBlockRangeRootProvider ,
20
+ InsertCardanoTransactionProvider ,
18
21
} ;
19
22
use crate :: database:: record:: { BlockRangeRootRecord , CardanoTransactionRecord } ;
20
23
use crate :: services:: { TransactionStore , TransactionsRetriever } ;
@@ -60,8 +63,14 @@ impl CardanoTransactionRepository {
60
63
& self ,
61
64
beacon : ImmutableFileNumber ,
62
65
) -> StdResult < Vec < CardanoTransactionRecord > > {
66
+ // Get the highest block number for the given immutable number.
67
+ // This is a temporary fix that will be removed when the retrieval is based on block number instead of immutable number.
68
+ let block_number = self
69
+ . get_highest_block_number_for_immutable_number ( beacon)
70
+ . await ?
71
+ . unwrap_or ( 0 ) ;
63
72
let provider = GetCardanoTransactionProvider :: new ( & self . connection ) ;
64
- let filters = provider. get_transaction_up_to_beacon_condition ( beacon ) ;
73
+ let filters = provider. get_transaction_between_blocks_condition ( 0 ..block_number ) ;
65
74
let transactions = provider. find ( filters) ?;
66
75
67
76
Ok ( transactions. collect ( ) )
@@ -130,6 +139,48 @@ impl CardanoTransactionRepository {
130
139
131
140
Ok ( cursor. collect ( ) )
132
141
}
142
+
143
+ // TODO: remove this function when the Cardano transaction signature is based on block number instead of immutable number
144
+ async fn get_highest_block_number_for_immutable_number (
145
+ & self ,
146
+ immutable_file_number : ImmutableFileNumber ,
147
+ ) -> StdResult < Option < BlockNumber > > {
148
+ let sql =
149
+ "select max(block_number) as highest from cardano_tx where immutable_file_number <= $1;" ;
150
+ match self
151
+ . connection
152
+ . prepare ( sql)
153
+ . with_context ( || {
154
+ format ! (
155
+ "Prepare query error: SQL=`{}`" ,
156
+ & sql. replace( '\n' , " " ) . trim( )
157
+ )
158
+ } ) ?
159
+ . iter ( )
160
+ . bind :: < & [ ( _ , Value ) ] > ( & [ ( 1 , Value :: Integer ( immutable_file_number as i64 ) ) ] ) ?
161
+ . next ( )
162
+ {
163
+ None => Ok ( None ) ,
164
+ Some ( row) => {
165
+ let highest = row?. read :: < Option < i64 > , _ > ( 0 ) ;
166
+ highest
167
+ . map ( u64:: try_from)
168
+ . transpose ( )
169
+ . with_context ( ||
170
+ format ! ( "Integer field max(block_number) (value={highest:?}) is incompatible with u64 representation." )
171
+ )
172
+ }
173
+ }
174
+ }
175
+
176
+ #[ cfg( test) ]
177
+ pub ( crate ) async fn get_all ( & self ) -> StdResult < Vec < CardanoTransaction > > {
178
+ let provider = GetCardanoTransactionProvider :: new ( & self . connection ) ;
179
+ let filters = WhereCondition :: default ( ) ;
180
+ let transactions = provider. find ( filters) ?;
181
+
182
+ Ok ( transactions. map ( |record| record. into ( ) ) . collect :: < Vec < _ > > ( ) )
183
+ }
133
184
}
134
185
135
186
#[ cfg( test) ]
@@ -261,6 +312,31 @@ impl TransactionsRetriever for CardanoTransactionRepository {
261
312
}
262
313
}
263
314
315
+ #[ async_trait]
316
+ impl BlockRangeRootRetriever for CardanoTransactionRepository {
317
+ async fn retrieve_block_range_roots (
318
+ & self ,
319
+ up_to_beacon : ImmutableFileNumber ,
320
+ ) -> StdResult < Box < dyn Iterator < Item = ( BlockRange , MKTreeNode ) > > > {
321
+ // Get the highest block number for the given immutable number.
322
+ // This is a temporary fix that will be removed when the retrieval is based on block number instead of immutable number.
323
+ let block_number = self
324
+ . get_highest_block_number_for_immutable_number ( up_to_beacon)
325
+ . await ?
326
+ . unwrap_or ( 0 ) ;
327
+ let provider = GetBlockRangeRootProvider :: new ( & self . connection ) ;
328
+ let filters = provider. get_up_to_block_number_condition ( block_number) ;
329
+ let block_range_roots = provider. find ( filters) ?;
330
+ let block_range_roots = block_range_roots
331
+ . into_iter ( )
332
+ . map ( |record| -> ( BlockRange , MKTreeNode ) { record. into ( ) } )
333
+ . collect :: < Vec < _ > > ( ) // TODO: remove this collect when we should ba able return the iterator directly
334
+ . into_iter ( ) ;
335
+
336
+ Ok ( Box :: new ( block_range_roots) )
337
+ }
338
+ }
339
+
264
340
#[ cfg( test) ]
265
341
mod tests {
266
342
use mithril_persistence:: sqlite:: GetAllProvider ;
@@ -413,7 +489,7 @@ mod tests {
413
489
let cardano_transactions: Vec < CardanoTransactionRecord > = ( 20 ..=40 )
414
490
. map ( |i| CardanoTransactionRecord {
415
491
transaction_hash : format ! ( "tx-hash-{i}" ) ,
416
- block_number : i % 10 ,
492
+ block_number : i / 10 ,
417
493
slot_number : i * 100 ,
418
494
block_hash : format ! ( "block-hash-{i}" ) ,
419
495
immutable_file_number : i,
@@ -425,10 +501,10 @@ mod tests {
425
501
. unwrap ( ) ;
426
502
427
503
let transaction_result = repository. get_transactions_up_to ( 34 ) . await . unwrap ( ) ;
428
- assert_eq ! ( cardano_transactions[ 0 ..= 14 ] . to_vec( ) , transaction_result) ;
504
+ assert_eq ! ( cardano_transactions[ 0 ..10 ] . to_vec( ) , transaction_result) ;
429
505
430
506
let transaction_result = repository. get_transactions_up_to ( 300 ) . await . unwrap ( ) ;
431
- assert_eq ! ( cardano_transactions. clone ( ) , transaction_result) ;
507
+ assert_eq ! ( cardano_transactions[ 0 .. 20 ] . to_vec ( ) , transaction_result) ;
432
508
433
509
let transaction_result = repository. get_transactions_up_to ( 19 ) . await . unwrap ( ) ;
434
510
assert_eq ! ( Vec :: <CardanoTransactionRecord >:: new( ) , transaction_result) ;
0 commit comments