From 6f6c9f7cdf5d77c9c5aeb267f4263bd52a74773f Mon Sep 17 00:00:00 2001 From: Luke Parker Date: Fri, 14 Apr 2023 11:41:01 -0400 Subject: [PATCH] Add a dedicated db crate with a basic DB trait It's needed by the processor and tributary (coordinator). --- Cargo.lock | 5 ++ Cargo.toml | 1 + common/db/Cargo.toml | 13 ++++ common/db/LICENSE | 21 ++++++ common/db/src/lib.rs | 91 +++++++++++++++++++++++++ processor/Cargo.toml | 1 + processor/src/db.rs | 59 +--------------- processor/src/key_gen.rs | 36 ++++------ processor/src/scanner.rs | 43 +++++------- processor/src/signer.rs | 28 +++----- processor/src/substrate_signer.rs | 14 ++-- processor/src/tests/addresses.rs | 4 +- processor/src/tests/key_gen.rs | 3 +- processor/src/tests/mod.rs | 2 - processor/src/tests/scanner.rs | 3 +- processor/src/tests/signer.rs | 3 +- processor/src/tests/substrate_signer.rs | 7 +- processor/src/tests/util/db.rs | 42 ------------ processor/src/tests/util/mod.rs | 1 - processor/src/tests/wallet.rs | 4 +- 20 files changed, 200 insertions(+), 181 deletions(-) create mode 100644 common/db/Cargo.toml create mode 100644 common/db/LICENSE create mode 100644 common/db/src/lib.rs delete mode 100644 processor/src/tests/util/db.rs delete mode 100644 processor/src/tests/util/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 0f849ff0..1225adf5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6620,6 +6620,7 @@ dependencies = [ "rand_core 0.6.4", "secp256k1", "serai-client", + "serai-db", "serde", "serde_json", "sp-application-crypto", @@ -8746,6 +8747,10 @@ dependencies = [ "tokio", ] +[[package]] +name = "serai-db" +version = "0.1.0" + [[package]] name = "serai-node" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 414fe40b..4fcfa1f7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,7 @@ [workspace] members = [ "common/zalloc", + "common/db", "crypto/transcript", diff --git a/common/db/Cargo.toml b/common/db/Cargo.toml new file mode 100644 index 00000000..4dba6679 --- /dev/null +++ b/common/db/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "serai-db" +version = "0.1.0" +description = "A simple database trait and backends for it" +license = "MIT" +repository = "https://github.com/serai-dex/serai/tree/develop/common/db" +authors = ["Luke Parker "] +keywords = [] +edition = "2021" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] diff --git a/common/db/LICENSE b/common/db/LICENSE new file mode 100644 index 00000000..6779f0ec --- /dev/null +++ b/common/db/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022-2023 Luke Parker + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/common/db/src/lib.rs b/common/db/src/lib.rs new file mode 100644 index 00000000..e3765b63 --- /dev/null +++ b/common/db/src/lib.rs @@ -0,0 +1,91 @@ +use core::fmt::Debug; +use std::{ + sync::{Arc, RwLock}, + collections::{HashSet, HashMap}, +}; + +/// An object implementing get. +pub trait Get: Send + Sync + Debug { + fn get(&self, key: impl AsRef<[u8]>) -> Option>; +} + +/// An atomic database operation. +pub trait DbTxn: Send + Sync + Debug + Get { + fn put(&mut self, key: impl AsRef<[u8]>, value: impl AsRef<[u8]>); + fn del(&mut self, key: impl AsRef<[u8]>); + fn commit(self); +} + +/// A database supporting atomic operations. +pub trait Db: 'static + Send + Sync + Clone + Debug + Get { + type Transaction<'a>: DbTxn; + fn key(db_dst: &'static [u8], item_dst: &'static [u8], key: impl AsRef<[u8]>) -> Vec { + let db_len = u8::try_from(db_dst.len()).unwrap(); + let dst_len = u8::try_from(item_dst.len()).unwrap(); + [[db_len].as_ref(), db_dst, [dst_len].as_ref(), item_dst, key.as_ref()].concat().to_vec() + } + fn txn(&mut self) -> Self::Transaction<'_>; +} + +/// An atomic operation for the in-memory databae. +#[derive(Debug)] +pub struct MemDbTxn<'a>(&'a MemDb, HashMap, Vec>, HashSet>); + +impl<'a> Get for MemDbTxn<'a> { + fn get(&self, key: impl AsRef<[u8]>) -> Option> { + if self.2.contains(key.as_ref()) { + return None; + } + self.1.get(key.as_ref()).cloned().or(self.0 .0.read().unwrap().get(key.as_ref()).cloned()) + } +} +impl<'a> DbTxn for MemDbTxn<'a> { + fn put(&mut self, key: impl AsRef<[u8]>, value: impl AsRef<[u8]>) { + self.2.remove(key.as_ref()); + self.1.insert(key.as_ref().to_vec(), value.as_ref().to_vec()); + } + fn del(&mut self, key: impl AsRef<[u8]>) { + self.1.remove(key.as_ref()); + self.2.insert(key.as_ref().to_vec()); + } + fn commit(mut self) { + let mut db = self.0 .0.write().unwrap(); + for (key, value) in self.1.drain() { + db.insert(key, value); + } + for key in self.2 { + db.remove(&key); + } + } +} + +/// An in-memory database. +#[derive(Clone, Debug)] +pub struct MemDb(Arc, Vec>>>); + +impl Default for MemDb { + fn default() -> MemDb { + MemDb(Arc::new(RwLock::new(HashMap::new()))) + } +} + +impl MemDb { + /// Create a new in-memory database. + pub fn new() -> MemDb { + MemDb::default() + } +} + +impl Get for MemDb { + fn get(&self, key: impl AsRef<[u8]>) -> Option> { + self.0.read().unwrap().get(key.as_ref()).cloned() + } +} +impl Db for MemDb { + type Transaction<'a> = MemDbTxn<'a>; + fn txn(&mut self) -> MemDbTxn<'_> { + MemDbTxn(self, HashMap::new(), HashSet::new()) + } +} + +// TODO: Also bind RocksDB diff --git a/processor/Cargo.toml b/processor/Cargo.toml index 11f0d613..f9a7c8ae 100644 --- a/processor/Cargo.toml +++ b/processor/Cargo.toml @@ -54,6 +54,7 @@ monero-serai = { path = "../coins/monero", features = ["multisig"], optional = t log = "0.4" tokio = { version = "1", features = ["full"] } +serai-db = { path = "../common/db", default-features = false } serai-client = { path = "../substrate/client", default-features = false } messages = { package = "processor-messages", path = "./messages" } diff --git a/processor/src/db.rs b/processor/src/db.rs index 5b2fe8a6..f6ef3589 100644 --- a/processor/src/db.rs +++ b/processor/src/db.rs @@ -1,62 +1,9 @@ -use core::{marker::PhantomData, fmt::Debug}; -use std::{ - sync::{Arc, RwLock}, - collections::HashMap, -}; +use core::marker::PhantomData; + +pub use serai_db::*; use crate::{Plan, coins::Coin}; -pub trait DbTxn: Send + Sync + Clone + Debug { - fn put(&mut self, key: impl AsRef<[u8]>, value: impl AsRef<[u8]>); - fn get(&self, key: impl AsRef<[u8]>) -> Option>; - fn del(&mut self, key: impl AsRef<[u8]>); - fn commit(self); -} - -pub trait Db: 'static + Send + Sync + Clone + Debug { - type Transaction: DbTxn; - fn key(db_dst: &'static [u8], item_dst: &'static [u8], key: impl AsRef<[u8]>) -> Vec { - let db_len = u8::try_from(db_dst.len()).unwrap(); - let dst_len = u8::try_from(item_dst.len()).unwrap(); - [[db_len].as_ref(), db_dst, [dst_len].as_ref(), item_dst, key.as_ref()].concat().to_vec() - } - fn txn(&mut self) -> Self::Transaction; - fn get(&self, key: impl AsRef<[u8]>) -> Option>; -} - -// TODO: Replace this with RocksDB -#[derive(Clone, Debug)] -pub struct MemDb(Arc, Vec>>>); -impl MemDb { - #[allow(clippy::new_without_default)] - pub fn new() -> MemDb { - MemDb(Arc::new(RwLock::new(HashMap::new()))) - } -} - -impl DbTxn for MemDb { - fn put(&mut self, key: impl AsRef<[u8]>, value: impl AsRef<[u8]>) { - self.0.write().unwrap().insert(key.as_ref().to_vec(), value.as_ref().to_vec()); - } - fn get(&self, key: impl AsRef<[u8]>) -> Option> { - self.0.read().unwrap().get(key.as_ref()).cloned() - } - fn del(&mut self, key: impl AsRef<[u8]>) { - self.0.write().unwrap().remove(key.as_ref()); - } - fn commit(self) {} -} - -impl Db for MemDb { - type Transaction = MemDb; - fn txn(&mut self) -> MemDb { - Self(self.0.clone()) - } - fn get(&self, key: impl AsRef<[u8]>) -> Option> { - self.0.read().unwrap().get(key.as_ref()).cloned() - } -} - #[derive(Debug)] pub struct MainDb(D, PhantomData); impl MainDb { diff --git a/processor/src/key_gen.rs b/processor/src/key_gen.rs index 85e5faa4..4b243efa 100644 --- a/processor/src/key_gen.rs +++ b/processor/src/key_gen.rs @@ -18,7 +18,7 @@ use log::info; use serai_client::{primitives::BlockHash, validator_sets::primitives::ValidatorSet}; use messages::key_gen::*; -use crate::{DbTxn, Db, coins::Coin}; +use crate::{Get, DbTxn, Db, coins::Coin}; #[derive(Debug)] pub enum KeyGenEvent { @@ -40,12 +40,7 @@ impl KeyGenDb { fn params_key(set: &ValidatorSet) -> Vec { Self::key_gen_key(b"params", bincode::serialize(set).unwrap()) } - fn save_params( - &mut self, - txn: &mut D::Transaction, - set: &ValidatorSet, - params: &ThresholdParams, - ) { + fn save_params(txn: &mut D::Transaction<'_>, set: &ValidatorSet, params: &ThresholdParams) { txn.put(Self::params_key(set), bincode::serialize(params).unwrap()); } fn params(&self, set: &ValidatorSet) -> ThresholdParams { @@ -60,8 +55,7 @@ impl KeyGenDb { Self::key_gen_key(b"commitments", bincode::serialize(id).unwrap()) } fn save_commitments( - &mut self, - txn: &mut D::Transaction, + txn: &mut D::Transaction<'_>, id: &KeyGenId, commitments: &HashMap>, ) { @@ -78,8 +72,7 @@ impl KeyGenDb { Self::key_gen_key(b"generated_keys", bincode::serialize(id).unwrap()) } fn save_keys( - &mut self, - txn: &mut D::Transaction, + txn: &mut D::Transaction<'_>, id: &KeyGenId, substrate_keys: &ThresholdCore, coin_keys: &ThresholdCore, @@ -93,11 +86,11 @@ impl KeyGenDb { Self::key_gen_key(b"keys", key.to_bytes()) } #[allow(clippy::type_complexity)] - fn read_keys( - &self, + fn read_keys( + getter: &G, key: &[u8], ) -> (Vec, (ThresholdKeys, ThresholdKeys)) { - let keys_vec = self.0.get(key).unwrap(); + let keys_vec = getter.get(key).unwrap(); let mut keys_ref: &[u8] = keys_vec.as_ref(); let substrate_keys = ThresholdKeys::new(ThresholdCore::read(&mut keys_ref).unwrap()); let mut coin_keys = ThresholdKeys::new(ThresholdCore::read(&mut keys_ref).unwrap()); @@ -105,11 +98,10 @@ impl KeyGenDb { (keys_vec, (substrate_keys, coin_keys)) } fn confirm_keys( - &mut self, - txn: &mut D::Transaction, + txn: &mut D::Transaction<'_>, id: &KeyGenId, ) -> (ThresholdKeys, ThresholdKeys) { - let (keys_vec, keys) = self.read_keys(&Self::generated_keys_key(id)); + let (keys_vec, keys) = Self::read_keys(txn, &Self::generated_keys_key(id)); txn.put(Self::keys_key(&keys.1.group_key()), keys_vec); keys } @@ -117,7 +109,7 @@ impl KeyGenDb { &self, key: &::G, ) -> (ThresholdKeys, ThresholdKeys) { - self.read_keys(&Self::keys_key(key)).1 + Self::read_keys(&self.0, &Self::keys_key(key)).1 } } @@ -191,7 +183,7 @@ impl KeyGen { // This may overwrite previously written params if we rebooted, yet that isn't a // concern let mut txn = self.db.0.txn(); - self.db.save_params(&mut txn, &id.set, ¶ms); + KeyGenDb::::save_params(&mut txn, &id.set, ¶ms); txn.commit(); } @@ -268,7 +260,7 @@ impl KeyGen { } let mut txn = self.db.0.txn(); - self.db.save_commitments(&mut txn, &id, &commitments); + KeyGenDb::::save_commitments(&mut txn, &id, &commitments); txn.commit(); KeyGenEvent::ProcessorMessage(ProcessorMessage::Shares { id, shares }) @@ -349,7 +341,7 @@ impl KeyGen { let coin_keys = handle_machine(&mut rng, params, machines.1, &mut shares_ref); let mut txn = self.db.0.txn(); - self.db.save_keys(&mut txn, &id, &substrate_keys, &coin_keys); + KeyGenDb::::save_keys(&mut txn, &id, &substrate_keys, &coin_keys); txn.commit(); let mut coin_keys = ThresholdKeys::new(coin_keys); @@ -363,7 +355,7 @@ impl KeyGen { CoordinatorMessage::ConfirmKeyPair { context, id } => { let mut txn = self.db.0.txn(); - let (substrate_keys, coin_keys) = self.db.confirm_keys(&mut txn, &id); + let (substrate_keys, coin_keys) = KeyGenDb::::confirm_keys(&mut txn, &id); txn.commit(); info!( diff --git a/processor/src/scanner.rs b/processor/src/scanner.rs index 473ca0d9..964ced40 100644 --- a/processor/src/scanner.rs +++ b/processor/src/scanner.rs @@ -15,7 +15,7 @@ use tokio::{ }; use crate::{ - DbTxn, Db, + Get, DbTxn, Db, coins::{Output, Transaction, EventualitiesTracker, Block, Coin}, }; @@ -48,17 +48,12 @@ impl ScannerDb { fn block_number_key(id: &>::Id) -> Vec { Self::scanner_key(b"block_number", id) } - fn save_block( - &mut self, - txn: &mut D::Transaction, - number: usize, - id: &>::Id, - ) { + fn save_block(txn: &mut D::Transaction<'_>, number: usize, id: &>::Id) { txn.put(Self::block_number_key(id), u64::try_from(number).unwrap().to_le_bytes()); txn.put(Self::block_key(number), id); } - fn block(&self, number: usize) -> Option<>::Id> { - self.0.get(Self::block_key(number)).map(|id| { + fn block(getter: &G, number: usize) -> Option<>::Id> { + getter.get(Self::block_key(number)).map(|id| { let mut res = >::Id::default(); res.as_mut().copy_from_slice(&id); res @@ -74,8 +69,8 @@ impl ScannerDb { fn active_keys_key() -> Vec { Self::scanner_key(b"active_keys", b"") } - fn add_active_key(&mut self, txn: &mut D::Transaction, key: ::G) { - let mut keys = self.0.get(Self::active_keys_key()).unwrap_or(vec![]); + fn add_active_key(txn: &mut D::Transaction<'_>, key: ::G) { + let mut keys = txn.get(Self::active_keys_key()).unwrap_or(vec![]); let key_bytes = key.to_bytes(); @@ -130,8 +125,7 @@ impl ScannerDb { Self::scanner_key(b"outputs", [key.to_bytes().as_ref(), block.as_ref()].concat()) } fn save_outputs( - &mut self, - txn: &mut D::Transaction, + txn: &mut D::Transaction<'_>, key: &::G, block: &>::Id, outputs: &[C::Output], @@ -165,11 +159,11 @@ impl ScannerDb { next } fn outputs( - &self, + txn: &D::Transaction<'_>, key: &::G, block: &>::Id, ) -> Option> { - let bytes_vec = self.0.get(Self::outputs_key(key, block))?; + let bytes_vec = txn.get(Self::outputs_key(key, block))?; let mut bytes: &[u8] = bytes_vec.as_ref(); let mut res = vec![]; @@ -183,13 +177,12 @@ impl ScannerDb { Self::scanner_key(b"scanned_block", key.to_bytes()) } fn save_scanned_block( - &mut self, - txn: &mut D::Transaction, + txn: &mut D::Transaction<'_>, key: &::G, block: usize, ) -> Vec { - let new_key = self.0.get(Self::scanned_block_key(key)).is_none(); - let outputs = self.block(block).and_then(|id| self.outputs(key, &id)); + let new_key = txn.get(Self::scanned_block_key(key)).is_none(); + let outputs = Self::block(txn, block).and_then(|id| Self::outputs(txn, key, &id)); // Either this is a new key, with no outputs, or we're acknowledging this block // If we're acknowledging it, we should have outputs available assert_eq!(new_key, outputs.is_none()); @@ -278,8 +271,8 @@ impl ScannerHandle { info!("Rotating to key {}", hex::encode(key.to_bytes())); let mut txn = scanner.db.0.txn(); - assert!(scanner.db.save_scanned_block(&mut txn, &key, activation_number).is_empty()); - scanner.db.add_active_key(&mut txn, key); + assert!(ScannerDb::::save_scanned_block(&mut txn, &key, activation_number).is_empty()); + ScannerDb::::add_active_key(&mut txn, key); txn.commit(); scanner.keys.push(key); } @@ -300,7 +293,7 @@ impl ScannerHandle { scanner.db.block_number(&id).expect("main loop trying to operate on data we haven't scanned"); let mut txn = scanner.db.0.txn(); - let outputs = scanner.db.save_scanned_block(&mut txn, &key, number); + let outputs = ScannerDb::::save_scanned_block(&mut txn, &key, number); txn.commit(); for output in &outputs { @@ -395,7 +388,7 @@ impl Scanner { }; let block_id = block.id(); - if let Some(id) = scanner.db.block(i) { + if let Some(id) = ScannerDb::::block(&scanner.db.0, i) { // TODO2: Also check this block builds off the previous block if id != block_id { panic!("reorg'd from finalized {} to {}", hex::encode(id), hex::encode(block_id)); @@ -403,7 +396,7 @@ impl Scanner { } else { info!("Found new block: {}", hex::encode(&block_id)); let mut txn = scanner.db.0.txn(); - scanner.db.save_block(&mut txn, i, &block_id); + ScannerDb::::save_block(&mut txn, i, &block_id); txn.commit(); } @@ -461,7 +454,7 @@ impl Scanner { // Save the outputs to disk let mut txn = scanner.db.0.txn(); - let batch = scanner.db.save_outputs(&mut txn, &key, &block_id, &outputs); + let batch = ScannerDb::::save_outputs(&mut txn, &key, &block_id, &outputs); txn.commit(); const TIME_TOLERANCE: u64 = 15; diff --git a/processor/src/signer.rs b/processor/src/signer.rs index 72eed75d..b2155685 100644 --- a/processor/src/signer.rs +++ b/processor/src/signer.rs @@ -21,7 +21,7 @@ use tokio::{ use messages::sign::*; use crate::{ - DbTxn, Db, + Get, DbTxn, Db, coins::{Transaction, Eventuality, Coin}, }; @@ -46,8 +46,7 @@ impl SignerDb { Self::sign_key(b"completed", id) } fn complete( - &mut self, - txn: &mut D::Transaction, + txn: &mut D::Transaction<'_>, id: [u8; 32], tx: &>::Id, ) { @@ -77,12 +76,7 @@ impl SignerDb { fn eventuality_key(id: [u8; 32]) -> Vec { Self::sign_key(b"eventuality", id) } - fn save_eventuality( - &mut self, - txn: &mut D::Transaction, - id: [u8; 32], - eventuality: C::Eventuality, - ) { + fn save_eventuality(txn: &mut D::Transaction<'_>, id: [u8; 32], eventuality: C::Eventuality) { txn.put(Self::eventuality_key(id), eventuality.serialize()); } fn eventuality(&self, id: [u8; 32]) -> Option { @@ -94,14 +88,14 @@ impl SignerDb { fn attempt_key(id: &SignId) -> Vec { Self::sign_key(b"attempt", bincode::serialize(id).unwrap()) } - fn attempt(&mut self, txn: &mut D::Transaction, id: &SignId) { + fn attempt(txn: &mut D::Transaction<'_>, id: &SignId) { txn.put(Self::attempt_key(id), []); } fn has_attempt(&mut self, id: &SignId) -> bool { self.0.get(Self::attempt_key(id)).is_some() } - fn save_transaction(&mut self, txn: &mut D::Transaction, tx: &C::Transaction) { + fn save_transaction(txn: &mut D::Transaction<'_>, tx: &C::Transaction) { txn.put(Self::sign_key(b"tx", tx.id()), tx.serialize()); } } @@ -231,8 +225,8 @@ impl Signer { // Stop trying to sign for this TX let mut txn = self.db.0.txn(); - self.db.save_transaction(&mut txn, &tx); - self.db.complete(&mut txn, id, tx_id); + SignerDb::::save_transaction(&mut txn, &tx); + SignerDb::::complete(&mut txn, id, tx_id); txn.commit(); self.signable.remove(&id); @@ -345,9 +339,9 @@ impl Signer { // Save the transaction in case it's needed for recovery let mut txn = self.db.0.txn(); - self.db.save_transaction(&mut txn, &tx); + SignerDb::::save_transaction(&mut txn, &tx); let tx_id = tx.id(); - self.db.complete(&mut txn, id.id, &tx_id); + SignerDb::::complete(&mut txn, id.id, &tx_id); txn.commit(); // Publish it @@ -481,7 +475,7 @@ impl Signer { } let mut txn = signer.db.0.txn(); - signer.db.attempt(&mut txn, &id); + SignerDb::::attempt(&mut txn, &id); txn.commit(); // Attempt to create the TX @@ -552,7 +546,7 @@ impl SignerHandle { } let mut txn = signer.db.0.txn(); - signer.db.save_eventuality(&mut txn, id, eventuality); + SignerDb::::save_eventuality(&mut txn, id, eventuality); txn.commit(); signer.signable.insert(id, (start, tx)); diff --git a/processor/src/substrate_signer.rs b/processor/src/substrate_signer.rs index a281ef17..ab668f6d 100644 --- a/processor/src/substrate_signer.rs +++ b/processor/src/substrate_signer.rs @@ -51,7 +51,7 @@ impl SubstrateSignerDb { fn completed_key(id: [u8; 32]) -> Vec { Self::sign_key(b"completed", id) } - fn complete(&mut self, txn: &mut D::Transaction, id: [u8; 32]) { + fn complete(txn: &mut D::Transaction<'_>, id: [u8; 32]) { txn.put(Self::completed_key(id), [1]); } fn completed(&self, id: [u8; 32]) -> bool { @@ -61,14 +61,14 @@ impl SubstrateSignerDb { fn attempt_key(id: &SignId) -> Vec { Self::sign_key(b"attempt", bincode::serialize(id).unwrap()) } - fn attempt(&mut self, txn: &mut D::Transaction, id: &SignId) { + fn attempt(txn: &mut D::Transaction<'_>, id: &SignId) { txn.put(Self::attempt_key(id), []); } fn has_attempt(&mut self, id: &SignId) -> bool { self.0.get(Self::attempt_key(id)).is_some() } - fn save_batch(&mut self, txn: &mut D::Transaction, batch: &SignedBatch) { + fn save_batch(txn: &mut D::Transaction<'_>, batch: &SignedBatch) { txn.put(Self::sign_key(b"batch", batch.batch.block), batch.encode()); } } @@ -252,8 +252,8 @@ impl SubstrateSigner { // Save the batch in case it's needed for recovery let mut txn = self.db.0.txn(); - self.db.save_batch(&mut txn, &batch); - self.db.complete(&mut txn, id.id); + SubstrateSignerDb::::save_batch(&mut txn, &batch); + SubstrateSignerDb::::complete(&mut txn, id.id); txn.commit(); // Stop trying to sign for this batch @@ -267,7 +267,7 @@ impl SubstrateSigner { CoordinatorMessage::BatchSigned { key: _, block } => { // Stop trying to sign for this batch let mut txn = self.db.0.txn(); - self.db.complete(&mut txn, block.0); + SubstrateSignerDb::::complete(&mut txn, block.0); txn.commit(); self.signable.remove(&block.0); @@ -377,7 +377,7 @@ impl SubstrateSigner { } let mut txn = signer.db.0.txn(); - signer.db.attempt(&mut txn, &id); + SubstrateSignerDb::::attempt(&mut txn, &id); txn.commit(); // b"substrate" is a literal from sp-core diff --git a/processor/src/tests/addresses.rs b/processor/src/tests/addresses.rs index f31ee942..62ef3b38 100644 --- a/processor/src/tests/addresses.rs +++ b/processor/src/tests/addresses.rs @@ -7,11 +7,13 @@ use frost::{Participant, ThresholdKeys}; use tokio::time::timeout; +use serai_db::MemDb; + use crate::{ Plan, Db, coins::{OutputType, Output, Block, Coin}, scanner::{ScannerEvent, Scanner, ScannerHandle}, - tests::{util::db::MemDb, sign}, + tests::sign, }; async fn spend( diff --git a/processor/src/tests/key_gen.rs b/processor/src/tests/key_gen.rs index b178f497..54ec961f 100644 --- a/processor/src/tests/key_gen.rs +++ b/processor/src/tests/key_gen.rs @@ -7,6 +7,8 @@ use rand_core::{RngCore, OsRng}; use group::GroupEncoding; use frost::{Participant, ThresholdParams, tests::clone_without}; +use serai_db::MemDb; + use serai_client::{ primitives::{MONERO_NET_ID, BlockHash}, validator_sets::primitives::{Session, ValidatorSet}, @@ -16,7 +18,6 @@ use messages::{SubstrateContext, key_gen::*}; use crate::{ coins::Coin, key_gen::{KeyGenEvent, KeyGen}, - tests::util::db::MemDb, }; const ID: KeyGenId = diff --git a/processor/src/tests/mod.rs b/processor/src/tests/mod.rs index 100238d1..5160d96b 100644 --- a/processor/src/tests/mod.rs +++ b/processor/src/tests/mod.rs @@ -1,5 +1,3 @@ -pub(crate) mod util; - mod key_gen; pub(crate) use key_gen::test_key_gen; diff --git a/processor/src/tests/scanner.rs b/processor/src/tests/scanner.rs index 696b0348..25923adc 100644 --- a/processor/src/tests/scanner.rs +++ b/processor/src/tests/scanner.rs @@ -7,10 +7,11 @@ use frost::Participant; use tokio::time::timeout; +use serai_db::MemDb; + use crate::{ coins::{OutputType, Output, Block, Coin}, scanner::{ScannerEvent, Scanner, ScannerHandle}, - tests::util::db::MemDb, }; pub async fn test_scanner(coin: C) { diff --git a/processor/src/tests/signer.rs b/processor/src/tests/signer.rs index 6fdd1c04..b39cc5e3 100644 --- a/processor/src/tests/signer.rs +++ b/processor/src/tests/signer.rs @@ -13,12 +13,13 @@ use frost::{ use tokio::time::timeout; +use serai_db::MemDb; + use messages::sign::*; use crate::{ Payment, Plan, coins::{Output, Transaction, Coin}, signer::{SignerEvent, Signer}, - tests::util::db::MemDb, }; #[allow(clippy::type_complexity)] diff --git a/processor/src/tests/substrate_signer.rs b/processor/src/tests/substrate_signer.rs index 913594a5..c198e2b1 100644 --- a/processor/src/tests/substrate_signer.rs +++ b/processor/src/tests/substrate_signer.rs @@ -17,13 +17,12 @@ use tokio::time::timeout; use scale::Encode; use sp_application_crypto::{RuntimePublic, sr25519::Public}; +use serai_db::MemDb; + use serai_client::{primitives::*, in_instructions::primitives::*}; use messages::{sign::SignId, coordinator::*}; -use crate::{ - substrate_signer::{SubstrateSignerEvent, SubstrateSigner}, - tests::util::db::MemDb, -}; +use crate::substrate_signer::{SubstrateSignerEvent, SubstrateSigner}; #[tokio::test] async fn test_substrate_signer() { diff --git a/processor/src/tests/util/db.rs b/processor/src/tests/util/db.rs deleted file mode 100644 index 6fc2d6ed..00000000 --- a/processor/src/tests/util/db.rs +++ /dev/null @@ -1,42 +0,0 @@ -use std::{ - sync::{Arc, RwLock}, - collections::HashMap, -}; - -use crate::{DbTxn, Db}; - -#[derive(Clone, Debug)] -pub struct MemDb(Arc, Vec>>>); -impl MemDb { - pub(crate) fn new() -> MemDb { - MemDb(Arc::new(RwLock::new(HashMap::new()))) - } -} -impl Default for MemDb { - fn default() -> MemDb { - MemDb::new() - } -} - -impl DbTxn for MemDb { - fn put(&mut self, key: impl AsRef<[u8]>, value: impl AsRef<[u8]>) { - self.0.write().unwrap().insert(key.as_ref().to_vec(), value.as_ref().to_vec()); - } - fn get(&self, key: impl AsRef<[u8]>) -> Option> { - self.0.read().unwrap().get(key.as_ref()).cloned() - } - fn del(&mut self, key: impl AsRef<[u8]>) { - self.0.write().unwrap().remove(key.as_ref()); - } - fn commit(self) {} -} - -impl Db for MemDb { - type Transaction = MemDb; - fn txn(&mut self) -> MemDb { - Self(self.0.clone()) - } - fn get(&self, key: impl AsRef<[u8]>) -> Option> { - self.0.read().unwrap().get(key.as_ref()).cloned() - } -} diff --git a/processor/src/tests/util/mod.rs b/processor/src/tests/util/mod.rs deleted file mode 100644 index eaaec036..00000000 --- a/processor/src/tests/util/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub(crate) mod db; diff --git a/processor/src/tests/wallet.rs b/processor/src/tests/wallet.rs index acb4f711..3bfcacfc 100644 --- a/processor/src/tests/wallet.rs +++ b/processor/src/tests/wallet.rs @@ -6,12 +6,14 @@ use frost::{Participant, dkg::tests::key_gen}; use tokio::time::timeout; +use serai_db::MemDb; + use crate::{ Payment, Plan, coins::{Output, Transaction, Block, Coin}, scanner::{ScannerEvent, Scanner}, scheduler::Scheduler, - tests::{util::db::MemDb, sign}, + tests::sign, }; // Tests the Scanner, Scheduler, and Signer together