From d783f659bcc28035efb495874d5023b29a9b6adc Mon Sep 17 00:00:00 2001 From: Ekrem BAL Date: Fri, 30 Aug 2024 15:24:18 +0300 Subject: [PATCH] Unify server binaries (#264) --- core/Cargo.toml | 23 ++++---- core/src/bin/all_servers.rs | 45 ++++++++++++++++ core/src/bin/operator.rs | 18 ------- core/src/bin/operators_and_verifiers.rs | 42 --------------- core/src/bin/server.rs | 71 +++++++++++++++++++++++++ core/src/bin/user_deposit.rs | 21 -------- core/src/bin/verifier.rs | 18 ------- core/src/database/common.rs | 16 +++--- core/src/mock/database.rs | 6 +-- scripts/schema.sql | 40 +++++++------- 10 files changed, 156 insertions(+), 144 deletions(-) create mode 100644 core/src/bin/all_servers.rs delete mode 100644 core/src/bin/operator.rs delete mode 100644 core/src/bin/operators_and_verifiers.rs create mode 100644 core/src/bin/server.rs delete mode 100644 core/src/bin/user_deposit.rs delete mode 100644 core/src/bin/verifier.rs diff --git a/core/Cargo.toml b/core/Cargo.toml index d3bef139..f04c07ed 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -31,25 +31,22 @@ musig2 = { workspace = true } [features] default = [] -poc = [] mock_rpc = [] +verifier_server = [] +operator_server = [] +aggregator_server = [] +testing = [] [[bin]] -name = "verifier" -path = "src/bin/verifier.rs" +name = "server" +path = "src/bin/server.rs" [[bin]] -name = "operator" -path = "src/bin/operator.rs" - -[[bin]] -name = "user_deposit" -path = "src/bin/user_deposit.rs" - -[[bin]] -name = "operators_and_verifiers" -path = "src/bin/operators_and_verifiers.rs" +name = "all_servers" +path = "src/bin/all_servers.rs" +required-features = ["testing"] [[bin]] name = "config_generator" path = "src/bin/config_generator.rs" +required-features = ["testing"] diff --git a/core/src/bin/all_servers.rs b/core/src/bin/all_servers.rs new file mode 100644 index 00000000..df9c0015 --- /dev/null +++ b/core/src/bin/all_servers.rs @@ -0,0 +1,45 @@ +use clementine_core::{cli, extended_rpc::ExtendedRpc, servers::create_verifiers_and_operators}; + +#[tokio::main] +async fn main() { + let config = cli::get_configuration(); + let _rpc = ExtendedRpc::::new( + config.bitcoin_rpc_url.clone(), + config.bitcoin_rpc_user.clone(), + config.bitcoin_rpc_password.clone(), + ); + + let (operator_clients, verifier_clients, aggregator) = + create_verifiers_and_operators("test_config.toml").await; + + println!( + "OPERATOR_URLS={}", + operator_clients + .iter() + .map(|(_, _, addr)| format!("http://localhost:{}", addr.port())) + .collect::>() + .join(",") + ); + println!( + "VERIFIER_URLS={}", + verifier_clients + .iter() + .map(|(_, _, addr)| format!("http://localhost:{}", addr.port())) + .collect::>() + .join(",") + ); + println!("AGGREGATOR_URL={}", aggregator.2); + + // Stop all servers + for (_, handle, _) in operator_clients { + handle.clone().stopped().await; + } + + for (_, handle, _) in verifier_clients { + handle.clone().stopped().await; + } + + aggregator.1.stopped().await; + + println!("All servers stopped"); +} diff --git a/core/src/bin/operator.rs b/core/src/bin/operator.rs deleted file mode 100644 index fc3e4d80..00000000 --- a/core/src/bin/operator.rs +++ /dev/null @@ -1,18 +0,0 @@ -use clementine_core::{cli, extended_rpc::ExtendedRpc, servers::create_operator_server}; - -#[tokio::main] -async fn main() { - let config = cli::get_configuration(); - let rpc = ExtendedRpc::::new( - config.bitcoin_rpc_url.clone(), - config.bitcoin_rpc_user.clone(), - config.bitcoin_rpc_password.clone(), - ); - - create_operator_server(config, rpc) - .await - .unwrap() - .1 - .stopped() - .await; -} diff --git a/core/src/bin/operators_and_verifiers.rs b/core/src/bin/operators_and_verifiers.rs deleted file mode 100644 index e12e2182..00000000 --- a/core/src/bin/operators_and_verifiers.rs +++ /dev/null @@ -1,42 +0,0 @@ -use clementine_core::{cli, extended_rpc::ExtendedRpc, servers::create_verifiers_and_operators}; - -/// ```bash -/// curl -X POST http://127.0.0.1:3434 -H "Content-Type: application/json" -d '{ -/// "jsonrpc": "2.0", -/// "method": "operator_new_deposit", -/// "params": { -/// "start_utxo": "2964713fecf26d6eec7df4420bed1e09de1bdab2cacd24a1c8c0afd70c8a5371:3", -/// "recovery_taproot_address": "781990d7e2118cc361a93a6fcc54ce611d6df38168d6b1edfb556535f2200c4b", -/// "evm_address": "0101010101010101010101010101010101010101" -/// }, -/// "id": 1 -/// }' -/// ``` -#[tokio::main] -async fn main() { - let config = cli::get_configuration(); - let _rpc = ExtendedRpc::::new( - config.bitcoin_rpc_url.clone(), - config.bitcoin_rpc_user.clone(), - config.bitcoin_rpc_password.clone(), - ); - - let (operator_clients, verifier_clients, _aggregator) = - create_verifiers_and_operators("test_config.toml").await; - - println!("Operator servers started: {:?}", operator_clients); - println!("Verifier servers started: {:?}", verifier_clients); - println!("Number of operator clients: {}", operator_clients.len()); - println!("Number of verifier clients: {}", verifier_clients.len()); - - // Stop all servers - for (_, handle, _) in operator_clients { - handle.clone().stopped().await; - } - - for (_, handle, _) in verifier_clients { - handle.clone().stopped().await; - } - - println!("All servers stopped"); -} diff --git a/core/src/bin/server.rs b/core/src/bin/server.rs new file mode 100644 index 00000000..bbbcb351 --- /dev/null +++ b/core/src/bin/server.rs @@ -0,0 +1,71 @@ +#[cfg(feature = "aggregator_server")] +use clementine_core::servers::create_aggregator_server; + +#[cfg(feature = "operator_server")] +use clementine_core::servers::create_operator_server; + +#[cfg(feature = "verifier_server")] +use clementine_core::servers::create_verifier_server; + +#[tokio::main] +async fn main() { + #[cfg(any( + feature = "verifier_server", + feature = "operator_server", + feature = "aggregator_server" + ))] + { + use clementine_core::{cli, database::common::Database, extended_rpc::ExtendedRpc}; + + let mut config = cli::get_configuration(); + let rpc = ExtendedRpc::::new( + config.bitcoin_rpc_url.clone(), + config.bitcoin_rpc_user.clone(), + config.bitcoin_rpc_password.clone(), + ); + + let database = Database::new(config.clone()).await.unwrap(); + database.init_from_schema().await.unwrap(); + database.close().await; + + let mut handles = vec![]; + + #[cfg(feature = "verifier_server")] + { + handles.push( + create_verifier_server(config.clone(), rpc.clone()) + .await + .unwrap() + .1 + .stopped(), + ); + config.port += 1; + } + + #[cfg(feature = "operator_server")] + { + handles.push( + create_operator_server(config.clone(), rpc.clone()) + .await + .unwrap() + .1 + .stopped(), + ); + config.port += 1; + } + + #[cfg(feature = "aggregator_server")] + handles.push(create_aggregator_server(config).await.unwrap().1.stopped()); + + futures::future::join_all(handles).await; + } + + #[cfg(not(any( + feature = "verifier_server", + feature = "operator_server", + feature = "aggregator_server" + )))] + { + println!("No server features are enabled. Exiting..."); + } +} diff --git a/core/src/bin/user_deposit.rs b/core/src/bin/user_deposit.rs deleted file mode 100644 index 2be4cbb6..00000000 --- a/core/src/bin/user_deposit.rs +++ /dev/null @@ -1,21 +0,0 @@ -fn main() { - // let config = BridgeConfig::new(); - - // let secp = bitcoin::secp256k1::Secp256k1::new(); - // let (xonly_pk, _) = config.secret_key.public_key(&secp).x_only_public_key(); - // let address = Address::p2tr(&secp, xonly_pk, None, config.network); - // let tx_builder = TransactionBuilder::new(config.verifiers_public_keys.clone(), config.network); - // let evm_address: EVMAddress = EVMAddress([1u8; 20]); - // let deposit_address = tx_builder - // .generate_deposit_address( - // address.as_unchecked(), - // &evm_address, - // BRIDGE_AMOUNT_SATS, - // config.user_takes_after, - // ) - // .unwrap(); - - // println!("EVM Address: {:?}", hex::encode(evm_address.0)); - // println!("User: {:?}", xonly_pk.to_string()); - // println!("Deposit address: {:?}", deposit_address); -} diff --git a/core/src/bin/verifier.rs b/core/src/bin/verifier.rs deleted file mode 100644 index e8f9a715..00000000 --- a/core/src/bin/verifier.rs +++ /dev/null @@ -1,18 +0,0 @@ -use clementine_core::{cli, extended_rpc::ExtendedRpc, servers::create_verifier_server}; - -#[tokio::main] -async fn main() { - let config = cli::get_configuration(); - let rpc = ExtendedRpc::::new( - config.bitcoin_rpc_url.clone(), - config.bitcoin_rpc_user.clone(), - config.bitcoin_rpc_password.clone(), - ); - - create_verifier_server(config, rpc) - .await - .unwrap() - .1 - .stopped() - .await; -} diff --git a/core/src/database/common.rs b/core/src/database/common.rs index 91d33e02..e479fa7e 100644 --- a/core/src/database/common.rs +++ b/core/src/database/common.rs @@ -11,7 +11,6 @@ use bitcoin::address::NetworkUnchecked; use bitcoin::{Address, OutPoint, Txid}; use secp256k1::schnorr; use sqlx::{Pool, Postgres, QueryBuilder}; -use std::fs; use super::wrapper::{AddressDB, EVMAddressDB, OutPointDB, SignatureDB, TxOutDB, TxidDB, UTXODB}; @@ -103,18 +102,19 @@ impl Database { Ok(config) } - /// Runs given SQL file to database. Database connection must be established + /// Runs given SQL string to database. Database connection must be established /// before calling this function. - pub async fn run_sql_file(&self, sql_file: &str) -> Result<(), BridgeError> { - let contents = fs::read_to_string(sql_file).unwrap(); - - sqlx::raw_sql(contents.as_str()) - .execute(&self.connection) - .await?; + pub async fn run_sql(&self, raw_sql: &str) -> Result<(), BridgeError> { + sqlx::raw_sql(raw_sql).execute(&self.connection).await?; Ok(()) } + pub async fn init_from_schema(&self) -> Result<(), BridgeError> { + let schema = include_str!("../../../scripts/schema.sql"); + self.run_sql(schema).await + } + /// Starts a database transaction. /// /// Return value can be used for committing changes. If not committed, diff --git a/core/src/mock/database.rs b/core/src/mock/database.rs index c585ff93..8322f1a7 100644 --- a/core/src/mock/database.rs +++ b/core/src/mock/database.rs @@ -18,11 +18,7 @@ macro_rules! create_test_config { let config = Database::create_database(config, &$db_name).await.unwrap(); let database = Database::new(config.clone()).await.unwrap(); - database - .run_sql_file("../scripts/schema.sql") - .await - .unwrap(); - + database.init_from_schema().await.unwrap(); database.close().await; config diff --git a/scripts/schema.sql b/scripts/schema.sql index 01bee841..5c6f4508 100644 --- a/scripts/schema.sql +++ b/scripts/schema.sql @@ -2,7 +2,7 @@ BEGIN; -- Verifier table for deposit details /* This table holds the information related to a deposit. */ -create table deposit_infos ( +create table if not exists deposit_infos ( id serial primary key, deposit_outpoint text not null check (deposit_outpoint ~ '^[a-fA-F0-9]{64}:(0|[1-9][0-9]{0,9})$'), recovery_taproot_address text not null, @@ -11,7 +11,7 @@ create table deposit_infos ( ); -- Verifier table for operator signatures, operator will read from here and send the take tx -create table operator_take_sigs ( +create table if not exists operator_take_sigs ( id serial primary key, deposit_outpoint text not null check (deposit_outpoint ~ '^[a-fA-F0-9]{64}:(0|[1-9][0-9]{0,9})$'), bridge_fund_txout text not null, @@ -26,7 +26,7 @@ For each deposit, we have (2 + num_operators) nonce triples. The first triple is move_commit_tx, the second triple is for move_reveal_tx, and the rest is for operator_takes_tx for each operator. Also for each triple, we hold the sig_hash to be signed to prevent reuse of the nonces. */ -create table nonces ( +create table if not exists nonces ( idx serial primary key, deposit_outpoint text not null check (deposit_outpoint ~ '^[a-fA-F0-9]{64}:(0|[1-9][0-9]{0,9})$'), pub_nonce bytea not null check (length(pub_nonce) = 66), @@ -47,15 +47,24 @@ BEGIN END; $$ LANGUAGE plpgsql; --- Create the trigger -CREATE TRIGGER prevent_sighash_update_trigger -BEFORE UPDATE ON nonces -FOR EACH ROW -EXECUTE FUNCTION prevent_sighash_update(); +-- Create the trigger if not exists +DO $$ +BEGIN + IF NOT EXISTS ( + SELECT 1 + FROM pg_trigger + WHERE tgname = 'prevent_sighash_update_trigger' + ) THEN + CREATE TRIGGER prevent_sighash_update_trigger + BEFORE UPDATE ON nonces + FOR EACH ROW + EXECUTE FUNCTION prevent_sighash_update(); + END IF; +END $$; -- Verifier table for kickoff for deposits /* This table holds the kickoff utxos sent by the operators for each deposit. */ -create table deposit_kickoff_utxos ( +create table if not exists deposit_kickoff_utxos ( id serial primary key, deposit_outpoint text not null check (deposit_outpoint ~ '^[a-fA-F0-9]{64}:(0|[1-9][0-9]{0,9})$'), kickoff_utxo jsonb not null, @@ -67,7 +76,7 @@ create table deposit_kickoff_utxos ( -- Operator table for kickoff utxo and funding utxo for deposits /* This table holds the funding utxos sent by the operators for each deposit. */ -create table deposit_kickoff_generator_txs ( +create table if not exists deposit_kickoff_generator_txs ( id serial primary key, txid text not null check (txid ~ '^[a-fA-F0-9]{64}'), raw_signed_tx text not null, @@ -79,24 +88,17 @@ create table deposit_kickoff_generator_txs ( -- Operator table for kickoff utxo related to deposits /* This table holds the kickoff utxos sent by the operators for each deposit. */ -create table operators_kickoff_utxo ( +create table if not exists operators_kickoff_utxo ( deposit_outpoint text primary key not null check (deposit_outpoint ~ '^[a-fA-F0-9]{64}:(0|[1-9][0-9]{0,9})$'), kickoff_utxo jsonb not null, created_at timestamp not null default now() ); -- Operator table for funding utxo used for deposits -create table funding_utxos ( +create table if not exists funding_utxos ( id serial primary key, funding_utxo jsonb not null, created_at timestamp not null default now() ); --- Verifier table for kickoff merkle roots for deposits --- create table kickoff_roots ( --- deposit_outpoint text primary key not null check (deposit_outpoint ~ '^[a-fA-F0-9]{64}:(0|[1-9][0-9]{0,9})$'), --- kickoff_merkle_root text not null check (kickoff_merkle_root ~ '^[a-fA-F0-9]{64}'), --- created_at timestamp not null default now() --- ); - COMMIT;