Skip to content

Commit 563dde0

Browse files
authored
Merge pull request #2159 from input-output-hk/dlachaume/2151/implement-artifact-builder-cardano-database
Feat: implement artifact builder for `CardanoDatabase`
2 parents 490e2c9 + d27a9a6 commit 563dde0

File tree

14 files changed

+516
-79
lines changed

14 files changed

+516
-79
lines changed

Cargo.lock

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

mithril-aggregator/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mithril-aggregator"
3-
version = "0.5.119"
3+
version = "0.5.120"
44
description = "A Mithril Aggregator server"
55
authors = { workspace = true }
66
edition = { workspace = true }
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
use std::path::{Path, PathBuf};
2+
3+
use anyhow::{anyhow, Context};
4+
use async_trait::async_trait;
5+
use semver::Version;
6+
7+
use mithril_common::{
8+
entities::{
9+
ArtifactsLocations, CardanoDatabaseSnapshot, CardanoDbBeacon, Certificate,
10+
CompressionAlgorithm, ProtocolMessagePartKey, SignedEntityType,
11+
},
12+
StdResult,
13+
};
14+
15+
use crate::artifact_builder::ArtifactBuilder;
16+
17+
pub struct CardanoDatabaseArtifactBuilder {
18+
db_directory: PathBuf, // TODO: temporary, will be accessed through another dependency instead of direct path.
19+
cardano_node_version: Version,
20+
compression_algorithm: CompressionAlgorithm,
21+
}
22+
23+
impl CardanoDatabaseArtifactBuilder {
24+
pub fn new(
25+
db_directory: PathBuf,
26+
cardano_node_version: &Version,
27+
compression_algorithm: CompressionAlgorithm,
28+
) -> Self {
29+
Self {
30+
db_directory,
31+
cardano_node_version: cardano_node_version.clone(),
32+
compression_algorithm,
33+
}
34+
}
35+
}
36+
37+
#[async_trait]
38+
impl ArtifactBuilder<CardanoDbBeacon, CardanoDatabaseSnapshot> for CardanoDatabaseArtifactBuilder {
39+
async fn compute_artifact(
40+
&self,
41+
beacon: CardanoDbBeacon,
42+
certificate: &Certificate,
43+
) -> StdResult<CardanoDatabaseSnapshot> {
44+
let merkle_root = certificate
45+
.protocol_message
46+
.get_message_part(&ProtocolMessagePartKey::CardanoDatabaseMerkleRoot)
47+
.ok_or(anyhow!(
48+
"Can not find CardanoDatabaseMerkleRoot protocol message part in certificate"
49+
))
50+
.with_context(|| {
51+
format!(
52+
"Can not compute CardanoDatabase artifact for signed_entity: {:?}",
53+
SignedEntityType::CardanoDatabase(beacon.clone())
54+
)
55+
})?;
56+
let total_db_size_uncompressed = compute_uncompressed_database_size(&self.db_directory)?;
57+
58+
let cardano_database = CardanoDatabaseSnapshot::new(
59+
merkle_root.to_string(),
60+
beacon,
61+
total_db_size_uncompressed,
62+
ArtifactsLocations::default(), // TODO: temporary default locations, will be injected in next PR.
63+
self.compression_algorithm,
64+
&self.cardano_node_version,
65+
);
66+
67+
Ok(cardano_database)
68+
}
69+
}
70+
71+
fn compute_uncompressed_database_size(path: &Path) -> StdResult<u64> {
72+
if path.is_file() {
73+
let metadata = std::fs::metadata(path)
74+
.with_context(|| format!("Failed to read metadata for file: {:?}", path))?;
75+
76+
return Ok(metadata.len());
77+
}
78+
79+
if path.is_dir() {
80+
let entries = std::fs::read_dir(path)
81+
.with_context(|| format!("Failed to read directory: {:?}", path))?;
82+
let mut directory_size = 0;
83+
for entry in entries {
84+
let path = entry
85+
.with_context(|| format!("Failed to read directory entry in {:?}", path))?
86+
.path();
87+
directory_size += compute_uncompressed_database_size(&path)?;
88+
}
89+
90+
return Ok(directory_size);
91+
}
92+
93+
Ok(0)
94+
}
95+
96+
#[cfg(test)]
97+
mod tests {
98+
use std::path::PathBuf;
99+
100+
use mithril_common::{
101+
digesters::DummyImmutablesDbBuilder,
102+
entities::{ProtocolMessage, ProtocolMessagePartKey},
103+
test_utils::{fake_data, TempDir},
104+
};
105+
106+
use super::*;
107+
108+
fn get_test_directory(dir_name: &str) -> PathBuf {
109+
TempDir::create("cardano_database", dir_name)
110+
}
111+
112+
#[test]
113+
fn should_compute_the_size_of_the_uncompressed_database_only_immutable_ledger_and_volatile() {
114+
let test_dir = get_test_directory("should_compute_the_size_of_the_uncompressed_database_only_immutable_ledger_and_volatile");
115+
116+
let immutable_trio_file_size = 777;
117+
let ledger_file_size = 6666;
118+
let volatile_file_size = 99;
119+
DummyImmutablesDbBuilder::new(test_dir.as_os_str().to_str().unwrap())
120+
.with_immutables(&[1, 2])
121+
.set_immutable_trio_file_size(immutable_trio_file_size)
122+
.with_ledger_files(&["blocks-0.dat", "blocks-1.dat", "blocks-2.dat"])
123+
.set_ledger_file_size(ledger_file_size)
124+
.with_volatile_files(&["437", "537", "637", "737"])
125+
.set_volatile_file_size(volatile_file_size)
126+
.build();
127+
let expected_total_size =
128+
(2 * immutable_trio_file_size) + (3 * ledger_file_size) + (4 * volatile_file_size);
129+
130+
let total_size = compute_uncompressed_database_size(&test_dir).unwrap();
131+
132+
assert_eq!(expected_total_size, total_size);
133+
}
134+
135+
#[tokio::test]
136+
async fn should_compute_valid_artifact() {
137+
let test_dir = get_test_directory("should_compute_valid_artifact");
138+
139+
let immutable_trio_file_size = 777;
140+
let ledger_file_size = 6666;
141+
let volatile_file_size = 99;
142+
DummyImmutablesDbBuilder::new(test_dir.as_os_str().to_str().unwrap())
143+
.with_immutables(&[1])
144+
.set_immutable_trio_file_size(immutable_trio_file_size)
145+
.with_ledger_files(&["blocks-0.dat"])
146+
.set_ledger_file_size(ledger_file_size)
147+
.with_volatile_files(&["437"])
148+
.set_volatile_file_size(volatile_file_size)
149+
.build();
150+
let expected_total_size = immutable_trio_file_size + ledger_file_size + volatile_file_size;
151+
152+
let cardano_database_artifact_builder = CardanoDatabaseArtifactBuilder::new(
153+
test_dir,
154+
&Version::parse("1.0.0").unwrap(),
155+
CompressionAlgorithm::Zstandard,
156+
);
157+
158+
let beacon = fake_data::beacon();
159+
let certificate_with_merkle_root = {
160+
let mut protocol_message = ProtocolMessage::new();
161+
protocol_message.set_message_part(
162+
ProtocolMessagePartKey::CardanoDatabaseMerkleRoot,
163+
"merkleroot".to_string(),
164+
);
165+
Certificate {
166+
protocol_message,
167+
..fake_data::certificate("certificate-123".to_string())
168+
}
169+
};
170+
171+
let artifact = cardano_database_artifact_builder
172+
.compute_artifact(beacon.clone(), &certificate_with_merkle_root)
173+
.await
174+
.unwrap();
175+
176+
let artifact_expected = CardanoDatabaseSnapshot::new(
177+
"merkleroot".to_string(),
178+
beacon,
179+
expected_total_size,
180+
ArtifactsLocations::default(),
181+
CompressionAlgorithm::Zstandard,
182+
&Version::parse("1.0.0").unwrap(),
183+
);
184+
185+
assert_eq!(artifact_expected, artifact);
186+
}
187+
}

