diff --git a/Cargo.toml b/Cargo.toml index d8f5d8a4..53da586e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ serde_json = "1.0.128" thiserror = "1.0.64" tracing = { version = "0.1.40", default-features = false } tracing-subscriber = { version = "0.3.18", features = ["json"] } -jsonrpsee = "0.22.5" +jsonrpsee = { version = "0.22.5", default-features = false } async-trait = "0.1.83" clap = "4.5.20" toml = "0.8.19" diff --git a/core/Cargo.toml b/core/Cargo.toml index d7a83619..a31134d9 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -21,7 +21,7 @@ thiserror = { workspace = true } tracing = { workspace = true } tracing-subscriber = { workspace = true, features = ["env-filter"] } tokio = { workspace = true, features = ["full"] } -jsonrpsee = { workspace = true, features = ["server", "http-client", "macros"] } +jsonrpsee = { workspace = true, features = ["http-client"] } async-trait = { workspace = true } futures = { workspace = true } clap = { workspace = true, features = ["derive"] } @@ -50,11 +50,6 @@ testing = [] name = "server" path = "src/bin/server.rs" -[[bin]] -name = "all_servers" -path = "src/bin/all_servers.rs" -required-features = ["testing"] - [[bin]] name = "config_generator" path = "src/bin/config_generator.rs" diff --git a/core/src/actor.rs b/core/src/actor.rs index ae0e28d4..ec874861 100644 --- a/core/src/actor.rs +++ b/core/src/actor.rs @@ -330,9 +330,11 @@ impl Actor { #[cfg(test)] mod tests { use super::Actor; + use crate::config::BridgeConfig; + use crate::utils::initialize_logger; use crate::{ actor::WinternitzDerivationPath, builder::transaction::TxHandler, - mock::database::create_test_config_with_thread_name, + create_test_config_with_thread_name, database::Database, initialize_database, }; use bitcoin::{ absolute::Height, transaction::Version, Amount, Network, OutPoint, Transaction, TxIn, TxOut, @@ -345,7 +347,9 @@ mod tests { treepp::script, }; use secp256k1::{rand, Secp256k1, SecretKey}; + use std::env; use std::str::FromStr; + use std::thread; /// Returns a valid [`TxHandler`]. fn create_valid_mock_tx_handler(actor: &Actor) -> TxHandler { @@ -508,7 +512,7 @@ mod tests { #[tokio::test] async fn derive_winternitz_pk_uniqueness() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let actor = Actor::new( config.secret_key, config.winternitz_secret_key, @@ -527,7 +531,7 @@ mod tests { #[tokio::test] async fn derive_winternitz_pk_fixed_pk() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let actor = Actor::new( config.secret_key, Some( @@ -549,7 +553,7 @@ mod tests { #[tokio::test] async fn sign_winternitz_signature() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let actor = Actor::new( config.secret_key, Some( diff --git a/core/src/aggregator.rs b/core/src/aggregator.rs index e41c360a..34f09d1d 100644 --- a/core/src/aggregator.rs +++ b/core/src/aggregator.rs @@ -16,11 +16,9 @@ use crate::{ clementine_watchtower_client::ClementineWatchtowerClient, }, }, - traits::rpc::AggregatorServer, utils::handle_taproot_witness_new, ByteArray32, ByteArray66, EVMAddress, UTXO, }; -use async_trait::async_trait; use bitcoin::{address::NetworkUnchecked, Address, OutPoint}; use bitcoin::{hashes::Hash, Txid}; use bitcoincore_rpc::RawTx; @@ -365,53 +363,3 @@ impl Aggregator { Ok((move_tx_handler.tx.raw_hex(), txid)) } } - -#[async_trait] -impl AggregatorServer for Aggregator { - async fn aggregate_pub_nonces_rpc( - &self, - pub_nonces: Vec>, - ) -> Result, BridgeError> { - self.aggregate_pub_nonces(pub_nonces).await - } - - async fn aggregate_slash_or_take_sigs_rpc( - &self, - deposit_outpoint: OutPoint, - kickoff_utxos: Vec, - agg_nonces: Vec, - partial_sigs: Vec>, - ) -> Result, BridgeError> { - self.aggregate_slash_or_take_sigs(deposit_outpoint, kickoff_utxos, agg_nonces, partial_sigs) - .await - } - - async fn aggregate_operator_take_sigs_rpc( - &self, - deposit_outpoint: OutPoint, - kickoff_utxos: Vec, - agg_nonces: Vec, - partial_sigs: Vec>, - ) -> Result, BridgeError> { - self.aggregate_operator_take_sigs(deposit_outpoint, kickoff_utxos, agg_nonces, partial_sigs) - .await - } - - async fn aggregate_move_tx_sigs_rpc( - &self, - deposit_outpoint: OutPoint, - recovery_taproot_address: Address, - evm_address: EVMAddress, - agg_nonce: MuSigAggNonce, - partial_sigs: Vec, - ) -> Result<(String, Txid), BridgeError> { - self.aggregate_move_tx_sigs( - deposit_outpoint, - recovery_taproot_address, - evm_address, - agg_nonce, - partial_sigs, - ) - .await - } -} diff --git a/core/src/bin/all_servers.rs b/core/src/bin/all_servers.rs deleted file mode 100644 index 1b9f0151..00000000 --- a/core/src/bin/all_servers.rs +++ /dev/null @@ -1,49 +0,0 @@ -use clementine_core::{ - musig2::AggregateFromPublicKeys, servers::create_verifiers_and_operators, - utils::get_configuration_for_binaries, -}; - -#[tokio::main] -async fn main() { - let (config, _) = get_configuration_for_binaries(); - - let (verifier_clients, operator_clients, aggregator) = - create_verifiers_and_operators("test_config.toml").await; - - println!( - "OPERATOR_URLS={}", - operator_clients - .iter() - .map(|(_, _, addr)| format!("http://127.0.0.1:{}", addr.port())) - .collect::>() - .join(",") - ); - println!( - "VERIFIER_URLS={}", - verifier_clients - .iter() - .map(|(_, _, addr)| format!("http://127.0.0.1:{}", addr.port())) - .collect::>() - .join(",") - ); - let xonly = - secp256k1::XOnlyPublicKey::from_musig2_pks(config.verifiers_public_keys, None, false); - println!( - "AGGREGATOR_URL={}", - format!("http://127.0.0.1:{}", aggregator.2.port()) - ); - println!("VERIFIER_PKS={}", xonly.to_string()); - - // 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/server.rs b/core/src/bin/server.rs index 8a1954eb..73746730 100644 --- a/core/src/bin/server.rs +++ b/core/src/bin/server.rs @@ -1,61 +1,62 @@ -use clementine_core::servers::create_aggregator_server; -use clementine_core::servers::create_operator_server; -use clementine_core::servers::create_verifier_server; -use clementine_core::utils::get_configuration_for_binaries; -use clementine_core::{database::Database, extended_rpc::ExtendedRpc}; -use std::process::exit; +// use clementine_core::servers::create_aggregator_server; +// use clementine_core::servers::create_operator_server; +// use clementine_core::servers::create_verifier_server; +// use clementine_core::utils::get_configuration_for_binaries; +// use clementine_core::{database::Database, extended_rpc::ExtendedRpc}; +// use std::process::exit; #[tokio::main] async fn main() { - let (mut config, args) = get_configuration_for_binaries(); - - if !args.verifier_server && !args.operator_server && !args.aggregator_server { - eprintln!("No servers are specified. Please specify one."); - exit(1); - } - - let rpc = ExtendedRpc::new( - config.bitcoin_rpc_url.clone(), - config.bitcoin_rpc_user.clone(), - config.bitcoin_rpc_password.clone(), - ) - .await; - - Database::run_schema_script(&config).await.unwrap(); - - let mut handles = vec![]; - - if args.verifier_server { - handles.push( - create_verifier_server(config.clone(), rpc.clone()) - .await - .unwrap() - .1 - .stopped(), - ); - config.port += 1; - - println!("Verifier server is started."); - } - - if args.operator_server { - handles.push( - create_operator_server(config.clone(), rpc.clone()) - .await - .unwrap() - .1 - .stopped(), - ); - config.port += 1; - - println!("Operator server is started."); - } - - if args.aggregator_server { - handles.push(create_aggregator_server(config).await.unwrap().1.stopped()); - - println!("Aggregator server is started."); - } - - futures::future::join_all(handles).await; + panic!("grpc switch in progress. please inform us if you get this error.") + // let (mut config, args) = get_configuration_for_binaries(); + + // if !args.verifier_server && !args.operator_server && !args.aggregator_server { + // eprintln!("No servers are specified. Please specify one."); + // exit(1); + // } + + // let rpc = ExtendedRpc::new( + // config.bitcoin_rpc_url.clone(), + // config.bitcoin_rpc_user.clone(), + // config.bitcoin_rpc_password.clone(), + // ) + // .await; + + // Database::run_schema_script(&config).await.unwrap(); + + // let mut handles = vec![]; + + // if args.verifier_server { + // handles.push( + // create_verifier_server(config.clone(), rpc.clone()) + // .await + // .unwrap() + // .1 + // .stopped(), + // ); + // config.port += 1; + + // println!("Verifier server is started."); + // } + + // if args.operator_server { + // handles.push( + // create_operator_server(config.clone(), rpc.clone()) + // .await + // .unwrap() + // .1 + // .stopped(), + // ); + // config.port += 1; + + // println!("Operator server is started."); + // } + + // if args.aggregator_server { + // handles.push(create_aggregator_server(config).await.unwrap().1.stopped()); + + // println!("Aggregator server is started."); + // } + + // futures::future::join_all(handles).await; } diff --git a/core/src/database/common.rs b/core/src/database/common.rs index 28e7c283..efd6876b 100644 --- a/core/src/database/common.rs +++ b/core/src/database/common.rs @@ -979,8 +979,9 @@ impl Database { #[cfg(test)] mod tests { use super::Database; + use crate::{config::BridgeConfig, initialize_database, utils::initialize_logger}; use crate::{ - mock::database::create_test_config_with_thread_name, + create_test_config_with_thread_name, musig2::{nonce_pair, MuSigAggNonce, MuSigPubNonce, MuSigSecNonce}, ByteArray32, EVMAddress, UTXO, }; @@ -999,10 +1000,11 @@ mod tests { use risc0_zkvm::Receipt; use secp256k1::{constants::SCHNORR_SIGNATURE_SIZE, rand::rngs::OsRng}; use secp256k1::{schnorr, Secp256k1}; + use std::{env, thread}; #[tokio::test] async fn save_get_timeout_tx_sigs() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let database = Database::new(&config).await.unwrap(); let signatures: Vec = (0..0x45) @@ -1021,7 +1023,7 @@ mod tests { #[tokio::test] async fn test_database_gets_previously_saved_operator_take_signature() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let database = Database::new(&config).await.unwrap(); let deposit_outpoint = OutPoint::null(); @@ -1059,7 +1061,7 @@ mod tests { #[tokio::test] async fn test_save_and_get_deposit_info() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let database = Database::new(&config).await.unwrap(); let secp = Secp256k1::new(); @@ -1092,7 +1094,7 @@ mod tests { #[tokio::test] async fn test_nonces_1() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let db = Database::new(&config).await.unwrap(); let secp = Secp256k1::new(); @@ -1137,7 +1139,7 @@ mod tests { #[tokio::test] async fn test_nonces_2() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let db = Database::new(&config).await.unwrap(); let secp = Secp256k1::new(); @@ -1181,7 +1183,7 @@ mod tests { #[tokio::test] async fn test_nonces_3() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let db = Database::new(&config).await.unwrap(); let secp = Secp256k1::new(); @@ -1229,7 +1231,7 @@ mod tests { #[tokio::test] async fn test_get_pub_nonces_1() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let db = Database::new(&config).await.unwrap(); let secp = Secp256k1::new(); @@ -1262,7 +1264,7 @@ mod tests { #[tokio::test] async fn test_get_pub_nonces_2() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let db = Database::new(&config).await.unwrap(); let outpoint = OutPoint { txid: Txid::from_byte_array([1u8; 32]), @@ -1274,7 +1276,7 @@ mod tests { #[tokio::test] async fn test_operators_kickoff_utxo_1() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let db = Database::new(&config).await.unwrap(); let outpoint = OutPoint { @@ -1299,7 +1301,7 @@ mod tests { #[tokio::test] async fn test_operators_kickoff_utxo_2() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let db = Database::new(&config).await.unwrap(); let outpoint = OutPoint { @@ -1312,7 +1314,7 @@ mod tests { #[tokio::test] async fn test_verifiers_kickoff_utxos_1() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let db = Database::new(&config).await.unwrap(); let outpoint = OutPoint { @@ -1349,7 +1351,7 @@ mod tests { #[tokio::test] async fn test_verifiers_kickoff_utxos_2() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let db = Database::new(&config).await.unwrap(); let outpoint = OutPoint { @@ -1362,7 +1364,7 @@ mod tests { #[tokio::test] async fn test_operators_funding_utxo_1() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let db = Database::new(&config).await.unwrap(); let utxo = UTXO { @@ -1384,7 +1386,7 @@ mod tests { #[tokio::test] async fn test_operators_funding_utxo_2() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let db = Database::new(&config).await.unwrap(); let db_utxo = db.get_funding_utxo(None).await.unwrap(); @@ -1394,7 +1396,7 @@ mod tests { #[tokio::test] async fn test_deposit_kickoff_generator_tx_0() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let db = Database::new(&config).await.unwrap(); let raw_hex = "02000000000101eb87b1a80d47b7f5bd5082b77653f5ca37e566951742b80c361875ba0e5c478f0a00000000fdffffff0ca086010000000000225120b23da6d2e0390018b953f7d74e3582da4da30fd0fd157cc84a2d2753003d1ca3a086010000000000225120b23da6d2e0390018b953f7d74e3582da4da30fd0fd157cc84a2d2753003d1ca3a086010000000000225120b23da6d2e0390018b953f7d74e3582da4da30fd0fd157cc84a2d2753003d1ca3a086010000000000225120b23da6d2e0390018b953f7d74e3582da4da30fd0fd157cc84a2d2753003d1ca3a086010000000000225120b23da6d2e0390018b953f7d74e3582da4da30fd0fd157cc84a2d2753003d1ca3a086010000000000225120b23da6d2e0390018b953f7d74e3582da4da30fd0fd157cc84a2d2753003d1ca3a086010000000000225120b23da6d2e0390018b953f7d74e3582da4da30fd0fd157cc84a2d2753003d1ca3a086010000000000225120b23da6d2e0390018b953f7d74e3582da4da30fd0fd157cc84a2d2753003d1ca3a086010000000000225120b23da6d2e0390018b953f7d74e3582da4da30fd0fd157cc84a2d2753003d1ca3a086010000000000225120b23da6d2e0390018b953f7d74e3582da4da30fd0fd157cc84a2d2753003d1ca35c081777000000002251202a64b1ee3375f3bb4b367b8cb8384a47f73cf231717f827c6c6fbbf5aecf0c364a010000000000002200204ae81572f06e1b88fd5ced7a1a000945432e83e1551e6f721ee9c00b8cc33260014005a41e6f4a4bcfcc5cd3ef602687215f97c18949019a491df56af7413c5dce9292ba3966edc4564a39d9bc0d6c0faae19030f1cedf4d931a6cdc57cc5b83c8ef00000000".to_string(); @@ -1440,7 +1442,7 @@ mod tests { #[tokio::test] async fn test_deposit_kickoff_generator_tx_2() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let db = Database::new(&config).await.unwrap(); let txid = Txid::from_byte_array([1u8; 32]); @@ -1450,7 +1452,7 @@ mod tests { #[tokio::test] async fn test_deposit_kickoff_generator_tx_1() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let db = Database::new(&config).await.unwrap(); let raw_hex = "01000000000101308d840c736eefd114a8fad04cb0d8338b4a3034a2b517250e5498701b25eb360100000000fdffffff02401f00000000000022512024985a1ab5724a5164ae5e0026b3e7e22031e83948eedf99d438b866857946b81f7e000000000000225120f7298da2a2be5b6e02a076ff7d35a1fe6b54a2bc7938c1c86bede23cadb7d9650140ad2fdb01ec5e2772f682867c8c6f30697c63f622e338f7390d3abc6c905b9fd7e96496fdc34cb9e872387758a6a334ec1307b3505b73121e0264fe2ba546d78ad11b0d00".to_string(); @@ -1500,7 +1502,7 @@ mod tests { #[tokio::test] async fn test_deposit_kickoff_generator_tx_3() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let db = Database::new(&config).await.unwrap(); let txid = Txid::from_byte_array([1u8; 32]); @@ -1510,7 +1512,7 @@ mod tests { #[tokio::test] async fn save_get_new_block() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let db = Database::new(&config).await.unwrap(); let block = block::Block { @@ -1539,7 +1541,7 @@ mod tests { #[tokio::test] async fn get_block_header() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let db = Database::new(&config).await.unwrap(); let block = block::Block { @@ -1576,7 +1578,7 @@ mod tests { #[tokio::test] pub async fn get_latest_chain_proof_height() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let db = Database::new(&config).await.unwrap(); let mut block = block::Block { @@ -1632,7 +1634,7 @@ mod tests { #[tokio::test] pub async fn save_get_block_proof() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let db = Database::new(&config).await.unwrap(); // Save dummy block. @@ -1676,7 +1678,7 @@ mod tests { #[tokio::test] pub async fn get_non_proven_block() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let db = Database::new(&config).await.unwrap(); assert!(db.get_non_proven_block(None).await.is_err()); @@ -1752,7 +1754,7 @@ mod tests { #[tokio::test] async fn save_get_winternitz_public_key() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let database = Database::new(&config).await.unwrap(); // Assuming there are 2 time_txs. diff --git a/core/src/database/mod.rs b/core/src/database/mod.rs index 498e9643..d3666b71 100644 --- a/core/src/database/mod.rs +++ b/core/src/database/mod.rs @@ -39,68 +39,6 @@ impl Database { self.connection.close().await; } - /// Initializes a new database with given configuration. If the database is - /// already initialized, it will be dropped before initialization. Meaning, - /// a clean state is guaranteed. - /// - /// [`Database::new`] must be called after this to connect to the - /// initialized database. - /// - /// **Warning:** This must not be used in release environments and is only - /// suitable for testing. - /// - /// TODO: This function must be marked with `#[cfg(test)]` to prevent it - /// from infiltrating the binaries. See: - /// https://github.com/chainwayxyz/clementine/issues/181 - pub async fn initialize_database(config: &BridgeConfig) -> Result<(), BridgeError> { - Database::drop_database(config).await?; - - Database::create_database(config).await?; - - Database::run_schema_script(config).await?; - - Ok(()) - } - - /// Creates a new database with given configuration. - /// - /// # Errors - /// - /// Will return [`BridgeError`] if there was a problem with database - /// connection. - async fn create_database(config: &BridgeConfig) -> Result<(), BridgeError> { - let url = Database::get_postgresql_url(config); - let conn = sqlx::PgPool::connect(url.as_str()).await?; - - sqlx::query(&format!( - "CREATE DATABASE {} WITH OWNER {}", - config.db_name, config.db_user - )) - .execute(&conn) - .await?; - - conn.close().await; - Ok(()) - } - - /// Drops the database for the given configuration, if it exists. - /// - /// # Errors - /// - /// Will return [`BridgeError`] if there was a problem with database - /// connection. It won't return any errors if the database does not already - /// exist. - async fn drop_database(config: &BridgeConfig) -> Result<(), BridgeError> { - let url = Database::get_postgresql_url(config); - let conn = sqlx::PgPool::connect(url.as_str()).await?; - - let query = format!("DROP DATABASE IF EXISTS {}", &config.db_name); - sqlx::query(&query).execute(&conn).await?; - - conn.close().await; - Ok(()) - } - /// Runs the schema script on a database for the given configuration. /// /// # Errors @@ -122,7 +60,7 @@ impl Database { /// /// URL contains user, password, host and port fields, which are picked from /// the given configuration. - fn get_postgresql_url(config: &BridgeConfig) -> String { + pub fn get_postgresql_url(config: &BridgeConfig) -> String { "postgresql://".to_owned() + &config.db_user + ":" @@ -154,15 +92,14 @@ impl Database { #[cfg(test)] mod tests { - use crate::{ - config::BridgeConfig, - database::Database, - mock::{common, database::create_test_config_with_thread_name}, - }; + use crate::create_test_config_with_thread_name; + use crate::{config::BridgeConfig, database::Database}; + use crate::{initialize_database, utils::initialize_logger}; + use std::{env, thread}; #[tokio::test] async fn valid_database_connection() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); Database::new(&config).await.unwrap(); } @@ -180,46 +117,6 @@ mod tests { Database::new(&config).await.unwrap(); } - #[tokio::test] - async fn create_drop_database() { - let mut config = common::get_test_config("test_config.toml").unwrap(); - config.db_name = "create_drop_database".to_string(); - - // Drop database (clear previous test run artifacts) and check that - // connection can't be established. - Database::drop_database(&config).await.unwrap(); - assert!(Database::new(&config).await.is_err()); - - // It should be possible to connect new database after creating it. - Database::create_database(&config).await.unwrap(); - Database::new(&config).await.unwrap(); - - // Dropping database again should result connection to not be - // established. - Database::drop_database(&config).await.unwrap(); - assert!(Database::new(&config).await.is_err()); - } - - #[tokio::test] - async fn initialize_database() { - let mut config = common::get_test_config("test_config.toml").unwrap(); - config.db_name = "initialize_database".to_string(); - - // Drop database (clear previous test run artifacts) and check that - // connection can't be established. - Database::drop_database(&config).await.unwrap(); - assert!(Database::new(&config).await.is_err()); - - // It should be possible to initialize and connect to the new database. - Database::initialize_database(&config).await.unwrap(); - Database::new(&config).await.unwrap(); - - // Dropping database again should result connection to not be - // established. - Database::drop_database(&config).await.unwrap(); - assert!(Database::new(&config).await.is_err()); - } - #[test] fn get_postgresql_url() { let mut config = BridgeConfig::new(); diff --git a/core/src/header_chain_prover/blockgazer.rs b/core/src/header_chain_prover/blockgazer.rs index 56776c38..a1706ce3 100644 --- a/core/src/header_chain_prover/blockgazer.rs +++ b/core/src/header_chain_prover/blockgazer.rs @@ -203,15 +203,19 @@ impl HeaderChainProver { #[cfg(test)] mod tests { use crate::{ + config::BridgeConfig, database::Database, initialize_database, utils::initialize_logger, + }; + use crate::{ + create_test_config_with_thread_name, extended_rpc::ExtendedRpc, header_chain_prover::{ blockgazer::{BlockFetchStatus, BATCH_DEEPNESS, BATCH_DEEPNESS_SAFETY_BARRIER}, HeaderChainProver, }, - mock::database::create_test_config_with_thread_name, }; use bitcoin::BlockHash; use bitcoincore_rpc::RpcApi; + use std::{env, thread}; async fn mine_and_save_blocks(prover: &HeaderChainProver, height: u64) -> Vec { let mut fork_block_hashes = Vec::new(); @@ -253,7 +257,7 @@ mod tests { #[tokio::test] #[serial_test::serial] async fn check_for_new_blocks_uptodate() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let rpc = ExtendedRpc::new( config.bitcoin_rpc_url.clone(), config.bitcoin_rpc_user.clone(), @@ -287,7 +291,7 @@ mod tests { #[tokio::test] #[serial_test::serial] async fn check_for_new_blocks_fallen_behind_single() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let rpc = ExtendedRpc::new( config.bitcoin_rpc_url.clone(), config.bitcoin_rpc_user.clone(), @@ -328,7 +332,7 @@ mod tests { #[tokio::test] #[serial_test::serial] async fn check_for_new_blocks_fallen_behind_multiple() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let rpc = ExtendedRpc::new( config.bitcoin_rpc_url.clone(), config.bitcoin_rpc_user.clone(), @@ -359,7 +363,7 @@ mod tests { #[tokio::test] #[serial_test::serial] async fn check_for_new_blocks_fork_and_mine_new() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let rpc = ExtendedRpc::new( config.bitcoin_rpc_url.clone(), config.bitcoin_rpc_user.clone(), @@ -391,7 +395,7 @@ mod tests { #[tokio::test] #[serial_test::serial] async fn sync_blockchain_single_block() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let rpc = ExtendedRpc::new( config.bitcoin_rpc_url.clone(), config.bitcoin_rpc_user.clone(), @@ -425,7 +429,7 @@ mod tests { #[tokio::test] #[serial_test::serial] async fn sync_blockchain_multiple_blocks() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let rpc = ExtendedRpc::new( config.bitcoin_rpc_url.clone(), config.bitcoin_rpc_user.clone(), @@ -459,7 +463,7 @@ mod tests { #[tokio::test] #[serial_test::serial] async fn sync_blockchain_multiple_blocks_with_fork() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let rpc = ExtendedRpc::new( config.bitcoin_rpc_url.clone(), config.bitcoin_rpc_user.clone(), diff --git a/core/src/header_chain_prover/mod.rs b/core/src/header_chain_prover/mod.rs index 6752c138..1c8797f2 100644 --- a/core/src/header_chain_prover/mod.rs +++ b/core/src/header_chain_prover/mod.rs @@ -99,19 +99,23 @@ impl HeaderChainProver { #[cfg(test)] mod tests { use crate::{ - extended_rpc::ExtendedRpc, header_chain_prover::HeaderChainProver, - mock::database::create_test_config_with_thread_name, + config::BridgeConfig, database::Database, initialize_database, utils::initialize_logger, + }; + use crate::{ + create_test_config_with_thread_name, extended_rpc::ExtendedRpc, + header_chain_prover::HeaderChainProver, }; use bitcoin::{hashes::Hash, BlockHash}; use bitcoincore_rpc::RpcApi; use borsh::BorshDeserialize; use risc0_zkvm::Receipt; use std::time::Duration; + use std::{env, thread}; use tokio::time::sleep; #[tokio::test] async fn new() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let rpc = ExtendedRpc::new( config.bitcoin_rpc_url.clone(), config.bitcoin_rpc_user.clone(), @@ -125,7 +129,7 @@ mod tests { #[tokio::test] #[serial_test::serial] async fn new_with_proof_assumption() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let rpc = ExtendedRpc::new( config.bitcoin_rpc_url.clone(), config.bitcoin_rpc_user.clone(), @@ -152,7 +156,7 @@ mod tests { #[serial_test::serial] #[ignore = "This test is very host dependent and needs a human observer"] async fn start_header_chain_prover() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let rpc = ExtendedRpc::new( config.bitcoin_rpc_url.clone(), config.bitcoin_rpc_user.clone(), diff --git a/core/src/header_chain_prover/prover.rs b/core/src/header_chain_prover/prover.rs index f96abac2..3bb0786d 100644 --- a/core/src/header_chain_prover/prover.rs +++ b/core/src/header_chain_prover/prover.rs @@ -137,8 +137,11 @@ impl HeaderChainProver { #[cfg(test)] mod tests { use crate::{ - extended_rpc::ExtendedRpc, header_chain_prover::HeaderChainProver, - mock::database::create_test_config_with_thread_name, + config::BridgeConfig, database::Database, initialize_database, utils::initialize_logger, + }; + use crate::{ + create_test_config_with_thread_name, extended_rpc::ExtendedRpc, + header_chain_prover::HeaderChainProver, }; use bitcoin::{ block::{Header, Version}, @@ -147,6 +150,7 @@ mod tests { }; use borsh::BorshDeserialize; use circuits::header_chain::{BlockHeader, BlockHeaderCircuitOutput}; + use std::{env, thread}; fn get_headers() -> Vec { let headers = include_bytes!("../../../scripts/headers.bin"); @@ -160,7 +164,7 @@ mod tests { #[tokio::test] #[serial_test::serial] async fn prove_block_headers_genesis() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let rpc = ExtendedRpc::new( config.bitcoin_rpc_url.clone(), config.bitcoin_rpc_user.clone(), @@ -184,7 +188,7 @@ mod tests { #[tokio::test] #[serial_test::serial] async fn prove_block_headers_second() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let rpc = ExtendedRpc::new( config.bitcoin_rpc_url.clone(), config.bitcoin_rpc_user.clone(), @@ -211,7 +215,7 @@ mod tests { #[tokio::test] #[serial_test::serial] async fn save_and_get_proof() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let rpc = ExtendedRpc::new( config.bitcoin_rpc_url.clone(), config.bitcoin_rpc_user.clone(), diff --git a/core/src/lib.rs b/core/src/lib.rs index 9e9f315f..c07adad8 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -6,7 +6,6 @@ #![allow(clippy::too_many_arguments)] use bitcoin::{OutPoint, Txid}; -// use clementine_circuits::{HashType, PreimageType}; use serde::{Deserialize, Serialize}; pub mod actor; @@ -22,17 +21,18 @@ pub mod extended_rpc; pub mod hashes; pub mod header_chain_prover; pub mod merkle; -pub mod mock; pub mod musig2; pub mod operator; pub mod rpc; pub mod servers; -pub mod traits; pub mod user; pub mod utils; pub mod verifier; pub mod watchtower; +#[cfg(test)] +mod test_utils; + pub type ConnectorUTXOTree = Vec>; // pub type HashTree = Vec>; // pub type PreimageTree = Vec>; diff --git a/core/src/mock/common.rs b/core/src/mock/common.rs deleted file mode 100644 index 6824c5f1..00000000 --- a/core/src/mock/common.rs +++ /dev/null @@ -1,95 +0,0 @@ -//! # Common Test Utilities -//! -//! This file includes common functions/variables for tests. - -use crate::config::BridgeConfig; -use crate::errors::BridgeError; -use std::{env, net::TcpListener}; - -pub const ENV_CONF_FILE: &str = "TEST_CONFIG"; - -/// Returns configuration, read from configuration file which is specified from -/// either an environment variable or the function argument. Environment -/// variable is priotirized over the function argument `configuration_file`. -pub fn get_test_config(configuration_file: &str) -> Result { - let env_config: Option = if let Ok(config_file_path) = env::var(ENV_CONF_FILE) { - Some(BridgeConfig::try_parse_file(config_file_path.into())?) - } else { - None - }; - - // Read specified configuration file from `tests/data` directory. - let mut config = match BridgeConfig::try_parse_file( - format!( - "{}/tests/data/{}", - env!("CARGO_MANIFEST_DIR"), - configuration_file - ) - .into(), - ) { - Ok(c) => c, - Err(e) => return Err(e), - }; - - // Overwrite user's environment to test's hard coded data if environment - // file is specified. - if let Some(env_config) = env_config { - config.db_host = env_config.db_host; - config.db_port = env_config.db_port; - config.db_user = env_config.db_user; - config.db_password = env_config.db_password; - config.db_name = env_config.db_name; - }; - - Ok(config) -} - -/// Finds consecutive idle ports starting from the given port, up to count num. -pub fn find_consecutive_idle_ports(port: u16, num: usize) -> Result { - let mut idle_ports = Vec::new(); - let mut current_port = port; - - while current_port < 65535 { - match TcpListener::bind(("0.0.0.0", current_port)) { - Ok(_) => { - idle_ports.push(current_port); - current_port += 1; - if idle_ports.len() == num + 1 { - break; - } - tracing::debug!( - "Ports {:?}-{:?} are available.", - current_port, - current_port + num as u16 - ); - } - Err(_e) => { - idle_ports.clear(); - if current_port < port + num as u16 { - tracing::debug!( - "Ports {:?}-{:?} are not available. Searching for new ports...", - current_port, - current_port + num as u16 - ); - } - current_port += 1; - } - } - } - - if idle_ports.len() == num + 1 { - Ok(idle_ports[0]) - } else { - Err(BridgeError::PortError( - "No consecutive idle ports found".to_string(), - )) - } -} - -mod tests { - #[tokio::test] - async fn ports() { - let res = super::find_consecutive_idle_ports(0, 5).unwrap(); - println!("{:?}", res); - } -} diff --git a/core/src/mock/database.rs b/core/src/mock/database.rs deleted file mode 100644 index d74c4007..00000000 --- a/core/src/mock/database.rs +++ /dev/null @@ -1,57 +0,0 @@ -//! # Database Mock Interface -//! -//! This module provides mock database interfaces, for testing. - -use super::common; -use crate::{config::BridgeConfig, database::Database, utils::initialize_logger}; -use std::thread; - -/// Creates a temporary database for testing. -/// -/// # Parameters -/// -/// - db_name: New database's name. -/// - config_file: Test configuration file. Rest of the config will be read from -/// here and only `db_name` will be overwritten. -/// -/// Returns new `BridgeConfig`. -async fn create_test_config(db_name: &str, config_file: &str) -> BridgeConfig { - // Use maximum log level for tests. - initialize_logger(5).unwrap(); - - let mut config = common::get_test_config(config_file).unwrap(); - config.db_name = db_name.to_string(); - Database::initialize_database(&config).await.unwrap(); - - config -} - -/// Creates a temporary database for testing, using current thread's name as the -/// database name. -/// -/// # Parameters -/// -/// - config_file: Test configuration file. Rest of the config will be read from -/// here and only `db_name` will be overwritten. -/// - suffix: Optional suffix added to the thread handle. -/// -/// # Returns -/// -/// `BridgeConfig` -pub async fn create_test_config_with_thread_name( - config_file: &str, - suffix: Option<&str>, -) -> BridgeConfig { - let suffix: String = suffix.unwrap_or(&String::default()).to_string(); - - let handle = thread::current() - .name() - .unwrap() - .split(':') - .last() - .unwrap() - .to_owned() - + &suffix; - - create_test_config(&handle, config_file).await -} diff --git a/core/src/mock/env.rs b/core/src/mock/env.rs deleted file mode 100644 index 45e18998..00000000 --- a/core/src/mock/env.rs +++ /dev/null @@ -1,158 +0,0 @@ -// use std::sync::RwLock; - -// use clementine_circuits::env::Environment; -// use risc0_zkvm::ExecutorEnv; - -// // Define a global static variable with RwLock for thread-safe interior mutability. -// static GLOBAL_DATA: RwLock> = RwLock::new(Vec::new()); -// static GLOBAL_DATA_TYPES: RwLock> = RwLock::new(Vec::new()); -// static READ_POSITION: RwLock = RwLock::new(0); - -// pub struct MockEnvironment; - -// impl MockEnvironment { -// // Helper function to write data to the global storage -// fn write_global(data: &[u8], data_type: u8) { -// let mut global_data = GLOBAL_DATA.write().unwrap(); -// global_data.extend_from_slice(data); -// let mut global_data_types = GLOBAL_DATA_TYPES.write().unwrap(); // Use write lock for data types since we're updating it -// global_data_types.push(data_type); -// } - -// // Helper function to read data from the global storage -// fn read_global(count: usize) -> Vec { -// let global_data = GLOBAL_DATA.read().unwrap(); // Use read lock for data -// let mut pos = READ_POSITION.write().unwrap(); // Use write lock for position since we're updating it - -// if *pos + count > global_data.len() { -// panic!("Not enough data in global storage to read"); -// } -// let result = global_data[*pos..*pos + count].to_vec(); -// *pos += count; // Update the read position - -// result -// } - -// pub fn reset_mock_env() { -// let mut global_data = GLOBAL_DATA.write().unwrap(); -// global_data.clear(); -// let mut global_data_types = GLOBAL_DATA_TYPES.write().unwrap(); -// global_data_types.clear(); -// let mut read_position = READ_POSITION.write().unwrap(); -// *read_position = 0; -// } - -// pub fn output_env<'a>() -> risc0_zkvm::ExecutorEnv<'a> { -// let global_data = GLOBAL_DATA.read().unwrap(); // Use read lock for data -// let global_data_types = GLOBAL_DATA_TYPES.read().unwrap(); // Use read lock for data types -// let mut env = ExecutorEnv::builder(); -// let mut i = 0; -// for data_type in global_data_types.iter() { -// // tracing::debug!("Data type: {}", data_type); -// match data_type { -// 0 => { -// let data: [u8; 32] = global_data[i..i + 32].try_into().unwrap(); -// env.write(&data).unwrap(); -// i += 32; -// } -// 1 => { -// env.write(&u32::from_le_bytes( -// global_data[i..i + 4].try_into().unwrap(), -// )) -// .unwrap(); -// i += 4 -// } -// 2 => { -// env.write(&u64::from_le_bytes( -// global_data[i..i + 8].try_into().unwrap(), -// )) -// .unwrap(); -// i += 8 -// } -// 3 => { -// env.write(&i32::from_le_bytes( -// global_data[i..i + 4].try_into().unwrap(), -// )) -// .unwrap(); -// i += 4; -// } -// _ => panic!("Invalid data type"), -// } -// } -// env.build().unwrap() -// } -// } - -// impl Environment for MockEnvironment { -// fn read_32bytes() -> [u8; 32] { -// let bytes = Self::read_global(32); -// let mut array = [0u8; 32]; -// array.copy_from_slice(&bytes[..]); -// array -// } - -// fn read_u32() -> u32 { -// let bytes = Self::read_global(4); -// u32::from_le_bytes(bytes.try_into().unwrap()) -// } - -// fn read_u64() -> u64 { -// let bytes = Self::read_global(8); -// u64::from_le_bytes(bytes.try_into().unwrap()) -// } - -// fn read_i32() -> i32 { -// let bytes = Self::read_global(4); -// i32::from_le_bytes(bytes.try_into().unwrap()) -// } - -// fn write_32bytes(data: [u8; 32]) { -// Self::write_global(&data, 0); -// } - -// fn write_u32(data: u32) { -// Self::write_global(&data.to_le_bytes(), 1); -// } - -// fn write_u64(data: u64) { -// Self::write_global(&data.to_le_bytes(), 2); -// } - -// fn write_i32(data: i32) { -// Self::write_global(&data.to_le_bytes(), 3); -// } -// } - -// pub struct RealEnvironment; - -// impl Environment for RealEnvironment { -// fn read_32bytes() -> [u8; 32] { -// unimplemented!() -// } - -// fn read_u32() -> u32 { -// unimplemented!() -// } - -// fn read_u64() -> u64 { -// unimplemented!() -// } - -// fn read_i32() -> i32 { -// unimplemented!() -// } - -// fn write_32bytes(_data: [u8; 32]) {} - -// fn write_u32(_data: u32) { -// unimplemented!() -// } - -// fn write_u64(_data: u64) { -// unimplemented!() -// } - -// fn write_i32(_data: i32) { -// unimplemented!() -// } -// } diff --git a/core/src/mock/mod.rs b/core/src/mock/mod.rs deleted file mode 100644 index 56662c90..00000000 --- a/core/src/mock/mod.rs +++ /dev/null @@ -1,8 +0,0 @@ -//! # Mock Interfaces -//! -//! This module includes mock interfaces for tests. There are also some common -//! elements for unit and integration tests. - -pub mod common; -pub mod database; -pub mod env; diff --git a/core/src/operator.rs b/core/src/operator.rs index 2b216dac..01aea53b 100644 --- a/core/src/operator.rs +++ b/core/src/operator.rs @@ -6,7 +6,6 @@ use crate::database::Database; use crate::errors::BridgeError; use crate::extended_rpc::ExtendedRpc; use crate::musig2::AggregateFromPublicKeys; -use crate::traits::rpc::OperatorRpcServer; use crate::utils::handle_taproot_witness_new; use crate::{utils, EVMAddress, UTXO}; use bitcoin::address::NetworkUnchecked; @@ -16,7 +15,6 @@ use bitcoin::script::PushBytesBuf; use bitcoin::sighash::SighashCache; use bitcoin::{Address, Amount, OutPoint, TapSighash, Transaction, TxOut, Txid}; use bitcoincore_rpc::{RawTx, RpcApi}; -use jsonrpsee::core::async_trait; use jsonrpsee::core::client::ClientT; use jsonrpsee::http_client::HttpClientBuilder; use jsonrpsee::rpc_params; @@ -699,54 +697,20 @@ impl Operator { } } -#[async_trait] -impl OperatorRpcServer for Operator { - async fn new_deposit_rpc( - &self, - deposit_outpoint: OutPoint, - recovery_taproot_address: Address, - evm_address: EVMAddress, - ) -> Result<(UTXO, secp256k1::schnorr::Signature), BridgeError> { - self.new_deposit(deposit_outpoint, recovery_taproot_address, evm_address) - .await - } - - async fn set_funding_utxo_rpc(&self, funding_utxo: UTXO) -> Result<(), BridgeError> { - self.set_funding_utxo(funding_utxo).await - } - - async fn new_withdrawal_sig_rpc( - &self, - withdrawal_idx: u32, - user_sig: schnorr::Signature, - input_utxo: UTXO, - output_txout: TxOut, - ) -> Result { - self.new_withdrawal_sig(withdrawal_idx, user_sig, input_utxo, output_txout) - .await - } - - async fn withdrawal_proved_on_citrea_rpc( - &self, - withdrawal_idx: u32, - deposit_outpoint: OutPoint, - ) -> Result, BridgeError> { - self.withdrawal_proved_on_citrea(withdrawal_idx, deposit_outpoint) - .await - } -} - #[cfg(test)] mod tests { use crate::{ - extended_rpc::ExtendedRpc, mock::database::create_test_config_with_thread_name, - operator::Operator, servers::create_operator_server, traits::rpc::OperatorRpcClient, UTXO, + config::BridgeConfig, database::Database, initialize_database, utils::initialize_logger, + }; + use crate::{ + create_test_config_with_thread_name, extended_rpc::ExtendedRpc, operator::Operator, UTXO, }; use bitcoin::{hashes::Hash, Amount, OutPoint, ScriptBuf, TxOut, Txid}; + use std::{env, thread}; #[tokio::test] async fn set_funding_utxo() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let rpc = ExtendedRpc::new( config.bitcoin_rpc_url.clone(), config.bitcoin_rpc_user.clone(), @@ -777,37 +741,9 @@ mod tests { assert_eq!(funding_utxo, db_funding_utxo); } - #[tokio::test] - async fn set_funding_utxo_rpc() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; - let rpc = ExtendedRpc::new( - config.bitcoin_rpc_url.clone(), - config.bitcoin_rpc_user.clone(), - config.bitcoin_rpc_password.clone(), - ) - .await; - let operator = create_operator_server(config, rpc).await.unwrap(); - - let funding_utxo = UTXO { - outpoint: OutPoint { - txid: Txid::all_zeros(), - vout: 0x45, - }, - txout: TxOut { - value: Amount::from_sat(0x1F), - script_pubkey: ScriptBuf::new(), - }, - }; - - operator.0.set_funding_utxo_rpc(funding_utxo).await.unwrap(); - - // TODO: Currently, no way to retrive this data using rpc calls. Add - // checks if added in the future. - } - #[tokio::test] async fn is_profitable() { - let mut config = create_test_config_with_thread_name("test_config.toml", None).await; + let mut config = create_test_config_with_thread_name!("test_config.toml", None); let rpc = ExtendedRpc::new( config.bitcoin_rpc_url.clone(), config.bitcoin_rpc_user.clone(), diff --git a/core/src/rpc/aggregator.rs b/core/src/rpc/aggregator.rs index bddbe6d3..5dd76aa6 100644 --- a/core/src/rpc/aggregator.rs +++ b/core/src/rpc/aggregator.rs @@ -398,20 +398,32 @@ impl ClementineAggregator for Aggregator { #[cfg(test)] mod tests { use crate::{ + config::BridgeConfig, + create_test_config_with_thread_name, + database::Database, + errors::BridgeError, + initialize_database, + servers::{ + create_aggregator_grpc_server, create_operator_grpc_server, + create_verifier_grpc_server, create_watchtower_grpc_server, + }, + utils::initialize_logger, + }; + use crate::{ + create_actors, extended_rpc::ExtendedRpc, - mock::database::create_test_config_with_thread_name, rpc::clementine::{self, clementine_aggregator_client::ClementineAggregatorClient}, - servers::create_actors_grpc, verifier::Verifier, watchtower::Watchtower, }; + use std::{env, thread}; #[tokio::test] #[serial_test::serial] async fn aggregator_double_setup_fail() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); - let (_, _, aggregator, _) = create_actors_grpc(config, 0).await; + let (_, _, aggregator, _) = create_actors!(config, 0); let mut aggregator_client = ClementineAggregatorClient::connect(format!("http://{}", aggregator.0)) .await @@ -431,10 +443,9 @@ mod tests { #[tokio::test] #[serial_test::serial] async fn aggregator_setup_winternitz_public_keys() { - let mut config = create_test_config_with_thread_name("test_config.toml", None).await; + let mut config = create_test_config_with_thread_name!("test_config.toml", None); - let (_verifiers, _operators, aggregator, _watchtowers) = - create_actors_grpc(config.clone(), 1).await; + let (_verifiers, _operators, aggregator, _watchtowers) = create_actors!(config.clone(), 1); let mut aggregator_client = ClementineAggregatorClient::connect(format!("http://{}", aggregator.0)) .await @@ -454,6 +465,7 @@ mod tests { config.bitcoin_rpc_password.clone(), ) .await; + config.db_name += "0"; // This modification is done by the create_actors_grpc function. let verifier = Verifier::new(rpc, config.clone()).await.unwrap(); let verifier_wpks = verifier diff --git a/core/src/rpc/watchtower.rs b/core/src/rpc/watchtower.rs index 9a5477bf..280a5162 100644 --- a/core/src/rpc/watchtower.rs +++ b/core/src/rpc/watchtower.rs @@ -29,18 +29,31 @@ impl ClementineWatchtower for Watchtower { #[cfg(test)] mod tests { use crate::{ - mock::database::create_test_config_with_thread_name, + config::BridgeConfig, + create_test_config_with_thread_name, + database::Database, + errors::BridgeError, + extended_rpc::ExtendedRpc, + initialize_database, + servers::{ + create_aggregator_grpc_server, create_operator_grpc_server, + create_verifier_grpc_server, create_watchtower_grpc_server, + }, + utils::initialize_logger, + }; + use crate::{ + create_actors, rpc::clementine::{clementine_watchtower_server::ClementineWatchtower, Empty}, - servers::create_actors_grpc, watchtower::Watchtower, }; + use std::{env, thread}; use tonic::Request; #[tokio::test] #[serial_test::serial] async fn watchtower_get_params() { - let mut config = create_test_config_with_thread_name("test_config.toml", None).await; - let (verifiers, operators, _, _watchtowers) = create_actors_grpc(config.clone(), 2).await; + let mut config = create_test_config_with_thread_name!("test_config.toml", None); + let (verifiers, operators, _, _watchtowers) = create_actors!(config.clone(), 2); config.verifier_endpoints = Some( verifiers diff --git a/core/src/servers.rs b/core/src/servers.rs index 37ad5515..1d5ce1ba 100644 --- a/core/src/servers.rs +++ b/core/src/servers.rs @@ -1,237 +1,27 @@ //! # Servers //! //! Utilities for operator and verifier servers. -use crate::aggregator; use crate::aggregator::Aggregator; -use crate::database::Database; -use crate::mock::database::create_test_config_with_thread_name; use crate::rpc::clementine::clementine_aggregator_server::ClementineAggregatorServer; use crate::rpc::clementine::clementine_operator_server::ClementineOperatorServer; use crate::rpc::clementine::clementine_verifier_server::ClementineVerifierServer; use crate::rpc::clementine::clementine_watchtower_server::ClementineWatchtowerServer; -use crate::traits::rpc::AggregatorServer; use crate::watchtower::Watchtower; use crate::{ - config::BridgeConfig, - errors, - extended_rpc::ExtendedRpc, - operator, - traits::{self, rpc::VerifierRpcServer}, - verifier::Verifier, + config::BridgeConfig, errors, extended_rpc::ExtendedRpc, operator, verifier::Verifier, }; use errors::BridgeError; -use jsonrpsee::{ - http_client::{HttpClient, HttpClientBuilder}, - server::{Server, ServerHandle}, -}; use operator::Operator; use std::thread; -use traits::rpc::OperatorRpcServer; pub type ServerFuture = dyn futures::Future>; -/// Starts a server for a verifier. -#[tracing::instrument(skip(rpc), err(level = tracing::Level::ERROR), ret(level = tracing::Level::TRACE))] -pub async fn create_verifier_server( - config: BridgeConfig, - rpc: ExtendedRpc, -) -> Result<(HttpClient, ServerHandle, std::net::SocketAddr), BridgeError> { - let server = match Server::builder() - .build(format!("{}:{}", config.host, config.port)) - .await - { - Ok(s) => s, - Err(e) => return Err(BridgeError::ServerError(e)), - }; - let verifier = Verifier::new(rpc, config).await?; - - let addr: std::net::SocketAddr = server.local_addr().map_err(BridgeError::ServerError)?; - let handle = server.start(verifier.into_rpc()); - - let client = - HttpClientBuilder::default().build(format!("http://{}:{}/", addr.ip(), addr.port()))?; - - tracing::info!("Verifier server started with address: {}", addr); - - Ok((client, handle, addr)) -} - -/// Starts the server for the operator. -#[tracing::instrument(skip(rpc), err(level = tracing::Level::ERROR), ret(level = tracing::Level::TRACE))] -pub async fn create_operator_server( - config: BridgeConfig, - rpc: ExtendedRpc, -) -> Result<(HttpClient, ServerHandle, std::net::SocketAddr), BridgeError> { - let operator = Operator::new(config.clone(), rpc).await?; - - let server = match Server::builder() - .build(format!("{}:{}", config.host, config.port)) - .await - { - Ok(s) => s, - Err(e) => return Err(BridgeError::ServerError(e)), - }; - - let addr: std::net::SocketAddr = server.local_addr().map_err(BridgeError::ServerError)?; - let handle = server.start(operator.into_rpc()); - - let client = - HttpClientBuilder::default().build(format!("http://{}:{}/", addr.ip(), addr.port()))?; - - tracing::info!("Operator server started with address: {}", addr); - - Ok((client, handle, addr)) -} - -/// Starts the server for the aggregator. -#[tracing::instrument(err(level = tracing::Level::ERROR), ret(level = tracing::Level::TRACE))] -pub async fn create_aggregator_server( - config: BridgeConfig, -) -> Result<(HttpClient, ServerHandle, std::net::SocketAddr), BridgeError> { - let aggregator = aggregator::Aggregator::new(config.clone()).await?; - - let server = match Server::builder() - .build(format!("{}:{}", config.host, config.port)) - .await - { - Ok(s) => s, - Err(e) => return Err(BridgeError::ServerError(e)), - }; - - let addr: std::net::SocketAddr = server.local_addr().map_err(BridgeError::ServerError)?; - let handle = server.start(aggregator.into_rpc()); - - let client = - HttpClientBuilder::default().build(format!("http://{}:{}/", addr.ip(), addr.port()))?; - - tracing::info!("Aggregator server started with address: {}", addr); - - Ok((client, handle, addr)) -} - #[tracing::instrument(ret(level = tracing::Level::TRACE))] fn is_test_env() -> bool { // if thread name is not main then it is a test thread::current().name().unwrap_or_default() != "main" } -/// Starts operators and verifiers servers. This function's intended use is for -/// tests. -/// -/// # Returns -/// -/// Returns a tuple of vectors of clients, handles, and addresses for the -/// verifiers + operators. -/// -/// # Panics -/// -/// Panics if there was an error while creating any of the servers. -#[tracing::instrument(ret(level = tracing::Level::TRACE))] -#[allow(clippy::type_complexity)] // Enabling tracing::instrument causes this. -pub async fn create_verifiers_and_operators( - config_name: &str, - // rpc: ExtendedRpc, -) -> ( - Vec<(HttpClient, ServerHandle, std::net::SocketAddr)>, // Verifier clients - Vec<(HttpClient, ServerHandle, std::net::SocketAddr)>, // Operator clients - (HttpClient, ServerHandle, std::net::SocketAddr), // Aggregator client -) { - let config = create_test_config_with_thread_name(config_name, None).await; - let start_port = config.port; - let rpc = ExtendedRpc::new( - config.bitcoin_rpc_url, - config.bitcoin_rpc_user, - config.bitcoin_rpc_password, - ) - .await; - let all_verifiers_secret_keys = config.all_verifiers_secret_keys.clone().unwrap_or_else(|| { - panic!("All secret keys of the verifiers are required for testing"); - }); - let verifier_futures = all_verifiers_secret_keys - .iter() - .enumerate() - .map(|(i, sk)| { - let port = start_port + i as u16; - // println!("Port: {}", port); - let i = i.to_string(); - let rpc = rpc.clone(); - async move { - let config_with_new_db = - create_test_config_with_thread_name(config_name, Some(&i.to_string())).await; - let verifier = create_verifier_server( - BridgeConfig { - secret_key: *sk, - port: if is_test_env() { 0 } else { port }, - ..config_with_new_db.clone() - }, - rpc, - ) - .await?; - Ok::< - ( - (HttpClient, ServerHandle, std::net::SocketAddr), - BridgeConfig, - ), - BridgeError, - >((verifier, config_with_new_db)) - } - }) - .collect::>(); - let verifier_results = futures::future::try_join_all(verifier_futures) - .await - .unwrap(); - let verifier_endpoints = verifier_results - .iter() - .map(|(v, _)| v.clone()) - .collect::>(); - let verifier_configs = verifier_results - .iter() - .map(|(_, c)| c.clone()) - .collect::>(); - - let all_operators_secret_keys = config.all_operators_secret_keys.clone().unwrap_or_else(|| { - panic!("All secret keys of the operators are required for testing"); - }); - - let operator_futures = all_operators_secret_keys - .iter() - .enumerate() - .map(|(i, sk)| { - let port = start_port + i as u16 + all_verifiers_secret_keys.len() as u16; - let rpc = rpc.clone(); - let verifier_config = verifier_configs[i].clone(); - async move { - create_operator_server( - BridgeConfig { - secret_key: *sk, - port: if is_test_env() { 0 } else { port }, - ..verifier_config - }, - rpc, - ) - .await - } - }) - .collect::>(); - let operator_endpoints = futures::future::try_join_all(operator_futures) - .await - .unwrap(); - - let config = create_test_config_with_thread_name(config_name, None).await; - println!("Port: {}", start_port); - let port = start_port - + all_verifiers_secret_keys.len() as u16 - + all_operators_secret_keys.len() as u16; - let aggregator = create_aggregator_server(BridgeConfig { - port: if is_test_env() { 0 } else { port }, - ..config - }) - .await - .unwrap(); - - (verifier_endpoints, operator_endpoints, aggregator) -} - pub async fn create_verifier_grpc_server( config: BridgeConfig, rpc: ExtendedRpc, @@ -333,165 +123,3 @@ pub async fn create_watchtower_grpc_server( tracing::info!("Watchtower gRPC server started with address: {}", addr); Ok((addr,)) } - -/// Starts operators, verifiers and aggergator gRPC servers. This function's intended use is for -/// tests. -/// -/// # Returns -/// -/// Returns a tuple of vectors of clients, handles, and addresses for the -/// verifiers + operators. -/// -/// # Panics -/// -/// Panics if there was an error while creating any of the servers. -// #[tracing::instrument(ret(level = tracing::Level::TRACE))] -#[allow(clippy::type_complexity)] // Enabling tracing::instrument causes this. -pub async fn create_actors_grpc( - config: BridgeConfig, - number_of_watchtowers: u32, -) -> ( - Vec<(std::net::SocketAddr,)>, // Verifier clients - Vec<(std::net::SocketAddr,)>, // Operator clients - (std::net::SocketAddr,), // Aggregator client - Vec<(std::net::SocketAddr,)>, // Watchtower clients -) { - let start_port = config.port; - let rpc = ExtendedRpc::new( - config.bitcoin_rpc_url.clone(), - config.bitcoin_rpc_user.clone(), - config.bitcoin_rpc_password.clone(), - ) - .await; - let all_verifiers_secret_keys = config.all_verifiers_secret_keys.clone().unwrap_or_else(|| { - panic!("All secret keys of the verifiers are required for testing"); - }); - let verifier_futures = all_verifiers_secret_keys - .iter() - .enumerate() - .map(|(i, sk)| { - let port = start_port + i as u16; - // println!("Port: {}", port); - let i = i.to_string(); - let rpc = rpc.clone(); - let mut config_with_new_db = config.clone(); - async move { - config_with_new_db.db_name += &i; - Database::initialize_database(&config_with_new_db) - .await - .unwrap(); - - let verifier = create_verifier_grpc_server( - BridgeConfig { - secret_key: *sk, - port, - ..config_with_new_db.clone() - }, - rpc, - ) - .await?; - Ok::<((std::net::SocketAddr,), BridgeConfig), BridgeError>(( - verifier, - config_with_new_db, - )) - } - }) - .collect::>(); - let verifier_results = futures::future::try_join_all(verifier_futures) - .await - .unwrap(); - let verifier_endpoints = verifier_results.iter().map(|(v, _)| *v).collect::>(); - let verifier_configs = verifier_results - .iter() - .map(|(_, c)| c.clone()) - .collect::>(); - - let all_operators_secret_keys = config.all_operators_secret_keys.clone().unwrap_or_else(|| { - panic!("All secret keys of the operators are required for testing"); - }); - - // Create futures for operator gRPC servers - let operator_futures = all_operators_secret_keys - .iter() - .enumerate() - .map(|(i, sk)| { - let port = start_port + i as u16 + all_verifiers_secret_keys.len() as u16; - let rpc = rpc.clone(); - let verifier_config = verifier_configs[i].clone(); - async move { - let socket_addr = create_operator_grpc_server( - BridgeConfig { - secret_key: *sk, - port, - ..verifier_config - }, - rpc, - ) - .await?; - Ok::<(std::net::SocketAddr,), BridgeError>(socket_addr) - } - }) - .collect::>(); - - let operator_endpoints = futures::future::try_join_all(operator_futures) - .await - .unwrap(); - - let port = start_port - + all_verifiers_secret_keys.len() as u16 - + all_operators_secret_keys.len() as u16 - + 1; - println!("Watchtower start port: {}", port); - let watchtower_futures = (0..number_of_watchtowers) - .map(|i| { - let verifier_configs = verifier_configs.clone(); - - create_watchtower_grpc_server(BridgeConfig { - port: port + i as u16, - ..verifier_configs[0].clone() - }) - }) - .collect::>(); - let watchtower_endpoints = futures::future::try_join_all(watchtower_futures) - .await - .unwrap(); - - let port = start_port - + all_verifiers_secret_keys.len() as u16 - + all_operators_secret_keys.len() as u16 - + number_of_watchtowers as u16 - + 1; - println!("Aggregator port: {}", port); - // + all_operators_secret_keys.len() as u16; - let aggregator = create_aggregator_grpc_server(BridgeConfig { - port, - verifier_endpoints: Some( - verifier_endpoints - .iter() - .map(|(socket_addr,)| format!("http://{}", socket_addr)) - .collect(), - ), - operator_endpoints: Some( - operator_endpoints - .iter() - .map(|(socket_addr,)| format!("http://{}", socket_addr)) - .collect(), - ), - watchtower_endpoints: Some( - watchtower_endpoints - .iter() - .map(|(socket_addr,)| format!("http://{}", socket_addr)) - .collect(), - ), - ..verifier_configs[0].clone() - }) - .await - .unwrap(); - - ( - verifier_endpoints, - operator_endpoints, - aggregator, - watchtower_endpoints, - ) -} diff --git a/core/src/test_utils.rs b/core/src/test_utils.rs new file mode 100644 index 00000000..a1395d91 --- /dev/null +++ b/core/src/test_utils.rs @@ -0,0 +1,316 @@ +//! # Testing Utilities +//! +//! This crate provides testing utilities, which are not possible to be included +//! in binaries. There will be multiple prerequisites that these macros require. +//! Please check comments of each for more information. + +/// Creates a temporary database for testing, using current thread's name as the +/// database name. +/// +/// # Parameters +/// +/// - `config_file`: Test configuration file in `str` type. Rest of the config +/// will be read from here and only `db_name` will be overwritten. +/// - `suffix`: Optional suffix added to the thread handle in `Option` +/// type. +/// +/// # Returns +/// +/// - [`BridgeConfig`]: Modified configuration struct +/// +/// # Required Imports +/// +/// ## Unit Tests +/// +/// ```rust +/// use crate::{ +/// config::BridgeConfig, database::Database, initialize_database, utils::initialize_logger, +/// }; +/// use std::{env, thread}; +/// ``` +/// +/// ## Integration Tests And Binaries +/// +/// ```rust +/// use clementine_core::{config::BridgeConfig, database::Database, utils::initialize_logger}; +/// use std::{env, thread}; +/// ``` +#[macro_export] +macro_rules! create_test_config_with_thread_name { + ($config_file:expr, $suffix:expr) => {{ + let suffix = $suffix.unwrap_or(&String::default()).to_string(); + + let handle = thread::current() + .name() + .unwrap() + .split(':') + .last() + .unwrap() + .to_owned() + + &suffix; + + // Use maximum log level for tests. + initialize_logger(5).unwrap(); + + // Read specified configuration file from `tests/data` directory. + let mut config = BridgeConfig::try_parse_file( + format!("{}/tests/data/{}", env!("CARGO_MANIFEST_DIR"), $config_file).into(), + ) + .unwrap(); + + // Check environment for an overwrite config. TODO: Convert this to env vars. + let env_config: Option = if let Ok(config_file_path) = env::var("TEST_CONFIG") + { + Some(BridgeConfig::try_parse_file(config_file_path.into()).unwrap()) + } else { + None + }; + + // Overwrite user's environment to test's hard coded data if environment + // file is specified. + if let Some(env_config) = env_config { + config.db_host = env_config.db_host; + config.db_port = env_config.db_port; + config.db_user = env_config.db_user; + config.db_password = env_config.db_password; + config.db_name = env_config.db_name; + }; + + config.db_name = handle.to_string(); + initialize_database!(&config); + + config + }}; +} + +/// Initializes a new database with given configuration. If the database is +/// already initialized, it will be dropped before initialization. Meaning, +/// a clean state is guaranteed. +/// +/// [`Database::new`] must be called after this to connect to the +/// initialized database. +/// +/// # Parameters +/// +/// - `config`: Configuration options in `BridgeConfig` type. +/// +/// # Required Imports +/// +/// ## Unit Tests +/// +/// ```rust +/// use crate::database::Database; +/// ``` +/// +/// ## Integration Tests And Binaries +/// +/// ```rust +/// use clementine_core::database::Database; +/// ``` +#[macro_export] +macro_rules! initialize_database { + ($config:expr) => {{ + let url = Database::get_postgresql_url(&$config); + let conn = sqlx::PgPool::connect(url.as_str()).await.unwrap(); + + sqlx::query(&format!("DROP DATABASE IF EXISTS {}", &$config.db_name)) + .execute(&conn) + .await + .unwrap(); + + sqlx::query(&format!( + "CREATE DATABASE {} WITH OWNER {}", + $config.db_name, $config.db_user + )) + .execute(&conn) + .await + .unwrap(); + + conn.close().await; + + Database::run_schema_script($config).await.unwrap(); + }}; +} + +/// Starts operators, verifiers, aggregator and watchtower servers. +/// +/// # Returns +/// +/// Returns a tuple of vectors of clients, handles, and addresses for the +/// verifiers, operators, aggregator and watchtowers. +/// +/// # Required Imports +/// +/// ## Unit Tests +/// +/// ```rust +/// use crate::{ +/// config::BridgeConfig, +/// database::Database, +/// errors::BridgeError, +/// initialize_database, +/// extended_rpc::ExtendedRpc, +/// servers::{ +/// create_aggregator_grpc_server, create_operator_grpc_server, +/// create_verifier_grpc_server, create_watchtower_grpc_server, +/// }, +/// }; +/// ``` +/// +/// ## Integration Tests And Binaries +/// +/// ```rust +/// use clementine_core::servers::{ +/// create_aggregator_grpc_server, create_operator_grpc_server, create_verifier_grpc_server, +/// create_watchtower_grpc_server, +/// }; +/// ``` +#[macro_export] +macro_rules! create_actors { + ($config:expr, $number_of_watchtowers:expr) => {{ + let start_port = $config.port; + let rpc = ExtendedRpc::new( + $config.bitcoin_rpc_url.clone(), + $config.bitcoin_rpc_user.clone(), + $config.bitcoin_rpc_password.clone(), + ) + .await; + let all_verifiers_secret_keys = + $config + .all_verifiers_secret_keys + .clone() + .unwrap_or_else(|| { + panic!("All secret keys of the verifiers are required for testing"); + }); + let verifier_futures = all_verifiers_secret_keys + .iter() + .enumerate() + .map(|(i, sk)| { + let port = start_port + i as u16; + // println!("Port: {}", port); + let i = i.to_string(); + let rpc = rpc.clone(); + let mut config_with_new_db = $config.clone(); + async move { + config_with_new_db.db_name += &i; + initialize_database!(&config_with_new_db); + + let verifier = create_verifier_grpc_server( + BridgeConfig { + secret_key: *sk, + port, + ..config_with_new_db.clone() + }, + rpc, + ) + .await?; + Ok::<((std::net::SocketAddr,), BridgeConfig), BridgeError>(( + verifier, + config_with_new_db, + )) + } + }) + .collect::>(); + let verifier_results = futures::future::try_join_all(verifier_futures) + .await + .unwrap(); + let verifier_endpoints = verifier_results.iter().map(|(v, _)| *v).collect::>(); + let verifier_configs = verifier_results + .iter() + .map(|(_, c)| c.clone()) + .collect::>(); + + let all_operators_secret_keys = + $config + .all_operators_secret_keys + .clone() + .unwrap_or_else(|| { + panic!("All secret keys of the operators are required for testing"); + }); + + // Create futures for operator gRPC servers + let operator_futures = all_operators_secret_keys + .iter() + .enumerate() + .map(|(i, sk)| { + let port = start_port + i as u16 + all_verifiers_secret_keys.len() as u16; + let rpc = rpc.clone(); + let verifier_config = verifier_configs[i].clone(); + async move { + let socket_addr = create_operator_grpc_server( + BridgeConfig { + secret_key: *sk, + port, + ..verifier_config + }, + rpc, + ) + .await?; + Ok::<(std::net::SocketAddr,), BridgeError>(socket_addr) + } + }) + .collect::>(); + + let operator_endpoints = futures::future::try_join_all(operator_futures) + .await + .unwrap(); + + let port = start_port + + all_verifiers_secret_keys.len() as u16 + + all_operators_secret_keys.len() as u16 + + 1; + println!("Watchtower start port: {}", port); + let watchtower_futures = (0..$number_of_watchtowers) + .map(|i| { + let verifier_configs = verifier_configs.clone(); + + create_watchtower_grpc_server(BridgeConfig { + port: port + i as u16, + ..verifier_configs[0].clone() + }) + }) + .collect::>(); + let watchtower_endpoints = futures::future::try_join_all(watchtower_futures) + .await + .unwrap(); + + let port = start_port + + all_verifiers_secret_keys.len() as u16 + + all_operators_secret_keys.len() as u16 + + $number_of_watchtowers as u16 + + 1; + println!("Aggregator port: {}", port); + // + all_operators_secret_keys.len() as u16; + let aggregator = create_aggregator_grpc_server(BridgeConfig { + port, + verifier_endpoints: Some( + verifier_endpoints + .iter() + .map(|(socket_addr,)| format!("http://{}", socket_addr)) + .collect(), + ), + operator_endpoints: Some( + operator_endpoints + .iter() + .map(|(socket_addr,)| format!("http://{}", socket_addr)) + .collect(), + ), + watchtower_endpoints: Some( + watchtower_endpoints + .iter() + .map(|(socket_addr,)| format!("http://{}", socket_addr)) + .collect(), + ), + ..verifier_configs[0].clone() + }) + .await + .unwrap(); + + ( + verifier_endpoints, + operator_endpoints, + aggregator, + watchtower_endpoints, + ) + }}; +} diff --git a/core/src/traits/mod.rs b/core/src/traits/mod.rs deleted file mode 100644 index 06a3fd02..00000000 --- a/core/src/traits/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod rpc; diff --git a/core/src/traits/rpc.rs b/core/src/traits/rpc.rs deleted file mode 100644 index 4fa8c5a8..00000000 --- a/core/src/traits/rpc.rs +++ /dev/null @@ -1,132 +0,0 @@ -use crate::musig2::{MuSigAggNonce, MuSigPartialSignature, MuSigPubNonce}; -use crate::UTXO; -use crate::{errors::BridgeError, EVMAddress}; -use bitcoin::address::NetworkUnchecked; -use bitcoin::{Address, OutPoint, TxOut, Txid}; -use jsonrpsee::proc_macros::rpc; -use secp256k1::schnorr; - -#[rpc(client, server, namespace = "verifier")] -pub trait VerifierRpc { - #[method(name = "new_deposit")] - /// - Check deposit UTXO, - /// - Generate random pubNonces, secNonces - /// - Save pubNonces and secNonces to a in-memory db - /// - Return pubNonces - async fn verifier_new_deposit_rpc( - &self, - deposit_outpoint: OutPoint, - recovery_taproot_address: Address, - evm_address: EVMAddress, - ) -> Result, BridgeError>; - - #[method(name = "operator_kickoffs_generated")] - /// - Check the kickoff_utxos - /// - for every kickoff_utxo, calculate kickoff2_tx - /// - for every kickoff2_tx, partial sign burn_tx (ommitted for now) - async fn operator_kickoffs_generated_rpc( - &self, - deposit_outpoint: OutPoint, - kickoff_utxos: Vec, - operators_kickoff_sigs: Vec, - agg_nonces: Vec, - ) -> Result<(Vec, Vec), BridgeError>; - - #[method(name = "burn_txs_signed")] - /// verify burn txs are signed by verifiers - /// sign operator_takes_txs - async fn burn_txs_signed_rpc( - &self, - deposit_outpoint: OutPoint, - burn_sigs: Vec, - slash_or_take_sigs: Vec, - ) -> Result, BridgeError>; - - // operator_take_txs_signed - #[method(name = "operator_take_txs_signed")] - /// verify the operator_take_sigs - /// sign move_tx - async fn operator_take_txs_signed_rpc( - &self, - deposit_outpoint: OutPoint, - operator_take_sigs: Vec, - ) -> Result; -} - -#[rpc(client, server, namespace = "operator")] -pub trait OperatorRpc { - #[method(name = "new_deposit")] - /// - Create kickoffUTXO, make sure to not send it to bitcoin yet - async fn new_deposit_rpc( - &self, - deposit_outpoint: OutPoint, - recovery_taproot_address: Address, - evm_address: EVMAddress, - ) -> Result<(UTXO, secp256k1::schnorr::Signature), BridgeError>; - - #[method(name = "set_funding_utxo")] - async fn set_funding_utxo_rpc(&self, funding_utxo: UTXO) -> Result<(), BridgeError>; - - #[method(name = "new_withdrawal_sig")] - /// Gets the withdrawal utxo from citrea, - /// checks wheter sig is for a correct withdrawal from citrea, - /// checks the signature, calls is_profitable, if is profitable pays the withdrawal, - /// adds it to flow, when its finalized, proves on citrea, sends kickoff2 - async fn new_withdrawal_sig_rpc( - &self, - withdrawal_idx: u32, - user_sig: schnorr::Signature, - input_utxo: UTXO, - output_txout: TxOut, - ) -> Result; - - #[method(name = "withdrawal_proved_on_citrea")] - /// 1- Calculate move_txid, check if the withdrawal idx matches the move_txid - /// 2- Check if it is really proved on citrea - /// 3- If it is, send operator_take_txs - async fn withdrawal_proved_on_citrea_rpc( - &self, - withdrawal_idx: u32, - deposit_outpoint: OutPoint, - ) -> Result, BridgeError>; - - // #[method(name = "operator_take_sendable")] - // async fn operator_take_sendable_rpc(&self, withdrawal_idx: usize) -> Result<(), BridgeError>; -} - -#[rpc(client, server, namespace = "aggregator")] -pub trait Aggregator { - #[method(name = "aggregate_pub_nonces")] - async fn aggregate_pub_nonces_rpc( - &self, - pub_nonces: Vec>, - ) -> Result, BridgeError>; - - #[method(name = "aggregate_slash_or_take_sigs")] - async fn aggregate_slash_or_take_sigs_rpc( - &self, - deposit_outpoint: OutPoint, - kickoff_utxos: Vec, - agg_nonces: Vec, - partial_sigs: Vec>, - ) -> Result, BridgeError>; - - #[method(name = "aggregate_operator_take_sigs")] - async fn aggregate_operator_take_sigs_rpc( - &self, - deposit_outpoint: OutPoint, - kickoff_utxos: Vec, - agg_nonces: Vec, - partial_sigs: Vec>, - ) -> Result, BridgeError>; - - #[method(name = "aggregate_move_tx_sigs")] - async fn aggregate_move_tx_sigs_rpc( - &self, - deposit_outpoint: OutPoint, - recovery_taproot_address: Address, - evm_address: EVMAddress, - agg_nonce: MuSigAggNonce, - partial_sigs: Vec, - ) -> Result<(String, Txid), BridgeError>; -} diff --git a/core/src/user.rs b/core/src/user.rs index a4a5c8c8..360bb5d2 100644 --- a/core/src/user.rs +++ b/core/src/user.rs @@ -114,17 +114,20 @@ impl User { #[cfg(test)] mod tests { - use crate::extended_rpc::ExtendedRpc; - use crate::mock::database::create_test_config_with_thread_name; use crate::user::User; use crate::EVMAddress; + use crate::{ + config::BridgeConfig, database::Database, initialize_database, utils::initialize_logger, + }; + use crate::{create_test_config_with_thread_name, extended_rpc::ExtendedRpc}; use bitcoincore_rpc::RpcApi; use secp256k1::{rand, SecretKey}; + use std::{env, thread}; #[tokio::test] #[serial_test::parallel] async fn deposit_tx() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let rpc = ExtendedRpc::new( config.bitcoin_rpc_url.clone(), config.bitcoin_rpc_user.clone(), diff --git a/core/src/verifier.rs b/core/src/verifier.rs index 12309d14..11f1a431 100644 --- a/core/src/verifier.rs +++ b/core/src/verifier.rs @@ -12,14 +12,12 @@ use crate::musig2::{ self, AggregateFromPublicKeys, MuSigAggNonce, MuSigPartialSignature, MuSigPubNonce, MuSigSecNonce, MuSigSigHash, }; -use crate::traits::rpc::VerifierRpcServer; use crate::{utils, ByteArray32, ByteArray64, ByteArray66, EVMAddress, UTXO}; use bitcoin::address::NetworkUnchecked; use bitcoin::hashes::Hash; use bitcoin::Address; use bitcoin::{secp256k1, OutPoint}; use bitcoincore_rpc::RawTx; -use jsonrpsee::core::async_trait; use secp256k1::{rand, schnorr}; #[derive(Debug)] @@ -129,7 +127,7 @@ impl Verifier { /// 3. Save pubNonces and secNonces to a db /// 4. Return pubNonces #[tracing::instrument(skip(self), err(level = tracing::Level::ERROR), ret(level = tracing::Level::TRACE))] - async fn new_deposit( + pub async fn new_deposit( &self, deposit_outpoint: OutPoint, recovery_taproot_address: Address, @@ -203,7 +201,7 @@ impl Verifier { /// do not forget to add tweak when signing since this address has n_of_n as internal_key /// and operator_timelock as script. #[tracing::instrument(skip(self), err(level = tracing::Level::ERROR), ret(level = tracing::Level::TRACE))] - async fn operator_kickoffs_generated( + pub async fn operator_kickoffs_generated( &self, deposit_outpoint: OutPoint, kickoff_utxos: Vec, @@ -331,7 +329,7 @@ impl Verifier { } #[tracing::instrument(skip(self), err(level = tracing::Level::ERROR), ret(level = tracing::Level::TRACE))] - async fn create_deposit_details( + pub async fn create_deposit_details( &self, deposit_outpoint: OutPoint, ) -> Result<(Vec, TxHandler, OutPoint), BridgeError> { @@ -373,7 +371,7 @@ impl Verifier { /// sign operator_takes_txs /// TODO: Change the name of this function. #[tracing::instrument(skip(self), err(level = tracing::Level::ERROR), ret(level = tracing::Level::TRACE))] - async fn burn_txs_signed( + pub async fn burn_txs_signed( &self, deposit_outpoint: OutPoint, _burn_sigs: Vec, @@ -470,7 +468,7 @@ impl Verifier { /// verify the operator_take_sigs /// sign move_tx #[tracing::instrument(skip(self), err(level = tracing::Level::ERROR), ret(level = tracing::Level::TRACE))] - async fn operator_take_txs_signed( + pub async fn operator_take_txs_signed( &self, deposit_outpoint: OutPoint, operator_take_sigs: Vec, @@ -587,69 +585,24 @@ impl Verifier { } } -#[async_trait] -impl VerifierRpcServer for Verifier { - async fn verifier_new_deposit_rpc( - &self, - deposit_outpoint: OutPoint, - recovery_taproot_address: Address, - evm_address: EVMAddress, - ) -> Result, BridgeError> { - self.new_deposit(deposit_outpoint, recovery_taproot_address, evm_address) - .await - } - - async fn operator_kickoffs_generated_rpc( - &self, - deposit_outpoint: OutPoint, - kickoff_utxos: Vec, - operators_kickoff_sigs: Vec, - agg_nonces: Vec, - ) -> Result<(Vec, Vec), BridgeError> { - self.operator_kickoffs_generated( - deposit_outpoint, - kickoff_utxos, - operators_kickoff_sigs, - agg_nonces, - ) - .await - } - - async fn burn_txs_signed_rpc( - &self, - deposit_outpoint: OutPoint, - burn_sigs: Vec, - slash_or_take_sigs: Vec, - ) -> Result, BridgeError> { - self.burn_txs_signed(deposit_outpoint, burn_sigs, slash_or_take_sigs) - .await - } - - async fn operator_take_txs_signed_rpc( - &self, - deposit_outpoint: OutPoint, - operator_take_sigs: Vec, - ) -> Result { - self.operator_take_txs_signed(deposit_outpoint, operator_take_sigs) - .await - } -} - #[cfg(test)] mod tests { - use crate::actor::Actor; use crate::errors::BridgeError; use crate::extended_rpc::ExtendedRpc; - use crate::mock::database::create_test_config_with_thread_name; use crate::musig2::nonce_pair; use crate::user::User; use crate::verifier::Verifier; use crate::EVMAddress; + use crate::{actor::Actor, create_test_config_with_thread_name}; + use crate::{ + config::BridgeConfig, database::Database, initialize_database, utils::initialize_logger, + }; use secp256k1::rand; + use std::{env, thread}; #[tokio::test] async fn verifier_new_public_key_check() { - let mut config = create_test_config_with_thread_name("test_config.toml", None).await; + let mut config = create_test_config_with_thread_name!("test_config.toml", None); let rpc = ExtendedRpc::new( config.bitcoin_rpc_url.clone(), config.bitcoin_rpc_user.clone(), @@ -668,7 +621,7 @@ mod tests { #[tokio::test] #[serial_test::serial] async fn new_deposit_nonce_checks() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); let rpc = ExtendedRpc::new( config.bitcoin_rpc_url.clone(), config.bitcoin_rpc_user.clone(), diff --git a/core/src/watchtower.rs b/core/src/watchtower.rs index 495ebece..9b522616 100644 --- a/core/src/watchtower.rs +++ b/core/src/watchtower.rs @@ -72,17 +72,27 @@ impl Watchtower { #[cfg(test)] mod tests { + use crate::utils::initialize_logger; + use crate::watchtower::Watchtower; use crate::{ - mock::database::create_test_config_with_thread_name, servers::create_actors_grpc, - watchtower::Watchtower, + config::BridgeConfig, + database::Database, + errors::BridgeError, + extended_rpc::ExtendedRpc, + initialize_database, + servers::{ + create_aggregator_grpc_server, create_operator_grpc_server, + create_verifier_grpc_server, create_watchtower_grpc_server, + }, }; + use crate::{create_actors, create_test_config_with_thread_name}; + use std::{env, thread}; #[tokio::test] #[serial_test::serial] async fn new_watchtower() { - let mut config = create_test_config_with_thread_name("test_config.toml", None).await; - let (verifiers, operators, _, _should_not_panic) = - create_actors_grpc(config.clone(), 1).await; + let mut config = create_test_config_with_thread_name!("test_config.toml", None); + let (verifiers, operators, _, _should_not_panic) = create_actors!(config.clone(), 1); config.verifier_endpoints = Some( verifiers @@ -103,8 +113,8 @@ mod tests { #[tokio::test] #[serial_test::serial] async fn get_winternitz_public_keys() { - let mut config = create_test_config_with_thread_name("test_config.toml", None).await; - let (verifiers, operators, _, _watchtowers) = create_actors_grpc(config.clone(), 2).await; + let mut config = create_test_config_with_thread_name!("test_config.toml", None); + let (verifiers, operators, _, _watchtowers) = create_actors!(config.clone(), 2); config.verifier_endpoints = Some( verifiers diff --git a/core/tests/common/deposit.rs b/core/tests/common/deposit.rs deleted file mode 100644 index f4e50358..00000000 --- a/core/tests/common/deposit.rs +++ /dev/null @@ -1,415 +0,0 @@ -//! # Deposit Related Utilities - -use bitcoin::consensus::encode::deserialize_hex; -use bitcoin::Address; -use bitcoin::Amount; -use bitcoin::OutPoint; -use bitcoin::Transaction; -use bitcoincore_rpc::RpcApi; -use clementine_core::actor::Actor; -use clementine_core::config::BridgeConfig; -use clementine_core::errors::BridgeError; -use clementine_core::extended_rpc::ExtendedRpc; -use clementine_core::mock::database::create_test_config_with_thread_name; -use clementine_core::musig2::MuSigPartialSignature; -use clementine_core::servers::*; -use clementine_core::traits::rpc::AggregatorClient; -use clementine_core::traits::rpc::OperatorRpcClient; -use clementine_core::traits::rpc::VerifierRpcClient; -use clementine_core::user::User; -use clementine_core::EVMAddress; -use jsonrpsee::http_client::HttpClient; -use jsonrpsee::server::ServerHandle; -use std::net::SocketAddr; - -pub async fn run_multiple_deposits(test_config_name: &str) { - let config = create_test_config_with_thread_name(test_config_name, None).await; - let rpc = ExtendedRpc::new( - config.bitcoin_rpc_url.clone(), - config.bitcoin_rpc_user.clone(), - config.bitcoin_rpc_password.clone(), - ) - .await; - let secp = secp256k1::Secp256k1::new(); - let (verifiers, operators, aggregator) = - create_verifiers_and_operators("test_config.toml").await; - - // println!("Operators: {:#?}", operators); - // println!("Verifiers: {:#?}", verifiers); - - let secret_key = secp256k1::SecretKey::new(&mut secp256k1::rand::thread_rng()); - - let signer_address = Actor::new(secret_key, config.winternitz_secret_key, config.network) - .address - .as_unchecked() - .clone(); - let user = User::new(rpc.clone(), secret_key, config.clone()); - - let evm_address = EVMAddress([1u8; 20]); - let deposit_address = user.get_deposit_address(evm_address).unwrap(); - let mut deposit_outpoints = Vec::new(); - for _ in 0..config.operator_num_kickoff_utxos_per_tx + 1 { - let deposit_outpoint = rpc - .send_to_address(&deposit_address, config.bridge_amount_sats) - .await - .unwrap(); - - rpc.mine_blocks(18).await.unwrap(); - - let mut pub_nonces = Vec::new(); - - for (client, _, _) in verifiers.iter() { - let musig_pub_nonces = client - .verifier_new_deposit_rpc(deposit_outpoint, signer_address.clone(), evm_address) - .await - .unwrap(); - - pub_nonces.push(musig_pub_nonces); - } - - let agg_nonces = aggregator - .0 - .aggregate_pub_nonces_rpc(pub_nonces) - .await - .unwrap(); - let mut kickoff_utxos = Vec::new(); - let mut signatures = Vec::new(); - - for (client, _, _) in operators.iter() { - let (kickoff_utxo, signature) = client - .new_deposit_rpc(deposit_outpoint, signer_address.clone(), evm_address) - .await - .unwrap(); - - kickoff_utxos.push(kickoff_utxo); - signatures.push(signature); - } - - println!("Now the verifiers sequence starts"); - let mut slash_or_take_partial_sigs = Vec::new(); - - for (client, ..) in verifiers.iter() { - let (partial_sigs, _) = client - .operator_kickoffs_generated_rpc( - deposit_outpoint, - kickoff_utxos.clone(), - signatures.clone(), - agg_nonces.clone(), - ) - .await - .unwrap(); - - slash_or_take_partial_sigs.push(partial_sigs); - } - - let slash_or_take_sigs = aggregator - .0 - .aggregate_slash_or_take_sigs_rpc( - deposit_outpoint, - kickoff_utxos.clone(), - agg_nonces[config.num_operators + 1..2 * config.num_operators + 1].to_vec(), - slash_or_take_partial_sigs, - ) - .await - .unwrap(); - let mut operator_take_partial_sigs: Vec> = Vec::new(); - for (client, ..) in verifiers.iter() { - let partial_sigs = client - .burn_txs_signed_rpc(deposit_outpoint, vec![], slash_or_take_sigs.clone()) - .await - .unwrap(); - operator_take_partial_sigs.push(partial_sigs); - } - - let operator_take_sigs = aggregator - .0 - .aggregate_operator_take_sigs_rpc( - deposit_outpoint, - kickoff_utxos.clone(), - agg_nonces[1..config.num_operators + 1].to_vec(), - operator_take_partial_sigs, - ) - .await - .unwrap(); - - let mut move_tx_partial_sigs = Vec::new(); - for (client, _, _) in verifiers.iter() { - let move_tx_partial_sig = client - .operator_take_txs_signed_rpc(deposit_outpoint, operator_take_sigs.clone()) - .await - .unwrap(); - move_tx_partial_sigs.push(move_tx_partial_sig); - } - - let (move_tx, _) = aggregator - .0 - .aggregate_move_tx_sigs_rpc( - deposit_outpoint, - signer_address.clone(), - evm_address, - agg_nonces[0], - move_tx_partial_sigs, - ) - .await - .unwrap(); - let move_tx: Transaction = deserialize_hex(&move_tx).unwrap(); - - println!("Move tx weight: {:?}", move_tx.weight()); - let move_txid = rpc.client.send_raw_transaction(&move_tx).await.unwrap(); - println!("Move txid: {:?}", move_txid); - deposit_outpoints.push(deposit_outpoint); - } - let withdrawal_address = Address::p2tr( - &secp, - secret_key.x_only_public_key(&secp).0, - None, - config.network, - ); - let (user_utxo, user_txout, user_sig) = user - .generate_withdrawal_transaction_and_signature( - withdrawal_address.clone(), - Amount::from_sat( - config.bridge_amount_sats.to_sat() - - 2 * config.operator_withdrawal_fee_sats.unwrap().to_sat(), - ), - ) - .await - .unwrap(); - let withdrawal_provide_txid = operators[0] - .0 - .new_withdrawal_sig_rpc(0, user_sig, user_utxo, user_txout) - .await - .unwrap(); - println!("Withdrawal provide txid: {:?}", withdrawal_provide_txid); - let txs_to_be_sent_0 = operators[0] - .0 - .withdrawal_proved_on_citrea_rpc(0, deposit_outpoints[0]) - .await - .unwrap(); - assert!(txs_to_be_sent_0.len() == 3); - let (user_utxo, user_txout, user_sig) = user - .generate_withdrawal_transaction_and_signature( - withdrawal_address.clone(), - Amount::from_sat( - config.bridge_amount_sats.to_sat() - - 2 * config.operator_withdrawal_fee_sats.unwrap().to_sat(), - ), - ) - .await - .unwrap(); - let withdrawal_provide_txid = operators[1] - .0 - .new_withdrawal_sig_rpc( - config.operator_num_kickoff_utxos_per_tx as u32 - 1, - user_sig, - user_utxo, - user_txout, - ) - .await - .unwrap(); - println!("Withdrawal provide txid: {:?}", withdrawal_provide_txid); - let txs_to_be_sent_penultimate = operators[1] - .0 - .withdrawal_proved_on_citrea_rpc( - config.operator_num_kickoff_utxos_per_tx as u32 - 1, - deposit_outpoints[config.operator_num_kickoff_utxos_per_tx - 1], - ) - .await - .unwrap(); - assert!(txs_to_be_sent_penultimate.len() == 3); - let (user_utxo, user_txout, user_sig) = user - .generate_withdrawal_transaction_and_signature( - withdrawal_address.clone(), - Amount::from_sat( - config.bridge_amount_sats.to_sat() - - 2 * config.operator_withdrawal_fee_sats.unwrap().to_sat(), - ), - ) - .await - .unwrap(); - let withdrawal_provide_txid = operators[0] - .0 - .new_withdrawal_sig_rpc(2, user_sig, user_utxo, user_txout) - .await - .unwrap(); - println!("Withdrawal provide txid: {:?}", withdrawal_provide_txid); - let txs_to_be_sent_last = operators[2] - .0 - .withdrawal_proved_on_citrea_rpc( - config.operator_num_kickoff_utxos_per_tx as u32, - deposit_outpoints[config.operator_num_kickoff_utxos_per_tx], - ) - .await - .unwrap(); - assert!(txs_to_be_sent_last.len() == 4); -} - -pub async fn run_single_deposit( - test_config_name: &str, -) -> Result< - ( - Vec<(HttpClient, ServerHandle, SocketAddr)>, - Vec<(HttpClient, ServerHandle, SocketAddr)>, - BridgeConfig, - OutPoint, - ), - BridgeError, -> { - let config = create_test_config_with_thread_name(test_config_name, None).await; - let rpc = ExtendedRpc::new( - config.bitcoin_rpc_url.clone(), - config.bitcoin_rpc_user.clone(), - config.bitcoin_rpc_password.clone(), - ) - .await; - - let secret_key = secp256k1::SecretKey::new(&mut secp256k1::rand::thread_rng()); - let signer_address = Actor::new(secret_key, config.winternitz_secret_key, config.network) - .address - .as_unchecked() - .clone(); - - let user = User::new(rpc.clone(), secret_key, config.clone()); - - let evm_address = EVMAddress([1u8; 20]); - let deposit_address = user.get_deposit_address(evm_address).unwrap(); - - let (verifiers, operators, aggregator) = - create_verifiers_and_operators("test_config.toml").await; - - let deposit_outpoint = rpc - .send_to_address(&deposit_address, config.bridge_amount_sats) - .await - .unwrap(); - rpc.mine_blocks(18).await.unwrap(); - - // for every verifier, we call new_deposit - // aggregate nonces - let mut pub_nonces = Vec::new(); - for (client, _, _) in verifiers.iter() { - let musig_pub_nonces = client - .verifier_new_deposit_rpc(deposit_outpoint, signer_address.clone(), evm_address) - .await - .unwrap(); - - pub_nonces.push(musig_pub_nonces); - } - - let agg_nonces = aggregator - .0 - .aggregate_pub_nonces_rpc(pub_nonces) - .await - .unwrap(); - - // call operators' new_deposit - let mut kickoff_utxos = Vec::new(); - let mut signatures = Vec::new(); - for (client, _, _) in operators.iter() { - // Create deposit kickoff transaction - let (kickoff_utxo, signature) = client - .new_deposit_rpc(deposit_outpoint, signer_address.clone(), evm_address) - .await - .unwrap(); - - kickoff_utxos.push(kickoff_utxo); - signatures.push(signature); - } - - // Verifiers part starts here. - let mut slash_or_take_partial_sigs = Vec::new(); - for (client, ..) in verifiers.iter() { - let (partial_sigs, _) = client - .operator_kickoffs_generated_rpc( - deposit_outpoint, - kickoff_utxos.clone(), - signatures.clone(), - agg_nonces.clone(), - ) - .await - .unwrap(); - - slash_or_take_partial_sigs.push(partial_sigs); - } - - let slash_or_take_sigs = aggregator - .0 - .aggregate_slash_or_take_sigs_rpc( - deposit_outpoint, - kickoff_utxos.clone(), - agg_nonces[config.num_operators + 1..2 * config.num_operators + 1].to_vec(), - slash_or_take_partial_sigs, - ) - .await - .unwrap(); - - // call burn_txs_signed_rpc - let mut operator_take_partial_sigs: Vec> = Vec::new(); - for (client, ..) in verifiers.iter() { - let partial_sigs = client - .burn_txs_signed_rpc(deposit_outpoint, vec![], slash_or_take_sigs.clone()) - .await - .unwrap(); - - operator_take_partial_sigs.push(partial_sigs); - } - - let operator_take_sigs = aggregator - .0 - .aggregate_operator_take_sigs_rpc( - deposit_outpoint, - kickoff_utxos.clone(), - agg_nonces[1..config.num_operators + 1].to_vec(), - operator_take_partial_sigs, - ) - .await - .unwrap(); - - // Call operator_take_txs_signed_rpc - let mut move_tx_partial_sigs = Vec::new(); - for (client, _, _) in verifiers.iter() { - let move_tx_partial_sig = client - .operator_take_txs_signed_rpc(deposit_outpoint, operator_take_sigs.clone()) - .await - .unwrap(); - - move_tx_partial_sigs.push(move_tx_partial_sig); - } - - // Aggregate move_tx_partial_sigs - let (move_tx, _) = aggregator - .0 - .aggregate_move_tx_sigs_rpc( - deposit_outpoint, - signer_address, - evm_address, - agg_nonces[0], - move_tx_partial_sigs, - ) - .await - .unwrap(); - - let move_tx: Transaction = deserialize_hex(&move_tx).unwrap(); - println!("Move tx weight: {:?}", move_tx.weight()); - - let move_txid = rpc.client.send_raw_transaction(&move_tx).await.unwrap(); - println!("Move txid: {:?}", move_txid); - - Ok((verifiers, operators, config, deposit_outpoint)) -} - -#[cfg(test)] -mod tests { - use crate::common::{run_multiple_deposits, run_single_deposit}; - - #[ignore = "We are switching to gRPC"] - #[tokio::test] - async fn test_deposit() { - run_single_deposit("test_config.toml").await.unwrap(); - } - - #[ignore = "We are switching to gRPC"] - #[tokio::test] - async fn multiple_deposits_for_operator() { - run_multiple_deposits("test_config.toml").await; - } -} diff --git a/core/tests/common/mod.rs b/core/tests/common/mod.rs index 061cc085..acbf6f96 100644 --- a/core/tests/common/mod.rs +++ b/core/tests/common/mod.rs @@ -1,5 +1,417 @@ //! # Common Utilities for Integration Tests -mod deposit; +#[path = "../../src/test_utils.rs"] +mod test_utils; -pub use deposit::*; +// use crate::{create_test_config_with_thread_name, initialize_database}; +// use bitcoin::consensus::encode::deserialize_hex; +// use bitcoin::Address; +// use bitcoin::Amount; +// use bitcoin::OutPoint; +// use bitcoin::Transaction; +// use bitcoincore_rpc::RpcApi; +// use clementine_core::actor::Actor; +// use clementine_core::config::BridgeConfig; +// use clementine_core::database::Database; +// use clementine_core::errors::BridgeError; +// use clementine_core::extended_rpc::ExtendedRpc; +// use clementine_core::musig2::MuSigPartialSignature; +// use clementine_core::user::User; +// use clementine_core::utils::initialize_logger; +// use clementine_core::EVMAddress; +// use jsonrpsee::http_client::HttpClient; +// use jsonrpsee::server::ServerHandle; +// use std::net::SocketAddr; +// use std::{env, thread}; + +// pub async fn run_multiple_deposits(test_config_name: &str) { +// let config = create_test_config_with_thread_name!(test_config_name, None); +// let rpc = ExtendedRpc::new( +// config.bitcoin_rpc_url.clone(), +// config.bitcoin_rpc_user.clone(), +// config.bitcoin_rpc_password.clone(), +// ) +// .await; +// let secp = secp256k1::Secp256k1::new(); +// let (verifiers, operators, aggregator) = +// create_verifiers_and_operators("test_config.toml").await; + +// // println!("Operators: {:#?}", operators); +// // println!("Verifiers: {:#?}", verifiers); + +// let secret_key = secp256k1::SecretKey::new(&mut secp256k1::rand::thread_rng()); + +// let signer_address = Actor::new(secret_key, config.winternitz_secret_key, config.network) +// .address +// .as_unchecked() +// .clone(); +// let user = User::new(rpc.clone(), secret_key, config.clone()); + +// let evm_address = EVMAddress([1u8; 20]); +// let deposit_address = user.get_deposit_address(evm_address).unwrap(); +// let mut deposit_outpoints = Vec::new(); +// for _ in 0..config.operator_num_kickoff_utxos_per_tx + 1 { +// let deposit_outpoint = rpc +// .send_to_address(&deposit_address, config.bridge_amount_sats) +// .await +// .unwrap(); + +// rpc.mine_blocks(18).await.unwrap(); + +// let mut pub_nonces = Vec::new(); + +// for (client, _, _) in verifiers.iter() { +// let musig_pub_nonces = client +// .verifier_new_deposit_rpc(deposit_outpoint, signer_address.clone(), evm_address) +// .await +// .unwrap(); + +// pub_nonces.push(musig_pub_nonces); +// } + +// let agg_nonces = aggregator +// .0 +// .aggregate_pub_nonces_rpc(pub_nonces) +// .await +// .unwrap(); +// let mut kickoff_utxos = Vec::new(); +// let mut signatures = Vec::new(); + +// for (client, _, _) in operators.iter() { +// let (kickoff_utxo, signature) = client +// .new_deposit_rpc(deposit_outpoint, signer_address.clone(), evm_address) +// .await +// .unwrap(); + +// kickoff_utxos.push(kickoff_utxo); +// signatures.push(signature); +// } + +// println!("Now the verifiers sequence starts"); +// let mut slash_or_take_partial_sigs = Vec::new(); + +// for (client, ..) in verifiers.iter() { +// let (partial_sigs, _) = client +// .operator_kickoffs_generated_rpc( +// deposit_outpoint, +// kickoff_utxos.clone(), +// signatures.clone(), +// agg_nonces.clone(), +// ) +// .await +// .unwrap(); + +// slash_or_take_partial_sigs.push(partial_sigs); +// } + +// let slash_or_take_sigs = aggregator +// .0 +// .aggregate_slash_or_take_sigs_rpc( +// deposit_outpoint, +// kickoff_utxos.clone(), +// agg_nonces[config.num_operators + 1..2 * config.num_operators + 1].to_vec(), +// slash_or_take_partial_sigs, +// ) +// .await +// .unwrap(); +// let mut operator_take_partial_sigs: Vec> = Vec::new(); +// for (client, ..) in verifiers.iter() { +// let partial_sigs = client +// .burn_txs_signed_rpc(deposit_outpoint, vec![], slash_or_take_sigs.clone()) +// .await +// .unwrap(); +// operator_take_partial_sigs.push(partial_sigs); +// } + +// let operator_take_sigs = aggregator +// .0 +// .aggregate_operator_take_sigs_rpc( +// deposit_outpoint, +// kickoff_utxos.clone(), +// agg_nonces[1..config.num_operators + 1].to_vec(), +// operator_take_partial_sigs, +// ) +// .await +// .unwrap(); + +// let mut move_tx_partial_sigs = Vec::new(); +// for (client, _, _) in verifiers.iter() { +// let move_tx_partial_sig = client +// .operator_take_txs_signed_rpc(deposit_outpoint, operator_take_sigs.clone()) +// .await +// .unwrap(); +// move_tx_partial_sigs.push(move_tx_partial_sig); +// } + +// let (move_tx, _) = aggregator +// .0 +// .aggregate_move_tx_sigs_rpc( +// deposit_outpoint, +// signer_address.clone(), +// evm_address, +// agg_nonces[0], +// move_tx_partial_sigs, +// ) +// .await +// .unwrap(); +// let move_tx: Transaction = deserialize_hex(&move_tx).unwrap(); + +// println!("Move tx weight: {:?}", move_tx.weight()); +// let move_txid = rpc.client.send_raw_transaction(&move_tx).await.unwrap(); +// println!("Move txid: {:?}", move_txid); +// deposit_outpoints.push(deposit_outpoint); +// } +// let withdrawal_address = Address::p2tr( +// &secp, +// secret_key.x_only_public_key(&secp).0, +// None, +// config.network, +// ); +// let (user_utxo, user_txout, user_sig) = user +// .generate_withdrawal_transaction_and_signature( +// withdrawal_address.clone(), +// Amount::from_sat( +// config.bridge_amount_sats.to_sat() +// - 2 * config.operator_withdrawal_fee_sats.unwrap().to_sat(), +// ), +// ) +// .await +// .unwrap(); +// let withdrawal_provide_txid = operators[0] +// .0 +// .new_withdrawal_sig_rpc(0, user_sig, user_utxo, user_txout) +// .await +// .unwrap(); +// println!("Withdrawal provide txid: {:?}", withdrawal_provide_txid); +// let txs_to_be_sent_0 = operators[0] +// .0 +// .withdrawal_proved_on_citrea_rpc(0, deposit_outpoints[0]) +// .await +// .unwrap(); +// assert!(txs_to_be_sent_0.len() == 3); +// let (user_utxo, user_txout, user_sig) = user +// .generate_withdrawal_transaction_and_signature( +// withdrawal_address.clone(), +// Amount::from_sat( +// config.bridge_amount_sats.to_sat() +// - 2 * config.operator_withdrawal_fee_sats.unwrap().to_sat(), +// ), +// ) +// .await +// .unwrap(); +// let withdrawal_provide_txid = operators[1] +// .0 +// .new_withdrawal_sig_rpc( +// config.operator_num_kickoff_utxos_per_tx as u32 - 1, +// user_sig, +// user_utxo, +// user_txout, +// ) +// .await +// .unwrap(); +// println!("Withdrawal provide txid: {:?}", withdrawal_provide_txid); +// let txs_to_be_sent_penultimate = operators[1] +// .0 +// .withdrawal_proved_on_citrea_rpc( +// config.operator_num_kickoff_utxos_per_tx as u32 - 1, +// deposit_outpoints[config.operator_num_kickoff_utxos_per_tx - 1], +// ) +// .await +// .unwrap(); +// assert!(txs_to_be_sent_penultimate.len() == 3); +// let (user_utxo, user_txout, user_sig) = user +// .generate_withdrawal_transaction_and_signature( +// withdrawal_address.clone(), +// Amount::from_sat( +// config.bridge_amount_sats.to_sat() +// - 2 * config.operator_withdrawal_fee_sats.unwrap().to_sat(), +// ), +// ) +// .await +// .unwrap(); +// let withdrawal_provide_txid = operators[0] +// .0 +// .new_withdrawal_sig_rpc(2, user_sig, user_utxo, user_txout) +// .await +// .unwrap(); +// println!("Withdrawal provide txid: {:?}", withdrawal_provide_txid); +// let txs_to_be_sent_last = operators[2] +// .0 +// .withdrawal_proved_on_citrea_rpc( +// config.operator_num_kickoff_utxos_per_tx as u32, +// deposit_outpoints[config.operator_num_kickoff_utxos_per_tx], +// ) +// .await +// .unwrap(); +// assert!(txs_to_be_sent_last.len() == 4); +// } + +// pub async fn run_single_deposit( +// test_config_name: &str, +// ) -> Result< +// ( +// Vec<(HttpClient, ServerHandle, SocketAddr)>, +// Vec<(HttpClient, ServerHandle, SocketAddr)>, +// BridgeConfig, +// OutPoint, +// ), +// BridgeError, +// > { +// let config = create_test_config_with_thread_name!(test_config_name, None); +// let rpc = ExtendedRpc::new( +// config.bitcoin_rpc_url.clone(), +// config.bitcoin_rpc_user.clone(), +// config.bitcoin_rpc_password.clone(), +// ) +// .await; + +// let secret_key = secp256k1::SecretKey::new(&mut secp256k1::rand::thread_rng()); +// let signer_address = Actor::new(secret_key, config.winternitz_secret_key, config.network) +// .address +// .as_unchecked() +// .clone(); + +// let user = User::new(rpc.clone(), secret_key, config.clone()); + +// let evm_address = EVMAddress([1u8; 20]); +// let deposit_address = user.get_deposit_address(evm_address).unwrap(); + +// let (verifiers, operators, aggregator) = +// create_verifiers_and_operators("test_config.toml").await; + +// let deposit_outpoint = rpc +// .send_to_address(&deposit_address, config.bridge_amount_sats) +// .await +// .unwrap(); +// rpc.mine_blocks(18).await.unwrap(); + +// // for every verifier, we call new_deposit +// // aggregate nonces +// let mut pub_nonces = Vec::new(); +// for (client, _, _) in verifiers.iter() { +// let musig_pub_nonces = client +// .verifier_new_deposit_rpc(deposit_outpoint, signer_address.clone(), evm_address) +// .await +// .unwrap(); + +// pub_nonces.push(musig_pub_nonces); +// } + +// let agg_nonces = aggregator +// .0 +// .aggregate_pub_nonces_rpc(pub_nonces) +// .await +// .unwrap(); + +// // call operators' new_deposit +// let mut kickoff_utxos = Vec::new(); +// let mut signatures = Vec::new(); +// for (client, _, _) in operators.iter() { +// // Create deposit kickoff transaction +// let (kickoff_utxo, signature) = client +// .new_deposit_rpc(deposit_outpoint, signer_address.clone(), evm_address) +// .await +// .unwrap(); + +// kickoff_utxos.push(kickoff_utxo); +// signatures.push(signature); +// } + +// // Verifiers part starts here. +// let mut slash_or_take_partial_sigs = Vec::new(); +// for (client, ..) in verifiers.iter() { +// let (partial_sigs, _) = client +// .operator_kickoffs_generated_rpc( +// deposit_outpoint, +// kickoff_utxos.clone(), +// signatures.clone(), +// agg_nonces.clone(), +// ) +// .await +// .unwrap(); + +// slash_or_take_partial_sigs.push(partial_sigs); +// } + +// let slash_or_take_sigs = aggregator +// .0 +// .aggregate_slash_or_take_sigs_rpc( +// deposit_outpoint, +// kickoff_utxos.clone(), +// agg_nonces[config.num_operators + 1..2 * config.num_operators + 1].to_vec(), +// slash_or_take_partial_sigs, +// ) +// .await +// .unwrap(); + +// // call burn_txs_signed_rpc +// let mut operator_take_partial_sigs: Vec> = Vec::new(); +// for (client, ..) in verifiers.iter() { +// let partial_sigs = client +// .burn_txs_signed_rpc(deposit_outpoint, vec![], slash_or_take_sigs.clone()) +// .await +// .unwrap(); + +// operator_take_partial_sigs.push(partial_sigs); +// } + +// let operator_take_sigs = aggregator +// .0 +// .aggregate_operator_take_sigs_rpc( +// deposit_outpoint, +// kickoff_utxos.clone(), +// agg_nonces[1..config.num_operators + 1].to_vec(), +// operator_take_partial_sigs, +// ) +// .await +// .unwrap(); + +// // Call operator_take_txs_signed_rpc +// let mut move_tx_partial_sigs = Vec::new(); +// for (client, _, _) in verifiers.iter() { +// let move_tx_partial_sig = client +// .operator_take_txs_signed_rpc(deposit_outpoint, operator_take_sigs.clone()) +// .await +// .unwrap(); + +// move_tx_partial_sigs.push(move_tx_partial_sig); +// } + +// // Aggregate move_tx_partial_sigs +// let (move_tx, _) = aggregator +// .0 +// .aggregate_move_tx_sigs_rpc( +// deposit_outpoint, +// signer_address, +// evm_address, +// agg_nonces[0], +// move_tx_partial_sigs, +// ) +// .await +// .unwrap(); + +// let move_tx: Transaction = deserialize_hex(&move_tx).unwrap(); +// println!("Move tx weight: {:?}", move_tx.weight()); + +// let move_txid = rpc.client.send_raw_transaction(&move_tx).await.unwrap(); +// println!("Move txid: {:?}", move_txid); + +// Ok((verifiers, operators, config, deposit_outpoint)) +// } + +// #[cfg(test)] +// mod tests { +// use crate::common::{run_multiple_deposits, run_single_deposit}; + +// #[ignore = "We are switching to gRPC"] +// #[tokio::test] +// async fn test_deposit() { +// run_single_deposit("test_config.toml").await.unwrap(); +// } + +// #[ignore = "We are switching to gRPC"] +// #[tokio::test] +// async fn multiple_deposits_for_operator() { +// run_multiple_deposits("test_config.toml").await; +// } +// } diff --git a/core/tests/deposit.rs b/core/tests/deposit.rs index 838ebf4a..654bc64f 100644 --- a/core/tests/deposit.rs +++ b/core/tests/deposit.rs @@ -1,277 +1,276 @@ //! # Deposit Tests -use bitcoin::consensus::encode::deserialize_hex; -use bitcoin::Transaction; -use clementine_core::actor::Actor; -use clementine_core::extended_rpc::ExtendedRpc; -use clementine_core::mock::database::create_test_config_with_thread_name; -use clementine_core::musig2::MuSigPartialSignature; -use clementine_core::servers::*; -use clementine_core::traits::rpc::AggregatorClient; -use clementine_core::traits::rpc::OperatorRpcClient; -use clementine_core::traits::rpc::VerifierRpcClient; -use clementine_core::user::User; -use clementine_core::EVMAddress; - -#[ignore = "We are switching to gRPC"] -#[tokio::test] -#[serial_test::serial] -async fn deposit_with_retry_checks() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; - let rpc = ExtendedRpc::new( - config.bitcoin_rpc_url.clone(), - config.bitcoin_rpc_user.clone(), - config.bitcoin_rpc_password.clone(), - ) - .await; - - let secret_key = secp256k1::SecretKey::new(&mut secp256k1::rand::thread_rng()); - let signer_address = Actor::new(secret_key, config.winternitz_secret_key, config.network) - .address - .as_unchecked() - .clone(); - let user = User::new(rpc.clone(), secret_key, config.clone()); - - let evm_address: EVMAddress = EVMAddress([1u8; 20]); - let deposit_address = user.get_deposit_address(evm_address).unwrap(); - - let deposit_outpoint = rpc - .send_to_address(&deposit_address, config.bridge_amount_sats) - .await - .unwrap(); - rpc.mine_blocks((config.confirmation_threshold + 2).into()) - .await - .unwrap(); - - let (verifiers, operators, aggregator) = - create_verifiers_and_operators("test_config.toml").await; - - let agg_nonces = { - let mut pub_nonces = Vec::new(); - - for (client, _, _) in verifiers.iter() { - let musig_pub_nonces = client - .verifier_new_deposit_rpc(deposit_outpoint, signer_address.clone(), evm_address) - .await - .unwrap(); - - pub_nonces.push(musig_pub_nonces); - } - let agg_nonces = aggregator - .0 - .aggregate_pub_nonces_rpc(pub_nonces) - .await - .unwrap(); - - let mut pub_nonces_retry = Vec::new(); - for (client, _, _) in verifiers.iter() { - let musig_pub_nonces = client - .verifier_new_deposit_rpc(deposit_outpoint, signer_address.clone(), evm_address) - .await - .unwrap(); - - pub_nonces_retry.push(musig_pub_nonces); - } - let agg_nonces_retry = aggregator - .0 - .aggregate_pub_nonces_rpc(pub_nonces_retry) - .await - .unwrap(); - - assert_eq!(agg_nonces, agg_nonces_retry); - - agg_nonces - }; - - let (kickoff_utxos, signatures) = { - let mut kickoff_utxos = Vec::new(); - let mut signatures = Vec::new(); - - for (client, _, _) in operators.iter() { - let (kickoff_utxo, signature) = client - .new_deposit_rpc(deposit_outpoint, signer_address.clone(), evm_address) - .await - .unwrap(); - - kickoff_utxos.push(kickoff_utxo); - signatures.push(signature); - } - - let mut kickoff_utxos_retry = Vec::new(); - let mut signatures_retry = Vec::new(); - for (client, _, _) in operators.iter() { - let (kickoff_utxo, signature) = client - .new_deposit_rpc(deposit_outpoint, signer_address.clone(), evm_address) - .await - .unwrap(); - - kickoff_utxos_retry.push(kickoff_utxo); - signatures_retry.push(signature); - } - - assert_eq!(kickoff_utxos, kickoff_utxos_retry); - - (kickoff_utxos, signatures) - }; - - // Operator part is done; Verifier part starts. - - let slash_or_take_sigs = { - let mut slash_or_take_partial_sigs = Vec::new(); - for (client, ..) in verifiers.iter() { - let (partial_sigs, _) = client - .operator_kickoffs_generated_rpc( - deposit_outpoint, - kickoff_utxos.clone(), - signatures.clone(), - agg_nonces.clone(), - ) - .await - .unwrap(); - - slash_or_take_partial_sigs.push(partial_sigs); - } - let slash_or_take_sigs = aggregator - .0 - .aggregate_slash_or_take_sigs_rpc( - deposit_outpoint, - kickoff_utxos.clone(), - agg_nonces[config.num_operators + 1..2 * config.num_operators + 1].to_vec(), - slash_or_take_partial_sigs.clone(), - ) - .await - .unwrap(); - - let mut slash_or_take_partial_sigs_retry = Vec::new(); - for (client, ..) in verifiers.iter() { - let (partial_sigs, _) = client - .operator_kickoffs_generated_rpc( - deposit_outpoint, - kickoff_utxos.clone(), - signatures.clone(), - agg_nonces.clone(), - ) - .await - .unwrap(); - - slash_or_take_partial_sigs_retry.push(partial_sigs); - } - let slash_or_take_sigs_retry = aggregator - .0 - .aggregate_slash_or_take_sigs_rpc( - deposit_outpoint, - kickoff_utxos.clone(), - agg_nonces[config.num_operators + 1..2 * config.num_operators + 1].to_vec(), - slash_or_take_partial_sigs_retry.clone(), - ) - .await - .unwrap(); - - assert_eq!(slash_or_take_partial_sigs, slash_or_take_partial_sigs_retry); - assert_eq!(slash_or_take_sigs, slash_or_take_sigs_retry); - - slash_or_take_sigs - }; - - let operator_take_sigs = { - let mut operator_take_partial_sigs: Vec> = Vec::new(); - for (client, ..) in verifiers.iter() { - let partial_sigs = client - .burn_txs_signed_rpc(deposit_outpoint, vec![], slash_or_take_sigs.clone()) - .await - .unwrap(); - operator_take_partial_sigs.push(partial_sigs); - } - let operator_take_sigs = aggregator - .0 - .aggregate_operator_take_sigs_rpc( - deposit_outpoint, - kickoff_utxos.clone(), - agg_nonces[1..config.num_operators + 1].to_vec(), - operator_take_partial_sigs, - ) - .await - .unwrap(); - - let mut operator_take_partial_sigs_retry = Vec::new(); - for (client, ..) in verifiers.iter() { - let partial_sigs = client - .burn_txs_signed_rpc(deposit_outpoint, vec![], slash_or_take_sigs.clone()) - .await - .unwrap(); - operator_take_partial_sigs_retry.push(partial_sigs); - } - let operator_take_sigs_retry = aggregator - .0 - .aggregate_operator_take_sigs_rpc( - deposit_outpoint, - kickoff_utxos.clone(), - agg_nonces[1..config.num_operators + 1].to_vec(), - operator_take_partial_sigs_retry, - ) - .await - .unwrap(); - - assert_eq!(operator_take_sigs, operator_take_sigs_retry); - - operator_take_sigs - }; - - let move_tx_partial_sigs = { - let mut move_tx_partial_sigs = Vec::new(); - for (client, _, _) in verifiers.iter() { - let move_tx_partial_sig = client - .operator_take_txs_signed_rpc(deposit_outpoint, operator_take_sigs.clone()) - .await - .unwrap(); - move_tx_partial_sigs.push(move_tx_partial_sig); - } - - let mut move_tx_partial_sigs_retry = Vec::new(); - for (client, _, _) in verifiers.iter() { - let move_tx_partial_sig = client - .operator_take_txs_signed_rpc(deposit_outpoint, operator_take_sigs.clone()) - .await - .unwrap(); - move_tx_partial_sigs_retry.push(move_tx_partial_sig); - } - - assert_eq!(move_tx_partial_sigs, move_tx_partial_sigs_retry); - - move_tx_partial_sigs - }; - - let move_tx = { - let (move_tx, _) = aggregator - .0 - .aggregate_move_tx_sigs_rpc( - deposit_outpoint, - signer_address.clone(), - evm_address, - agg_nonces[0], - move_tx_partial_sigs.clone(), - ) - .await - .unwrap(); - - let (move_tx_retry, _) = aggregator - .0 - .aggregate_move_tx_sigs_rpc( - deposit_outpoint, - signer_address, - evm_address, - agg_nonces[0], - move_tx_partial_sigs, - ) - .await - .unwrap(); - - assert_eq!(move_tx, move_tx_retry); - - move_tx - }; - - let move_tx: Transaction = deserialize_hex(&move_tx).unwrap(); - - println!("Move tx weight: {:?}", move_tx.weight()); -} +// use bitcoin::consensus::encode::deserialize_hex; +// use bitcoin::Transaction; +// use clementine_core::actor::Actor; +// use clementine_core::extended_rpc::ExtendedRpc; +// use clementine_core::musig2::MuSigPartialSignature; +// use clementine_core::user::User; +// use clementine_core::EVMAddress; +// use clementine_core::{config::BridgeConfig, database::Database, utils::initialize_logger}; +// use std::{env, thread}; + +// mod common; + +// #[ignore = "We are switching to gRPC"] +// #[tokio::test] +// #[serial_test::serial] +// async fn deposit_with_retry_checks() { +// let config = create_test_config_with_thread_name!("test_config.toml", None); +// let rpc = ExtendedRpc::new( +// config.bitcoin_rpc_url.clone(), +// config.bitcoin_rpc_user.clone(), +// config.bitcoin_rpc_password.clone(), +// ) +// .await; + +// let secret_key = secp256k1::SecretKey::new(&mut secp256k1::rand::thread_rng()); +// let signer_address = Actor::new(secret_key, config.winternitz_secret_key, config.network) +// .address +// .as_unchecked() +// .clone(); +// let user = User::new(rpc.clone(), secret_key, config.clone()); + +// let evm_address: EVMAddress = EVMAddress([1u8; 20]); +// let deposit_address = user.get_deposit_address(evm_address).unwrap(); + +// let deposit_outpoint = rpc +// .send_to_address(&deposit_address, config.bridge_amount_sats) +// .await +// .unwrap(); +// rpc.mine_blocks((config.confirmation_threshold + 2).into()) +// .await +// .unwrap(); + +// let (verifiers, operators, aggregator) = +// create_verifiers_and_operators("test_config.toml").await; + +// let agg_nonces = { +// let mut pub_nonces = Vec::new(); + +// for (client, _, _) in verifiers.iter() { +// let musig_pub_nonces = client +// .verifier_new_deposit_rpc(deposit_outpoint, signer_address.clone(), evm_address) +// .await +// .unwrap(); + +// pub_nonces.push(musig_pub_nonces); +// } +// let agg_nonces = aggregator +// .0 +// .aggregate_pub_nonces_rpc(pub_nonces) +// .await +// .unwrap(); + +// let mut pub_nonces_retry = Vec::new(); +// for (client, _, _) in verifiers.iter() { +// let musig_pub_nonces = client +// .verifier_new_deposit_rpc(deposit_outpoint, signer_address.clone(), evm_address) +// .await +// .unwrap(); + +// pub_nonces_retry.push(musig_pub_nonces); +// } +// let agg_nonces_retry = aggregator +// .0 +// .aggregate_pub_nonces_rpc(pub_nonces_retry) +// .await +// .unwrap(); + +// assert_eq!(agg_nonces, agg_nonces_retry); + +// agg_nonces +// }; + +// let (kickoff_utxos, signatures) = { +// let mut kickoff_utxos = Vec::new(); +// let mut signatures = Vec::new(); + +// for (client, _, _) in operators.iter() { +// let (kickoff_utxo, signature) = client +// .new_deposit_rpc(deposit_outpoint, signer_address.clone(), evm_address) +// .await +// .unwrap(); + +// kickoff_utxos.push(kickoff_utxo); +// signatures.push(signature); +// } + +// let mut kickoff_utxos_retry = Vec::new(); +// let mut signatures_retry = Vec::new(); +// for (client, _, _) in operators.iter() { +// let (kickoff_utxo, signature) = client +// .new_deposit_rpc(deposit_outpoint, signer_address.clone(), evm_address) +// .await +// .unwrap(); + +// kickoff_utxos_retry.push(kickoff_utxo); +// signatures_retry.push(signature); +// } + +// assert_eq!(kickoff_utxos, kickoff_utxos_retry); + +// (kickoff_utxos, signatures) +// }; + +// // Operator part is done; Verifier part starts. + +// let slash_or_take_sigs = { +// let mut slash_or_take_partial_sigs = Vec::new(); +// for (client, ..) in verifiers.iter() { +// let (partial_sigs, _) = client +// .operator_kickoffs_generated_rpc( +// deposit_outpoint, +// kickoff_utxos.clone(), +// signatures.clone(), +// agg_nonces.clone(), +// ) +// .await +// .unwrap(); + +// slash_or_take_partial_sigs.push(partial_sigs); +// } +// let slash_or_take_sigs = aggregator +// .0 +// .aggregate_slash_or_take_sigs_rpc( +// deposit_outpoint, +// kickoff_utxos.clone(), +// agg_nonces[config.num_operators + 1..2 * config.num_operators + 1].to_vec(), +// slash_or_take_partial_sigs.clone(), +// ) +// .await +// .unwrap(); + +// let mut slash_or_take_partial_sigs_retry = Vec::new(); +// for (client, ..) in verifiers.iter() { +// let (partial_sigs, _) = client +// .operator_kickoffs_generated_rpc( +// deposit_outpoint, +// kickoff_utxos.clone(), +// signatures.clone(), +// agg_nonces.clone(), +// ) +// .await +// .unwrap(); + +// slash_or_take_partial_sigs_retry.push(partial_sigs); +// } +// let slash_or_take_sigs_retry = aggregator +// .0 +// .aggregate_slash_or_take_sigs_rpc( +// deposit_outpoint, +// kickoff_utxos.clone(), +// agg_nonces[config.num_operators + 1..2 * config.num_operators + 1].to_vec(), +// slash_or_take_partial_sigs_retry.clone(), +// ) +// .await +// .unwrap(); + +// assert_eq!(slash_or_take_partial_sigs, slash_or_take_partial_sigs_retry); +// assert_eq!(slash_or_take_sigs, slash_or_take_sigs_retry); + +// slash_or_take_sigs +// }; + +// let operator_take_sigs = { +// let mut operator_take_partial_sigs: Vec> = Vec::new(); +// for (client, ..) in verifiers.iter() { +// let partial_sigs = client +// .burn_txs_signed_rpc(deposit_outpoint, vec![], slash_or_take_sigs.clone()) +// .await +// .unwrap(); +// operator_take_partial_sigs.push(partial_sigs); +// } +// let operator_take_sigs = aggregator +// .0 +// .aggregate_operator_take_sigs_rpc( +// deposit_outpoint, +// kickoff_utxos.clone(), +// agg_nonces[1..config.num_operators + 1].to_vec(), +// operator_take_partial_sigs, +// ) +// .await +// .unwrap(); + +// let mut operator_take_partial_sigs_retry = Vec::new(); +// for (client, ..) in verifiers.iter() { +// let partial_sigs = client +// .burn_txs_signed_rpc(deposit_outpoint, vec![], slash_or_take_sigs.clone()) +// .await +// .unwrap(); +// operator_take_partial_sigs_retry.push(partial_sigs); +// } +// let operator_take_sigs_retry = aggregator +// .0 +// .aggregate_operator_take_sigs_rpc( +// deposit_outpoint, +// kickoff_utxos.clone(), +// agg_nonces[1..config.num_operators + 1].to_vec(), +// operator_take_partial_sigs_retry, +// ) +// .await +// .unwrap(); + +// assert_eq!(operator_take_sigs, operator_take_sigs_retry); + +// operator_take_sigs +// }; + +// let move_tx_partial_sigs = { +// let mut move_tx_partial_sigs = Vec::new(); +// for (client, _, _) in verifiers.iter() { +// let move_tx_partial_sig = client +// .operator_take_txs_signed_rpc(deposit_outpoint, operator_take_sigs.clone()) +// .await +// .unwrap(); +// move_tx_partial_sigs.push(move_tx_partial_sig); +// } + +// let mut move_tx_partial_sigs_retry = Vec::new(); +// for (client, _, _) in verifiers.iter() { +// let move_tx_partial_sig = client +// .operator_take_txs_signed_rpc(deposit_outpoint, operator_take_sigs.clone()) +// .await +// .unwrap(); +// move_tx_partial_sigs_retry.push(move_tx_partial_sig); +// } + +// assert_eq!(move_tx_partial_sigs, move_tx_partial_sigs_retry); + +// move_tx_partial_sigs +// }; + +// let move_tx = { +// let (move_tx, _) = aggregator +// .0 +// .aggregate_move_tx_sigs_rpc( +// deposit_outpoint, +// signer_address.clone(), +// evm_address, +// agg_nonces[0], +// move_tx_partial_sigs.clone(), +// ) +// .await +// .unwrap(); + +// let (move_tx_retry, _) = aggregator +// .0 +// .aggregate_move_tx_sigs_rpc( +// deposit_outpoint, +// signer_address, +// evm_address, +// agg_nonces[0], +// move_tx_partial_sigs, +// ) +// .await +// .unwrap(); + +// assert_eq!(move_tx, move_tx_retry); + +// move_tx +// }; + +// let move_tx: Transaction = deserialize_hex(&move_tx).unwrap(); + +// println!("Move tx weight: {:?}", move_tx.weight()); +// } diff --git a/core/tests/flow.rs b/core/tests/flow.rs index 3cda9334..85cf4b9d 100644 --- a/core/tests/flow.rs +++ b/core/tests/flow.rs @@ -2,151 +2,150 @@ //! //! This tests checks if typical flows works or not. -use bitcoin::{Address, Amount, Txid}; -use bitcoincore_rpc::RpcApi; +use bitcoin::Txid; use clementine_core::errors::BridgeError; use clementine_core::extended_rpc::ExtendedRpc; -use clementine_core::mock::database::create_test_config_with_thread_name; use clementine_core::rpc::clementine::clementine_aggregator_client::ClementineAggregatorClient; use clementine_core::rpc::clementine::{self, DepositParams}; -use clementine_core::servers::create_actors_grpc; -use clementine_core::utils::SECP; -use clementine_core::{traits::rpc::OperatorRpcClient, user::User}; -use common::run_single_deposit; -use secp256k1::SecretKey; +use clementine_core::servers::{ + create_aggregator_grpc_server, create_operator_grpc_server, create_verifier_grpc_server, + create_watchtower_grpc_server, +}; +use clementine_core::{config::BridgeConfig, database::Database, utils::initialize_logger}; use std::str::FromStr; +use std::{env, thread}; use tonic::transport::Uri; mod common; -#[ignore = "We are switching to gRPC"] -#[tokio::test] -#[serial_test::serial] -async fn honest_operator_takes_refund() { - let (_verifiers, operators, config, deposit_outpoint) = - run_single_deposit("test_config.toml").await.unwrap(); - let rpc = ExtendedRpc::new( - config.bitcoin_rpc_url.clone(), - config.bitcoin_rpc_user.clone(), - config.bitcoin_rpc_password.clone(), - ) - .await; - - let user_sk = SecretKey::from_slice(&[13u8; 32]).unwrap(); - let user = User::new(rpc.clone(), user_sk, config.clone()); - - let withdrawal_address = Address::p2tr( - &SECP, - user_sk.x_only_public_key(&SECP).0, - None, - config.network, - ); - - // We are giving enough sats to the user so that the operator can pay the - // withdrawal and profit. - let withdrawal_amount = Amount::from_sat( - config.bridge_amount_sats.to_sat() - - 2 * config.operator_withdrawal_fee_sats.unwrap().to_sat(), - ); - - let (empty_utxo, withdrawal_tx_out, user_sig) = user - .generate_withdrawal_transaction_and_signature(withdrawal_address, withdrawal_amount) - .await - .unwrap(); - - let _withdrawal_provide_txid = operators[1] - .0 - .new_withdrawal_sig_rpc(0, user_sig, empty_utxo, withdrawal_tx_out) - .await - .unwrap(); - - let txs_to_be_sent = operators[1] - .0 - .withdrawal_proved_on_citrea_rpc(0, deposit_outpoint) - .await - .unwrap(); - - for tx in txs_to_be_sent.iter().take(txs_to_be_sent.len() - 1) { - rpc.client.send_raw_transaction(tx.clone()).await.unwrap(); - rpc.mine_blocks(1).await.unwrap(); - } - rpc.mine_blocks(1 + config.operator_takes_after as u64) - .await - .unwrap(); - - // Send last transaction. - let operator_take_txid = rpc - .client - .send_raw_transaction(txs_to_be_sent.last().unwrap().clone()) - .await - .unwrap(); - let operator_take_tx = rpc - .client - .get_raw_transaction(&operator_take_txid, None) - .await - .unwrap(); - - assert!(operator_take_tx.output[0].value > withdrawal_amount); - - assert_eq!( - operator_take_tx.output[0].script_pubkey, - config.operator_wallet_addresses[1] - .clone() - .assume_checked() - .script_pubkey() - ); -} - -#[ignore = "We are switching to gRPC"] -#[tokio::test] -async fn withdrawal_fee_too_low() { - let (_verifiers, operators, config, _) = run_single_deposit("test_config.toml").await.unwrap(); - let rpc = ExtendedRpc::new( - config.bitcoin_rpc_url.clone(), - config.bitcoin_rpc_user.clone(), - config.bitcoin_rpc_password.clone(), - ) - .await; - - let user_sk = SecretKey::from_slice(&[12u8; 32]).unwrap(); - let withdrawal_address = Address::p2tr( - &SECP, - user_sk.x_only_public_key(&SECP).0, - None, - config.network, - ); - - let user = User::new(rpc.clone(), user_sk, config.clone()); - - // We are giving too much sats to the user so that operator won't pay it. - let (empty_utxo, withdrawal_tx_out, user_sig) = user - .generate_withdrawal_transaction_and_signature( - withdrawal_address, - Amount::from_sat(config.bridge_amount_sats.to_sat()), - ) - .await - .unwrap(); - - // Operator will reject because it its not profitable. - assert!(operators[0] - .0 - .new_withdrawal_sig_rpc(0, user_sig, empty_utxo, withdrawal_tx_out) - .await - .is_err_and(|err| { - if let jsonrpsee::core::client::Error::Call(err) = err { - err.message() == BridgeError::NotEnoughFeeForOperator.to_string() - } else { - false - } - })); -} +// #[ignore = "We are switching to gRPC"] +// #[tokio::test] +// #[serial_test::serial] +// async fn honest_operator_takes_refund() { +// let (_verifiers, operators, config, deposit_outpoint) = +// run_single_deposit("test_config.toml").await.unwrap(); +// let rpc = ExtendedRpc::new( +// config.bitcoin_rpc_url.clone(), +// config.bitcoin_rpc_user.clone(), +// config.bitcoin_rpc_password.clone(), +// ) +// .await; + +// let user_sk = SecretKey::from_slice(&[13u8; 32]).unwrap(); +// let user = User::new(rpc.clone(), user_sk, config.clone()); + +// let withdrawal_address = Address::p2tr( +// &SECP, +// user_sk.x_only_public_key(&SECP).0, +// None, +// config.network, +// ); + +// // We are giving enough sats to the user so that the operator can pay the +// // withdrawal and profit. +// let withdrawal_amount = Amount::from_sat( +// config.bridge_amount_sats.to_sat() +// - 2 * config.operator_withdrawal_fee_sats.unwrap().to_sat(), +// ); + +// let (empty_utxo, withdrawal_tx_out, user_sig) = user +// .generate_withdrawal_transaction_and_signature(withdrawal_address, withdrawal_amount) +// .await +// .unwrap(); + +// let _withdrawal_provide_txid = operators[1] +// .0 +// .new_withdrawal_sig_rpc(0, user_sig, empty_utxo, withdrawal_tx_out) +// .await +// .unwrap(); + +// let txs_to_be_sent = operators[1] +// .0 +// .withdrawal_proved_on_citrea_rpc(0, deposit_outpoint) +// .await +// .unwrap(); + +// for tx in txs_to_be_sent.iter().take(txs_to_be_sent.len() - 1) { +// rpc.client.send_raw_transaction(tx.clone()).await.unwrap(); +// rpc.mine_blocks(1).await.unwrap(); +// } +// rpc.mine_blocks(1 + config.operator_takes_after as u64) +// .await +// .unwrap(); + +// // Send last transaction. +// let operator_take_txid = rpc +// .client +// .send_raw_transaction(txs_to_be_sent.last().unwrap().clone()) +// .await +// .unwrap(); +// let operator_take_tx = rpc +// .client +// .get_raw_transaction(&operator_take_txid, None) +// .await +// .unwrap(); + +// assert!(operator_take_tx.output[0].value > withdrawal_amount); + +// assert_eq!( +// operator_take_tx.output[0].script_pubkey, +// config.operator_wallet_addresses[1] +// .clone() +// .assume_checked() +// .script_pubkey() +// ); +// } + +// #[ignore = "We are switching to gRPC"] +// #[tokio::test] +// async fn withdrawal_fee_too_low() { +// let (_verifiers, operators, config, _) = run_single_deposit("test_config.toml").await.unwrap(); +// let rpc = ExtendedRpc::new( +// config.bitcoin_rpc_url.clone(), +// config.bitcoin_rpc_user.clone(), +// config.bitcoin_rpc_password.clone(), +// ) +// .await; + +// let user_sk = SecretKey::from_slice(&[12u8; 32]).unwrap(); +// let withdrawal_address = Address::p2tr( +// &SECP, +// user_sk.x_only_public_key(&SECP).0, +// None, +// config.network, +// ); + +// let user = User::new(rpc.clone(), user_sk, config.clone()); + +// // We are giving too much sats to the user so that operator won't pay it. +// let (empty_utxo, withdrawal_tx_out, user_sig) = user +// .generate_withdrawal_transaction_and_signature( +// withdrawal_address, +// Amount::from_sat(config.bridge_amount_sats.to_sat()), +// ) +// .await +// .unwrap(); + +// // Operator will reject because it its not profitable. +// assert!(operators[0] +// .0 +// .new_withdrawal_sig_rpc(0, user_sig, empty_utxo, withdrawal_tx_out) +// .await +// .is_err_and(|err| { +// if let jsonrpsee::core::client::Error::Call(err) = err { +// err.message() == BridgeError::NotEnoughFeeForOperator.to_string() +// } else { +// false +// } +// })); +// } /// TODO: Move this test to a new RPC test file and rename test. #[tokio::test] #[serial_test::serial] async fn grpc_flow() { - let config = create_test_config_with_thread_name("test_config.toml", None).await; - let (_verifiers, _operators, aggregator, _watchtowers) = create_actors_grpc(config, 0).await; + let config = create_test_config_with_thread_name!("test_config.toml", None); + let (_verifiers, _operators, aggregator, _watchtowers) = create_actors!(config, 0); let x: Uri = format!("http://{}", aggregator.0).parse().unwrap(); diff --git a/core/tests/musig2.rs b/core/tests/musig2.rs index 728a0ac0..c7e00ee6 100644 --- a/core/tests/musig2.rs +++ b/core/tests/musig2.rs @@ -2,7 +2,6 @@ use bitcoin::opcodes::all::OP_CHECKSIG; use bitcoin::{hashes::Hash, script, Amount, ScriptBuf}; use bitcoincore_rpc::RpcApi; use clementine_core::builder::transaction::TxHandler; -use clementine_core::mock::database::create_test_config_with_thread_name; use clementine_core::musig2::{ aggregate_nonces, aggregate_partial_signatures, MuSigPartialSignature, MuSigPubNonce, }; @@ -16,7 +15,11 @@ use clementine_core::{ musig2::{create_key_agg_ctx, nonce_pair, partial_sign, MuSigNoncePair}, utils, ByteArray66, }; +use clementine_core::{database::Database, utils::initialize_logger}; use secp256k1::{Keypair, Message, PublicKey}; +use std::{env, thread}; + +mod common; fn get_verifiers_keys( config: &BridgeConfig, @@ -66,7 +69,7 @@ fn get_nonces(verifiers_secret_public_keys: Vec) -> (Vec