diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cdbfe43..83b5b69 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -97,8 +97,8 @@ jobs: - name: Setup rust toolchain run: rustup show - uses: Swatinem/rust-cache@v1.3.0 - - run: cargo build --features expensive_tests --bins --tests - - run: cargo test --workspace --features expensive_tests + - run: cargo build --bins --tests + - run: cargo test --workspace - name: Smoke test ${{ matrix.os }} binary shell: bash run: | diff --git a/daemon/Cargo.toml b/daemon/Cargo.toml index 1e3fa8d..053ffc5 100644 --- a/daemon/Cargo.toml +++ b/daemon/Cargo.toml @@ -48,10 +48,6 @@ x25519-dalek = { version = "1.1" } xtra = { version = "0.6", features = ["with-tokio-1"] } xtra_productivity = { version = "0.1.0" } -[features] -# Feature flag to enable tests that take longer to compile. -expensive_tests = [] - [[bin]] name = "taker" path = "src/taker.rs" diff --git a/daemon/src/lib.rs b/daemon/src/lib.rs index 3237272..551b180 100644 --- a/daemon/src/lib.rs +++ b/daemon/src/lib.rs @@ -46,6 +46,8 @@ pub mod wallet; pub mod wallet_sync; pub mod wire; +pub const N_PAYOUTS: usize = 200; + pub struct MakerActorSystem { pub cfd_actor_addr: Address>, pub cfd_feed_receiver: watch::Receiver>, @@ -70,6 +72,7 @@ where + xtra::Handler + xtra::Handler, { + #[allow(clippy::too_many_arguments)] pub async fn new( db: SqlitePool, wallet_addr: Address, @@ -81,6 +84,7 @@ where Box>, ) -> T, settlement_time_interval_hours: time::Duration, + n_payouts: usize, ) -> Result where F: Future>, @@ -109,6 +113,7 @@ where inc_conn_addr.clone(), monitor_addr.clone(), oracle_addr.clone(), + n_payouts, ) .create(None) .spawn_global(); @@ -172,6 +177,7 @@ where + xtra::Handler + xtra::Handler, { + #[allow(clippy::too_many_arguments)] pub async fn new( db: SqlitePool, wallet_addr: Address, @@ -180,6 +186,7 @@ where read_from_maker: Box + Unpin + Send>, oracle_constructor: impl FnOnce(Vec, Box>) -> O, monitor_constructor: impl FnOnce(Box>, Vec) -> F, + n_payouts: usize, ) -> Result where F: Future>, @@ -206,6 +213,7 @@ where send_to_maker, monitor_addr.clone(), oracle_addr, + n_payouts, ) .create(None) .spawn_global(); diff --git a/daemon/src/maker.rs b/daemon/src/maker.rs index a7bacfb..8746a95 100644 --- a/daemon/src/maker.rs +++ b/daemon/src/maker.rs @@ -1,26 +1,20 @@ use anyhow::{Context, Result}; use bdk::bitcoin::secp256k1::schnorrsig; +use bdk::bitcoin::Amount; use bdk::{bitcoin, FeeRate}; use clap::{Parser, Subcommand}; use daemon::auth::{self, MAKER_USERNAME}; -use daemon::db::{self}; - use daemon::model::WalletInfo; - use daemon::seed::Seed; use daemon::{ - bitmex_price_feed, housekeeping, logger, maker_cfd, maker_inc_connections, monitor, oracle, - wallet, wallet_sync, MakerActorSystem, + bitmex_price_feed, db, housekeeping, logger, maker_cfd, maker_inc_connections, monitor, oracle, + wallet, wallet_sync, MakerActorSystem, N_PAYOUTS, }; - use sqlx::sqlite::SqliteConnectOptions; use sqlx::SqlitePool; - use std::net::SocketAddr; use std::path::PathBuf; use std::str::FromStr; - -use bdk::bitcoin::Amount; use std::task::Poll; use tokio::sync::watch; use tracing_subscriber::filter::LevelFilter; @@ -270,6 +264,7 @@ async fn main() -> Result<()> { }, |channel0, channel1| maker_inc_connections::Actor::new(channel0, channel1, noise_static_sk), time::Duration::hours(opts.settlement_time_interval_hours as i64), + N_PAYOUTS, ) .await?; diff --git a/daemon/src/maker_cfd.rs b/daemon/src/maker_cfd.rs index 9f0cf01..bace1fa 100644 --- a/daemon/src/maker_cfd.rs +++ b/daemon/src/maker_cfd.rs @@ -74,6 +74,7 @@ pub struct Actor { // Maker needs to also store TakerId to be able to send a reply back current_pending_proposals: HashMap, current_agreed_proposals: HashMap, + n_payouts: usize, } enum SetupState { @@ -105,6 +106,7 @@ impl Actor { takers: Address, monitor_actor: Address, oracle_actor: Address, + n_payouts: usize, ) -> Self { Self { db, @@ -122,6 +124,7 @@ impl Actor { oracle_actor, current_pending_proposals: HashMap::new(), current_agreed_proposals: HashMap::new(), + n_payouts, } } @@ -593,6 +596,7 @@ where cfd, self.wallet.clone(), Role::Maker, + self.n_payouts, ); let this = ctx @@ -795,6 +799,7 @@ where cfd, Role::Maker, dlc, + self.n_payouts, ); let this = ctx diff --git a/daemon/src/model/cfd.rs b/daemon/src/model/cfd.rs index 3fb1e36..b984987 100644 --- a/daemon/src/model/cfd.rs +++ b/daemon/src/model/cfd.rs @@ -627,9 +627,17 @@ impl Cfd { Ok((p_n_l, p_n_l_percent)) } - pub fn calculate_settlement(&self, current_price: Price) -> Result { - let payout_curve = - payout_curve::calculate(self.order.price, self.quantity_usd, self.order.leverage)?; + pub fn calculate_settlement( + &self, + current_price: Price, + n_payouts: usize, + ) -> Result { + let payout_curve = payout_curve::calculate( + self.order.price, + self.quantity_usd, + self.order.leverage, + n_payouts, + )?; let payout = { let current_price = current_price.try_into_u64()?; diff --git a/daemon/src/payout_curve.rs b/daemon/src/payout_curve.rs index 7b11008..c6b5677 100644 --- a/daemon/src/payout_curve.rs +++ b/daemon/src/payout_curve.rs @@ -43,8 +43,13 @@ mod utils; /// ### Returns /// /// The list of [`Payout`]s for the given price, quantity and leverage. -pub fn calculate(price: Price, quantity: Usd, leverage: Leverage) -> Result> { - let payouts = calculate_payout_parameters(price, quantity, leverage)? +pub fn calculate( + price: Price, + quantity: Usd, + leverage: Leverage, + n_payouts: usize, +) -> Result> { + let payouts = calculate_payout_parameters(price, quantity, leverage, n_payouts)? .into_iter() .map(PayoutParameter::into_payouts) .flatten_ok() @@ -54,7 +59,6 @@ pub fn calculate(price: Price, quantity: Usd, leverage: Leverage) -> Result Result> { let initial_rate = price .try_into_f64() @@ -83,7 +88,7 @@ fn calculate_payout_parameters( )?; let payout_parameters = payout_curve - .generate_payout_scheme(N_PAYOUTS)? + .generate_payout_scheme(n_payouts)? .rows() .into_iter() .map(|row| { @@ -509,6 +514,7 @@ mod tests { Price::new(dec!(54000.00)).unwrap(), Usd::new(dec!(3500.00)), Leverage::new(5).unwrap(), + 200, ) .unwrap(); @@ -725,6 +731,7 @@ mod tests { Price::new(dec!(54000.00)).unwrap(), Usd::new(dec!(3500.00)), Leverage::new(5).unwrap(), + 200, ) .unwrap(); diff --git a/daemon/src/setup_contract.rs b/daemon/src/setup_contract.rs index 3de3ce7..515ada0 100644 --- a/daemon/src/setup_contract.rs +++ b/daemon/src/setup_contract.rs @@ -33,6 +33,7 @@ pub async fn new( cfd: Cfd, wallet: Address, role: Role, + n_payouts: usize, ) -> Result where W: xtra::Handler + xtra::Handler, @@ -83,7 +84,12 @@ where let payouts = HashMap::from_iter([( announcement.into(), - payout_curve::calculate(cfd.order.price, cfd.quantity_usd, cfd.order.leverage)?, + payout_curve::calculate( + cfd.order.price, + cfd.quantity_usd, + cfd.order.leverage, + n_payouts, + )?, )]); let own_cfd_txs = create_cfd_transactions( @@ -267,6 +273,7 @@ pub async fn roll_over( cfd: Cfd, our_role: Role, dlc: Dlc, + n_payouts: usize, ) -> Result { let sk = dlc.identity; let pk = PublicKey::new(secp256k1_zkp::PublicKey::from_secret_key(SECP256K1, &sk)); @@ -301,7 +308,12 @@ pub async fn roll_over( id: announcement.id.to_string(), nonce_pks: announcement.nonce_pks.clone(), }, - payout_curve::calculate(cfd.order.price, cfd.quantity_usd, cfd.order.leverage)?, + payout_curve::calculate( + cfd.order.price, + cfd.quantity_usd, + cfd.order.leverage, + n_payouts, + )?, )]); // unsign lock tx because PartiallySignedTransaction needs an unsigned tx diff --git a/daemon/src/taker.rs b/daemon/src/taker.rs index b5b41cb..3a20070 100644 --- a/daemon/src/taker.rs +++ b/daemon/src/taker.rs @@ -3,12 +3,11 @@ use bdk::bitcoin::secp256k1::schnorrsig; use bdk::bitcoin::{Address, Amount}; use bdk::{bitcoin, FeeRate}; use clap::{Parser, Subcommand}; -use daemon::db::{self}; use daemon::model::WalletInfo; use daemon::seed::Seed; use daemon::{ - bitmex_price_feed, connection, housekeeping, logger, monitor, oracle, taker_cfd, wallet, - wallet_sync, TakerActorSystem, + bitmex_price_feed, connection, db, housekeeping, logger, monitor, oracle, taker_cfd, wallet, + wallet_sync, TakerActorSystem, N_PAYOUTS, }; use sqlx::sqlite::SqliteConnectOptions; use sqlx::SqlitePool; @@ -250,6 +249,7 @@ async fn main() -> Result<()> { monitor::Actor::new(electrum, channel, cfds) } }, + N_PAYOUTS, ) .await?; diff --git a/daemon/src/taker_cfd.rs b/daemon/src/taker_cfd.rs index b20d1a4..879a0c0 100644 --- a/daemon/src/taker_cfd.rs +++ b/daemon/src/taker_cfd.rs @@ -78,6 +78,7 @@ pub struct Actor { roll_over_state: RollOverState, oracle_actor: Address, current_pending_proposals: UpdateCfdProposals, + n_payouts: usize, } impl Actor @@ -97,6 +98,7 @@ where send_to_maker: Box>, monitor_actor: Address, oracle_actor: Address, + n_payouts: usize, ) -> Self { Self { db, @@ -111,6 +113,7 @@ where roll_over_state: RollOverState::None, oracle_actor, current_pending_proposals: HashMap::new(), + n_payouts, } } } @@ -197,7 +200,7 @@ where let mut conn = self.db.acquire().await?; let cfd = load_cfd_by_order_id(order_id, &mut conn).await?; - let proposal = cfd.calculate_settlement(current_price)?; + let proposal = cfd.calculate_settlement(current_price, self.n_payouts)?; if self .current_pending_proposals @@ -510,6 +513,7 @@ where cfd, self.wallet.clone(), Role::Taker, + self.n_payouts, ); let this = ctx @@ -571,6 +575,7 @@ where cfd, Role::Taker, dlc, + self.n_payouts, ); let this = ctx diff --git a/daemon/tests/happy_path.rs b/daemon/tests/happy_path.rs index 899eccb..c960c53 100644 --- a/daemon/tests/happy_path.rs +++ b/daemon/tests/happy_path.rs @@ -58,8 +58,8 @@ async fn taker_takes_order_and_maker_rejects() { assert!(matches!(taker_cfd.state, CfdState::Rejected { .. })); assert!(matches!(maker_cfd.state, CfdState::Rejected { .. })); } + #[tokio::test] -#[cfg_attr(not(feature = "expensive_tests"), ignore)] async fn taker_takes_order_and_maker_accepts_and_contract_setup() { let _guard = init_tracing(); let (mut maker, mut taker) = start_both().await; diff --git a/daemon/tests/harness/mod.rs b/daemon/tests/harness/mod.rs index e4c5a28..effc157 100644 --- a/daemon/tests/harness/mod.rs +++ b/daemon/tests/harness/mod.rs @@ -36,6 +36,8 @@ pub async fn start_both() -> (Maker, Taker) { (maker, taker) } +const N_PAYOUTS_FOR_TEST: usize = 5; + /// Maker Test Setup #[derive(Clone)] pub struct Maker { @@ -78,6 +80,7 @@ impl Maker { maker_inc_connections::Actor::new(channel0, channel1, noise_static_sk) }, settlement_time_interval_hours, + N_PAYOUTS_FOR_TEST, ) .await .unwrap(); @@ -178,6 +181,7 @@ impl Taker { read_from_maker, |_, _| oracle, |_, _| async { Ok(monitor) }, + N_PAYOUTS_FOR_TEST, ) .await .unwrap();