From 913db1a50a142773d3e14c0b22b8015135ee4921 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Turmel?= Date: Wed, 25 Jun 2025 12:08:28 +0200 Subject: [PATCH 1/8] feature(aggregator, signer, common): keep only MithrilStakeDistribution in default allowed discriminants --- .github/workflows/backward-compatibility.yml | 4 +- .../develop/nodes/mithril-aggregator.md | 2 +- mithril-aggregator/src/configuration.rs | 5 +- mithril-aggregator/src/runtime/runner.rs | 74 +++++++++++++++---- mithril-aggregator/tests/certificate_chain.rs | 3 + .../tests/create_certificate.rs | 1 + .../tests/create_certificate_follower.rs | 3 + .../tests/open_message_expiration.rs | 3 + .../tests/open_message_newer_exists.rs | 3 + .../src/entities/signed_entity_config.rs | 7 +- ...te_cardano_transaction_single_signature.rs | 5 +- .../mithril-end-to-end/src/main.rs | 2 +- .../src/stress_test/aggregator_helpers.rs | 2 +- 13 files changed, 85 insertions(+), 29 deletions(-) diff --git a/.github/workflows/backward-compatibility.yml b/.github/workflows/backward-compatibility.yml index a86bffe2e65..dcc740142ed 100644 --- a/.github/workflows/backward-compatibility.yml +++ b/.github/workflows/backward-compatibility.yml @@ -17,7 +17,7 @@ on: description: "Signed entity types parameters (discriminants names in an ordered comma separated list)" required: true type: string - default: "CardanoTransactions,CardanoStakeDistribution,CardanoDatabase" + default: "CardanoTransactions,CardanoStakeDistribution,CardanoDatabase,CardanoImmutableFilesFull" workflow_call: inputs: total-releases: @@ -28,7 +28,7 @@ on: default: "10.4.1" signed-entity-types: type: string - default: "CardanoTransactions,CardanoStakeDistribution,CardanoDatabase" + default: "CardanoTransactions,CardanoStakeDistribution,CardanoDatabase,CardanoImmutableFilesFull" jobs: prepare-env-variables: diff --git a/docs/website/root/manual/develop/nodes/mithril-aggregator.md b/docs/website/root/manual/develop/nodes/mithril-aggregator.md index 574b006bdc6..b000730c69e 100644 --- a/docs/website/root/manual/develop/nodes/mithril-aggregator.md +++ b/docs/website/root/manual/develop/nodes/mithril-aggregator.md @@ -527,7 +527,7 @@ Here is a list of the available parameters for the serve command: | `era_reader_adapter_type` | `--era-reader-adapter-type` | - | `ERA_READER_ADAPTER_TYPE` | Era reader adapter type that can be `cardano-chain`, `file` or `bootstrap`. | `bootstrap` | - | - | | `era_reader_adapter_params` | `--era-reader-adapter-params` | - | `ERA_READER_ADAPTER_PARAMS` | Era reader adapter params that is an optional JSON encoded parameters structure that is expected depending on the `era_reader_adapter_type` parameter | - | - | - | | `ancillary_files_signer_config` | - | - | `ANCILLARY_FILES_SIGNER_CONFIG` | Configuration of the ancillary files signer

Can either be a secret key or a key stored in a Google Cloud Platform KMS account.

