Skip to content

Commit 9d9e963

Browse files
authored
Merge pull request #2637 from input-output-hk/ctl/2618-list-invalid-or-missing-immutable-files-in-verify-command
List invalid or tampered immutable files in verify command
2 parents 0461172 + 9370314 commit 9d9e963

File tree

15 files changed

+1334
-265
lines changed

15 files changed

+1334
-265
lines changed

Cargo.lock

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

docs/website/root/manual/develop/nodes/mithril-client.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,9 @@ Here is a list of the available parameters:
618618
| `digest` | - | - | - | Digest of the Cardano db snapshot to verify or `latest` for the latest artifact | - | - | :heavy_check_mark: |
619619
| `db_dir` | `--db-dir` | - | - | Directory from where the immutable will be verified | - | - | - |
620620
| `genesis_verification_key` | `--genesis-verification-key` | - | `GENESIS_VERIFICATION_KEY` | Genesis verification key to check the certificate chain | - | - | - |
621+
| `start` | `--start` | - | - | The first immutable file number to verify | - | - | - |
622+
| `end` | `--end` | - | - | The last immutable file number to verify | - | - | - |
623+
| `allow_missing` | `--allow-missing` | - | - | If set, the verification will not fail if some immutable files are missing | `false` | - | - |
621624
| `run_mode` | `--run-mode` | - | `RUN_MODE` | Run Mode | `dev` | - | - |
622625
| `verbose` | `--verbose` | `-v` | - | Verbosity level (-v=warning, -vv=info, -vvv=debug, -vvvv=trace) | `0` | - | - |
623626
| `config_directory` | `--config-directory` | - | - | Directory where configuration file is located | `./config` | - | - |

examples/client-cardano-database-v2/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "client-cardano-database-v2"
33
description = "Mithril client Cardano database example"
4-
version = "0.0.12"
4+
version = "0.0.13"
55
66
documentation = "https://mithril.network/doc"
77
edition = "2021"

examples/client-cardano-database-v2/src/main.rs

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use std::time::Duration;
1717
use tokio::sync::RwLock;
1818

1919
use mithril_client::feedback::{FeedbackReceiver, MithrilEvent, MithrilEventCardanoDatabase};
20-
use mithril_client::{ClientBuilder, MessageBuilder, MithrilResult};
20+
use mithril_client::{ClientBuilder, MessageBuilder, MithrilError, MithrilResult};
2121

