1
1
//! The module used for parsing Cardano transactions
2
-
3
2
use crate :: {
4
3
digesters:: ImmutableFile ,
5
4
entities:: { Beacon , BlockNumber , CardanoTransaction , ImmutableFileNumber , TransactionHash } ,
6
5
StdResult ,
7
6
} ;
8
- use anyhow:: Context ;
7
+ use anyhow:: { anyhow , Context } ;
9
8
use async_trait:: async_trait;
10
- use pallas_traverse:: {
11
- probe:: { block_era, Outcome } ,
12
- MultiEraBlock ,
13
- } ;
14
- use std:: { cmp:: min, fs, path:: Path } ;
9
+ use pallas_hardano:: storage:: immutable:: chunk:: { read_blocks, Reader } ;
10
+ use pallas_traverse:: MultiEraBlock ;
11
+ use std:: path:: Path ;
15
12
use tokio:: sync:: RwLock ;
16
13
17
14
/// A parser that can read cardano transactions in a cardano database
@@ -119,43 +116,54 @@ impl CardanoTransactionParser {
119
116
120
117
/// Read blocks from immutable file
121
118
fn read_blocks_from_immutable_file ( immutable_file : & ImmutableFile ) -> StdResult < Vec < Block > > {
122
- let cbor = fs:: read ( & immutable_file. path ) . with_context ( || {
119
+ let cardano_blocks_reader =
120
+ CardanoTransactionParser :: cardano_blocks_reader ( immutable_file) ?;
121
+
122
+ let mut blocks = Vec :: new ( ) ;
123
+ for parsed_block in cardano_blocks_reader {
124
+ let block = parsed_block. with_context ( || {
125
+ format ! (
126
+ "Error while reading block in immutable file: '{:?}'" ,
127
+ immutable_file. path
128
+ )
129
+ } ) ?;
130
+ blocks. push ( CardanoTransactionParser :: convert_to_block (
131
+ & block,
132
+ immutable_file,
133
+ ) ?) ;
134
+ }
135
+ Ok ( blocks)
136
+ }
137
+
138
+ fn convert_to_block ( block : & [ u8 ] , immutable_file : & ImmutableFile ) -> StdResult < Block > {
139
+ let multi_era_block = MultiEraBlock :: decode ( block) . with_context ( || {
123
140
format ! (
124
- "CardanoTransactionParser could not read from immutable file: {:?}" ,
141
+ "Error while decoding block in immutable file: ' {:?}' " ,
125
142
immutable_file. path
126
143
)
127
144
} ) ?;
128
145
129
- let mut blocks_start_byte_index: Vec < _ > = ( 0 ..cbor. len ( ) )
130
- . filter ( |& byte_index| {
131
- let cbor_header_maybe = & cbor[ byte_index..min ( byte_index + 2 , cbor. len ( ) ) ] ;
132
- match block_era ( cbor_header_maybe) {
133
- Outcome :: Matched ( _) | Outcome :: EpochBoundary => true ,
134
- Outcome :: Inconclusive => false ,
135
- }
136
- } )
137
- . collect ( ) ;
138
-
139
- blocks_start_byte_index. push ( cbor. len ( ) + 1 ) ;
146
+ Block :: try_convert ( multi_era_block, immutable_file. number ) . with_context ( || {
147
+ format ! (
148
+ "CardanoTransactionParser could not read data from block in immutable file: {:?}" ,
149
+ immutable_file. path
150
+ )
151
+ } )
152
+ }
140
153
141
- let mut blocks = Vec :: new ( ) ;
142
- let mut last_start_byte_index = 0 ;
143
- for block_start_index in blocks_start_byte_index. into_iter ( ) . skip ( 1 ) {
144
- let maybe_end_byte_index = min ( block_start_index, cbor. len ( ) ) ;
145
- if let Ok ( multi_era_block) =
146
- MultiEraBlock :: decode ( & cbor[ last_start_byte_index..maybe_end_byte_index] )
147
- {
148
- let block = Block :: try_convert ( multi_era_block, immutable_file. number )
149
- . with_context ( || {
150
- format ! (
151
- "CardanoTransactionParser could not read data from block in immutable file: {:?}" ,
152
- immutable_file. path
153
- )
154
- } ) ?;
155
- blocks. push ( block) ;
156
- last_start_byte_index = block_start_index;
157
- }
158
- }
154
+ fn cardano_blocks_reader ( immutable_file : & ImmutableFile ) -> StdResult < Reader > {
155
+ let dir_path = immutable_file. path . parent ( ) . ok_or ( anyhow ! ( format!(
156
+ "Could not retrieve immutable file directory with immutable file path: '{:?}'" ,
157
+ immutable_file. path
158
+ ) ) ) ?;
159
+ let file_name = & Path :: new ( & immutable_file. filename )
160
+ . file_stem ( )
161
+ . ok_or ( anyhow ! ( format!(
162
+ "Could not extract immutable file name from file: '{}'" ,
163
+ immutable_file. filename
164
+ ) ) ) ?
165
+ . to_string_lossy ( ) ;
166
+ let blocks = read_blocks ( dir_path, file_name) ?;
159
167
160
168
Ok ( blocks)
161
169
}
@@ -222,7 +230,7 @@ mod tests {
222
230
#[ tokio:: test]
223
231
async fn test_parse_expected_number_of_transactions ( ) {
224
232
// We known the number of transactions in those prebuilt immutables
225
- let immutable_files = [ ( "00000" , 20usize ) , ( "00001" , 9 ) , ( "00002" , 0 ) ] ;
233
+ let immutable_files = [ ( "00000" , 0usize ) , ( "00001" , 2 ) , ( "00002" , 3 ) ] ;
226
234
let db_path = Path :: new ( "../mithril-test-lab/test_data/immutable/" ) ;
227
235
assert ! ( get_number_of_immutable_chunk_in_dir( db_path) >= 3 ) ;
228
236
@@ -244,12 +252,12 @@ mod tests {
244
252
#[ tokio:: test]
245
253
async fn test_parse_up_to_given_beacon ( ) {
246
254
// We known the number of transactions in those prebuilt immutables
247
- let immutable_files = [ ( "00000" , 20usize ) ] ;
255
+ let immutable_files = [ ( "00000" , 0usize ) , ( "00001" , 2 ) ] ;
248
256
let db_path = Path :: new ( "../mithril-test-lab/test_data/immutable/" ) ;
249
257
assert ! ( get_number_of_immutable_chunk_in_dir( db_path) >= 2 ) ;
250
258
251
259
let beacon = Beacon {
252
- immutable_file_number : 0 ,
260
+ immutable_file_number : 1 ,
253
261
..Beacon :: default ( )
254
262
} ;
255
263
let tx_count: usize = immutable_files. iter ( ) . map ( |( _, count) | * count) . sum ( ) ;
0 commit comments