**IMPORTANT**: The cryptographic scheme used is ED25519 | - | - secret-key:
`{ "type": "secret-key", "secret_key": "136372c3138312c3138382c3130352c3233312c3135" }`
- Gcp kms:
`{ "type": "gcp-kms", "resource_name": "projects/project_name/locations/_location_name/keyRings/key_ring_name/cryptoKeys/key_name/cryptoKeyVersions/key_version" }` | - | -| `signed_entity_types` | `--signed-entity-types` | - | `SIGNED_ENTITY_TYPES` | Signed entity types parameters (discriminants names in an ordered comma separated list) | - | `MithrilStakeDistribution,CardanoImmutableFilesFull,CardanoStakeDistribution` | - | +| `signed_entity_types` | `--signed-entity-types` | - | `SIGNED_ENTITY_TYPES` | Signed entity types parameters (discriminants names in an ordered comma separated list) | - | `MithrilStakeDistribution,CardanoImmutableFilesFull,CardanoStakeDistribution,CardanoDatabase,CardanoTransactions` | - | | `snapshot_compression_algorithm` | `--snapshot-compression-algorithm` | - | `SNAPSHOT_COMPRESSION_ALGORITHM` | Compression algorithm of the snapshot archive | `zstandard` | `gzip` or `zstandard` | - | | `zstandard_parameters` | - | - | `ZSTANDARD_PARAMETERS__LEVEL` and `ZSTANDARD_PARAMETERS__NUMBER_OF_WORKERS` | Zstandard specific parameters | - | `{ level: 9, number_of_workers: 4 }` | - | | `allow_unparsable_block` | `--allow-unparsable-block` | - | `ALLOW_UNPARSABLE_BLOCK` | If set no error is returned in case of unparsable block and an error log is written instead. Will be ignored on (pre)production networks. | `false` | - | - | diff --git a/mithril-aggregator/src/configuration.rs b/mithril-aggregator/src/configuration.rs index b925a1c14e4..b363c8cb694 100644 --- a/mithril-aggregator/src/configuration.rs +++ b/mithril-aggregator/src/configuration.rs @@ -495,9 +495,8 @@ pub struct ServeCommandConfiguration { /// Signed entity types parameters (discriminants names in an ordered, case-sensitive, comma /// separated list). /// - /// The values `MithrilStakeDistribution` and `CardanoImmutableFilesFull` are prepended - /// automatically to the list. - #[example = "`MithrilStakeDistribution,CardanoImmutableFilesFull,CardanoStakeDistribution`"] + /// The value `MithrilStakeDistribution` is prepended is automatically to the list. + #[example = "`MithrilStakeDistribution,CardanoImmutableFilesFull,CardanoStakeDistribution,CardanoDatabase,CardanoTransactions`"] pub signed_entity_types: Option, /// Compression algorithm used for the snapshot archive artifacts. diff --git a/mithril-aggregator/src/runtime/runner.rs b/mithril-aggregator/src/runtime/runner.rs index dfeebffda2a..60b710d5aa3 100644 --- a/mithril-aggregator/src/runtime/runner.rs +++ b/mithril-aggregator/src/runtime/runner.rs @@ -597,6 +597,14 @@ pub mod tests { async fn build_runner( temp_dir: PathBuf, mock_certifier_service: MockCertifierService, + ) -> AggregatorRunner { + build_runner_with_discriminants(temp_dir, mock_certifier_service, vec![]).await + } + + async fn build_runner_with_discriminants( + temp_dir: PathBuf, + mock_certifier_service: MockCertifierService, + allowed_discriminants: Vec, ) -> AggregatorRunner { let mut deps = initialize_dependencies(temp_dir).await; deps.certifier_service = Arc::new(mock_certifier_service); @@ -607,6 +615,20 @@ pub mod tests { .return_once(|_| Ok(ProtocolMessage::default())); deps.signable_builder_service = Arc::new(mock_signable_builder_service); + // Configure EpochService with allowed_discriminants + if !allowed_discriminants.is_empty() { + let current_epoch = deps.ticker_service.get_current_epoch().await.unwrap(); + let epoch_service = FakeEpochServiceBuilder { + signed_entity_config: SignedEntityConfig { + allowed_discriminants: allowed_discriminants.into_iter().collect(), + ..SignedEntityConfig::dummy() + }, + ..FakeEpochServiceBuilder::dummy(current_epoch) + } + .build(); + deps.epoch_service = Arc::new(RwLock::new(epoch_service)); + } + let runner = build_runner_with_fixture_data(deps).await; let current_epoch = runner @@ -1014,7 +1036,15 @@ pub mod tests { ); mock_certifier_service.expect_create_open_message().never(); - build_runner(temp_dir!(), mock_certifier_service).await + build_runner_with_discriminants( + temp_dir!(), + mock_certifier_service, + vec![ + SignedEntityTypeDiscriminants::MithrilStakeDistribution, + SignedEntityTypeDiscriminants::CardanoImmutableFilesFull, + ], + ) + .await }; let open_message_returned = runner @@ -1044,7 +1074,15 @@ pub mod tests { .expect_create_open_message() .return_once(|_, _| Ok(open_message_created)) .times(1); - build_runner(temp_dir!(), mock_certifier_service).await + build_runner_with_discriminants( + temp_dir!(), + mock_certifier_service, + vec![ + SignedEntityTypeDiscriminants::MithrilStakeDistribution, + SignedEntityTypeDiscriminants::CardanoImmutableFilesFull, + ], + ) + .await }; let open_message_returned = runner @@ -1069,7 +1107,15 @@ pub mod tests { ); mock_certifier_service.expect_create_open_message().never(); - build_runner(temp_dir!(), mock_certifier_service).await + build_runner_with_discriminants( + temp_dir!(), + mock_certifier_service, + vec![ + SignedEntityTypeDiscriminants::MithrilStakeDistribution, + SignedEntityTypeDiscriminants::CardanoImmutableFilesFull, + ], + ) + .await }; let open_message_returned = runner @@ -1096,7 +1142,15 @@ pub mod tests { ); mock_certifier_service.expect_create_open_message().never(); - build_runner(temp_dir!(), mock_certifier_service).await + build_runner_with_discriminants( + temp_dir!(), + mock_certifier_service, + vec![ + SignedEntityTypeDiscriminants::MithrilStakeDistribution, + SignedEntityTypeDiscriminants::CardanoImmutableFilesFull, + ], + ) + .await }; let open_message_returned = runner @@ -1108,8 +1162,7 @@ pub mod tests { } #[tokio::test] - async fn test_get_current_non_certified_open_message_called_for_mithril_stake_distribution_and_then_for_immutable_file( - ) { + async fn test_get_current_non_certified_open_message_called_for_mithril_stake_distribution() { let mut mock_certifier_service = MockCertifierService::new(); let mut seq = Sequence::new(); @@ -1122,15 +1175,6 @@ pub mod tests { .in_sequence(&mut seq) .return_once(|_| Ok(Some(create_open_message(IsCertified::Yes, IsExpired::No)))); - mock_certifier_service - .expect_get_open_message() - .with(eq(SignedEntityType::CardanoImmutableFilesFull( - fake_data::beacon(), - ))) - .times(1) - .in_sequence(&mut seq) - .return_once(|_| Ok(Some(create_open_message(IsCertified::Yes, IsExpired::No)))); - mock_certifier_service.expect_create_open_message().never(); mock_certifier_service diff --git a/mithril-aggregator/tests/certificate_chain.rs b/mithril-aggregator/tests/certificate_chain.rs index db5c18f0692..67bc5ad320c 100644 --- a/mithril-aggregator/tests/certificate_chain.rs +++ b/mithril-aggregator/tests/certificate_chain.rs @@ -24,6 +24,9 @@ async fn certificate_chain() { let configuration = ServeCommandConfiguration { protocol_parameters: protocol_parameters.clone(), data_stores_directory: get_test_dir("certificate_chain"), + signed_entity_types: Some( + SignedEntityTypeDiscriminants::CardanoImmutableFilesFull.to_string(), + ), ..ServeCommandConfiguration::new_sample(temp_dir!()) }; let mut tester = RuntimeTester::build( diff --git a/mithril-aggregator/tests/create_certificate.rs b/mithril-aggregator/tests/create_certificate.rs index 202baedaf2d..52e7fc3ea05 100644 --- a/mithril-aggregator/tests/create_certificate.rs +++ b/mithril-aggregator/tests/create_certificate.rs @@ -25,6 +25,7 @@ async fn create_certificate() { protocol_parameters: protocol_parameters.clone(), signed_entity_types: Some( [ + SignedEntityTypeDiscriminants::CardanoImmutableFilesFull.to_string(), SignedEntityTypeDiscriminants::CardanoTransactions.to_string(), SignedEntityTypeDiscriminants::CardanoDatabase.to_string(), ] diff --git a/mithril-aggregator/tests/create_certificate_follower.rs b/mithril-aggregator/tests/create_certificate_follower.rs index a01be9d6903..08f9e9d87a3 100644 --- a/mithril-aggregator/tests/create_certificate_follower.rs +++ b/mithril-aggregator/tests/create_certificate_follower.rs @@ -104,6 +104,9 @@ async fn create_certificate_follower() { security_parameter: BlockNumber(0), step: BlockNumber(30), }, + signed_entity_types: Some( + SignedEntityTypeDiscriminants::CardanoImmutableFilesFull.to_string(), + ), ..ServeCommandConfiguration::new_sample(temp_dir!()) }; let mut leader_tester = diff --git a/mithril-aggregator/tests/open_message_expiration.rs b/mithril-aggregator/tests/open_message_expiration.rs index 92c48cedb66..486ecc17619 100644 --- a/mithril-aggregator/tests/open_message_expiration.rs +++ b/mithril-aggregator/tests/open_message_expiration.rs @@ -25,6 +25,9 @@ async fn open_message_expiration() { let configuration = ServeCommandConfiguration { protocol_parameters: protocol_parameters.clone(), data_stores_directory: get_test_dir("open_message_expiration"), + signed_entity_types: Some( + SignedEntityTypeDiscriminants::CardanoImmutableFilesFull.to_string(), + ), ..ServeCommandConfiguration::new_sample(temp_dir!()) }; let mut tester = RuntimeTester::build( diff --git a/mithril-aggregator/tests/open_message_newer_exists.rs b/mithril-aggregator/tests/open_message_newer_exists.rs index 753839df055..808ae0a446b 100644 --- a/mithril-aggregator/tests/open_message_newer_exists.rs +++ b/mithril-aggregator/tests/open_message_newer_exists.rs @@ -23,6 +23,9 @@ async fn open_message_newer_exists() { let configuration = ServeCommandConfiguration { protocol_parameters: protocol_parameters.clone(), data_stores_directory: get_test_dir("open_message_newer_exists"), + signed_entity_types: Some( + SignedEntityTypeDiscriminants::CardanoImmutableFilesFull.to_string(), + ), ..ServeCommandConfiguration::new_sample(temp_dir!()) }; let mut tester = RuntimeTester::build( diff --git a/mithril-common/src/entities/signed_entity_config.rs b/mithril-common/src/entities/signed_entity_config.rs index 8a63a33d65e..a6ce8bbd864 100644 --- a/mithril-common/src/entities/signed_entity_config.rs +++ b/mithril-common/src/entities/signed_entity_config.rs @@ -32,10 +32,8 @@ impl SignedEntityConfig { /// Default allowed discriminants /// /// Appended to the allowed discriminants in the configuration. - pub const DEFAULT_ALLOWED_DISCRIMINANTS: [SignedEntityTypeDiscriminants; 2] = [ - SignedEntityTypeDiscriminants::MithrilStakeDistribution, - SignedEntityTypeDiscriminants::CardanoImmutableFilesFull, - ]; + pub const DEFAULT_ALLOWED_DISCRIMINANTS: [SignedEntityTypeDiscriminants; 1] = + [SignedEntityTypeDiscriminants::MithrilStakeDistribution]; /// Append to the given list of allowed signed entity types discriminants the [Self::DEFAULT_ALLOWED_DISCRIMINANTS] /// if not already present. @@ -466,7 +464,6 @@ mod tests { vec![ SignedEntityType::MithrilStakeDistribution(beacon.epoch), SignedEntityType::CardanoStakeDistribution(beacon.epoch - 1), - SignedEntityType::CardanoImmutableFilesFull(beacon.clone()), SignedEntityType::CardanoTransactions(beacon.epoch, chain_point.block_number - 1), ], signed_entity_types diff --git a/mithril-signer/tests/create_cardano_transaction_single_signature.rs b/mithril-signer/tests/create_cardano_transaction_single_signature.rs index 9c5a80fc2b5..46489c1ccdc 100644 --- a/mithril-signer/tests/create_cardano_transaction_single_signature.rs +++ b/mithril-signer/tests/create_cardano_transaction_single_signature.rs @@ -42,7 +42,10 @@ async fn test_create_cardano_transaction_single_signature() { tester .comment("state machine starts in Init and transit to Unregistered state.") .is_init().await.unwrap() - .aggregator_allow_signed_entities(&[SignedEntityTypeDiscriminants::CardanoTransactions]).await + .aggregator_allow_signed_entities(&[ + SignedEntityTypeDiscriminants::CardanoTransactions, + SignedEntityTypeDiscriminants::CardanoImmutableFilesFull + ]).await .cycle_unregistered().await.unwrap() .comment("getting an epoch settings changes the state → RegisteredNotAbleToSign") diff --git a/mithril-test-lab/mithril-end-to-end/src/main.rs b/mithril-test-lab/mithril-end-to-end/src/main.rs index 465d4c9d4c9..b68df044199 100644 --- a/mithril-test-lab/mithril-end-to-end/src/main.rs +++ b/mithril-test-lab/mithril-end-to-end/src/main.rs @@ -99,7 +99,7 @@ pub struct Args { #[clap( long, value_delimiter = ',', - default_value = "CardanoTransactions,CardanoStakeDistribution,CardanoDatabase" + default_value = "CardanoTransactions,CardanoImmutableFilesFull,CardanoStakeDistribution,CardanoDatabase" )] signed_entity_types: Vec, diff --git a/mithril-test-lab/mithril-end-to-end/src/stress_test/aggregator_helpers.rs b/mithril-test-lab/mithril-end-to-end/src/stress_test/aggregator_helpers.rs index 490bf189dde..0cef889539b 100644 --- a/mithril-test-lab/mithril-end-to-end/src/stress_test/aggregator_helpers.rs +++ b/mithril-test-lab/mithril-end-to-end/src/stress_test/aggregator_helpers.rs @@ -15,7 +15,7 @@ pub async fn bootstrap_aggregator( current_epoch: &mut Epoch, ) -> StdResult { info!(">> Launch Aggregator"); - let signed_entity_types = vec![]; + let signed_entity_types = vec!["CardanoImmutableFilesFull".to_string()]; let chain_observer_type = "cardano-cli"; let mut aggregator = Aggregator::new(&AggregatorConfig { From 0fda44516ddbc60bbfb1c7fd591d7c6d2068ecf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Turmel?= Date: Thu, 26 Jun 2025 15:08:14 +0200 Subject: [PATCH 2/8] refactor(client-cli, e2e): rename cardano-db download directory --- .github/workflows/test-client.yml | 22 +++++++++---------- .../src/commands/cardano_db/download/mod.rs | 2 ++ .../src/commands/cardano_db/download/v1.rs | 7 ++++-- .../src/commands/cardano_db/download/v2.rs | 7 ++++-- .../mithril-end-to-end/src/mithril/client.rs | 4 ++++ 5 files changed, 27 insertions(+), 15 deletions(-) diff --git a/.github/workflows/test-client.yml b/.github/workflows/test-client.yml index 3cf272b4656..8b8ab9a70f7 100644 --- a/.github/workflows/test-client.yml +++ b/.github/workflows/test-client.yml @@ -160,7 +160,7 @@ jobs: - name: Cardano Database Snapshot / download & restore latest shell: bash working-directory: ./bin - run: ./mithril-client ${{ steps.prepare.outputs.debug_level }} --origin-tag CI cardano-db download $CDB_SNAPSHOT_DIGEST --backend v1 ${{ matrix.extra_args }} 2>&1 | tee cdb-download-output.txt + run: ./mithril-client ${{ steps.prepare.outputs.debug_level }} --origin-tag CI cardano-db download $CDB_SNAPSHOT_DIGEST --backend v1 --download-dir v1 ${{ matrix.extra_args }} 2>&1 | tee cdb-download-output.txt - name: Cardano Database Snapshot / verify Cardano node starts successfully if: runner.os == 'Linux' @@ -173,19 +173,19 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} shell: bash working-directory: ./bin - run: ./mithril-client ${{ steps.prepare.outputs.debug_level }} --unstable tools utxo-hd snapshot-converter --db-directory db --cardano-node-version latest --utxo-hd-flavor LMDB --commit + run: ./mithril-client ${{ steps.prepare.outputs.debug_level }} --unstable tools utxo-hd snapshot-converter --db-directory v1/db --cardano-node-version latest --utxo-hd-flavor LMDB --commit - name: Remove downloaded artifacts to free up disk space (Linux, Windows) if: runner.os != 'macOS' shell: bash working-directory: ./bin - run: rm --force db/immutable/*.{chunk,primary,secondary} + run: rm --force v1/db/immutable/*.{chunk,primary,secondary} - name: Remove downloaded artifacts to free up disk space (macOs) if: runner.os == 'macOS' shell: bash working-directory: ./bin - run: sudo rm -rf db/ + run: sudo rm -rf v1/db/ - name: Mithril Stake Distribution / list and get last hash shell: bash @@ -259,13 +259,13 @@ jobs: if: steps.aggregator_capability_unix.outputs.cardano_database_v2_enabled == 'true' || steps.aggregator_capability_windows.outputs.cardano_database_v2_enabled == 'true' shell: bash working-directory: ./bin - run: ./mithril-client ${{ steps.prepare.outputs.debug_level }} --origin-tag CI cardano-db download --backend v2 $CARDANO_DATABASE_V2_SNAPSHOT_HASH ${{ matrix.extra_args }} 2>&1 | tee cdb-v2-download-output.txt + run: ./mithril-client ${{ steps.prepare.outputs.debug_level }} --origin-tag CI cardano-db download --backend v2 --download-dir v2 $CARDANO_DATABASE_V2_SNAPSHOT_HASH ${{ matrix.extra_args }} 2>&1 | tee cdb-v2-download-output.txt - name: Cardano Database V2 Snapshot / verify immutables if: steps.aggregator_capability_unix.outputs.cardano_database_v2_enabled == 'true' || steps.aggregator_capability_windows.outputs.cardano_database_v2_enabled == 'true' shell: bash working-directory: ./bin - run: ./mithril-client ${{ steps.prepare.outputs.debug_level }} --origin-tag CI cardano-db verify --backend v2 --db-dir db_v2 $CARDANO_DATABASE_V2_SNAPSHOT_HASH | tee cdb-v2-verify-output.txt + run: ./mithril-client ${{ steps.prepare.outputs.debug_level }} --origin-tag CI cardano-db verify --backend v2 --db-dir v2/db $CARDANO_DATABASE_V2_SNAPSHOT_HASH | tee cdb-v2-verify-output.txt - name: Cardano Database V2 Snapshot / verify Cardano node starts successfully if: runner.os == 'Linux' && steps.aggregator_capability_unix.outputs.cardano_database_v2_enabled == 'true' @@ -329,16 +329,16 @@ jobs: - name: Cardano Database Snapshot / download & restore latest shell: bash - run: ${{ steps.command.outputs.mithril_client }} ${{ steps.prepare.outputs.debug_level }} --origin-tag CI cardano-db download $CDB_SNAPSHOT_DIGEST --backend v1 --download-dir /app/data ${{ matrix.extra_args }} + run: ${{ steps.command.outputs.mithril_client }} ${{ steps.prepare.outputs.debug_level }} --origin-tag CI cardano-db download $CDB_SNAPSHOT_DIGEST --backend v1 --download-dir /app/data/v1 ${{ matrix.extra_args }} - name: Ledger state snapshot conversion from InMemory to LMDB if: matrix.extra_args == '--include-ancillary' shell: bash - run: ${{ steps.command.outputs.mithril_client }} ${{ steps.prepare.outputs.debug_level }} --unstable tools utxo-hd snapshot-converter --db-directory /app/data/db --cardano-node-version latest --utxo-hd-flavor LMDB --commit + run: ${{ steps.command.outputs.mithril_client }} ${{ steps.prepare.outputs.debug_level }} --unstable tools utxo-hd snapshot-converter --db-directory /app/data/v1/db --cardano-node-version latest --utxo-hd-flavor LMDB --commit - name: Remove downloaded artifacts to free up disk space shell: bash - run: sudo rm -rf $PWD/data/db/ + run: sudo rm -rf $PWD/data/v1/db/ - name: Mithril Stake Distribution / list and get last hash shell: bash @@ -401,12 +401,12 @@ jobs: - name: Cardano Database V2 Snapshot / download & restore latest (Full restoration) if: steps.aggregator_capability.outputs.cardano_database_v2_enabled == 'true' shell: bash - run: ${{ steps.command.outputs.mithril_client }} ${{ steps.prepare.outputs.debug_level }} --origin-tag CI cardano-db download --backend v2 $CARDANO_DATABASE_V2_SNAPSHOT_HASH --download-dir /app/data ${{ matrix.extra_args }} + run: ${{ steps.command.outputs.mithril_client }} ${{ steps.prepare.outputs.debug_level }} --origin-tag CI cardano-db download --backend v2 $CARDANO_DATABASE_V2_SNAPSHOT_HASH --download-dir /app/data/v2 ${{ matrix.extra_args }} - name: Cardano Database V2 Snapshot / verify immutables if: steps.aggregator_capability.outputs.cardano_database_v2_enabled == 'true' shell: bash - run: ${{ steps.command.outputs.mithril_client }} ${{ steps.prepare.outputs.debug_level }} --origin-tag CI cardano-db verify --backend v2 $CARDANO_DATABASE_V2_SNAPSHOT_HASH --db-dir /app/data/db_v2 + run: ${{ steps.command.outputs.mithril_client }} ${{ steps.prepare.outputs.debug_level }} --origin-tag CI cardano-db verify --backend v2 $CARDANO_DATABASE_V2_SNAPSHOT_HASH --db-dir /app/data/v2/db test-mithril-client-wasm: strategy: diff --git a/mithril-client-cli/src/commands/cardano_db/download/mod.rs b/mithril-client-cli/src/commands/cardano_db/download/mod.rs index ea70557b4a9..79d8ffbd012 100644 --- a/mithril-client-cli/src/commands/cardano_db/download/mod.rs +++ b/mithril-client-cli/src/commands/cardano_db/download/mod.rs @@ -16,6 +16,8 @@ use crate::{ }; use mithril_client::{common::ImmutableFileNumber, MithrilResult}; +const DB_DIRECTORY_NAME: &str = "db"; + /// Clap command to download a Cardano db and verify its associated certificate. #[derive(Parser, Debug, Clone)] pub struct CardanoDbDownloadCommand { diff --git a/mithril-client-cli/src/commands/cardano_db/download/v1.rs b/mithril-client-cli/src/commands/cardano_db/download/v1.rs index 2b732b4d7e2..7fd682b741d 100644 --- a/mithril-client-cli/src/commands/cardano_db/download/v1.rs +++ b/mithril-client-cli/src/commands/cardano_db/download/v1.rs @@ -8,7 +8,10 @@ use mithril_client::{ }; use crate::{ - commands::{cardano_db::shared_steps, client_builder, SharedArgs}, + commands::{ + cardano_db::{download::DB_DIRECTORY_NAME, shared_steps}, + client_builder, SharedArgs, + }, configuration::ConfigParameters, utils::{ CardanoDbDownloadChecker, CardanoDbUtils, ExpanderUtils, IndicatifFeedbackReceiver, @@ -32,7 +35,7 @@ impl PreparedCardanoDbV1Download { /// Command execution pub async fn execute(&self, logger: &Logger, params: ConfigParameters) -> MithrilResult<()> { - let db_dir = Path::new(&self.download_dir).join("db"); + let db_dir = Path::new(&self.download_dir).join(DB_DIRECTORY_NAME); let progress_output_type = if self.is_json_output_enabled() { ProgressOutputType::JsonReporter diff --git a/mithril-client-cli/src/commands/cardano_db/download/v2.rs b/mithril-client-cli/src/commands/cardano_db/download/v2.rs index b48c700fd43..08af29430db 100644 --- a/mithril-client-cli/src/commands/cardano_db/download/v2.rs +++ b/mithril-client-cli/src/commands/cardano_db/download/v2.rs @@ -13,7 +13,10 @@ use mithril_client::{ }; use crate::{ - commands::{cardano_db::shared_steps, client_builder, SharedArgs}, + commands::{ + cardano_db::{download::DB_DIRECTORY_NAME, shared_steps}, + client_builder, SharedArgs, + }, configuration::ConfigParameters, utils::{ CardanoDbDownloadChecker, CardanoDbUtils, ExpanderUtils, IndicatifFeedbackReceiver, @@ -45,7 +48,7 @@ pub(super) struct PreparedCardanoDbV2Download { impl PreparedCardanoDbV2Download { pub async fn execute(&self, logger: &Logger, params: ConfigParameters) -> MithrilResult<()> { let restoration_options = RestorationOptions { - db_dir: Path::new(&self.download_dir).join("db_v2"), + db_dir: Path::new(&self.download_dir).join(DB_DIRECTORY_NAME), immutable_file_range: shared_steps::immutable_file_range(self.start, self.end), download_unpack_options: DownloadUnpackOptions { allow_override: self.allow_override, diff --git a/mithril-test-lab/mithril-end-to-end/src/mithril/client.rs b/mithril-test-lab/mithril-end-to-end/src/mithril/client.rs index c8a76851132..8cd4c603c10 100644 --- a/mithril-test-lab/mithril-end-to-end/src/mithril/client.rs +++ b/mithril-test-lab/mithril-end-to-end/src/mithril/client.rs @@ -38,6 +38,8 @@ impl CardanoDbCommand { vec![ "download".to_string(), "--include-ancillary".to_string(), + "--download-dir".to_string(), + "v1".to_string(), digest.clone(), ] } @@ -73,6 +75,8 @@ impl CardanoDbV2Command { vec![ "download".to_string(), "--include-ancillary".to_string(), + "--download-dir".to_string(), + "v2".to_string(), hash.clone(), ] } From 21632a5a05f7f4eb57f91887f74790f6dfc9e981 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Turmel?= Date: Fri, 27 Jun 2025 16:20:30 +0200 Subject: [PATCH 3/8] feat(docs): add cardano-db download example with a range of immutables --- .../getting-started/bootstrap-cardano-node.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/docs/website/versioned_docs/version-maintained/manual/getting-started/bootstrap-cardano-node.md b/docs/website/versioned_docs/version-maintained/manual/getting-started/bootstrap-cardano-node.md index 36416ba2940..53bff3c71ed 100644 --- a/docs/website/versioned_docs/version-maintained/manual/getting-started/bootstrap-cardano-node.md +++ b/docs/website/versioned_docs/version-maintained/manual/getting-started/bootstrap-cardano-node.md @@ -446,7 +446,9 @@ You will see more information about the snapshot: ### Step 4: Download the selected Cardano DB snapshot -To download the selected snapshot from the remote location to your remote location, run: +#### Step 4.1 : Download the full Cardano node database + +To download the full selected snapshot from the remote location to your local location, run: ```bash ./mithril-client cardano-db download --include-ancillary $SNAPSHOT_DIGEST @@ -493,6 +495,21 @@ Upgrade and replace the restored ledger state snapshot to 'LMDB' flavor by runni mithril-client --unstable tools utxo-hd snapshot-converter --db-directory db --cardano-node-version 10.4.1 --utxo-hd-flavor Legacy --cardano-network preview --commit ``` +#### Step 4.2 : Download a partial range of immutable files + +To download a range of immutable files (e.g. from 17,000 to 18,000) from the remote location to your local location, prepare the following environment variables: + +```bash +export IMMUTABLE_START=17000 +export IMMUTABLE_END=18000 +``` + +And run the command: + +```bash +./mithril-client cardano-db download $SNAPSHOT_DIGEST --include-ancillary --backend v2 --start $IMMUTABLE_START --end $IMMUTABLE_END +``` + ### Step 5 (optional): Convert the ledger state snapshot to another flavor After restoring a snapshot with the `--include-ancillary` option, the ledger state is in the `InMemory` format. You can convert it to another UTxO-HD flavor (e.g., `LMDB` or `Legacy`) using the Mithril client `tools utxo-hd snapshot-converter` command. From 7d4236db7a8033941d5ae0a9bc483a64d7182ca7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Turmel?= Date: Fri, 27 Jun 2025 17:03:34 +0200 Subject: [PATCH 4/8] fix(docs): default backend for cardano-db verify is v2 --- docs/website/root/manual/develop/nodes/mithril-client.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/website/root/manual/develop/nodes/mithril-client.md b/docs/website/root/manual/develop/nodes/mithril-client.md index 1a4aa4969da..3fb2cb81538 100644 --- a/docs/website/root/manual/develop/nodes/mithril-client.md +++ b/docs/website/root/manual/develop/nodes/mithril-client.md @@ -578,7 +578,7 @@ Here is a list of the available parameters: | Parameter | Command line (long) | Command line (short) | Environment variable | Description | Default value | Example | Mandatory | | -------------------------- | ---------------------------- | :------------------: | -------------------------- | ------------------------------------------------------------------------------- | ------------- | ------- | :----------------: | -| `backend` | `--backend` | `-b` | - | - | `v1` | - | - | +| `backend` | `--backend` | `-b` | - | - | `v2` | - | - | | `json` | `--json` | - | - | Enable JSON output for command results | `false` | - | - | | `digest` | - | - | - | Digest of the Cardano db snapshot to verify or `latest` for the latest artifact | - | - | :heavy_check_mark: | | `db_dir` | `--db-dir` | - | - | Directory from where the immutable will be verified | - | - | - | From 29321a716b74dd2405dfb93c7fe80654ef942d28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Turmel?= Date: Fri, 27 Jun 2025 17:07:18 +0200 Subject: [PATCH 5/8] feat(client-cli): remove unstable in CardanoDbCommandsBackend V2 clap help comment --- mithril-client-cli/src/commands/cardano_db/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mithril-client-cli/src/commands/cardano_db/mod.rs b/mithril-client-cli/src/commands/cardano_db/mod.rs index bbcd21700d4..d1db0c6f824 100644 --- a/mithril-client-cli/src/commands/cardano_db/mod.rs +++ b/mithril-client-cli/src/commands/cardano_db/mod.rs @@ -22,7 +22,7 @@ pub enum CardanoDbCommandsBackend { #[clap(help = "[default] Legacy backend, full database restoration only")] V1, /// V2 backend - #[clap(help = "[unstable] V2 backend, full or partial database restoration")] + #[clap(help = "V2 backend, full or partial database restoration")] V2, } From 404e14bc973640e426efb54b43dc061090caa768 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Turmel?= Date: Tue, 1 Jul 2025 09:17:08 +0200 Subject: [PATCH 6/8] refactor(aggregator): switch from immutableFilesFull to cardanoDatabase in tests --- mithril-aggregator/src/runtime/runner.rs | 89 ++++++++++++++----- mithril-aggregator/tests/certificate_chain.rs | 35 +++----- .../tests/create_certificate.rs | 33 +------ .../tests/create_certificate_follower.rs | 4 +- .../tests/open_message_expiration.rs | 14 ++- .../tests/open_message_newer_exists.rs | 18 ++-- .../tests/test_extensions/runtime_tester.rs | 9 ++ mithril-common/src/test_utils/fake_data.rs | 6 ++ 8 files changed, 114 insertions(+), 94 deletions(-) diff --git a/mithril-aggregator/src/runtime/runner.rs b/mithril-aggregator/src/runtime/runner.rs index 60b710d5aa3..5ef8abb4533 100644 --- a/mithril-aggregator/src/runtime/runner.rs +++ b/mithril-aggregator/src/runtime/runner.rs @@ -520,8 +520,8 @@ impl AggregatorRunnerTrait for AggregatorRunner { pub mod tests { use async_trait::async_trait; use chrono::{DateTime, Utc}; + use mockall::mock; use mockall::predicate::eq; - use mockall::{mock, Sequence}; use std::path::PathBuf; use std::sync::Arc; use tokio::sync::RwLock; @@ -665,9 +665,13 @@ pub mod tests { .returning(|_| Ok(None)); } - fn create_open_message(is_certified: IsCertified, is_expired: IsExpired) -> OpenMessage { + fn create_open_message( + is_certified: IsCertified, + is_expired: IsExpired, + signed_entity_type: SignedEntityType, + ) -> OpenMessage { OpenMessage { - signed_entity_type: SignedEntityType::CardanoImmutableFilesFull(fake_data::beacon()), + signed_entity_type, is_certified: is_certified == IsCertified::Yes, is_expired: is_expired == IsExpired::Yes, ..OpenMessage::dummy() @@ -973,7 +977,11 @@ pub mod tests { #[tokio::test] async fn test_get_current_non_certified_open_message_should_create_new_open_message_if_none_exists( ) { - let open_message_created = create_open_message(IsCertified::No, IsExpired::No); + let open_message_created = create_open_message( + IsCertified::No, + IsExpired::No, + SignedEntityType::MithrilStakeDistribution(fake_data::epoch()), + ); let open_message_expected = open_message_created.clone(); let runner = { @@ -997,7 +1005,11 @@ pub mod tests { #[tokio::test] async fn test_get_current_non_certified_open_message_should_return_existing_open_message_if_already_exists_and_not_expired( ) { - let not_certified_and_not_expired = create_open_message(IsCertified::No, IsExpired::No); + let not_certified_and_not_expired = create_open_message( + IsCertified::No, + IsExpired::No, + SignedEntityType::MithrilStakeDistribution(fake_data::epoch()), + ); let open_message_expected = not_certified_and_not_expired.clone(); @@ -1023,8 +1035,16 @@ pub mod tests { #[tokio::test] async fn test_get_current_non_certified_open_message_should_return_existing_open_message_if_already_exists_and_open_message_already_certified( ) { - let certified_and_not_expired = create_open_message(IsCertified::Yes, IsExpired::No); - let not_certified_and_not_expired = create_open_message(IsCertified::No, IsExpired::No); + let certified_and_not_expired = create_open_message( + IsCertified::Yes, + IsExpired::No, + SignedEntityType::MithrilStakeDistribution(fake_data::epoch()), + ); + let not_certified_and_not_expired = create_open_message( + IsCertified::No, + IsExpired::No, + SignedEntityType::CardanoStakeDistribution(fake_data::epoch()), + ); let open_message_expected = not_certified_and_not_expired.clone(); @@ -1041,7 +1061,7 @@ pub mod tests { mock_certifier_service, vec![ SignedEntityTypeDiscriminants::MithrilStakeDistribution, - SignedEntityTypeDiscriminants::CardanoImmutableFilesFull, + SignedEntityTypeDiscriminants::CardanoStakeDistribution, ], ) .await @@ -1058,9 +1078,16 @@ pub mod tests { #[tokio::test] async fn test_get_current_non_certified_open_message_should_create_open_message_if_none_exists_and_open_message_already_certified( ) { - let certified_and_not_expired = create_open_message(IsCertified::Yes, IsExpired::No); - - let open_message_created = create_open_message(IsCertified::No, IsExpired::No); + let certified_and_not_expired = create_open_message( + IsCertified::Yes, + IsExpired::No, + SignedEntityType::MithrilStakeDistribution(fake_data::epoch()), + ); + let open_message_created = create_open_message( + IsCertified::No, + IsExpired::No, + SignedEntityType::CardanoStakeDistribution(fake_data::epoch()), + ); let open_message_expected = open_message_created.clone(); let runner = { @@ -1079,7 +1106,7 @@ pub mod tests { mock_certifier_service, vec![ SignedEntityTypeDiscriminants::MithrilStakeDistribution, - SignedEntityTypeDiscriminants::CardanoImmutableFilesFull, + SignedEntityTypeDiscriminants::CardanoStakeDistribution, ], ) .await @@ -1096,8 +1123,16 @@ pub mod tests { #[tokio::test] async fn test_get_current_non_certified_open_message_should_return_none_if_all_open_message_already_certified( ) { - let certified_and_not_expired_1 = create_open_message(IsCertified::Yes, IsExpired::No); - let certified_and_not_expired_2 = create_open_message(IsCertified::Yes, IsExpired::No); + let certified_and_not_expired_1 = create_open_message( + IsCertified::Yes, + IsExpired::No, + SignedEntityType::MithrilStakeDistribution(fake_data::epoch()), + ); + let certified_and_not_expired_2 = create_open_message( + IsCertified::Yes, + IsExpired::No, + SignedEntityType::CardanoStakeDistribution(fake_data::epoch()), + ); let runner = { let mut mock_certifier_service = MockCertifierService::new(); @@ -1112,7 +1147,7 @@ pub mod tests { mock_certifier_service, vec![ SignedEntityTypeDiscriminants::MithrilStakeDistribution, - SignedEntityTypeDiscriminants::CardanoImmutableFilesFull, + SignedEntityTypeDiscriminants::CardanoStakeDistribution, ], ) .await @@ -1129,8 +1164,16 @@ pub mod tests { #[tokio::test] async fn test_get_current_non_certified_open_message_should_return_first_not_certified_and_not_expired_open_message( ) { - let not_certified_and_expired = create_open_message(IsCertified::No, IsExpired::Yes); - let not_certified_and_not_expired = create_open_message(IsCertified::No, IsExpired::No); + let not_certified_and_expired = create_open_message( + IsCertified::No, + IsExpired::Yes, + SignedEntityType::MithrilStakeDistribution(fake_data::epoch()), + ); + let not_certified_and_not_expired = create_open_message( + IsCertified::No, + IsExpired::No, + SignedEntityType::CardanoStakeDistribution(fake_data::epoch()), + ); let open_message_expected = not_certified_and_not_expired.clone(); @@ -1147,7 +1190,7 @@ pub mod tests { mock_certifier_service, vec![ SignedEntityTypeDiscriminants::MithrilStakeDistribution, - SignedEntityTypeDiscriminants::CardanoImmutableFilesFull, + SignedEntityTypeDiscriminants::CardanoStakeDistribution, ], ) .await @@ -1165,15 +1208,19 @@ pub mod tests { async fn test_get_current_non_certified_open_message_called_for_mithril_stake_distribution() { let mut mock_certifier_service = MockCertifierService::new(); - let mut seq = Sequence::new(); mock_certifier_service .expect_get_open_message() .with(eq(SignedEntityType::MithrilStakeDistribution( TimePoint::dummy().epoch, ))) .times(1) - .in_sequence(&mut seq) - .return_once(|_| Ok(Some(create_open_message(IsCertified::Yes, IsExpired::No)))); + .return_once(|_| { + Ok(Some(create_open_message( + IsCertified::Yes, + IsExpired::No, + SignedEntityType::MithrilStakeDistribution(fake_data::epoch()), + ))) + }); mock_certifier_service.expect_create_open_message().never(); diff --git a/mithril-aggregator/tests/certificate_chain.rs b/mithril-aggregator/tests/certificate_chain.rs index 67bc5ad320c..3d9e6c397e4 100644 --- a/mithril-aggregator/tests/certificate_chain.rs +++ b/mithril-aggregator/tests/certificate_chain.rs @@ -24,9 +24,7 @@ async fn certificate_chain() { let configuration = ServeCommandConfiguration { protocol_parameters: protocol_parameters.clone(), data_stores_directory: get_test_dir("certificate_chain"), - signed_entity_types: Some( - SignedEntityTypeDiscriminants::CardanoImmutableFilesFull.to_string(), - ), + signed_entity_types: Some(SignedEntityTypeDiscriminants::CardanoDatabase.to_string()), ..ServeCommandConfiguration::new_sample(temp_dir!()) }; let mut tester = RuntimeTester::build( @@ -92,17 +90,14 @@ async fn certificate_chain() { ) ); - comment!("The state machine should get back to signing to sign CardanoImmutableFilesFull"); + comment!("The state machine should get back to signing to sign CardanoDatabase"); tester.increase_immutable_number().await.unwrap(); cycle!(tester, "signing"); tester - .send_single_signatures( - SignedEntityTypeDiscriminants::CardanoImmutableFilesFull, - &signers, - ) + .send_single_signatures(SignedEntityTypeDiscriminants::CardanoDatabase, &signers) .await .unwrap(); - comment!("The state machine should issue a certificate for the CardanoImmutableFilesFull"); + comment!("The state machine should issue a certificate for the CardanoDatabase"); cycle!(tester, "ready"); assert_last_certificate_eq!( tester, @@ -110,32 +105,30 @@ async fn certificate_chain() { Epoch(1), StakeDistributionParty::from_signers(initial_fixture.signers_with_stake()).as_slice(), initial_fixture.compute_and_encode_avk(), - SignedEntityType::CardanoImmutableFilesFull(CardanoDbBeacon::new(1, 3)), + SignedEntityType::CardanoDatabase(CardanoDbBeacon::new(1, 3)), ExpectedCertificate::genesis_identifier(Epoch(1)), ) ); comment!( - "Increase immutable number to do a second CardanoImmutableFilesFull certificate for this epoch, {:?}", + "Increase immutable number to do a second CardanoDatabase certificate for this epoch, {:?}", current_epoch ); tester.increase_immutable_number().await.unwrap(); cycle!(tester, "signing"); tester - .send_single_signatures( - SignedEntityTypeDiscriminants::CardanoImmutableFilesFull, - &signers, - ) + .send_single_signatures(SignedEntityTypeDiscriminants::CardanoDatabase, &signers) .await .unwrap(); cycle!(tester, "ready"); + tokio::time::sleep(std::time::Duration::from_secs(2)).await; assert_last_certificate_eq!( tester, ExpectedCertificate::new( Epoch(1), StakeDistributionParty::from_signers(initial_fixture.signers_with_stake()).as_slice(), initial_fixture.compute_and_encode_avk(), - SignedEntityType::CardanoImmutableFilesFull(CardanoDbBeacon::new(1, 4)), + SignedEntityType::CardanoDatabase(CardanoDbBeacon::new(1, 4)), ExpectedCertificate::genesis_identifier(Epoch(1)), ) ); @@ -267,7 +260,7 @@ async fn certificate_chain() { ); comment!( - "Increase immutable number to do a CardanoImmutableFilesFull certificate for this epoch, {:?}", + "Increase immutable number to do a CardanoDatabase certificate for this epoch, {:?}", current_epoch ); tester.increase_immutable_number().await.unwrap(); @@ -275,7 +268,7 @@ async fn certificate_chain() { tester .send_single_signatures( - SignedEntityTypeDiscriminants::CardanoImmutableFilesFull, + SignedEntityTypeDiscriminants::CardanoDatabase, &next_signers, ) .await @@ -283,7 +276,7 @@ async fn certificate_chain() { cycle!(tester, "ready"); comment!( - "A CardanoImmutableFilesFull, linked to the MithrilStakeDistribution of the current epoch, should have been created, {:?}", + "A CardanoDatabase, linked to the MithrilStakeDistribution of the current epoch, should have been created, {:?}", current_epoch ); assert_last_certificate_eq!( @@ -292,7 +285,7 @@ async fn certificate_chain() { Epoch(4), StakeDistributionParty::from_signers(next_fixture.signers_with_stake()).as_slice(), next_fixture.compute_and_encode_avk(), - SignedEntityType::CardanoImmutableFilesFull(CardanoDbBeacon::new(4, 7)), + SignedEntityType::CardanoDatabase(CardanoDbBeacon::new(4, 7)), ExpectedCertificate::identifier(&SignedEntityType::MithrilStakeDistribution(Epoch(4))), ) ); @@ -301,7 +294,7 @@ async fn certificate_chain() { tester.metrics_verifier, ExpectedMetrics::new() .certificate_total(7) - .artifact_cardano_immutable_files_full_total(3) + .artifact_cardano_database_total(3) .artifact_mithril_stake_distribution_total(4) ); } diff --git a/mithril-aggregator/tests/create_certificate.rs b/mithril-aggregator/tests/create_certificate.rs index 52e7fc3ea05..6b5f34e54b5 100644 --- a/mithril-aggregator/tests/create_certificate.rs +++ b/mithril-aggregator/tests/create_certificate.rs @@ -25,7 +25,6 @@ async fn create_certificate() { protocol_parameters: protocol_parameters.clone(), signed_entity_types: Some( [ - SignedEntityTypeDiscriminants::CardanoImmutableFilesFull.to_string(), SignedEntityTypeDiscriminants::CardanoTransactions.to_string(), SignedEntityTypeDiscriminants::CardanoDatabase.to_string(), ] @@ -104,35 +103,8 @@ async fn create_certificate() { ) ); - comment!("The state machine should get back to signing to sign CardanoImmutableFilesFull when a new immutable file exists"); - tester.increase_immutable_number().await.unwrap(); - cycle!(tester, "signing"); - let signers_for_immutables = &fixture.signers_fixture()[0..=6]; - tester - .send_single_signatures( - SignedEntityTypeDiscriminants::CardanoImmutableFilesFull, - signers_for_immutables, - ) - .await - .unwrap(); - - comment!("The state machine should issue a certificate for the CardanoImmutableFilesFull"); - cycle!(tester, "ready"); - assert_last_certificate_eq!( - tester, - ExpectedCertificate::new( - Epoch(1), - &signers_for_immutables - .iter() - .map(|s| s.signer_with_stake.clone().into()) - .collect::>(), - fixture.compute_and_encode_avk(), - SignedEntityType::CardanoImmutableFilesFull(CardanoDbBeacon::new(1, 3)), - ExpectedCertificate::genesis_identifier(Epoch(1)), - ) - ); - comment!("The state machine should get back to signing to sign CardanoDatabase with the previously created immutable file"); + tester.increase_immutable_number().await.unwrap(); cycle!(tester, "signing"); let signers_for_cardano_database = &fixture.signers_fixture()[1..=6]; tester @@ -238,8 +210,7 @@ async fn create_certificate() { assert_metrics_eq!( tester.metrics_verifier, ExpectedMetrics::new() - .certificate_total(5) - .artifact_cardano_immutable_files_full_total(1) + .certificate_total(4) .artifact_cardano_database_total(1) .artifact_mithril_stake_distribution_total(1) .artifact_cardano_transaction_total(2) diff --git a/mithril-aggregator/tests/create_certificate_follower.rs b/mithril-aggregator/tests/create_certificate_follower.rs index 08f9e9d87a3..710a7bc655e 100644 --- a/mithril-aggregator/tests/create_certificate_follower.rs +++ b/mithril-aggregator/tests/create_certificate_follower.rs @@ -104,9 +104,7 @@ async fn create_certificate_follower() { security_parameter: BlockNumber(0), step: BlockNumber(30), }, - signed_entity_types: Some( - SignedEntityTypeDiscriminants::CardanoImmutableFilesFull.to_string(), - ), + signed_entity_types: Some(SignedEntityTypeDiscriminants::CardanoDatabase.to_string()), ..ServeCommandConfiguration::new_sample(temp_dir!()) }; let mut leader_tester = diff --git a/mithril-aggregator/tests/open_message_expiration.rs b/mithril-aggregator/tests/open_message_expiration.rs index 486ecc17619..4e37ccc917a 100644 --- a/mithril-aggregator/tests/open_message_expiration.rs +++ b/mithril-aggregator/tests/open_message_expiration.rs @@ -25,9 +25,7 @@ async fn open_message_expiration() { let configuration = ServeCommandConfiguration { protocol_parameters: protocol_parameters.clone(), data_stores_directory: get_test_dir("open_message_expiration"), - signed_entity_types: Some( - SignedEntityTypeDiscriminants::CardanoImmutableFilesFull.to_string(), - ), + signed_entity_types: Some(SignedEntityTypeDiscriminants::CardanoDatabase.to_string()), ..ServeCommandConfiguration::new_sample(temp_dir!()) }; let mut tester = RuntimeTester::build( @@ -103,17 +101,17 @@ async fn open_message_expiration() { tester.increase_immutable_number().await.unwrap(); cycle!(tester, "signing"); - comment!("The state machine should get back to signing to sign CardanoImmutableFilesFull"); + comment!("The state machine should get back to signing to sign CardanoDatabase"); let signers_for_immutables = &fixture.signers_fixture()[0..=6]; tester .send_single_signatures( - SignedEntityTypeDiscriminants::CardanoImmutableFilesFull, + SignedEntityTypeDiscriminants::CardanoDatabase, signers_for_immutables, ) .await .unwrap(); - comment!("The state machine should issue a certificate for the CardanoImmutableFilesFull"); + comment!("The state machine should issue a certificate for the CardanoDatabase"); cycle!(tester, "ready"); assert_last_certificate_eq!( tester, @@ -124,7 +122,7 @@ async fn open_message_expiration() { .map(|s| s.signer_with_stake.clone().into()) .collect::>(), fixture.compute_and_encode_avk(), - SignedEntityType::CardanoImmutableFilesFull(CardanoDbBeacon::new(1, 3)), + SignedEntityType::CardanoDatabase(CardanoDbBeacon::new(1, 3)), ExpectedCertificate::genesis_identifier(Epoch(1)), ) ); @@ -133,6 +131,6 @@ async fn open_message_expiration() { tester.metrics_verifier, ExpectedMetrics::new() .certificate_total(1) - .artifact_cardano_immutable_files_full_total(1) + .artifact_cardano_database_total(1) ); } diff --git a/mithril-aggregator/tests/open_message_newer_exists.rs b/mithril-aggregator/tests/open_message_newer_exists.rs index 808ae0a446b..c85f36f066a 100644 --- a/mithril-aggregator/tests/open_message_newer_exists.rs +++ b/mithril-aggregator/tests/open_message_newer_exists.rs @@ -23,9 +23,7 @@ async fn open_message_newer_exists() { let configuration = ServeCommandConfiguration { protocol_parameters: protocol_parameters.clone(), data_stores_directory: get_test_dir("open_message_newer_exists"), - signed_entity_types: Some( - SignedEntityTypeDiscriminants::CardanoImmutableFilesFull.to_string(), - ), + signed_entity_types: Some(SignedEntityTypeDiscriminants::CardanoDatabase.to_string()), ..ServeCommandConfiguration::new_sample(temp_dir!()) }; let mut tester = RuntimeTester::build( @@ -90,29 +88,29 @@ async fn open_message_newer_exists() { ) ); - comment!("The state machine should get back to signing to sign CardanoImmutableFilesFull when a new immutable file exists"); + comment!("The state machine should get back to signing to sign CardanoDatabase when a new immutable file exists"); tester.increase_immutable_number().await.unwrap(); cycle!(tester, "signing"); - comment!("The state machine should stay there as it is not able to create a certificate for the CardanoImmutableFilesFull"); + comment!("The state machine should stay there as it is not able to create a certificate for the CardanoDatabase"); cycle_err!(tester, "signing"); comment!("Increase the immutable file number"); tester.increase_immutable_number().await.unwrap(); cycle!(tester, "ready"); - comment!("The state machine should get back to signing to sign CardanoImmutableFilesFull"); + comment!("The state machine should get back to signing to sign CardanoDatabase"); cycle!(tester, "signing"); let signers_for_immutables = &fixture.signers_fixture()[0..=6]; tester .send_single_signatures( - SignedEntityTypeDiscriminants::CardanoImmutableFilesFull, + SignedEntityTypeDiscriminants::CardanoDatabase, signers_for_immutables, ) .await .unwrap(); - comment!("The state machine should issue a certificate for the CardanoImmutableFilesFull"); + comment!("The state machine should issue a certificate for the CardanoDatabase"); cycle!(tester, "ready"); assert_last_certificate_eq!( tester, @@ -123,7 +121,7 @@ async fn open_message_newer_exists() { .map(|s| s.signer_with_stake.clone().into()) .collect::>(), fixture.compute_and_encode_avk(), - SignedEntityType::CardanoImmutableFilesFull(CardanoDbBeacon::new(1, 4)), + SignedEntityType::CardanoDatabase(CardanoDbBeacon::new(1, 4)), ExpectedCertificate::genesis_identifier(Epoch(1)), ) ); @@ -133,6 +131,6 @@ async fn open_message_newer_exists() { ExpectedMetrics::new() .certificate_total(2) .artifact_mithril_stake_distribution_total(1) - .artifact_cardano_immutable_files_full_total(1) + .artifact_cardano_database_total(1) ); } diff --git a/mithril-aggregator/tests/test_extensions/runtime_tester.rs b/mithril-aggregator/tests/test_extensions/runtime_tester.rs index c49e0c13b0c..856784d73c6 100644 --- a/mithril-aggregator/tests/test_extensions/runtime_tester.rs +++ b/mithril-aggregator/tests/test_extensions/runtime_tester.rs @@ -287,6 +287,7 @@ impl RuntimeTester { pub async fn increase_immutable_number(&mut self) -> StdResult { let new_immutable_number = self.immutable_file_observer.increase().await.unwrap(); self.update_digester_digest().await; + self.update_digester_merkle_tree().await; let updated_number = self .observer @@ -552,6 +553,14 @@ impl RuntimeTester { .await; } + pub async fn update_digester_merkle_tree(&mut self) { + let time_point = self.observer.current_time_point().await; + + self.digester + .update_merkle_tree(vec![time_point.immutable_file_number.to_string()]) + .await; + } + /// Activate open message expiration pub async fn activate_open_message_expiration( &self, diff --git a/mithril-common/src/test_utils/fake_data.rs b/mithril-common/src/test_utils/fake_data.rs index 185b4c83357..beff3b88055 100644 --- a/mithril-common/src/test_utils/fake_data.rs +++ b/mithril-common/src/test_utils/fake_data.rs @@ -26,6 +26,12 @@ pub fn beacon() -> entities::CardanoDbBeacon { entities::CardanoDbBeacon::new(*time_point.epoch, time_point.immutable_file_number) } +/// Fake Epoch +pub fn epoch() -> Epoch { + let time_point = entities::TimePoint::dummy(); + time_point.epoch +} + /// Fake ChainPoint pub fn chain_point() -> entities::ChainPoint { entities::ChainPoint { From 1a05752a355c0e24bff630b6f0cb6cd60104e36e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Turmel?= Date: Wed, 2 Jul 2025 14:35:31 +0200 Subject: [PATCH 7/8] refactor(aggregator): remove MithrilStakeDistribution from example --- mithril-aggregator/src/configuration.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mithril-aggregator/src/configuration.rs b/mithril-aggregator/src/configuration.rs index b363c8cb694..dc85963089d 100644 --- a/mithril-aggregator/src/configuration.rs +++ b/mithril-aggregator/src/configuration.rs @@ -496,7 +496,7 @@ pub struct ServeCommandConfiguration { /// separated list). /// /// The value `MithrilStakeDistribution` is prepended is automatically to the list. - #[example = "`MithrilStakeDistribution,CardanoImmutableFilesFull,CardanoStakeDistribution,CardanoDatabase,CardanoTransactions`"] + #[example = "`CardanoImmutableFilesFull,CardanoStakeDistribution,CardanoDatabase,CardanoTransactions`"] pub signed_entity_types: Option, /// Compression algorithm used for the snapshot archive artifacts. From 77385e4ee21ad66dbd9ff5f1417512195a7828e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Turmel?= Date: Wed, 2 Jul 2025 15:23:47 +0200 Subject: [PATCH 8/8] chore: upgrade crate versions * mithril-aggregator from `0.7.70` to `0.7.71` * mithril-client-cli from `0.12.16` to `0.12.17` * mithril-common from `0.6.4` to `0.6.5` * mithril-signer from `0.2.257` to `0.2.258` * mithril-end-to-end from `0.4.93` to `0.4.94` --- Cargo.lock | 10 +++++----- mithril-aggregator/Cargo.toml | 2 +- mithril-client-cli/Cargo.toml | 2 +- mithril-common/Cargo.toml | 2 +- mithril-signer/Cargo.toml | 2 +- mithril-test-lab/mithril-end-to-end/Cargo.toml | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 44d0d601941..065e8f346a9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3910,7 +3910,7 @@ dependencies = [ [[package]] name = "mithril-aggregator" -version = "0.7.70" +version = "0.7.71" dependencies = [ "anyhow", "async-trait", @@ -4108,7 +4108,7 @@ dependencies = [ [[package]] name = "mithril-client-cli" -version = "0.12.16" +version = "0.12.17" dependencies = [ "anyhow", "async-trait", @@ -4160,7 +4160,7 @@ dependencies = [ [[package]] name = "mithril-common" -version = "0.6.4" +version = "0.6.5" dependencies = [ "anyhow", "async-trait", @@ -4238,7 +4238,7 @@ dependencies = [ [[package]] name = "mithril-end-to-end" -version = "0.4.93" +version = "0.4.94" dependencies = [ "anyhow", "async-recursion", @@ -4370,7 +4370,7 @@ dependencies = [ [[package]] name = "mithril-signer" -version = "0.2.257" +version = "0.2.258" dependencies = [ "anyhow", "async-trait", diff --git a/mithril-aggregator/Cargo.toml b/mithril-aggregator/Cargo.toml index 256228e502b..4970c0e9a87 100644 --- a/mithril-aggregator/Cargo.toml +++ b/mithril-aggregator/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mithril-aggregator" -version = "0.7.70" +version = "0.7.71" description = "A Mithril Aggregator server" authors = { workspace = true } edition = { workspace = true } diff --git a/mithril-client-cli/Cargo.toml b/mithril-client-cli/Cargo.toml index 01c823dbe4b..969abb3304a 100644 --- a/mithril-client-cli/Cargo.toml +++ b/mithril-client-cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mithril-client-cli" -version = "0.12.16" +version = "0.12.17" description = "A Mithril Client" authors = { workspace = true } edition = { workspace = true } diff --git a/mithril-common/Cargo.toml b/mithril-common/Cargo.toml index 70ca27fcd5a..f0798002106 100644 --- a/mithril-common/Cargo.toml +++ b/mithril-common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mithril-common" -version = "0.6.4" +version = "0.6.5" description = "Common types, interfaces, and utilities for Mithril nodes." authors = { workspace = true } edition = { workspace = true } diff --git a/mithril-signer/Cargo.toml b/mithril-signer/Cargo.toml index 8dc2c7a1d96..db47b944427 100644 --- a/mithril-signer/Cargo.toml +++ b/mithril-signer/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mithril-signer" -version = "0.2.257" +version = "0.2.258" description = "A Mithril Signer" authors = { workspace = true } edition = { workspace = true } diff --git a/mithril-test-lab/mithril-end-to-end/Cargo.toml b/mithril-test-lab/mithril-end-to-end/Cargo.toml index 329546478db..dde93d6c500 100644 --- a/mithril-test-lab/mithril-end-to-end/Cargo.toml +++ b/mithril-test-lab/mithril-end-to-end/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mithril-end-to-end" -version = "0.4.93" +version = "0.4.94" authors = { workspace = true } edition = { workspace = true } documentation = { workspace = true }