2222
#[derive(Parser, Debug)]
2323
#[command(version)]
@@ -82,7 +82,7 @@ async fn main() -> MithrilResult<()> {
8282
.verify_chain(&cardano_database_snapshot.certificate_hash)
8383
.await?;
8484

85-
let immutable_file_range = ImmutableFileRange::From(15000);
85+
let immutable_file_range = ImmutableFileRange::From(4000);
8686
let download_unpack_options = DownloadUnpackOptions {
8787
allow_override: true,
8888
include_ancillary: true,
@@ -98,19 +98,11 @@ async fn main() -> MithrilResult<()> {
9898
)
9999
.await?;
100100

101-
println!("Computing Cardano database Merkle proof...",);
102-
let merkle_proof = client
101+
println!("Downloading and verifying digests file authenticity...");
102+
let verified_digests = client
103103
.cardano_database_v2()
104-
.compute_merkle_proof(
105-
&certificate,
106-
&cardano_database_snapshot,
107-
&immutable_file_range,
108-
&unpacked_dir,
109-
)
104+
.download_and_verify_digests(&certificate, &cardano_database_snapshot)
110105
.await?;
111-
merkle_proof
112-
.verify()
113-
.with_context(|| "Merkle proof verification failed")?;
114106

115107
println!("Sending usage statistics to the aggregator...");
116108
let full_restoration = immutable_file_range == ImmutableFileRange::Full;
@@ -133,9 +125,17 @@ async fn main() -> MithrilResult<()> {
133125
"Computing Cardano database snapshot '{}' message...",
134126
cardano_database_snapshot.hash
135127
);
128+
let allow_missing_immutables_files = false;
136129
let message = wait_spinner(
137130
&progress_bar,
138-
MessageBuilder::new().compute_cardano_database_message(&certificate, &merkle_proof),
131+
MessageBuilder::new().compute_cardano_database_message(
132+
&certificate,
133+
&cardano_database_snapshot,
134+
&immutable_file_range,
135+
allow_missing_immutables_files,
136+
&unpacked_dir,
137+
&verified_digests,
138+
),
139139
)
140140
.await?;
141141

@@ -261,10 +261,13 @@ fn get_temp_dir() -> MithrilResult<PathBuf> {
261261
Ok(dir)
262262
}
263263

264-
async fn wait_spinner<T>(
264+
pub async fn wait_spinner<T, E>(
265265
progress_bar: &MultiProgress,
266-
future: impl Future<Output = MithrilResult<T>>,
267-
) -> MithrilResult<T> {
266+
future: impl Future<Output = Result<T, E>>,
267+
) -> MithrilResult<T>
268+
where
269+
MithrilError: From<E>,
270+
{
268271
let pb = progress_bar.add(ProgressBar::new_spinner());
269272
let spinner = async move {
270273
loop {
@@ -275,6 +278,6 @@ async fn wait_spinner<T>(
275278

276279
tokio::select! {
277280
_ = spinner => Err(anyhow!("timeout")),
278-
res = future => res,
281+
res = future => res.map_err(Into::into),
279282
}
280283
}

mithril-client-cli/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-client-cli"
3-
version = "0.12.26"
3+
version = "0.12.27"
44
description = "A Mithril Client"
55
authors = { workspace = true }
66
edition = { workspace = true }

mithril-client-cli/src/commands/cardano_db/download/v2.rs

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ use mithril_client::{
1515
use crate::{
1616
CommandContext,
1717
commands::{
18-
cardano_db::{download::DB_DIRECTORY_NAME, shared_steps},
18+
cardano_db::{
19+
download::DB_DIRECTORY_NAME,
20+
shared_steps::{self, ComputeCardanoDatabaseMessageOptions},
21+
},
1922
client_builder,
2023
},
2124
utils::{
@@ -124,22 +127,33 @@ impl PreparedCardanoDbV2Download {
124127
)
125128
})?;
126129

127-
let merkle_proof = shared_steps::compute_verify_merkle_proof(
130+
let verified_digests = shared_steps::download_and_verify_digests(
128131
4,
129132
&progress_printer,
130133
&client,
131134
&certificate,
132135
&cardano_db_message,
133-
&restoration_options.immutable_file_range,
134-
&restoration_options.db_dir,
135136
)
136-
.await?;
137+
.await
138+
.with_context(|| {
139+
format!(
140+
"Can not download and verify digests file for cardano db snapshot with hash: '{}'",
141+
self.hash
142+
)
143+
})?;
137144

145+
let options = ComputeCardanoDatabaseMessageOptions {
146+
db_dir: restoration_options.db_dir.clone(),
147+
immutable_file_range: restoration_options.immutable_file_range,
148+
allow_missing: false,
149+
};
138150
let message = shared_steps::compute_cardano_db_snapshot_message(
139151
5,
140152
&progress_printer,
141153
&certificate,
142-
&merkle_proof,
154+
&cardano_db_message,
155+
&options,
156+
&verified_digests,
143157
)
144158
.await?;
145159

mithril-client-cli/src/commands/cardano_db/shared_steps.rs

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,22 @@
11
use anyhow::{Context, anyhow};
22
use chrono::Utc;
33
use slog::{Logger, debug, warn};
4-
use std::path::Path;
4+
use std::path::{Path, PathBuf};
55

66
use mithril_client::{
77
CardanoDatabaseSnapshot, Client, MessageBuilder, MithrilCertificate, MithrilResult,
8-
cardano_database_client::ImmutableFileRange,
9-
common::{ImmutableFileNumber, MKProof, ProtocolMessage},
8+
cardano_database_client::{ImmutableFileRange, VerifiedDigests},
9+
common::{ImmutableFileNumber, ProtocolMessage},
1010
};
1111

1212
use crate::utils::{CardanoDbUtils, ProgressPrinter};
1313

14+
pub struct ComputeCardanoDatabaseMessageOptions {
15+
pub db_dir: PathBuf,
16+
pub immutable_file_range: ImmutableFileRange,
17+
pub allow_missing: bool,
18+
}
19+
1420
pub async fn fetch_certificate_and_verifying_chain(
1521
step_number: u16,
1622
progress_printer: &ProgressPrinter,
@@ -47,45 +53,42 @@ pub fn immutable_file_range(
4753
}
4854
}
4955

50-
/// Computes and verifies the Merkle proof for the given certificate and database snapshot.
51-
pub async fn compute_verify_merkle_proof(
56+
pub async fn download_and_verify_digests(
5257
step_number: u16,
5358
progress_printer: &ProgressPrinter,
5459
client: &Client,
5560
certificate: &MithrilCertificate,
5661
cardano_database_snapshot: &CardanoDatabaseSnapshot,
57-
immutable_file_range: &ImmutableFileRange,
58-
unpacked_dir: &Path,
59-
) -> MithrilResult<MKProof> {
60-
progress_printer.report_step(step_number, "Computing and verifying the Merkle proof…")?;
61-
let merkle_proof = client
62+
) -> MithrilResult<VerifiedDigests> {
63+
progress_printer.report_step(step_number, "Downloading and verifying digests…")?;
64+
let verified_digests = client
6265
.cardano_database_v2()
63-
.compute_merkle_proof(
64-
certificate,
65-
cardano_database_snapshot,
66-
immutable_file_range,
67-
Path::new(&unpacked_dir),
68-
)
66+
.download_and_verify_digests(certificate, cardano_database_snapshot)
6967
.await?;
7068

71-
merkle_proof
72-
.verify()
73-
.with_context(|| "Merkle proof verification failed")?;
74-
75-
Ok(merkle_proof)
69+
Ok(verified_digests)
7670
}
7771

7872
/// Computes the Cardano database snapshot message using the provided certificate and Merkle proof.
7973
pub async fn compute_cardano_db_snapshot_message(
8074
step_number: u16,
8175
progress_printer: &ProgressPrinter,
8276
certificate: &MithrilCertificate,
83-
merkle_proof: &MKProof,
77+
cardano_database_snapshot: &CardanoDatabaseSnapshot,
78+
options: &ComputeCardanoDatabaseMessageOptions,
79+
verified_digest: &VerifiedDigests,
8480
) -> MithrilResult<ProtocolMessage> {
8581
progress_printer.report_step(step_number, "Computing the cardano db snapshot message")?;
8682
let message = CardanoDbUtils::wait_spinner(
8783
progress_printer,
88-
MessageBuilder::new().compute_cardano_database_message(certificate, merkle_proof),
84+
MessageBuilder::new().compute_cardano_database_message(
85+
certificate,
86+
cardano_database_snapshot,
87+
&options.immutable_file_range,
88+
options.allow_missing,
89+
&options.db_dir,
90+
verified_digest,
91+
),
8992
)
9093
.await
9194
.with_context(|| "Can not compute the cardano db snapshot message")?;

0 commit comments

Comments
 (0)