diff --git a/schemas/database/011_drop_root_uniqueness.sql b/schemas/database/011_drop_root_uniqueness.sql new file mode 100644 index 00000000..c5f04f95 --- /dev/null +++ b/schemas/database/011_drop_root_uniqueness.sql @@ -0,0 +1,4 @@ +ALTER TABLE identities + DROP CONSTRAINT identities_root_key; + +CREATE INDEX identities_root ON identities (root); diff --git a/src/app.rs b/src/app.rs index 9078e155..35f2400b 100644 --- a/src/app.rs +++ b/src/app.rs @@ -228,7 +228,7 @@ impl App { &initial_leaf_value, initial_root_hash, mined_items.clone(), - &mmap_file_path, + mmap_file_path, ) .await? { @@ -872,7 +872,7 @@ mod test { ); // check if the index is correct - assert_eq!(last_mined_index_in_dense, identities.iter().count()); + assert_eq!(last_mined_index_in_dense, identities.len()); // since there are less identities then dense prefix, the leavs should be empty // vector assert!(leaves.is_empty()); @@ -893,7 +893,7 @@ mod test { assert_eq!(last_mined_index_in_dense, (1 << dense_prefix_depth) - 1); // since there are more identities then dense prefix, the leavs should be 2 - assert_eq!(leaves.iter().count(), 2); + assert_eq!(leaves.len(), 2); // additional check for correctness assert_eq!(leaves[0], identities[8].element); diff --git a/src/contracts/abi.rs b/src/contracts/abi.rs index d7f55a35..c9cec180 100644 --- a/src/contracts/abi.rs +++ b/src/contracts/abi.rs @@ -25,7 +25,7 @@ impl From for TreeChangeKind { 0 => Self::Insertion, 1 => Self::Deletion, 2 => Self::Update, - _ => panic!("Invalid value for TreeChangeKind: {}", value), + _ => panic!("Invalid value for TreeChangeKind: {value}"), } } } diff --git a/src/database/mod.rs b/src/database/mod.rs index 0be9dcd3..94cd669b 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -145,7 +145,6 @@ impl Database { r#" INSERT INTO identities (leaf_index, commitment, root, status, pending_as_of) VALUES ($1, $2, $3, $4, CURRENT_TIMESTAMP) - ON CONFLICT (root) DO NOTHING; "#, ) .bind(leaf_index as i64) @@ -166,7 +165,11 @@ impl Database { ) -> Result, Error> { let root_index_query = sqlx::query( r#" - SELECT id FROM identities WHERE root = $1 + SELECT id + FROM identities + WHERE root = $1 + ORDER BY id ASC + LIMIT 1 "#, ) .bind(root); @@ -465,7 +468,9 @@ impl Database { pending_as_of as pending_valid_as_of, mined_at as mined_valid_as_of FROM identities - WHERE root = $1; + WHERE root = $1 + ORDER BY id + LIMIT 1 "#, ) .bind(root); @@ -1392,7 +1397,7 @@ mod test { db.mark_all_as_pending().await?; - for root in roots.iter() { + for root in &roots { let root = db .get_root_state(root) .await? @@ -2042,4 +2047,26 @@ mod test { Ok(()) } + + #[tokio::test] + async fn can_insert_same_root_multiple_times() -> anyhow::Result<()> { + let (db, _db_container) = setup_db().await?; + let identities = mock_identities(2); + let roots = mock_roots(2); + + db.insert_pending_identity(0, &identities[0], &roots[0]) + .await?; + + db.insert_pending_identity(1, &identities[1], &roots[0]) + .await?; + + let root_state = db + .get_root_state(&roots[0]) + .await? + .context("Missing root")?; + + assert_eq!(root_state.status, ProcessedStatus::Pending); + + Ok(()) + } } diff --git a/src/identity_tree/status.rs b/src/identity_tree/status.rs index 92e11125..3e339f21 100644 --- a/src/identity_tree/status.rs +++ b/src/identity_tree/status.rs @@ -141,7 +141,7 @@ mod tests { let s = s.leak() as &'static str; // Unwrap from the redundant JSON quotes - s.trim_start_matches("\"").trim_end_matches("\"") + s.trim_start_matches('\"').trim_end_matches('\"') } #[test_case("pending" => Status::Processed(ProcessedStatus::Pending))] diff --git a/src/lib.rs b/src/lib.rs index d34ee322..0936f6a0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,10 @@ #![doc = include_str!("../Readme.md")] -#![warn(clippy::all, clippy::pedantic, clippy::cargo)] -#![allow(clippy::module_name_repetitions, clippy::wildcard_imports)] +#![warn(clippy::cargo)] +#![allow( + clippy::module_name_repetitions, + clippy::wildcard_imports, + clippy::too_many_arguments +)] pub mod app; mod contracts; diff --git a/src/main.rs b/src/main.rs index cadc544a..612cc4b1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ #![doc = include_str!("../Readme.md")] -#![warn(clippy::all, clippy::pedantic, clippy::cargo)] +#![warn(clippy::cargo)] #![allow(clippy::module_name_repetitions, clippy::wildcard_imports)] use cli_batteries::{run, version}; diff --git a/src/server/data.rs b/src/server/data.rs index 8236b822..027063d4 100644 --- a/src/server/data.rs +++ b/src/server/data.rs @@ -207,10 +207,12 @@ impl ToResponseCode for VerifySemaphoreProofResponse { } impl IdentityHistoryEntryKind { + #[must_use] pub fn is_insertion(&self) -> bool { matches!(self, IdentityHistoryEntryKind::Insertion) } + #[must_use] pub fn is_deletion(&self) -> bool { matches!(self, IdentityHistoryEntryKind::Deletion) } diff --git a/src/task_monitor/tasks/delete_identities.rs b/src/task_monitor/tasks/delete_identities.rs index 50b63f8d..ca95557e 100644 --- a/src/task_monitor/tasks/delete_identities.rs +++ b/src/task_monitor/tasks/delete_identities.rs @@ -91,7 +91,7 @@ async fn delete_identities( ); // Insert the new items into pending identities - let items = data.into_iter().zip(leaf_indices.into_iter()); + let items = data.into_iter().zip(leaf_indices); for ((root, _proof), leaf_index) in items { database .insert_pending_identity(leaf_index, &Hash::ZERO, &root) diff --git a/src/task_monitor/tasks/finalize_identities.rs b/src/task_monitor/tasks/finalize_identities.rs index d24f8aec..6f92aeba 100644 --- a/src/task_monitor/tasks/finalize_identities.rs +++ b/src/task_monitor/tasks/finalize_identities.rs @@ -200,7 +200,7 @@ async fn finalize_mainnet_roots( database, identity_manager, processed_tree, - &log, + log, max_epoch_duration, ) .await?; @@ -311,7 +311,10 @@ async fn update_eligible_recoveries( .context("Could not fetch deletion indices from tx")?; let commitments = processed_tree.commitments_by_indices(commitments.iter().copied()); - let commitments: Vec = commitments.into_iter().map(|c| c.into()).collect(); + let commitments: Vec = commitments + .into_iter() + .map(std::convert::Into::into) + .collect(); // Check if any deleted commitments correspond with entries in the // recoveries table and insert the new commitment into the unprocessed diff --git a/src/task_monitor/tasks/insert_identities.rs b/src/task_monitor/tasks/insert_identities.rs index f0700d13..4e2eb17d 100644 --- a/src/task_monitor/tasks/insert_identities.rs +++ b/src/task_monitor/tasks/insert_identities.rs @@ -121,7 +121,7 @@ async fn insert_identities( "Length mismatch when appending identities to tree" ); - let items = data.into_iter().zip(identities.into_iter()); + let items = data.into_iter().zip(identities); for ((root, _proof, leaf_index), identity) in items { database diff --git a/src/task_monitor/tasks/monitor_txs.rs b/src/task_monitor/tasks/monitor_txs.rs index f8c86d46..8c68d3b9 100644 --- a/src/task_monitor/tasks/monitor_txs.rs +++ b/src/task_monitor/tasks/monitor_txs.rs @@ -36,9 +36,11 @@ async fn monitor_txs_loop( let mut monitored_txs_receiver = monitored_txs_receiver.lock().await; while let Some(tx) = monitored_txs_receiver.recv().await { - if !identity_manager.mine_transaction(tx.clone()).await? { - panic!("Failed to mine transaction: {}", tx); - } + assert!( + (identity_manager.mine_transaction(tx.clone()).await?), + "Failed to mine transaction: {}", + tx + ); } Ok(()) diff --git a/src/utils/index_packing.rs b/src/utils/index_packing.rs index 7873a40b..e6fbf25a 100644 --- a/src/utils/index_packing.rs +++ b/src/utils/index_packing.rs @@ -1,3 +1,4 @@ +#[must_use] pub fn pack_indices(indices: &[u32]) -> Vec { let mut packed = Vec::with_capacity(indices.len() * 4); @@ -8,6 +9,7 @@ pub fn pack_indices(indices: &[u32]) -> Vec { packed } +#[must_use] pub fn unpack_indices(packed: &[u8]) -> Vec { let mut indices = Vec::with_capacity(packed.len() / 4); diff --git a/src/utils/tree_updates.rs b/src/utils/tree_updates.rs index ae28c548..32a30fc3 100644 --- a/src/utils/tree_updates.rs +++ b/src/utils/tree_updates.rs @@ -1,5 +1,6 @@ use crate::identity_tree::TreeUpdate; +#[must_use] pub fn dedup_tree_updates(updates: Vec) -> Vec { let mut deduped = Vec::new(); let mut temp: Option = None; diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 47a3fb2b..25376b4a 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -1,6 +1,6 @@ // We include this module in multiple in multiple integration // test crates - so some code may not be used in some cases -#![allow(dead_code)] +#![allow(dead_code, clippy::too_many_arguments)] pub mod abi; mod chain_mock; diff --git a/tests/delete_identities.rs b/tests/delete_identities.rs index e380c605..3129c8d8 100644 --- a/tests/delete_identities.rs +++ b/tests/delete_identities.rs @@ -1,3 +1,5 @@ +#![allow(clippy::needless_range_loop)] + mod common; use common::prelude::*; diff --git a/tests/delete_padded_identity.rs b/tests/delete_padded_identity.rs index 5db2cc86..645bc76c 100644 --- a/tests/delete_padded_identity.rs +++ b/tests/delete_padded_identity.rs @@ -1,3 +1,5 @@ +#![allow(clippy::needless_range_loop)] + mod common; use common::prelude::*; diff --git a/tests/dynamic_batch_sizes.rs b/tests/dynamic_batch_sizes.rs index dd617d23..6ad6c7f0 100644 --- a/tests/dynamic_batch_sizes.rs +++ b/tests/dynamic_batch_sizes.rs @@ -4,7 +4,6 @@ use std::str::FromStr; use common::prelude::*; use hyper::Uri; -use tempfile; use crate::common::{test_add_batch_size, test_remove_batch_size}; diff --git a/tests/identity_history.rs b/tests/identity_history.rs index 5fe26c8e..7e9c7caa 100644 --- a/tests/identity_history.rs +++ b/tests/identity_history.rs @@ -310,7 +310,7 @@ async fn fetch_identity_history( ) -> anyhow::Result> { let uri = format!("{uri}/identityHistory"); let body = IdentityHistoryRequest { - identity_commitment: identity.clone(), + identity_commitment: *identity, }; let req = Request::post(uri) diff --git a/tests/recover_identities.rs b/tests/recover_identities.rs index 1e83af4c..2e11155a 100644 --- a/tests/recover_identities.rs +++ b/tests/recover_identities.rs @@ -1,3 +1,5 @@ +#![allow(clippy::needless_range_loop)] + mod common; use common::prelude::*;