Skip to content

Commit 5658d8b

Browse files
authored
Merge pull request #1564 from input-output-hk/ensemble/1557-use-pallas-hardano-transactions-parser
Use pallas hardano transactions parser
2 parents 3f4b049 + 1c18a84 commit 5658d8b

File tree

17 files changed

+99
-110
lines changed

17 files changed

+99
-110
lines changed

Cargo.lock

Lines changed: 38 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

mithril-common/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mithril-common"
3-
version = "0.3.16"
3+
version = "0.3.17"
44
description = "Common types, interfaces, and utilities for Mithril nodes."
55
authors = { workspace = true }
66
edition = { workspace = true }
@@ -42,6 +42,7 @@ minicbor = { version = "0.20", features = [
4242
nom = "7.1.3"
4343
pallas-addresses = { version = "0.24.0", optional = true }
4444
pallas-codec = { version = "0.24.0", optional = true }
45+
pallas-hardano = { version = "0.24.0", optional = true }
4546
pallas-network = { version = "0.24.0", optional = true }
4647
pallas-primitives = { version = "0.24.0", optional = true }
4748
pallas-traverse = { version = "0.24.0", optional = true }
@@ -107,6 +108,7 @@ fs = [
107108
"dep:minicbor",
108109
"dep:pallas-addresses",
109110
"dep:pallas-codec",
111+
"dep:pallas-hardano",
110112
"dep:pallas-network",
111113
"dep:pallas-primitives",
112114
"dep:pallas-traverse",

mithril-common/src/cardano_transaction_parser.rs

Lines changed: 49 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,14 @@
11
//! The module used for parsing Cardano transactions
2-
32
use crate::{
43
digesters::ImmutableFile,
54
entities::{Beacon, BlockNumber, CardanoTransaction, ImmutableFileNumber, TransactionHash},
65
StdResult,
76
};
8-
use anyhow::Context;
7+
use anyhow::{anyhow, Context};
98
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;
1512
use tokio::sync::RwLock;
1613

1714
/// A parser that can read cardano transactions in a cardano database
@@ -119,43 +116,54 @@ impl CardanoTransactionParser {
119116

120117
/// Read blocks from immutable file
121118
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(|| {
123140
format!(
124-
"CardanoTransactionParser could not read from immutable file: {:?}",
141+
"Error while decoding block in immutable file: '{:?}'",
125142
immutable_file.path
126143
)
127144
})?;
128145

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+
}
140153

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)?;
159167

160168
Ok(blocks)
161169
}
@@ -222,7 +230,7 @@ mod tests {
222230
#[tokio::test]
223231
async fn test_parse_expected_number_of_transactions() {
224232
// 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)];
226234
let db_path = Path::new("../mithril-test-lab/test_data/immutable/");
227235
assert!(get_number_of_immutable_chunk_in_dir(db_path) >= 3);
228236

@@ -244,12 +252,12 @@ mod tests {
244252
#[tokio::test]
245253
async fn test_parse_up_to_given_beacon() {
246254
// We known the number of transactions in those prebuilt immutables
247-
let immutable_files = [("00000", 20usize)];
255+
let immutable_files = [("00000", 0usize), ("00001", 2)];
248256
let db_path = Path::new("../mithril-test-lab/test_data/immutable/");
249257
assert!(get_number_of_immutable_chunk_in_dir(db_path) >= 2);
250258

251259
let beacon = Beacon {
252-
immutable_file_number: 0,
260+
immutable_file_number: 1,
253261
..Beacon::default()
254262
};
255263
let tx_count: usize = immutable_files.iter().map(|(_, count)| *count).sum();

mithril-test-lab/mithril-end-to-end/README.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@
1717
# Download sources from github
1818
git clone https://github.com/input-output-hk/mithril
1919

20+
# Build nodes
21+
make -C mithril-aggregator build
22+
make -C mithril-signer build
23+
make -C mithril-client-cli build
24+
make -C mithril-relay build
25+
2026
# Go to sources directory
2127
cd mithril-test-lab/mithril-end-to-end
2228
```
@@ -31,7 +37,7 @@ make build
3137
./mithril-end-to-end --help
3238

3339
# Run
34-
./mithril-end-to-end -vvv --db-directory db/ --bin-directory ../../target/release
40+
./mithril-end-to-end -vvv --work-directory db/ --bin-directory ../../target/release --devnet-scripts-directory=../mithril-devnet
3541
```
3642

3743
To run `mithril-end-to-end` command, you must first compile the Mithril nodes:

mithril-test-lab/test_data/README.md

Lines changed: 2 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -5,69 +5,5 @@
55
> immutable db directory by our db parser (see ([immutable_file.rs](./../../mithril-common/src/digesters/immutable_file.rs))).
66
77
> [!NOTE]
8-
> The `.primary` and `.secondary` files are not real data. They're empty files that are
9-
> here in order to simulate a real cardano immutable db structure.
10-
11-
These files were generated manually from the blocks in the sibling folder:
12-
13-
| Imput Block file | Number of transactions | Output immutable file |
14-
|------------------|------------------------|-----------------------|
15-
| [byron2.block](./blocks/byron2.block) | `2` | `00000.chunk` |
16-
| [shelley1.block](./blocks/shelley1.block) | `4` | `00000.chunk` |
17-
| [mary1.block](./blocks/mary1.block) | `14` | `00000.chunk` |
18-
| [allegra1.block](./blocks/allegra1.block) | `3` | `00001.chunk` |
19-
| [alonzo1.block](./blocks/alonzo1.block) | `5` | `00001.chunk` |
20-
| [conway1.block](./blocks/conway1.block) | `1` | `00001.chunk` |
21-
22-
The following code was used to generate the immutable files:
23-
```rust
24-
use std::io::Write;
25-
26-
let immutable_files = vec![
27-
(
28-
"./00000.chunk",
29-
vec![
30-
(
31-
include_str!("./blocks/byron2.block"),
32-
2usize,
33-
),
34-
(
35-
include_str!("./blocks/shelley1.block"),
36-
4,
37-
),
38-
(
39-
include_str!("./blocks/mary1.block"),
40-
14,
41-
),
42-
],
43-
),
44-
(
45-
"./00001.chunk",
46-
vec![
47-
(
48-
include_str!("./blocks/allegra1.block"),
49-
3,
50-
),
51-
(
52-
include_str!("./blocks/alonzo1.block"),
53-
5,
54-
),
55-
(
56-
include_str!("./blocks/conway1.block"),
57-
5,
58-
),
59-
],
60-
),
61-
];
62-
63-
for immutable_file_definition in immutable_files {
64-
let immutable_file_path = immutable_file_definition.0;
65-
let mut immutable_file = fs::File::create(immutable_file_path).unwrap();
66-
67-
for (block_str, _tx_count) in immutable_file_definition.1.into_iter() {
68-
let cbor = hex::decode(block_str).expect("invalid hex");
69-
immutable_file.write_all(&cbor).unwrap();
70-
}
71-
}
72-
```
73-
8+
> The immutable files (`.chunk`, `.primary` and `.secondary`) files are data that are the result of
9+
> the `mithril-end-to-end` test command execution.
58.6 KB
Binary file not shown.
409 Bytes
Binary file not shown.
5.47 KB
Binary file not shown.
76.8 KB
Binary file not shown.
409 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)