From b823413c9b7ae6747b9af99e18379cfc49f4271a Mon Sep 17 00:00:00 2001 From: Luke Parker Date: Thu, 30 Nov 2023 04:22:37 -0500 Subject: [PATCH] Use parity-db in current Dockerfiles (#455) * Use redb and in Dockerfiles The motivation for redb was to remove the multiple rocksdb compile times from CI. * Correct feature flagging of coordinator and message-queue in Dockerfiles * Correct message-queue DB type alias * Use consistent table typing in redb * Correct rebase artifacts * Correct removal of binaries feature from message-queue * Correct processor feature flagging * Replace redb with parity-db It still has much better compile times yet doesn't block when creating multiple transactions. It also is actively maintained and doesn't grow our tree. The MPT aspects are irrelevant. * Correct stray Redb * clippy warning * Correct txn get --- Cargo.lock | 3 +- common/db/Cargo.toml | 2 + common/db/src/lib.rs | 5 + common/db/src/parity_db.rs | 46 +++ coordinator/Cargo.toml | 6 +- coordinator/src/main.rs | 14 +- message-queue/Cargo.toml | 5 +- message-queue/src/main.rs | 265 +++++++++--------- orchestration/coordinator/Dockerfile | 2 +- .../coordinator/Dockerfile.coordinator | 2 +- orchestration/message-queue/Dockerfile | 2 +- .../message-queue/Dockerfile.message-queue | 2 +- orchestration/processor/bitcoin/Dockerfile | 2 +- .../bitcoin/Dockerfile.processor.bitcoin | 2 +- orchestration/processor/monero/Dockerfile | 2 +- .../monero/Dockerfile.processor.monero | 2 +- processor/Cargo.toml | 6 +- processor/src/main.rs | 13 +- 18 files changed, 232 insertions(+), 149 deletions(-) create mode 100644 common/db/src/parity_db.rs diff --git a/Cargo.lock b/Cargo.lock index d4236e69..8937c439 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4718,7 +4718,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c11e44798ad209ccdd91fc192f0526a369a01234f7373e1b141c96d7cee4f0e" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate 2.0.0", "proc-macro2", "quote", "syn 2.0.39", @@ -7372,6 +7372,7 @@ dependencies = [ name = "serai-db" version = "0.1.0" dependencies = [ + "parity-db", "rocksdb", ] diff --git a/common/db/Cargo.toml b/common/db/Cargo.toml index e2adffe1..9833f755 100644 --- a/common/db/Cargo.toml +++ b/common/db/Cargo.toml @@ -14,7 +14,9 @@ all-features = true rustdoc-args = ["--cfg", "docsrs"] [dependencies] +parity-db = { version = "0.4", default-features = false, optional = true } rocksdb = { version = "0.21", default-features = false, features = ["lz4"], optional = true } [features] +parity-db = ["dep:parity-db"] rocksdb = ["dep:rocksdb"] diff --git a/common/db/src/lib.rs b/common/db/src/lib.rs index 031bcd4e..1c08fe3d 100644 --- a/common/db/src/lib.rs +++ b/common/db/src/lib.rs @@ -9,6 +9,11 @@ mod rocks; #[cfg(feature = "rocksdb")] pub use rocks::{RocksDB, new_rocksdb}; +#[cfg(feature = "parity-db")] +mod parity_db; +#[cfg(feature = "parity-db")] +pub use parity_db::{ParityDb, new_parity_db}; + /// An object implementing get. pub trait Get { fn get(&self, key: impl AsRef<[u8]>) -> Option>; diff --git a/common/db/src/parity_db.rs b/common/db/src/parity_db.rs new file mode 100644 index 00000000..06fd0c7c --- /dev/null +++ b/common/db/src/parity_db.rs @@ -0,0 +1,46 @@ +use std::sync::Arc; + +pub use ::parity_db::{Options, Db as ParityDb}; + +use crate::*; + +pub struct Transaction<'a>(&'a Arc, Vec<(u8, Vec, Option>)>); + +impl Get for Transaction<'_> { + fn get(&self, key: impl AsRef<[u8]>) -> Option> { + let mut res = self.0.get(&key); + for change in &self.1 { + if change.1 == key.as_ref() { + res = change.2.clone(); + } + } + res + } +} +impl DbTxn for Transaction<'_> { + fn put(&mut self, key: impl AsRef<[u8]>, value: impl AsRef<[u8]>) { + self.1.push((0, key.as_ref().to_vec(), Some(value.as_ref().to_vec()))) + } + fn del(&mut self, key: impl AsRef<[u8]>) { + self.1.push((0, key.as_ref().to_vec(), None)) + } + fn commit(self) { + self.0.commit(self.1).unwrap() + } +} + +impl Get for Arc { + fn get(&self, key: impl AsRef<[u8]>) -> Option> { + ParityDb::get(self, 0, key.as_ref()).unwrap() + } +} +impl Db for Arc { + type Transaction<'a> = Transaction<'a>; + fn txn(&mut self) -> Self::Transaction<'_> { + Transaction(self, vec![]) + } +} + +pub fn new_parity_db(path: &str) -> Arc { + Arc::new(ParityDb::open_or_create(&Options::with_columns(std::path::Path::new(path), 1)).unwrap()) +} diff --git a/coordinator/Cargo.toml b/coordinator/Cargo.toml index 460e5d8b..525ee1ba 100644 --- a/coordinator/Cargo.toml +++ b/coordinator/Cargo.toml @@ -30,7 +30,7 @@ frost-schnorrkel = { path = "../crypto/schnorrkel" } scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["std", "derive"] } -serai-db = { path = "../common/db", features = ["rocksdb"] } +serai-db = { path = "../common/db" } serai-env = { path = "../common/env" } processor-messages = { package = "serai-processor-messages", path = "../processor/messages" } @@ -55,3 +55,7 @@ futures = { version = "0.3", default-features = false, features = ["std"] } tributary = { package = "tributary-chain", path = "./tributary", features = ["tests"] } sp-application-crypto = { git = "https://github.com/serai-dex/substrate", default-features = false, features = ["std"] } sp-runtime = { git = "https://github.com/serai-dex/substrate", default-features = false, features = ["std"] } + +[features] +parity-db = ["serai-db/parity-db"] +rocksdb = ["serai-db/rocksdb"] diff --git a/coordinator/src/main.rs b/coordinator/src/main.rs index 4734b519..203d29e7 100644 --- a/coordinator/src/main.rs +++ b/coordinator/src/main.rs @@ -16,7 +16,6 @@ use schnorr::SchnorrSignature; use frost::Participant; use serai_db::{DbTxn, Db}; -use serai_env as env; use scale::Encode; use serai_client::{ @@ -1199,7 +1198,18 @@ async fn main() { log::info!("starting coordinator service..."); - let db = serai_db::new_rocksdb(&env::var("DB_PATH").expect("path to DB wasn't specified")); + #[allow(unused_variables, unreachable_code)] + let db = { + #[cfg(all(feature = "parity-db", feature = "rocksdb"))] + panic!("built with parity-db and rocksdb"); + #[cfg(all(feature = "parity-db", not(feature = "rocksdb")))] + let db = + serai_db::new_parity_db(&serai_env::var("DB_PATH").expect("path to DB wasn't specified")); + #[cfg(feature = "rocksdb")] + let db = + serai_db::new_rocksdb(&serai_env::var("DB_PATH").expect("path to DB wasn't specified")); + db + }; let key = { let mut key_hex = serai_env::var("SERAI_KEY").expect("Serai key wasn't provided"); diff --git a/message-queue/Cargo.toml b/message-queue/Cargo.toml index 77fb5264..b775d6a9 100644 --- a/message-queue/Cargo.toml +++ b/message-queue/Cargo.toml @@ -37,11 +37,12 @@ env_logger = { version = "0.10", default-features = false, features = ["humantim # Uses a single threaded runtime since this shouldn't ever be CPU-bound tokio = { version = "1", default-features = false, features = ["rt", "time", "io-util", "net", "macros"] } -serai-db = { path = "../common/db", features = ["rocksdb"], optional = true } +serai-db = { path = "../common/db", optional = true } serai-env = { path = "../common/env" } serai-primitives = { path = "../substrate/primitives", features = ["borsh"] } [features] -binaries = ["serai-db"] +parity-db = ["serai-db/parity-db"] +rocksdb = ["serai-db/rocksdb"] diff --git a/message-queue/src/main.rs b/message-queue/src/main.rs index c3ca7003..25a36edf 100644 --- a/message-queue/src/main.rs +++ b/message-queue/src/main.rs @@ -1,154 +1,149 @@ -#[cfg(feature = "binaries")] mod messages; -#[cfg(feature = "binaries")] mod queue; -#[cfg(feature = "binaries")] -mod binaries { - pub(crate) use std::{ - sync::{Arc, RwLock}, - collections::HashMap, - }; +pub(crate) use std::{ + sync::{Arc, RwLock}, + collections::HashMap, +}; - pub(crate) use ciphersuite::{group::GroupEncoding, Ciphersuite, Ristretto}; - pub(crate) use schnorr_signatures::SchnorrSignature; +pub(crate) use ciphersuite::{group::GroupEncoding, Ciphersuite, Ristretto}; +pub(crate) use schnorr_signatures::SchnorrSignature; - pub(crate) use serai_primitives::NetworkId; +pub(crate) use serai_primitives::NetworkId; - pub(crate) use tokio::{ - io::{AsyncReadExt, AsyncWriteExt}, - net::TcpListener, - }; +pub(crate) use tokio::{ + io::{AsyncReadExt, AsyncWriteExt}, + net::TcpListener, +}; - use serai_db::{Get, DbTxn, Db as DbTrait}; +use serai_db::{Get, DbTxn, Db as DbTrait}; - pub(crate) use crate::messages::*; +pub(crate) use crate::messages::*; - pub(crate) use crate::queue::Queue; +pub(crate) use crate::queue::Queue; - pub(crate) type Db = serai_db::RocksDB; +#[cfg(all(feature = "parity-db", not(feature = "rocksdb")))] +pub(crate) type Db = Arc; +#[cfg(feature = "rocksdb")] +pub(crate) type Db = serai_db::RocksDB; - #[allow(clippy::type_complexity)] - mod clippy { - use super::*; - use once_cell::sync::Lazy; - pub(crate) static KEYS: Lazy::G>>>> = - Lazy::new(|| Arc::new(RwLock::new(HashMap::new()))); - pub(crate) static QUEUES: Lazy>>>>> = - Lazy::new(|| Arc::new(RwLock::new(HashMap::new()))); - } - pub(crate) use self::clippy::*; +#[allow(clippy::type_complexity)] +mod clippy { + use super::*; + use once_cell::sync::Lazy; + pub(crate) static KEYS: Lazy::G>>>> = + Lazy::new(|| Arc::new(RwLock::new(HashMap::new()))); + pub(crate) static QUEUES: Lazy>>>>> = + Lazy::new(|| Arc::new(RwLock::new(HashMap::new()))); +} +pub(crate) use self::clippy::*; - // queue RPC method - /* - Queues a message to be delivered from a processor to a coordinator, or vice versa. +// queue RPC method +/* + Queues a message to be delivered from a processor to a coordinator, or vice versa. - Messages are authenticated to be coming from the claimed service. Recipient services SHOULD - independently verify signatures. + Messages are authenticated to be coming from the claimed service. Recipient services SHOULD + independently verify signatures. - The metadata specifies an intent. Only one message, for a specified intent, will be delivered. - This allows services to safely send messages multiple times without them being delivered - multiple times. + The metadata specifies an intent. Only one message, for a specified intent, will be delivered. + This allows services to safely send messages multiple times without them being delivered + multiple times. - The message will be ordered by this service, with the order having no guarantees other than - successful ordering by the time this call returns. - */ - pub(crate) fn queue_message( - db: &mut Db, - meta: Metadata, - msg: Vec, - sig: SchnorrSignature, - ) { - { - let from = (*KEYS).read().unwrap()[&meta.from]; - assert!( - sig.verify(from, message_challenge(meta.from, from, meta.to, &meta.intent, &msg, sig.R)) - ); - } - - // Assert one, and only one of these, is the coordinator - assert!(matches!(meta.from, Service::Coordinator) ^ matches!(meta.to, Service::Coordinator)); - - // Verify (from, to, intent) hasn't been prior seen - fn key(domain: &'static [u8], key: impl AsRef<[u8]>) -> Vec { - [&[u8::try_from(domain.len()).unwrap()], domain, key.as_ref()].concat() - } - fn intent_key(from: Service, to: Service, intent: &[u8]) -> Vec { - key(b"intent_seen", borsh::to_vec(&(from, to, intent)).unwrap()) - } - let mut txn = db.txn(); - let intent_key = intent_key(meta.from, meta.to, &meta.intent); - if Get::get(&txn, &intent_key).is_some() { - log::warn!( - "Prior queued message attempted to be queued again. From: {:?} To: {:?} Intent: {}", - meta.from, - meta.to, - hex::encode(&meta.intent) - ); - return; - } - DbTxn::put(&mut txn, intent_key, []); - - // Queue it - let id = (*QUEUES).read().unwrap()[&(meta.from, meta.to)].write().unwrap().queue_message( - &mut txn, - QueuedMessage { - from: meta.from, - // Temporary value which queue_message will override - id: u64::MAX, - msg, - sig: sig.serialize(), - }, + The message will be ordered by this service, with the order having no guarantees other than + successful ordering by the time this call returns. +*/ +pub(crate) fn queue_message( + db: &mut Db, + meta: Metadata, + msg: Vec, + sig: SchnorrSignature, +) { + { + let from = (*KEYS).read().unwrap()[&meta.from]; + assert!( + sig.verify(from, message_challenge(meta.from, from, meta.to, &meta.intent, &msg, sig.R)) ); - - log::info!("Queued message. From: {:?} To: {:?} ID: {id}", meta.from, meta.to); - DbTxn::commit(txn); } - // next RPC method - /* - Gets the next message in queue for the named services. + // Assert one, and only one of these, is the coordinator + assert!(matches!(meta.from, Service::Coordinator) ^ matches!(meta.to, Service::Coordinator)); - This is not authenticated due to the fact every nonce would have to be saved to prevent - replays, or a challenge-response protocol implemented. Neither are worth doing when there - should be no sensitive data on this server. - */ - pub(crate) fn get_next_message(from: Service, to: Service) -> Option { - let queue_outer = (*QUEUES).read().unwrap(); - let queue = queue_outer[&(from, to)].read().unwrap(); - let next = queue.last_acknowledged().map(|i| i + 1).unwrap_or(0); - queue.get_message(next) + // Verify (from, to, intent) hasn't been prior seen + fn key(domain: &'static [u8], key: impl AsRef<[u8]>) -> Vec { + [&[u8::try_from(domain.len()).unwrap()], domain, key.as_ref()].concat() } - - // ack RPC method - /* - Acknowledges a message as received and handled, meaning it'll no longer be returned as the next - message. - */ - pub(crate) fn ack_message(from: Service, to: Service, id: u64, sig: SchnorrSignature) { - { - let to_key = (*KEYS).read().unwrap()[&to]; - assert!(sig.verify(to_key, ack_challenge(to, to_key, from, id, sig.R))); - } - - // Is it: - // The acknowledged message should be > last acknowledged OR - // The acknowledged message should be >= - // It's the first if we save messages as acknowledged before acknowledging them - // It's the second if we acknowledge messages before saving them as acknowledged - // TODO: Check only a proper message is being acked - - log::info!("Acknowledging From: {:?} To: {:?} ID: {}", from, to, id); - - (*QUEUES).read().unwrap()[&(from, to)].write().unwrap().ack_message(id) + fn intent_key(from: Service, to: Service, intent: &[u8]) -> Vec { + key(b"intent_seen", borsh::to_vec(&(from, to, intent)).unwrap()) } + let mut txn = db.txn(); + let intent_key = intent_key(meta.from, meta.to, &meta.intent); + if Get::get(&txn, &intent_key).is_some() { + log::warn!( + "Prior queued message attempted to be queued again. From: {:?} To: {:?} Intent: {}", + meta.from, + meta.to, + hex::encode(&meta.intent) + ); + return; + } + DbTxn::put(&mut txn, intent_key, []); + + // Queue it + let id = (*QUEUES).read().unwrap()[&(meta.from, meta.to)].write().unwrap().queue_message( + &mut txn, + QueuedMessage { + from: meta.from, + // Temporary value which queue_message will override + id: u64::MAX, + msg, + sig: sig.serialize(), + }, + ); + + log::info!("Queued message. From: {:?} To: {:?} ID: {id}", meta.from, meta.to); + DbTxn::commit(txn); +} + +// next RPC method +/* + Gets the next message in queue for the named services. + + This is not authenticated due to the fact every nonce would have to be saved to prevent + replays, or a challenge-response protocol implemented. Neither are worth doing when there + should be no sensitive data on this server. +*/ +pub(crate) fn get_next_message(from: Service, to: Service) -> Option { + let queue_outer = (*QUEUES).read().unwrap(); + let queue = queue_outer[&(from, to)].read().unwrap(); + let next = queue.last_acknowledged().map(|i| i + 1).unwrap_or(0); + queue.get_message(next) +} + +// ack RPC method +/* + Acknowledges a message as received and handled, meaning it'll no longer be returned as the next + message. +*/ +pub(crate) fn ack_message(from: Service, to: Service, id: u64, sig: SchnorrSignature) { + { + let to_key = (*KEYS).read().unwrap()[&to]; + assert!(sig.verify(to_key, ack_challenge(to, to_key, from, id, sig.R))); + } + + // Is it: + // The acknowledged message should be > last acknowledged OR + // The acknowledged message should be >= + // It's the first if we save messages as acknowledged before acknowledging them + // It's the second if we acknowledge messages before saving them as acknowledged + // TODO: Check only a proper message is being acked + + log::info!("Acknowledging From: {:?} To: {:?} ID: {}", from, to, id); + + (*QUEUES).read().unwrap()[&(from, to)].write().unwrap().ack_message(id) } -#[cfg(feature = "binaries")] #[tokio::main(flavor = "current_thread")] async fn main() { - use binaries::*; - // Override the panic handler with one which will panic if any tokio task panics { let existing = std::panic::take_hook(); @@ -169,7 +164,18 @@ async fn main() { log::info!("Starting message-queue service..."); // Open the DB - let db = serai_db::new_rocksdb(&serai_env::var("DB_PATH").expect("path to DB wasn't specified")); + #[allow(unused_variables, unreachable_code)] + let db = { + #[cfg(all(feature = "parity-db", feature = "rocksdb"))] + panic!("built with parity-db and rocksdb"); + #[cfg(all(feature = "parity-db", not(feature = "rocksdb")))] + let db = + serai_db::new_parity_db(&serai_env::var("DB_PATH").expect("path to DB wasn't specified")); + #[cfg(feature = "rocksdb")] + let db = + serai_db::new_rocksdb(&serai_env::var("DB_PATH").expect("path to DB wasn't specified")); + db + }; let read_key = |str| { let key = serai_env::var(str)?; @@ -272,8 +278,3 @@ async fn main() { }); } } - -#[cfg(not(feature = "binaries"))] -fn main() { - panic!("To run binaries, please build with `--feature binaries`."); -} diff --git a/orchestration/coordinator/Dockerfile b/orchestration/coordinator/Dockerfile index 44be3116..f941d8ca 100644 --- a/orchestration/coordinator/Dockerfile +++ b/orchestration/coordinator/Dockerfile @@ -46,7 +46,7 @@ RUN --mount=type=cache,target=/root/.cargo \ --mount=type=cache,target=/usr/local/cargo/git \ --mount=type=cache,target=/serai/target \ mkdir /serai/bin && \ - cargo build -p serai-coordinator --all-features && \ + cargo build -p serai-coordinator --features parity-db && \ mv /serai/target/debug/serai-coordinator /serai/bin FROM debian:bookworm-slim as image diff --git a/orchestration/coordinator/Dockerfile.coordinator b/orchestration/coordinator/Dockerfile.coordinator index c3cbbb45..8fca5622 100644 --- a/orchestration/coordinator/Dockerfile.coordinator +++ b/orchestration/coordinator/Dockerfile.coordinator @@ -1,2 +1,2 @@ - cargo build -p serai-coordinator --all-features && \ + cargo build -p serai-coordinator --features parity-db && \ mv /serai/target/debug/serai-coordinator /serai/bin diff --git a/orchestration/message-queue/Dockerfile b/orchestration/message-queue/Dockerfile index c5ea8a6d..02c859bc 100644 --- a/orchestration/message-queue/Dockerfile +++ b/orchestration/message-queue/Dockerfile @@ -46,7 +46,7 @@ RUN --mount=type=cache,target=/root/.cargo \ --mount=type=cache,target=/usr/local/cargo/git \ --mount=type=cache,target=/serai/target \ mkdir /serai/bin && \ - cargo build --all-features -p serai-message-queue && \ + cargo build --features parity-db -p serai-message-queue && \ mv /serai/target/debug/serai-message-queue /serai/bin FROM debian:bookworm-slim as image diff --git a/orchestration/message-queue/Dockerfile.message-queue b/orchestration/message-queue/Dockerfile.message-queue index beb69720..a40fad49 100644 --- a/orchestration/message-queue/Dockerfile.message-queue +++ b/orchestration/message-queue/Dockerfile.message-queue @@ -1,2 +1,2 @@ - cargo build --all-features -p serai-message-queue && \ + cargo build --features parity-db -p serai-message-queue && \ mv /serai/target/debug/serai-message-queue /serai/bin diff --git a/orchestration/processor/bitcoin/Dockerfile b/orchestration/processor/bitcoin/Dockerfile index f7d1c9c1..b23e2913 100644 --- a/orchestration/processor/bitcoin/Dockerfile +++ b/orchestration/processor/bitcoin/Dockerfile @@ -46,7 +46,7 @@ RUN --mount=type=cache,target=/root/.cargo \ --mount=type=cache,target=/usr/local/cargo/git \ --mount=type=cache,target=/serai/target \ mkdir /serai/bin && \ - cargo build --features "binaries bitcoin" -p serai-processor && \ + cargo build --features "binaries parity-db bitcoin" -p serai-processor && \ mv /serai/target/debug/serai-processor /serai/bin FROM debian:bookworm-slim as image diff --git a/orchestration/processor/bitcoin/Dockerfile.processor.bitcoin b/orchestration/processor/bitcoin/Dockerfile.processor.bitcoin index 9ed38e03..685eaf7f 100644 --- a/orchestration/processor/bitcoin/Dockerfile.processor.bitcoin +++ b/orchestration/processor/bitcoin/Dockerfile.processor.bitcoin @@ -1,2 +1,2 @@ - cargo build --features "binaries bitcoin" -p serai-processor && \ + cargo build --features "binaries parity-db bitcoin" -p serai-processor && \ mv /serai/target/debug/serai-processor /serai/bin diff --git a/orchestration/processor/monero/Dockerfile b/orchestration/processor/monero/Dockerfile index cf531aa9..1fff6593 100644 --- a/orchestration/processor/monero/Dockerfile +++ b/orchestration/processor/monero/Dockerfile @@ -46,7 +46,7 @@ RUN --mount=type=cache,target=/root/.cargo \ --mount=type=cache,target=/usr/local/cargo/git \ --mount=type=cache,target=/serai/target \ mkdir /serai/bin && \ - cargo build --features "binaries monero" -p serai-processor && \ + cargo build --features "binaries parity-db monero" -p serai-processor && \ mv /serai/target/debug/serai-processor /serai/bin FROM debian:bookworm-slim as image diff --git a/orchestration/processor/monero/Dockerfile.processor.monero b/orchestration/processor/monero/Dockerfile.processor.monero index 31d0a811..920097f1 100644 --- a/orchestration/processor/monero/Dockerfile.processor.monero +++ b/orchestration/processor/monero/Dockerfile.processor.monero @@ -1,2 +1,2 @@ - cargo build --features "binaries monero" -p serai-processor && \ + cargo build --features "binaries parity-db monero" -p serai-processor && \ mv /serai/target/debug/serai-processor /serai/bin diff --git a/processor/Cargo.toml b/processor/Cargo.toml index a95567f3..33e91046 100644 --- a/processor/Cargo.toml +++ b/processor/Cargo.toml @@ -52,7 +52,7 @@ log = { version = "0.4", default-features = false, features = ["std"] } env_logger = { version = "0.10", default-features = false, features = ["humantime"], optional = true } tokio = { version = "1", default-features = false, features = ["rt-multi-thread", "sync", "time", "macros"] } -serai-db = { path = "../common/db", features = ["rocksdb"], optional = true } +serai-db = { path = "../common/db", optional = true } serai-env = { path = "../common/env", optional = true } # TODO: Replace with direct usage of primitives serai-client = { path = "../substrate/client", default-features = false } @@ -78,4 +78,6 @@ bitcoin = ["dep:secp256k1", "secp256k1", "bitcoin-serai", "serai-client/bitcoin" ed25519 = ["dalek-ff-group", "frost/ed25519"] monero = ["ed25519", "monero-serai", "serai-client/monero"] -binaries = ["env_logger", "serai-db", "serai-env", "messages", "message-queue"] +binaries = ["env_logger", "serai-env", "messages", "message-queue"] +parity-db = ["serai-db/parity-db"] +rocksdb = ["serai-db/rocksdb"] diff --git a/processor/src/main.rs b/processor/src/main.rs index 8c63b2ae..a80f93dc 100644 --- a/processor/src/main.rs +++ b/processor/src/main.rs @@ -679,7 +679,18 @@ async fn main() { } env_logger::init(); - let db = serai_db::new_rocksdb(&env::var("DB_PATH").expect("path to DB wasn't specified")); + #[allow(unused_variables, unreachable_code)] + let db = { + #[cfg(all(feature = "parity-db", feature = "rocksdb"))] + panic!("built with parity-db and rocksdb"); + #[cfg(all(feature = "parity-db", not(feature = "rocksdb")))] + let db = + serai_db::new_parity_db(&serai_env::var("DB_PATH").expect("path to DB wasn't specified")); + #[cfg(feature = "rocksdb")] + let db = + serai_db::new_rocksdb(&serai_env::var("DB_PATH").expect("path to DB wasn't specified")); + db + }; // Network configuration let url = {