mithril-aggregator/src/artifact_builder/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
//! The module used for building artifact
2+
mod cardano_database;
23
mod cardano_immutable_files_full;
34
mod cardano_stake_distribution;
45
mod cardano_transactions;
56
mod interface;
67
mod mithril_stake_distribution;
78

9+
pub use cardano_database::*;
810
pub use cardano_immutable_files_full::*;
911
pub use cardano_stake_distribution::*;
1012
pub use cardano_transactions::*;

mithril-aggregator/src/dependency_injection/builder.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,9 @@ use mithril_persistence::{
5252
use super::{DependenciesBuilderError, EpochServiceWrapper, Result};
5353
use crate::{
5454
artifact_builder::{
55-
CardanoImmutableFilesFullArtifactBuilder, CardanoStakeDistributionArtifactBuilder,
56-
CardanoTransactionsArtifactBuilder, MithrilStakeDistributionArtifactBuilder,
55+
CardanoDatabaseArtifactBuilder, CardanoImmutableFilesFullArtifactBuilder,
56+
CardanoStakeDistributionArtifactBuilder, CardanoTransactionsArtifactBuilder,
57+
MithrilStakeDistributionArtifactBuilder,
5758
},
5859
configuration::ExecutionEnvironment,
5960
database::repository::{
@@ -1208,11 +1209,17 @@ impl DependenciesBuilder {
12081209
let stake_store = self.get_stake_store().await?;
12091210
let cardano_stake_distribution_artifact_builder =
12101211
Arc::new(CardanoStakeDistributionArtifactBuilder::new(stake_store));
1212+
let cardano_database_artifact_builder = Arc::new(CardanoDatabaseArtifactBuilder::new(
1213+
self.configuration.db_directory.clone(),
1214+
&cardano_node_version,
1215+
self.configuration.snapshot_compression_algorithm,
1216+
));
12111217
let dependencies = SignedEntityServiceArtifactsDependencies::new(
12121218
mithril_stake_distribution_artifact_builder,
12131219
cardano_immutable_files_full_artifact_builder,
12141220
cardano_transactions_artifact_builder,
12151221
cardano_stake_distribution_artifact_builder,
1222+
cardano_database_artifact_builder,
12161223
);
12171224
let signed_entity_service = Arc::new(MithrilSignedEntityService::new(
12181225
signed_entity_storer,

0 commit comments

Comments
 (0)