From 3937e10cbb39c4a99f8070273be90ccfc0b49fe6 Mon Sep 17 00:00:00 2001 From: DJO <790521+Alenar@users.noreply.github.com> Date: Mon, 1 Jul 2024 17:55:10 +0200 Subject: [PATCH 1/9] Add a public `replace` method to `MKMap` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous, private, `replace` is renamed to `replace_unchecked`. The new replace call `replace_unchecked` but it check that the replaced key exist and that the value is the same. Co-authored-by: Sébastien Fauvel --- .../src/crypto_helper/merkle_map.rs | 124 +++++++++++++++++- 1 file changed, 121 insertions(+), 3 deletions(-) diff --git a/mithril-common/src/crypto_helper/merkle_map.rs b/mithril-common/src/crypto_helper/merkle_map.rs index 816b9cf25cb..13422578ddf 100644 --- a/mithril-common/src/crypto_helper/merkle_map.rs +++ b/mithril-common/src/crypto_helper/merkle_map.rs @@ -74,7 +74,7 @@ impl> MKMap { "MKMap values should be replaced by entry with same root" )); } - return self.replace(key, value); + return self.replace_unchecked(key, value); } else { let key_max = self.inner_map_values.keys().max(); if key_max > Some(&key) { @@ -101,7 +101,18 @@ impl> MKMap { } /// Replace the value of an existing key - fn replace(&mut self, key: K, value: V) -> StdResult<()> { + pub fn replace(&mut self, key: K, value: V) -> StdResult<()> { + match self.inner_map_values.get(&key) { + Some(existing_value) if existing_value.compute_root()? != value.compute_root()? => Err( + anyhow!("MKMap values should be replaced by entry with same root"), + ), + Some(_) => self.replace_unchecked(key, value), + None => Err(anyhow!("MKMap could not replace non-existing key")), + } + } + + /// Replace the value of an existing key without checking if the key is already present + fn replace_unchecked(&mut self, key: K, value: V) -> StdResult<()> { self.update_provable_keys(&key, &value)?; self.inner_map_values.insert(key.clone(), value.clone()); @@ -159,7 +170,7 @@ impl> MKMap { .compute_root()? .try_into() .map_err(|_| anyhow!("Merkle root could not be converted to V"))?; - self.replace(key.to_owned(), value)?; + self.replace_unchecked(key.to_owned(), value)?; } } @@ -480,6 +491,31 @@ mod tests { MKTree::new(&leaves).unwrap() } + fn join_merkle_tree(block_ranges: &[BlockRange]) -> Vec<(BlockRange, MKTree)> { + block_ranges + .iter() + .map(|block_range| (block_range.to_owned(), generate_merkle_tree(block_range))) + .collect() + } + + fn into_mkmap_tree_entries( + entries: Vec<(BlockRange, MKTree)>, + ) -> Vec<(BlockRange, MKMapNode)> { + entries + .into_iter() + .map(|(range, mktree)| (range, MKMapNode::Tree(Arc::new(mktree)))) + .collect() + } + + fn into_mkmap_tree_node_entries( + entries: Vec<(BlockRange, MKTree)>, + ) -> Vec<(BlockRange, MKMapNode)> { + entries + .into_iter() + .map(|(range, mktree)| (range, MKMapNode::TreeNode(mktree.try_into().unwrap()))) + .collect() + } + #[test] fn test_mk_map_should_compute_same_root_when_replacing_entry_with_equivalent() { let entries = generate_merkle_trees(10, 3); @@ -561,6 +597,88 @@ mod tests { .expect_err("the MKMap should reject replacement with different root value"); } + #[test] + fn test_mk_map_replace_should_accept_replacement_with_same_root_value() { + let entries = join_merkle_tree(&[ + BlockRange::new(0, 3), + BlockRange::new(4, 6), + BlockRange::new(7, 9), + ]); + let mut mk_map = MKMap::new(&into_mkmap_tree_entries(entries)).unwrap(); + let block_range_replacement = BlockRange::new(0, 3); + let same_root_value = MKMapNode::TreeNode( + mk_map + .get(&block_range_replacement) + .unwrap() + .compute_root() + .unwrap(), + ); + let mk_map_root_expected = mk_map.compute_root().unwrap(); + + assert!(matches!( + mk_map.get(&block_range_replacement).unwrap(), + MKMapNode::Tree(..) + )); + + mk_map + .replace(block_range_replacement.clone(), same_root_value) + .unwrap(); + + assert_eq!(mk_map_root_expected, mk_map.compute_root().unwrap()); + assert!(matches!( + mk_map.get(&block_range_replacement).unwrap(), + MKMapNode::TreeNode(..) + )); + } + + #[test] + fn test_mk_map_replace_should_reject_replacement_if_key_doesnt_exist() { + let entries = join_merkle_tree(&[ + BlockRange::new(0, 3), + BlockRange::new(4, 6), + BlockRange::new(7, 9), + ]); + let mut mk_map = MKMap::new(&into_mkmap_tree_entries(entries)).unwrap(); + + let error = mk_map + .replace( + BlockRange::new(10, 12), + MKMapNode::TreeNode("whatever".into()), + ) + .expect_err("the MKMap should reject replacement for inexisting key"); + + assert!( + error + .to_string() + .contains("MKMap could not replace non-existing key"), + "Invalid error message: `{error}`", + ); + } + + #[test] + fn test_mk_map_replace_should_reject_replacement_with_different_root_value() { + let entries = join_merkle_tree(&[ + BlockRange::new(0, 3), + BlockRange::new(4, 6), + BlockRange::new(7, 9), + ]); + let mut mk_map = MKMap::new(&into_mkmap_tree_entries(entries)).unwrap(); + + let error = mk_map + .replace( + BlockRange::new(0, 3), + MKMapNode::TreeNode("different_value".into()), + ) + .expect_err("the MKMap should reject replacement with different root value"); + + assert!( + error + .to_string() + .contains("MKMap values should be replaced by entry with same root"), + "Invalid error message: `{error}`", + ); + } + #[test] fn test_mk_map_should_compress_correctly() { let entries = [ From 617003d53a8691746b2bcf0a4d3698084889c9a1 Mon Sep 17 00:00:00 2001 From: DJO <790521+Alenar@users.noreply.github.com> Date: Mon, 1 Jul 2024 18:11:49 +0200 Subject: [PATCH 2/9] Simplify MKMap unit tests By using shared methods to construct boilerplate. --- .../src/crypto_helper/merkle_map.rs | 151 ++++-------------- 1 file changed, 29 insertions(+), 122 deletions(-) diff --git a/mithril-common/src/crypto_helper/merkle_map.rs b/mithril-common/src/crypto_helper/merkle_map.rs index 13422578ddf..e373eeb988c 100644 --- a/mithril-common/src/crypto_helper/merkle_map.rs +++ b/mithril-common/src/crypto_helper/merkle_map.rs @@ -519,21 +519,8 @@ mod tests { #[test] fn test_mk_map_should_compute_same_root_when_replacing_entry_with_equivalent() { let entries = generate_merkle_trees(10, 3); - let merkle_tree_node_entries = &entries - .iter() - .map(|(range, mktree)| { - ( - range.to_owned(), - MKMapNode::TreeNode(mktree.try_into().unwrap()), - ) - }) - .collect::>(); - let merkle_tree_full_entries = &entries - .into_iter() - .map(|(range, mktree)| (range.to_owned(), mktree.into())) - .collect::)>>(); - let mk_map_nodes = MKMap::new(merkle_tree_node_entries.as_slice()).unwrap(); - let mk_map_full = MKMap::new(merkle_tree_full_entries).unwrap(); + let mk_map_nodes = MKMap::new(&into_mkmap_tree_node_entries(entries.clone())).unwrap(); + let mk_map_full = MKMap::new(&into_mkmap_tree_entries(entries)).unwrap(); let mk_map_nodes_root = mk_map_nodes.compute_root().unwrap(); let mk_map_full_root = mk_map_full.compute_root().unwrap(); @@ -543,19 +530,12 @@ mod tests { #[test] fn test_mk_map_should_accept_replacement_with_same_root_value() { - let entries = [ + let entries = join_merkle_tree(&[ BlockRange::new(0, 3), BlockRange::new(4, 6), BlockRange::new(7, 9), - ] - .iter() - .map(|block_range| (block_range.to_owned(), generate_merkle_tree(block_range))) - .collect::>(); - let merkle_tree_entries = &entries - .into_iter() - .map(|(range, mktree)| (range.to_owned(), mktree.into())) - .collect::)>>(); - let mut mk_map = MKMap::new(merkle_tree_entries.as_slice()).unwrap(); + ]); + let mut mk_map = MKMap::new(&into_mkmap_tree_entries(entries)).unwrap(); let mk_map_root_expected = mk_map.compute_root().unwrap(); let block_range_replacement = BlockRange::new(0, 3); let same_root_value = MKMapNode::TreeNode( @@ -575,19 +555,12 @@ mod tests { #[test] fn test_mk_map_should_reject_replacement_with_different_root_value() { - let entries = [ + let entries = join_merkle_tree(&[ BlockRange::new(0, 3), BlockRange::new(4, 6), BlockRange::new(7, 9), - ] - .iter() - .map(|block_range| (block_range.to_owned(), generate_merkle_tree(block_range))) - .collect::>(); - let merkle_tree_entries = &entries - .into_iter() - .map(|(range, mktree)| (range.to_owned(), mktree.into())) - .collect::>(); - let mut mk_map = MKMap::new(merkle_tree_entries.as_slice()).unwrap(); + ]); + let mut mk_map = MKMap::new(&into_mkmap_tree_entries(entries)).unwrap(); let block_range_replacement = BlockRange::new(0, 3); let value_replacement: MKTreeNode = "test-123".to_string().into(); let different_root_value = MKMapNode::TreeNode(value_replacement); @@ -681,19 +654,12 @@ mod tests { #[test] fn test_mk_map_should_compress_correctly() { - let entries = [ + let entries = join_merkle_tree(&[ BlockRange::new(0, 3), BlockRange::new(4, 6), BlockRange::new(7, 9), - ] - .iter() - .map(|block_range| (block_range.to_owned(), generate_merkle_tree(block_range))) - .collect::>(); - let merkle_tree_entries = &entries - .into_iter() - .map(|(range, mktree)| (range.to_owned(), mktree.into())) - .collect::)>>(); - let mk_map = MKMap::new(merkle_tree_entries.as_slice()).unwrap(); + ]); + let mk_map = MKMap::new(&into_mkmap_tree_entries(entries)).unwrap(); let mk_map_root_expected = mk_map.compute_root().unwrap(); let mk_map_provable_keys = mk_map.get_provable_keys(); assert!(!mk_map_provable_keys.is_empty()); @@ -709,24 +675,12 @@ mod tests { #[test] fn test_mk_map_should_reject_out_of_order_insertion() { - let entries = [ + let entries = join_merkle_tree(&[ BlockRange::new(0, 3), BlockRange::new(4, 6), BlockRange::new(7, 9), - ] - .iter() - .map(|block_range| (block_range.to_owned(), generate_merkle_tree(block_range))) - .collect::>(); - let merkle_tree_entries = &entries - .iter() - .map(|(range, mktree)| { - ( - range.to_owned(), - MKMapNode::TreeNode(mktree.try_into().unwrap()), - ) - }) - .collect::>(); - let mut mk_map = MKMap::new(merkle_tree_entries.as_slice()).unwrap(); + ]); + let mut mk_map = MKMap::new(&into_mkmap_tree_node_entries(entries)).unwrap(); let out_of_order_entry = ( BlockRange::new(0, 25), MKMapNode::TreeNode("test-123".into()), @@ -739,23 +693,12 @@ mod tests { #[test] fn test_mk_map_should_list_keys_correctly() { - let entries = [ + let entries = join_merkle_tree(&[ BlockRange::new(0, 3), BlockRange::new(4, 6), BlockRange::new(7, 9), - ] - .iter() - .map(|block_range| (block_range.to_owned(), generate_merkle_tree(block_range))) - .collect::>(); - let merkle_tree_entries = &entries - .iter() - .map(|(range, mktree)| { - ( - range.to_owned(), - MKMapNode::TreeNode(mktree.try_into().unwrap()), - ) - }) - .collect::>(); + ]); + let merkle_tree_entries = &into_mkmap_tree_node_entries(entries); let mk_map = MKMap::new(merkle_tree_entries.as_slice()).unwrap(); let keys = mk_map @@ -773,23 +716,12 @@ mod tests { #[test] fn test_mk_map_should_list_values_correctly() { - let entries = [ + let entries = join_merkle_tree(&[ BlockRange::new(0, 3), BlockRange::new(4, 6), BlockRange::new(7, 9), - ] - .iter() - .map(|block_range| (block_range.to_owned(), generate_merkle_tree(block_range))) - .collect::>(); - let merkle_tree_entries = &entries - .iter() - .map(|(range, mktree)| { - ( - range.to_owned(), - MKMapNode::TreeNode(mktree.try_into().unwrap()), - ) - }) - .collect::>(); + ]); + let merkle_tree_entries = &into_mkmap_tree_node_entries(entries); let mk_map = MKMap::new(merkle_tree_entries.as_slice()).unwrap(); let values = mk_map @@ -810,39 +742,25 @@ mod tests { #[test] fn test_mk_map_should_find_value_correctly() { - let entries = [ + let entries = join_merkle_tree(&[ BlockRange::new(0, 3), BlockRange::new(4, 6), BlockRange::new(7, 9), - ] - .iter() - .map(|block_range| (block_range.to_owned(), generate_merkle_tree(block_range))) - .collect::>(); + ]); let mktree_node_to_certify = entries[2].1.leaves()[1].clone(); - let merkle_tree_entries = &entries - .into_iter() - .map(|(range, mktree)| (range.to_owned(), mktree.into())) - .collect::)>>(); - let mk_map_full = MKMap::new(merkle_tree_entries.as_slice()).unwrap(); + let mk_map_full = MKMap::new(&into_mkmap_tree_entries(entries)).unwrap(); mk_map_full.contains(&mktree_node_to_certify).unwrap(); } #[test] fn test_mk_map_should_clone_and_compute_same_root() { - let entries = [ + let entries = join_merkle_tree(&[ BlockRange::new(0, 3), BlockRange::new(4, 6), BlockRange::new(7, 9), - ] - .iter() - .map(|block_range| (block_range.to_owned(), generate_merkle_tree(block_range))) - .collect::>(); - let merkle_tree_node_entries = &entries - .into_iter() - .map(|(range, mktree)| (range.to_owned(), mktree.into())) - .collect::)>>(); - let mk_map = MKMap::new(merkle_tree_node_entries.as_slice()).unwrap(); + ]); + let mk_map = MKMap::new(&into_mkmap_tree_entries(entries)).unwrap(); let mk_map_clone = mk_map.clone(); @@ -856,11 +774,7 @@ mod tests { fn test_mk_map_should_not_compute_proof_for_no_leaves() { let entries = generate_merkle_trees(10, 3); let mktree_nodes_to_certify: &[MKTreeNode] = &[]; - let merkle_tree_node_entries = &entries - .into_iter() - .map(|(range, mktree)| (range.to_owned(), mktree.into())) - .collect::)>>(); - let mk_map_full = MKMap::new(merkle_tree_node_entries.as_slice()).unwrap(); + let mk_map_full = MKMap::new(&into_mkmap_tree_entries(entries)).unwrap(); mk_map_full .compute_proof(mktree_nodes_to_certify) @@ -876,11 +790,7 @@ mod tests { entries[1].1.leaves()[1].clone(), entries[2].1.leaves()[1].clone(), ]; - let merkle_tree_node_entries = &entries - .into_iter() - .map(|(range, mktree)| (range.to_owned(), mktree.into())) - .collect::)>>(); - let mk_map_full = MKMap::new(merkle_tree_node_entries.as_slice()).unwrap(); + let mk_map_full = MKMap::new(&into_mkmap_tree_entries(entries)).unwrap(); let mk_map_proof = mk_map_full.compute_proof(&mktree_nodes_to_certify).unwrap(); mk_map_proof.verify().unwrap(); @@ -903,10 +813,7 @@ mod tests { entries[20].1.leaves()[0].clone(), entries[30].1.leaves()[0].clone(), ]; - let merkle_tree_node_entries = &entries - .into_iter() - .map(|(range, mktree)| (range.to_owned(), MKMapNode::Tree(Arc::new(mktree)))) - .collect::>() + let merkle_tree_node_entries = &into_mkmap_tree_entries(entries) .chunks(10) .map(|entries| { ( From c40df8feb3cedbfcb824979d8c07613048cbd678 Mon Sep 17 00:00:00 2001 From: DJO <790521+Alenar@users.noreply.github.com> Date: Mon, 1 Jul 2024 18:19:01 +0200 Subject: [PATCH 3/9] Make aggregator prover fail when trying to add key to the merkle tree Before it allowed to add new keys to the merkle tree, making it create proofs based on a different merkle root than the one signed in the last certificate. Even more worrisome this merkle tree would be then returned modified to its mkpool, making this corruption persist until the pool is refreshed. --- mithril-aggregator/src/services/prover.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mithril-aggregator/src/services/prover.rs b/mithril-aggregator/src/services/prover.rs index 0ada3f86ef1..f2213c872a5 100644 --- a/mithril-aggregator/src/services/prover.rs +++ b/mithril-aggregator/src/services/prover.rs @@ -141,7 +141,7 @@ impl ProverService for MithrilProverService { // 4 - Enrich the Merkle map with the block ranges Merkle trees for (block_range, mk_tree) in mk_trees { - mk_map.insert(block_range, mk_tree.into())?; + mk_map.replace(block_range, mk_tree.into())?; } // 5 - Compute the proof for all transactions @@ -167,7 +167,8 @@ impl ProverService for MithrilProverService { let pool_size = self.mk_map_pool.size(); info!( self.logger, - "Prover starts computing the Merkle map pool resource of size {pool_size}" + "Prover starts computing the Merkle map pool resource of size {pool_size}"; + "up_to_block_number" => up_to, ); let mk_map_cache = self .block_range_root_retriever From 3167a20d178deca67e958e92a48e6103d7d2b824 Mon Sep 17 00:00:00 2001 From: DJO <790521+Alenar@users.noreply.github.com> Date: Tue, 2 Jul 2024 16:58:13 +0200 Subject: [PATCH 4/9] Make easier for IDE to navigate in aggregator integration tests macro By using the "static" method calls. --- .../tests/test_extensions/runtime_tester.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/mithril-aggregator/tests/test_extensions/runtime_tester.rs b/mithril-aggregator/tests/test_extensions/runtime_tester.rs index 43d6beee62e..d5b721b1ed4 100644 --- a/mithril-aggregator/tests/test_extensions/runtime_tester.rs +++ b/mithril-aggregator/tests/test_extensions/runtime_tester.rs @@ -33,7 +33,7 @@ use crate::test_extensions::{AggregatorObserver, ExpectedCertificate}; #[macro_export] macro_rules! cycle { ( $tester:expr, $expected_state:expr ) => {{ - $tester.cycle().await.unwrap(); + RuntimeTester::cycle(&mut $tester).await.unwrap(); assert_eq!($expected_state, $tester.runtime.get_state()); }}; } @@ -41,8 +41,7 @@ macro_rules! cycle { #[macro_export] macro_rules! cycle_err { ( $tester:expr, $expected_state:expr ) => {{ - $tester - .cycle() + RuntimeTester::cycle(&mut $tester) .await .expect_err("cycle tick should have returned an error"); assert_eq!($expected_state, $tester.runtime.get_state()); @@ -52,7 +51,9 @@ macro_rules! cycle_err { #[macro_export] macro_rules! assert_last_certificate_eq { ( $tester:expr, $expected_certificate:expr ) => {{ - let last_certificate = $tester.get_last_expected_certificate().await.unwrap(); + let last_certificate = RuntimeTester::get_last_expected_certificate(&mut $tester) + .await + .unwrap(); assert_eq!($expected_certificate, last_certificate); }}; } From 571ccb91b89043b6eb94b19afb45e3685641be48 Mon Sep 17 00:00:00 2001 From: DJO <790521+Alenar@users.noreply.github.com> Date: Mon, 1 Jul 2024 18:46:26 +0200 Subject: [PATCH 5/9] Add a integration test on the prover in `mithril-aggregator` --- .../tests/prove_transactions.rs | 149 ++++++++++++++++++ .../test_extensions/aggregator_observer.rs | 35 +++- .../tests/test_extensions/runtime_tester.rs | 18 +-- .../tests/test_extensions/utilities.rs | 5 + 4 files changed, 192 insertions(+), 15 deletions(-) create mode 100644 mithril-aggregator/tests/prove_transactions.rs diff --git a/mithril-aggregator/tests/prove_transactions.rs b/mithril-aggregator/tests/prove_transactions.rs new file mode 100644 index 00000000000..9e079f4099e --- /dev/null +++ b/mithril-aggregator/tests/prove_transactions.rs @@ -0,0 +1,149 @@ +use mithril_aggregator::Configuration; +use mithril_common::{ + entities::{ + CardanoDbBeacon, CardanoTransactionsSigningConfig, ChainPoint, Epoch, + ProtocolMessagePartKey, ProtocolParameters, SignedEntityType, + SignedEntityTypeDiscriminants, TimePoint, + }, + test_utils::MithrilFixtureBuilder, +}; +use test_extensions::{utilities::get_test_dir, ExpectedCertificate, RuntimeTester}; + +use crate::test_extensions::utilities::tx_hash; + +mod test_extensions; + +#[tokio::test(flavor = "multi_thread")] +async fn prove_transactions() { + let protocol_parameters = ProtocolParameters { + k: 5, + m: 150, + phi_f: 0.95, + }; + let configuration = Configuration { + protocol_parameters: protocol_parameters.clone(), + signed_entity_types: Some(SignedEntityTypeDiscriminants::CardanoTransactions.to_string()), + data_stores_directory: get_test_dir("prove_transactions"), + cardano_transactions_signing_config: CardanoTransactionsSigningConfig { + security_parameter: 0, + step: 30, + }, + ..Configuration::new_sample() + }; + let mut tester = RuntimeTester::build( + TimePoint { + epoch: Epoch(1), + immutable_file_number: 1, + chain_point: ChainPoint { + slot_number: 10, + block_number: 100, + block_hash: "block_hash-100".to_string(), + }, + }, + configuration, + ) + .await; + let observer = tester.observer.clone(); + let prover = tester.dependencies.prover_service.clone(); + + comment!("create signers & declare stake distribution"); + let fixture = MithrilFixtureBuilder::default() + .with_signers(10) + .with_protocol_parameters(protocol_parameters.clone()) + .build(); + let signers = &fixture.signers_fixture(); + + tester.init_state_from_fixture(&fixture).await.unwrap(); + + comment!("Boostrap the genesis certificate"); + tester.register_genesis_certificate(&fixture).await.unwrap(); + + assert_last_certificate_eq!( + tester, + ExpectedCertificate::new_genesis( + CardanoDbBeacon::new("devnet", 1, 1), + fixture.compute_and_encode_avk() + ) + ); + + // Lock all signed entity types except CardanoTransactions to limit the scope of the test + for entity in SignedEntityTypeDiscriminants::all() + .into_iter() + .filter(|e| e != &SignedEntityTypeDiscriminants::CardanoTransactions) + { + tester + .dependencies + .signed_entity_type_lock + .lock(entity) + .await; + } + + comment!("register signers"); + cycle!(tester, "ready"); + tester + .register_signers(&fixture.signers_fixture()) + .await + .unwrap(); + + comment!( + "Increase cardano chain block number to 185, + the state machine should be signing CardanoTransactions up to block 179 included" + ); + tester.increase_block_number(85, 185).await.unwrap(); + cycle!(tester, "signing"); + tester + .send_single_signatures(SignedEntityTypeDiscriminants::CardanoTransactions, signers) + .await + .unwrap(); + + comment!("The state machine should issue a certificate for the CardanoTransactions"); + cycle!(tester, "ready"); + assert_last_certificate_eq!( + tester, + ExpectedCertificate::new( + CardanoDbBeacon::new("devnet", 1, 1), + &signers + .iter() + .map(|s| s.signer_with_stake.clone().into()) + .collect::>(), + fixture.compute_and_encode_avk(), + SignedEntityType::CardanoTransactions(Epoch(1), 179), + ExpectedCertificate::genesis_identifier(&CardanoDbBeacon::new("devnet", 1, 1)), + ) + ); + + cycle!(tester, "ready"); + + comment!("Get the proof for the last transaction, BlockNumber(179), and verify it"); + let last_transaction_hash = tx_hash(179, 1); + let last_tx_snapshot = observer + .get_last_cardano_transactions_snapshot() + .await + .unwrap(); + let proof_for_last_transaction = prover + .compute_transactions_proofs( + last_tx_snapshot.artifact.block_number, + &[last_transaction_hash.clone()], + ) + .await + .unwrap() + .pop() + .unwrap(); + assert!(proof_for_last_transaction + .transactions_hashes() + .contains(&last_transaction_hash)); + + proof_for_last_transaction.verify().unwrap(); + + comment!("Get the certificate associated with the last transaction and check that it matches the proof"); + let proof_merkle_root = proof_for_last_transaction.merkle_root(); + let proof_certificate = observer.get_last_certificate().await.unwrap(); + assert_eq!(&last_tx_snapshot.certificate_id, &proof_certificate.hash); + assert_eq!( + proof_certificate + .protocol_message + .get_message_part(&ProtocolMessagePartKey::CardanoTransactionsMerkleRoot), + Some(&proof_merkle_root), + "The proof merkle root should match the one in the certificate" + ); +} diff --git a/mithril-aggregator/tests/test_extensions/aggregator_observer.rs b/mithril-aggregator/tests/test_extensions/aggregator_observer.rs index 0c7c0a4b6a7..6c809b9db06 100644 --- a/mithril-aggregator/tests/test_extensions/aggregator_observer.rs +++ b/mithril-aggregator/tests/test_extensions/aggregator_observer.rs @@ -1,7 +1,9 @@ use anyhow::{anyhow, Context}; +use mithril_aggregator::services::SignedEntityService; use mithril_aggregator::{ dependency_injection::DependenciesBuilder, entities::OpenMessage, services::CertifierService, }; +use mithril_common::entities::{CardanoTransactionsSnapshot, Certificate, SignedEntity}; use mithril_common::{ entities::{ Epoch, SignedEntityConfig, SignedEntityType, SignedEntityTypeDiscriminants, TimePoint, @@ -14,6 +16,7 @@ use std::sync::Arc; pub struct AggregatorObserver { network: CardanoNetwork, certifier_service: Arc, + signed_entity_service: Arc, ticker_service: Arc, signed_entity_config: SignedEntityConfig, } @@ -24,6 +27,7 @@ impl AggregatorObserver { Self { network: deps_builder.configuration.get_network().unwrap(), certifier_service: deps_builder.get_certifier_service().await.unwrap(), + signed_entity_service: deps_builder.get_signed_entity_service().await.unwrap(), ticker_service: deps_builder.get_ticker_service().await.unwrap(), signed_entity_config: deps_builder.get_signed_entity_config().unwrap(), } @@ -52,7 +56,7 @@ impl AggregatorObserver { .with_context(|| "Requesting current open message of type CardanoImmutableFilesFull should be not fail") } - // Get the [entity type][SignedEntityType::CardanoImmutableFilesFull] of the current current open message + /// Get the [entity type][SignedEntityType::CardanoImmutableFilesFull] of the current current open message pub async fn get_current_signed_entity_type( &self, discriminant: SignedEntityTypeDiscriminants, @@ -65,6 +69,35 @@ impl AggregatorObserver { } } + /// Get the last certificate produced by the aggregator + pub async fn get_last_certificate(&self) -> StdResult { + let certificate = self + .certifier_service + .get_latest_certificates(1) + .await + .with_context(|| "Querying last certificate should not fail")? + .pop() + .ok_or(anyhow!( + "No certificate have been produced by the aggregator" + ))?; + Ok(certificate) + } + + /// Get the last cardano transactions snapshot produced by the aggregator + pub async fn get_last_cardano_transactions_snapshot( + &self, + ) -> StdResult> { + let last_tx_snapshot = self + .signed_entity_service + .get_last_cardano_transaction_snapshot() + .await + .with_context(|| "Querying last cardano transactions snapshot should not fail")? + .ok_or(anyhow!( + "No cardano transactions snapshot have been produced by the aggregator" + ))?; + Ok(last_tx_snapshot) + } + async fn build_current_signed_entity_type( &self, discriminant: SignedEntityTypeDiscriminants, diff --git a/mithril-aggregator/tests/test_extensions/runtime_tester.rs b/mithril-aggregator/tests/test_extensions/runtime_tester.rs index d5b721b1ed4..729ca5fe981 100644 --- a/mithril-aggregator/tests/test_extensions/runtime_tester.rs +++ b/mithril-aggregator/tests/test_extensions/runtime_tester.rs @@ -1,3 +1,5 @@ +use crate::test_extensions::utilities::tx_hash; +use crate::test_extensions::{AggregatorObserver, ExpectedCertificate}; use anyhow::{anyhow, Context}; use chrono::Utc; use mithril_aggregator::{ @@ -28,8 +30,6 @@ use std::sync::Arc; use std::time::Duration; use tokio::sync::mpsc::UnboundedReceiver; -use crate::test_extensions::{AggregatorObserver, ExpectedCertificate}; - #[macro_export] macro_rules! cycle { ( $tester:expr, $expected_state:expr ) => {{ @@ -276,7 +276,7 @@ impl RuntimeTester { block_number, slot_number, current_immutable, - vec![format!("tx_hash-{block_number}-1")], + vec![tx_hash(block_number, 1)], ) }) .collect(); @@ -485,17 +485,7 @@ impl RuntimeTester { pub async fn get_last_certificate_with_signed_entity( &mut self, ) -> StdResult<(Certificate, Option)> { - let certificate = self - .dependencies - .certifier_service - .get_latest_certificates(1) - .await - .with_context(|| "Querying last certificate should not fail")? - .first() - .ok_or(anyhow!( - "No certificate have been produced by the aggregator" - ))? - .clone(); + let certificate = self.observer.get_last_certificate().await?; let signed_entity = match &certificate.signature { CertificateSignature::GenesisSignature(..) => None, diff --git a/mithril-aggregator/tests/test_extensions/utilities.rs b/mithril-aggregator/tests/test_extensions/utilities.rs index e1dea9d91ce..c07622f4d39 100644 --- a/mithril-aggregator/tests/test_extensions/utilities.rs +++ b/mithril-aggregator/tests/test_extensions/utilities.rs @@ -1,3 +1,4 @@ +use mithril_common::entities::BlockNumber; use mithril_common::test_utils::TempDir; use slog_scope::debug; use std::{ @@ -19,6 +20,10 @@ pub fn comment(comment: String) { debug!("COMMENT {:02} 💬 {}", old_count + 1, comment); } +pub fn tx_hash(block_number: BlockNumber, tx_index: u64) -> String { + format!("tx_hash-{block_number}-{tx_index}") +} + #[macro_export] macro_rules! comment { ( $($comment:tt)* ) => {{ From e2c42cfcc3cddeef3bb2b9866ea7a70c206cb951 Mon Sep 17 00:00:00 2001 From: DJO <790521+Alenar@users.noreply.github.com> Date: Tue, 2 Jul 2024 19:52:00 +0200 Subject: [PATCH 6/9] Fix retrieval of block ranges when computing merkle root It was missing one block range when retrieving data. With the given block ranges in DB (end is exclusive): [ (15..30), (30..45), (45..60) ] Before the fix it would return when asked block number: - `44`: [ (15..30) ] -> WRONG, should also include (30..45) - `45`: [ (15..30) ] -> WRONG, should also include (30..45) - `46`: [ (15..30), (30..45) ] -> WRONG, should also include (45..60) --- .../delete_block_range_root.rs | 11 +- .../block_range_root/get_block_range_root.rs | 107 +++++++++++++++++- .../database/query/block_range_root/mod.rs | 17 +++ .../cardano_transaction_repository.rs | 69 +++-------- .../signable_builder/cardano_transactions.rs | 2 +- 5 files changed, 137 insertions(+), 69 deletions(-) diff --git a/internal/mithril-persistence/src/database/query/block_range_root/delete_block_range_root.rs b/internal/mithril-persistence/src/database/query/block_range_root/delete_block_range_root.rs index b0e0a2aeed8..e3f9165a581 100644 --- a/internal/mithril-persistence/src/database/query/block_range_root/delete_block_range_root.rs +++ b/internal/mithril-persistence/src/database/query/block_range_root/delete_block_range_root.rs @@ -49,18 +49,13 @@ mod tests { use mithril_common::crypto_helper::MKTreeNode; use mithril_common::entities::BlockRange; - use crate::database::query::{GetBlockRangeRootQuery, InsertBlockRangeRootQuery}; + use crate::database::query::block_range_root::test_helper::insert_block_range_roots; + use crate::database::query::GetBlockRangeRootQuery; use crate::database::test_helper::cardano_tx_db_connection; - use crate::sqlite::{ConnectionExtensions, SqliteConnection}; + use crate::sqlite::ConnectionExtensions; use super::*; - fn insert_block_range_roots(connection: &SqliteConnection, records: Vec) { - connection - .fetch_first(InsertBlockRangeRootQuery::insert_many(records).unwrap()) - .unwrap(); - } - fn block_range_root_dataset() -> Vec { [ ( diff --git a/internal/mithril-persistence/src/database/query/block_range_root/get_block_range_root.rs b/internal/mithril-persistence/src/database/query/block_range_root/get_block_range_root.rs index 44b32f08b2d..fd8018f9b13 100644 --- a/internal/mithril-persistence/src/database/query/block_range_root/get_block_range_root.rs +++ b/internal/mithril-persistence/src/database/query/block_range_root/get_block_range_root.rs @@ -1,6 +1,7 @@ -use mithril_common::entities::BlockNumber; use sqlite::Value; +use mithril_common::entities::BlockNumber; + use crate::database::record::BlockRangeRootRecord; use crate::sqlite::{Query, SourceAlias, SqLiteEntity, WhereCondition}; @@ -16,12 +17,9 @@ impl GetBlockRangeRootQuery { } } - pub fn up_to_block_number(up_to_or_equal_end_block_number: BlockNumber) -> Self { + pub fn contains_or_below_block_number(block_number: BlockNumber) -> Self { Self { - condition: WhereCondition::new( - "end <= ?*", - vec![Value::Integer(up_to_or_equal_end_block_number as i64)], - ), + condition: WhereCondition::new("start < ?*", vec![Value::Integer(block_number as i64)]), } } } @@ -40,3 +38,100 @@ impl Query for GetBlockRangeRootQuery { format!("select {projection} from block_range_root where {condition} order by start, end") } } + +#[cfg(test)] +mod tests { + use mithril_common::crypto_helper::MKTreeNode; + use mithril_common::entities::BlockRange; + + use crate::database::query::block_range_root::test_helper::insert_block_range_roots; + use crate::database::query::GetBlockRangeRootQuery; + use crate::database::test_helper::cardano_tx_db_connection; + use crate::sqlite::ConnectionExtensions; + + use super::*; + + fn block_range_root_dataset() -> Vec { + [ + ( + BlockRange::from_block_number(15), + MKTreeNode::from_hex("AAAA").unwrap(), + ), + ( + BlockRange::from_block_number(30), + MKTreeNode::from_hex("BBBB").unwrap(), + ), + ( + BlockRange::from_block_number(45), + MKTreeNode::from_hex("CCCC").unwrap(), + ), + ] + .into_iter() + .map(BlockRangeRootRecord::from) + .collect() + } + + #[test] + fn test_get_contains_or_below_block_number_with_empty_db() { + let connection = cardano_tx_db_connection().unwrap(); + + let cursor: Vec = connection + .fetch_collect(GetBlockRangeRootQuery::contains_or_below_block_number(100)) + .unwrap(); + assert_eq!(Vec::::new(), cursor); + } + + #[test] + fn test_get_contains_or_below_block_number_higher_than_the_highest_stored_block_range() { + let connection = cardano_tx_db_connection().unwrap(); + let dataset = block_range_root_dataset(); + insert_block_range_roots(&connection, dataset.clone()); + + let cursor: Vec = connection + .fetch_collect(GetBlockRangeRootQuery::contains_or_below_block_number( + 10_000, + )) + .unwrap(); + + assert_eq!(dataset, cursor); + } + + #[test] + fn test_get_contains_or_below_block_number_below_end_of_the_third_block_range() { + let connection = cardano_tx_db_connection().unwrap(); + let dataset = block_range_root_dataset(); + insert_block_range_roots(&connection, dataset.clone()); + + let cursor: Vec = connection + .fetch_collect(GetBlockRangeRootQuery::contains_or_below_block_number(44)) + .unwrap(); + + assert_eq!(&dataset[0..2], &cursor); + } + + #[test] + fn test_get_contains_or_below_block_number_equal_to_end_of_the_third_block_range() { + let connection = cardano_tx_db_connection().unwrap(); + let dataset = block_range_root_dataset(); + insert_block_range_roots(&connection, dataset.clone()); + + let cursor: Vec = connection + .fetch_collect(GetBlockRangeRootQuery::contains_or_below_block_number(45)) + .unwrap(); + + assert_eq!(&dataset[0..2], &cursor); + } + + #[test] + fn test_get_contains_or_below_block_number_after_end_of_the_third_block_range() { + let connection = cardano_tx_db_connection().unwrap(); + let dataset = block_range_root_dataset(); + insert_block_range_roots(&connection, dataset.clone()); + + let cursor: Vec = connection + .fetch_collect(GetBlockRangeRootQuery::contains_or_below_block_number(46)) + .unwrap(); + + assert_eq!(dataset, cursor); + } +} diff --git a/internal/mithril-persistence/src/database/query/block_range_root/mod.rs b/internal/mithril-persistence/src/database/query/block_range_root/mod.rs index d10fb75852a..6e50e8216c9 100644 --- a/internal/mithril-persistence/src/database/query/block_range_root/mod.rs +++ b/internal/mithril-persistence/src/database/query/block_range_root/mod.rs @@ -7,3 +7,20 @@ pub use delete_block_range_root::*; pub use get_block_range_root::*; pub use get_interval_without_block_range::*; pub use insert_block_range::*; + +#[cfg(test)] +mod test_helper { + use crate::database::record::BlockRangeRootRecord; + use crate::sqlite::{ConnectionExtensions, SqliteConnection}; + + use super::*; + + pub fn insert_block_range_roots( + connection: &SqliteConnection, + records: Vec, + ) { + connection + .fetch_first(InsertBlockRangeRootQuery::insert_many(records).unwrap()) + .unwrap(); + } +} diff --git a/internal/mithril-persistence/src/database/repository/cardano_transaction_repository.rs b/internal/mithril-persistence/src/database/repository/cardano_transaction_repository.rs index f7af54bd8b6..60d96de5a88 100644 --- a/internal/mithril-persistence/src/database/repository/cardano_transaction_repository.rs +++ b/internal/mithril-persistence/src/database/repository/cardano_transaction_repository.rs @@ -146,16 +146,17 @@ impl CardanoTransactionRepository { ) } - /// Retrieve all the Block Range Roots in database up to the given end block number included. + /// Retrieve all the Block Range Roots in database up to the block range that contains the given + /// block number. pub async fn retrieve_block_range_roots_up_to( &self, - up_to_or_equal_end_block_number: BlockNumber, + block_number: BlockNumber, ) -> StdResult + '_>> { let block_range_roots = self .connection_pool .connection()? - .fetch(GetBlockRangeRootQuery::up_to_block_number( - up_to_or_equal_end_block_number, + .fetch(GetBlockRangeRootQuery::contains_or_below_block_number( + block_number, ))? .map(|record| -> (BlockRange, MKTreeNode) { record.into() }) .collect::>(); // TODO: remove this collect to return the iterator directly @@ -325,13 +326,9 @@ impl CardanoTransactionRepository { impl BlockRangeRootRetriever for CardanoTransactionRepository { async fn retrieve_block_range_roots<'a>( &'a self, - up_to_or_equal_beacon: BlockNumber, + up_to_beacon: BlockNumber, ) -> StdResult + 'a>> { - let iterator = self - .retrieve_block_range_roots_up_to(up_to_or_equal_beacon) - .await?; - - Ok(Box::new(iterator)) + self.retrieve_block_range_roots_up_to(up_to_beacon).await } } @@ -973,50 +970,14 @@ mod tests { .await .unwrap(); - // Retrieve with a block far higher than the highest block range - should return all - { - let retrieved_block_ranges = repository - .retrieve_block_range_roots_up_to(1000) - .await - .unwrap(); - assert_eq!( - block_range_roots, - retrieved_block_ranges.collect::>() - ); - } - // Retrieve with a block bellow than the smallest block range - should return none - { - let retrieved_block_ranges = repository - .retrieve_block_range_roots_up_to(2) - .await - .unwrap(); - assert_eq!( - Vec::<(BlockRange, MKTreeNode)>::new(), - retrieved_block_ranges.collect::>() - ); - } - // Right below the end of the second block range - should return first of the three - { - let retrieved_block_ranges = repository - .retrieve_block_range_roots_up_to(44) - .await - .unwrap(); - assert_eq!( - vec![block_range_roots[0].clone()], - retrieved_block_ranges.collect::>() - ); - } - // The given block is matched to the end (included) - should return the two of the three - { - let retrieved_block_ranges = repository - .retrieve_block_range_roots_up_to(45) - .await - .unwrap(); - assert_eq!( - block_range_roots[0..=1].to_vec(), - retrieved_block_ranges.collect::>() - ); - } + let retrieved_block_ranges = repository + .retrieve_block_range_roots_up_to(45) + .await + .unwrap(); + assert_eq!( + block_range_roots[0..2].to_vec(), + retrieved_block_ranges.collect::>() + ); } #[tokio::test] diff --git a/mithril-common/src/signable_builder/cardano_transactions.rs b/mithril-common/src/signable_builder/cardano_transactions.rs index 6c767acc329..00394243f16 100644 --- a/mithril-common/src/signable_builder/cardano_transactions.rs +++ b/mithril-common/src/signable_builder/cardano_transactions.rs @@ -29,7 +29,7 @@ pub trait BlockRangeRootRetriever: Send + Sync { /// Returns a Merkle map of the block ranges roots up to a given beacon async fn retrieve_block_range_roots<'a>( &'a self, - up_to_or_equal_beacon: BlockNumber, + up_to_beacon: BlockNumber, ) -> StdResult + 'a>>; /// Returns a Merkle map of the block ranges roots up to a given beacon From b629b31977951f4a39dbcebf76ff28b0aa3c51e3 Mon Sep 17 00:00:00 2001 From: DJO <790521+Alenar@users.noreply.github.com> Date: Wed, 3 Jul 2024 11:55:58 +0200 Subject: [PATCH 7/9] Adjust computation of block number to sign Substacting `1` to the result to account for the fact that a block range end is exclusive. --- .../tests/create_certificate.rs | 6 ++-- .../src/entities/signed_entity_config.rs | 29 +++++++++++-------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/mithril-aggregator/tests/create_certificate.rs b/mithril-aggregator/tests/create_certificate.rs index 324a1aba678..046a20a96aa 100644 --- a/mithril-aggregator/tests/create_certificate.rs +++ b/mithril-aggregator/tests/create_certificate.rs @@ -142,7 +142,7 @@ async fn create_certificate() { comment!( "Increase cardano chain block number to 185, - the state machine should be signing CardanoTransactions for block 180" + the state machine should be signing CardanoTransactions for block 179" ); tester.increase_block_number(85, 185).await.unwrap(); cycle!(tester, "signing"); @@ -166,7 +166,7 @@ async fn create_certificate() { .map(|s| s.signer_with_stake.clone().into()) .collect::>(), fixture.compute_and_encode_avk(), - SignedEntityType::CardanoTransactions(Epoch(1), 180), + SignedEntityType::CardanoTransactions(Epoch(1), 179), ExpectedCertificate::genesis_identifier(&CardanoDbBeacon::new( "devnet".to_string(), 1, @@ -201,7 +201,7 @@ async fn create_certificate() { .map(|s| s.signer_with_stake.clone().into()) .collect::>(), fixture.compute_and_encode_avk(), - SignedEntityType::CardanoTransactions(Epoch(1), 120), + SignedEntityType::CardanoTransactions(Epoch(1), 119), ExpectedCertificate::genesis_identifier(&CardanoDbBeacon::new( "devnet".to_string(), 1, diff --git a/mithril-common/src/entities/signed_entity_config.rs b/mithril-common/src/entities/signed_entity_config.rs index 1978882ea25..a949f3145aa 100644 --- a/mithril-common/src/entities/signed_entity_config.rs +++ b/mithril-common/src/entities/signed_entity_config.rs @@ -131,12 +131,15 @@ impl CardanoTransactionsSigningConfig { /// /// The formula is as follows: /// - /// `block_number = ⌊(tip.block_number - security_parameter) / step⌋ × step` + /// `block_number = ⌊(tip.block_number - security_parameter) / step⌋ × step - 1` /// /// where `⌊x⌋` is the floor function which rounds to the greatest integer less than or equal to `x`. /// - /// *Note: The step is adjusted to be a multiple of the block range length in order + /// *Notes:* + /// * *The step is adjusted to be a multiple of the block range length in order /// to guarantee that the block number signed in a certificate is effectively signed.* + /// * *1 is subtracted to the result because block range end is exclusive (ie: a BlockRange over + /// `30..45` finish at 44 included, 45 is included in the next block range).* pub fn compute_block_number_to_be_signed(&self, block_number: BlockNumber) -> BlockNumber { // TODO: See if we can remove this adjustment by including a "partial" block range in // the signed data. @@ -144,7 +147,9 @@ impl CardanoTransactionsSigningConfig { // We can't have a step lower than the block range length. let adjusted_step = std::cmp::max(adjusted_step, BlockRange::LENGTH); - (block_number.saturating_sub(self.security_parameter)) / adjusted_step * adjusted_step + let block_number_to_be_signed = + (block_number.saturating_sub(self.security_parameter)) / adjusted_step * adjusted_step; + block_number_to_be_signed.saturating_sub(1) } } @@ -199,11 +204,11 @@ mod tests { ) ); - // The block number to be signed is 0 because the step is 15, the block number is 20, and + // The block number to be signed is 14 because the step is 15, the block number is 20, and // the security parameter is 0. // This is further tested in the "computing_block_number_to_be_signed" tests below. assert_eq!( - SignedEntityType::CardanoTransactions(Epoch(1), 15), + SignedEntityType::CardanoTransactions(Epoch(1), 14), config.time_point_to_signed_entity( SignedEntityTypeDiscriminants::CardanoTransactions, &time_point @@ -220,7 +225,7 @@ mod tests { step: 15, } .compute_block_number_to_be_signed(105), - 105 + 104 ); assert_eq!( @@ -229,7 +234,7 @@ mod tests { step: 15, } .compute_block_number_to_be_signed(100), - 90 + 89 ); assert_eq!( @@ -238,7 +243,7 @@ mod tests { step: 15, } .compute_block_number_to_be_signed(100), - 15 + 14 ); assert_eq!( @@ -271,7 +276,7 @@ mod tests { step: BlockRange::LENGTH * 2 - 1, } .compute_block_number_to_be_signed(BlockRange::LENGTH * 5 + 1), - BlockRange::LENGTH * 5 + BlockRange::LENGTH * 5 - 1 ); assert_eq!( @@ -280,7 +285,7 @@ mod tests { step: BlockRange::LENGTH * 2 + 1, } .compute_block_number_to_be_signed(BlockRange::LENGTH * 5 + 1), - BlockRange::LENGTH * 4 + BlockRange::LENGTH * 4 - 1 ); // Adjusted step is always at least BLOCK_RANGE_LENGTH. @@ -290,7 +295,7 @@ mod tests { step: BlockRange::LENGTH - 1, } .compute_block_number_to_be_signed(BlockRange::LENGTH * 10 - 1), - BlockRange::LENGTH * 9 + BlockRange::LENGTH * 9 - 1 ); assert_eq!( @@ -424,7 +429,7 @@ mod tests { SignedEntityType::MithrilStakeDistribution(beacon.epoch), SignedEntityType::CardanoStakeDistribution(beacon.epoch), SignedEntityType::CardanoImmutableFilesFull(beacon.clone()), - SignedEntityType::CardanoTransactions(beacon.epoch, chain_point.block_number), + SignedEntityType::CardanoTransactions(beacon.epoch, chain_point.block_number - 1), ], signed_entity_types ); From 1a6103a8c5f41547a93a096e4f95ba324f4176e0 Mon Sep 17 00:00:00 2001 From: DJO <790521+Alenar@users.noreply.github.com> Date: Thu, 4 Jul 2024 15:22:44 +0200 Subject: [PATCH 8/9] PR review adjustment: better naming for a test helper --- .../src/crypto_helper/merkle_map.rs | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/mithril-common/src/crypto_helper/merkle_map.rs b/mithril-common/src/crypto_helper/merkle_map.rs index e373eeb988c..77a2c48f0c9 100644 --- a/mithril-common/src/crypto_helper/merkle_map.rs +++ b/mithril-common/src/crypto_helper/merkle_map.rs @@ -491,7 +491,7 @@ mod tests { MKTree::new(&leaves).unwrap() } - fn join_merkle_tree(block_ranges: &[BlockRange]) -> Vec<(BlockRange, MKTree)> { + fn generate_merkle_trees_for_ranges(block_ranges: &[BlockRange]) -> Vec<(BlockRange, MKTree)> { block_ranges .iter() .map(|block_range| (block_range.to_owned(), generate_merkle_tree(block_range))) @@ -530,7 +530,7 @@ mod tests { #[test] fn test_mk_map_should_accept_replacement_with_same_root_value() { - let entries = join_merkle_tree(&[ + let entries = generate_merkle_trees_for_ranges(&[ BlockRange::new(0, 3), BlockRange::new(4, 6), BlockRange::new(7, 9), @@ -555,7 +555,7 @@ mod tests { #[test] fn test_mk_map_should_reject_replacement_with_different_root_value() { - let entries = join_merkle_tree(&[ + let entries = generate_merkle_trees_for_ranges(&[ BlockRange::new(0, 3), BlockRange::new(4, 6), BlockRange::new(7, 9), @@ -572,7 +572,7 @@ mod tests { #[test] fn test_mk_map_replace_should_accept_replacement_with_same_root_value() { - let entries = join_merkle_tree(&[ + let entries = generate_merkle_trees_for_ranges(&[ BlockRange::new(0, 3), BlockRange::new(4, 6), BlockRange::new(7, 9), @@ -606,7 +606,7 @@ mod tests { #[test] fn test_mk_map_replace_should_reject_replacement_if_key_doesnt_exist() { - let entries = join_merkle_tree(&[ + let entries = generate_merkle_trees_for_ranges(&[ BlockRange::new(0, 3), BlockRange::new(4, 6), BlockRange::new(7, 9), @@ -630,7 +630,7 @@ mod tests { #[test] fn test_mk_map_replace_should_reject_replacement_with_different_root_value() { - let entries = join_merkle_tree(&[ + let entries = generate_merkle_trees_for_ranges(&[ BlockRange::new(0, 3), BlockRange::new(4, 6), BlockRange::new(7, 9), @@ -654,7 +654,7 @@ mod tests { #[test] fn test_mk_map_should_compress_correctly() { - let entries = join_merkle_tree(&[ + let entries = generate_merkle_trees_for_ranges(&[ BlockRange::new(0, 3), BlockRange::new(4, 6), BlockRange::new(7, 9), @@ -675,7 +675,7 @@ mod tests { #[test] fn test_mk_map_should_reject_out_of_order_insertion() { - let entries = join_merkle_tree(&[ + let entries = generate_merkle_trees_for_ranges(&[ BlockRange::new(0, 3), BlockRange::new(4, 6), BlockRange::new(7, 9), @@ -693,7 +693,7 @@ mod tests { #[test] fn test_mk_map_should_list_keys_correctly() { - let entries = join_merkle_tree(&[ + let entries = generate_merkle_trees_for_ranges(&[ BlockRange::new(0, 3), BlockRange::new(4, 6), BlockRange::new(7, 9), @@ -716,7 +716,7 @@ mod tests { #[test] fn test_mk_map_should_list_values_correctly() { - let entries = join_merkle_tree(&[ + let entries = generate_merkle_trees_for_ranges(&[ BlockRange::new(0, 3), BlockRange::new(4, 6), BlockRange::new(7, 9), @@ -742,7 +742,7 @@ mod tests { #[test] fn test_mk_map_should_find_value_correctly() { - let entries = join_merkle_tree(&[ + let entries = generate_merkle_trees_for_ranges(&[ BlockRange::new(0, 3), BlockRange::new(4, 6), BlockRange::new(7, 9), @@ -755,7 +755,7 @@ mod tests { #[test] fn test_mk_map_should_clone_and_compute_same_root() { - let entries = join_merkle_tree(&[ + let entries = generate_merkle_trees_for_ranges(&[ BlockRange::new(0, 3), BlockRange::new(4, 6), BlockRange::new(7, 9), From 10e2a20d07e9512331dde87e475922b4b418e14b Mon Sep 17 00:00:00 2001 From: DJO <790521+Alenar@users.noreply.github.com> Date: Thu, 4 Jul 2024 15:25:39 +0200 Subject: [PATCH 9/9] Upgrade crates versions * Mithril-aggregator from `0.5.34` to `0.5.35` * Mithril-signer from `0.2.157` to `0.2.158` * Mithril-common from `0.4.25` to `0.4.26` * Mithril-persistence from `0.2.14` to `0.2.15` --- Cargo.lock | 8 ++++---- internal/mithril-persistence/Cargo.toml | 2 +- mithril-aggregator/Cargo.toml | 2 +- mithril-common/Cargo.toml | 2 +- mithril-signer/Cargo.toml | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 36c2dcf5365..5c2844ec5b7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3547,7 +3547,7 @@ dependencies = [ [[package]] name = "mithril-aggregator" -version = "0.5.34" +version = "0.5.35" dependencies = [ "anyhow", "async-trait", @@ -3703,7 +3703,7 @@ dependencies = [ [[package]] name = "mithril-common" -version = "0.4.25" +version = "0.4.26" dependencies = [ "anyhow", "async-trait", @@ -3801,7 +3801,7 @@ dependencies = [ [[package]] name = "mithril-persistence" -version = "0.2.14" +version = "0.2.15" dependencies = [ "anyhow", "async-trait", @@ -3848,7 +3848,7 @@ dependencies = [ [[package]] name = "mithril-signer" -version = "0.2.157" +version = "0.2.158" dependencies = [ "anyhow", "async-trait", diff --git a/internal/mithril-persistence/Cargo.toml b/internal/mithril-persistence/Cargo.toml index 837a175bbae..513a6619c53 100644 --- a/internal/mithril-persistence/Cargo.toml +++ b/internal/mithril-persistence/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mithril-persistence" -version = "0.2.14" +version = "0.2.15" description = "Common types, interfaces, and utilities to persist data for Mithril nodes." authors = { workspace = true } edition = { workspace = true } diff --git a/mithril-aggregator/Cargo.toml b/mithril-aggregator/Cargo.toml index c3fcf928e70..9153c843f34 100644 --- a/mithril-aggregator/Cargo.toml +++ b/mithril-aggregator/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mithril-aggregator" -version = "0.5.34" +version = "0.5.35" description = "A Mithril Aggregator server" authors = { workspace = true } edition = { workspace = true } diff --git a/mithril-common/Cargo.toml b/mithril-common/Cargo.toml index 6844708f376..763197ad74c 100644 --- a/mithril-common/Cargo.toml +++ b/mithril-common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mithril-common" -version = "0.4.25" +version = "0.4.26" 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 34ae8565bec..7e330b1e0d6 100644 --- a/mithril-signer/Cargo.toml +++ b/mithril-signer/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mithril-signer" -version = "0.2.157" +version = "0.2.158" description = "A Mithril Signer" authors = { workspace = true } edition = { workspace = true }