diff --git a/swap/src/bin/asb.rs b/swap/src/bin/asb.rs index 96359070..8593ee5a 100644 --- a/swap/src/bin/asb.rs +++ b/swap/src/bin/asb.rs @@ -140,7 +140,7 @@ async fn main() -> Result<()> { Arc::new(bitcoin_wallet), Arc::new(monero_wallet), Arc::new(db), - kraken_rate, + kraken_rate.clone(), config.maker.min_buy_btc, config.maker.max_buy_btc, ) @@ -148,9 +148,10 @@ async fn main() -> Result<()> { tokio::spawn(async move { while let Some(swap) = swap_receiver.recv().await { + let rate = kraken_rate.clone(); tokio::spawn(async move { let swap_id = swap.swap_id; - match run(swap).await { + match run(swap, rate).await { Ok(state) => { tracing::debug!(%swap_id, "Swap finished with state {}", state) } diff --git a/swap/src/protocol/alice/swap.rs b/swap/src/protocol/alice/swap.rs index 14002f60..41d62f07 100644 --- a/swap/src/protocol/alice/swap.rs +++ b/swap/src/protocol/alice/swap.rs @@ -2,7 +2,7 @@ //! Alice holds XMR and wishes receive BTC. use crate::bitcoin::ExpiredTimelocks; use crate::env::Config; -use crate::protocol::alice::event_loop::EventLoopHandle; +use crate::protocol::alice::event_loop::{EventLoopHandle, LatestRate}; use crate::protocol::alice::{AliceState, Swap}; use crate::{bitcoin, database, monero}; use anyhow::{bail, Context, Result}; @@ -11,12 +11,22 @@ use tokio::time::timeout; use tracing::{error, info}; use uuid::Uuid; -pub async fn run(swap: Swap) -> Result { - run_until(swap, |_| false).await +pub async fn run(swap: Swap, rate_service: LR) -> Result +where + LR: LatestRate + Clone, +{ + run_until(swap, |_| false, rate_service).await } -#[tracing::instrument(name = "swap", skip(swap,exit_early), fields(id = %swap.swap_id), err)] -pub async fn run_until(mut swap: Swap, exit_early: fn(&AliceState) -> bool) -> Result { +#[tracing::instrument(name = "swap", skip(swap,exit_early,rate_service), fields(id = %swap.swap_id), err)] +pub async fn run_until( + mut swap: Swap, + exit_early: fn(&AliceState) -> bool, + rate_service: LR, +) -> Result +where + LR: LatestRate + Clone, +{ let mut current_state = swap.state; while !is_complete(¤t_state) && !exit_early(¤t_state) { @@ -27,6 +37,7 @@ pub async fn run_until(mut swap: Swap, exit_early: fn(&AliceState) -> bool) -> R swap.bitcoin_wallet.as_ref(), swap.monero_wallet.as_ref(), &swap.env_config, + rate_service.clone(), ) .await?; @@ -39,15 +50,23 @@ pub async fn run_until(mut swap: Swap, exit_early: fn(&AliceState) -> bool) -> R Ok(current_state) } -async fn next_state( +async fn next_state( swap_id: Uuid, state: AliceState, event_loop_handle: &mut EventLoopHandle, bitcoin_wallet: &bitcoin::Wallet, monero_wallet: &monero::Wallet, env_config: &Config, -) -> Result { - info!("Current state: {}", state); + mut rate_service: LR, +) -> Result +where + LR: LatestRate, +{ + let rate = rate_service + .latest_rate() + .map_or("NaN".to_string(), |rate| format!("{}", rate)); + + info!(%state, %rate, "Update"); Ok(match state { AliceState::Started { state3 } => { diff --git a/swap/tests/alice_and_bob_refund_using_cancel_and_refund_command.rs b/swap/tests/alice_and_bob_refund_using_cancel_and_refund_command.rs index d342d8e7..557768a3 100644 --- a/swap/tests/alice_and_bob_refund_using_cancel_and_refund_command.rs +++ b/swap/tests/alice_and_bob_refund_using_cancel_and_refund_command.rs @@ -3,6 +3,7 @@ pub mod harness; use harness::alice_run_until::is_xmr_lock_transaction_sent; use harness::bob_run_until::is_btc_locked; use harness::FastCancelConfig; +use swap::protocol::alice::event_loop::FixedRate; use swap::protocol::alice::AliceState; use swap::protocol::bob::BobState; use swap::protocol::{alice, bob}; @@ -15,7 +16,11 @@ async fn given_alice_and_bob_manually_refund_after_funds_locked_both_refund() { let bob_swap = tokio::spawn(bob::run_until(bob_swap, is_btc_locked)); let alice_swap = ctx.alice_next_swap().await; - let alice_swap = tokio::spawn(alice::run_until(alice_swap, is_xmr_lock_transaction_sent)); + let alice_swap = tokio::spawn(alice::run_until( + alice_swap, + is_xmr_lock_transaction_sent, + FixedRate::default(), + )); let bob_state = bob_swap.await??; assert!(matches!(bob_state, BobState::BtcLocked { .. })); diff --git a/swap/tests/alice_and_bob_refund_using_cancel_and_refund_command_timelock_not_expired.rs b/swap/tests/alice_and_bob_refund_using_cancel_and_refund_command_timelock_not_expired.rs index bd0761e3..9a20127e 100644 --- a/swap/tests/alice_and_bob_refund_using_cancel_and_refund_command_timelock_not_expired.rs +++ b/swap/tests/alice_and_bob_refund_using_cancel_and_refund_command_timelock_not_expired.rs @@ -3,6 +3,7 @@ pub mod harness; use harness::alice_run_until::is_xmr_lock_transaction_sent; use harness::bob_run_until::is_btc_locked; use harness::SlowCancelConfig; +use swap::protocol::alice::event_loop::FixedRate; use swap::protocol::alice::AliceState; use swap::protocol::bob::BobState; use swap::protocol::{alice, bob}; @@ -15,7 +16,11 @@ async fn given_alice_and_bob_manually_cancel_when_timelock_not_expired_errors() let bob_swap = tokio::spawn(bob::run_until(bob_swap, is_btc_locked)); let alice_swap = ctx.alice_next_swap().await; - let alice_swap = tokio::spawn(alice::run_until(alice_swap, is_xmr_lock_transaction_sent)); + let alice_swap = tokio::spawn(alice::run_until( + alice_swap, + is_xmr_lock_transaction_sent, + FixedRate::default(), + )); let bob_state = bob_swap.await??; assert!(matches!(bob_state, BobState::BtcLocked { .. })); diff --git a/swap/tests/alice_and_bob_refund_using_cancel_and_refund_command_timelock_not_expired_force.rs b/swap/tests/alice_and_bob_refund_using_cancel_and_refund_command_timelock_not_expired_force.rs index 59f5141e..843d6a79 100644 --- a/swap/tests/alice_and_bob_refund_using_cancel_and_refund_command_timelock_not_expired_force.rs +++ b/swap/tests/alice_and_bob_refund_using_cancel_and_refund_command_timelock_not_expired_force.rs @@ -3,6 +3,7 @@ pub mod harness; use harness::alice_run_until::is_xmr_lock_transaction_sent; use harness::bob_run_until::is_btc_locked; use harness::SlowCancelConfig; +use swap::protocol::alice::event_loop::FixedRate; use swap::protocol::alice::AliceState; use swap::protocol::bob::BobState; use swap::protocol::{alice, bob}; @@ -15,7 +16,11 @@ async fn given_alice_and_bob_manually_force_cancel_when_timelock_not_expired_err let bob_swap = tokio::spawn(bob::run_until(bob_swap, is_btc_locked)); let alice_swap = ctx.alice_next_swap().await; - let alice_swap = tokio::spawn(alice::run_until(alice_swap, is_xmr_lock_transaction_sent)); + let alice_swap = tokio::spawn(alice::run_until( + alice_swap, + is_xmr_lock_transaction_sent, + FixedRate::default(), + )); let bob_state = bob_swap.await??; assert!(matches!(bob_state, BobState::BtcLocked { .. })); diff --git a/swap/tests/alice_manually_punishes_after_bob_dead.rs b/swap/tests/alice_manually_punishes_after_bob_dead.rs index 1bf71d62..2da13969 100644 --- a/swap/tests/alice_manually_punishes_after_bob_dead.rs +++ b/swap/tests/alice_manually_punishes_after_bob_dead.rs @@ -3,6 +3,7 @@ pub mod harness; use harness::alice_run_until::is_xmr_lock_transaction_sent; use harness::bob_run_until::is_btc_locked; use harness::FastPunishConfig; +use swap::protocol::alice::event_loop::FixedRate; use swap::protocol::alice::AliceState; use swap::protocol::bob::BobState; use swap::protocol::{alice, bob}; @@ -20,7 +21,11 @@ async fn alice_manually_punishes_after_bob_dead() { let alice_swap = ctx.alice_next_swap().await; let alice_bitcoin_wallet = alice_swap.bitcoin_wallet.clone(); - let alice_swap = tokio::spawn(alice::run_until(alice_swap, is_xmr_lock_transaction_sent)); + let alice_swap = tokio::spawn(alice::run_until( + alice_swap, + is_xmr_lock_transaction_sent, + FixedRate::default(), + )); let bob_state = bob_swap.await??; assert!(matches!(bob_state, BobState::BtcLocked { .. })); diff --git a/swap/tests/alice_manually_redeems_after_enc_sig_learned.rs b/swap/tests/alice_manually_redeems_after_enc_sig_learned.rs index 38a0da9b..720dad19 100644 --- a/swap/tests/alice_manually_redeems_after_enc_sig_learned.rs +++ b/swap/tests/alice_manually_redeems_after_enc_sig_learned.rs @@ -2,6 +2,7 @@ pub mod harness; use harness::alice_run_until::is_encsig_learned; use harness::SlowCancelConfig; +use swap::protocol::alice::event_loop::FixedRate; use swap::protocol::alice::redeem::Finality; use swap::protocol::alice::AliceState; use swap::protocol::{alice, bob}; @@ -15,7 +16,11 @@ async fn alice_manually_redeems_after_enc_sig_learned() { let bob_swap = tokio::spawn(bob::run(bob_swap)); let alice_swap = ctx.alice_next_swap().await; - let alice_swap = tokio::spawn(alice::run_until(alice_swap, is_encsig_learned)); + let alice_swap = tokio::spawn(alice::run_until( + alice_swap, + is_encsig_learned, + FixedRate::default(), + )); let alice_state = alice_swap.await??; assert!(matches!(alice_state, AliceState::EncSigLearned { .. })); diff --git a/swap/tests/alice_punishes_after_restart_bob_dead.rs b/swap/tests/alice_punishes_after_restart_bob_dead.rs index 377b7b47..a272dbf1 100644 --- a/swap/tests/alice_punishes_after_restart_bob_dead.rs +++ b/swap/tests/alice_punishes_after_restart_bob_dead.rs @@ -3,6 +3,7 @@ pub mod harness; use harness::alice_run_until::is_xmr_lock_transaction_sent; use harness::bob_run_until::is_btc_locked; use harness::FastPunishConfig; +use swap::protocol::alice::event_loop::FixedRate; use swap::protocol::alice::AliceState; use swap::protocol::bob::BobState; use swap::protocol::{alice, bob}; @@ -19,7 +20,11 @@ async fn alice_punishes_after_restart_if_bob_dead() { let alice_swap = ctx.alice_next_swap().await; let alice_bitcoin_wallet = alice_swap.bitcoin_wallet.clone(); - let alice_swap = tokio::spawn(alice::run_until(alice_swap, is_xmr_lock_transaction_sent)); + let alice_swap = tokio::spawn(alice::run_until( + alice_swap, + is_xmr_lock_transaction_sent, + FixedRate::default(), + )); let bob_state = bob_swap.await??; assert!(matches!(bob_state, BobState::BtcLocked { .. })); @@ -40,7 +45,7 @@ async fn alice_punishes_after_restart_if_bob_dead() { ctx.restart_alice().await; let alice_swap = ctx.alice_next_swap().await; - let alice_swap = tokio::spawn(alice::run(alice_swap)); + let alice_swap = tokio::spawn(alice::run(alice_swap, FixedRate::default())); let alice_state = alice_swap.await??; ctx.assert_alice_punished(alice_state).await; diff --git a/swap/tests/alice_refunds_after_restart_bob_refunded.rs b/swap/tests/alice_refunds_after_restart_bob_refunded.rs index 0c341b7d..2cf12605 100644 --- a/swap/tests/alice_refunds_after_restart_bob_refunded.rs +++ b/swap/tests/alice_refunds_after_restart_bob_refunded.rs @@ -2,6 +2,7 @@ pub mod harness; use harness::alice_run_until::is_xmr_lock_transaction_sent; use harness::FastCancelConfig; +use swap::protocol::alice::event_loop::FixedRate; use swap::protocol::alice::AliceState; use swap::protocol::{alice, bob}; @@ -14,7 +15,11 @@ async fn alice_refunds_after_restart_if_bob_already_refunded() { let bob_swap = tokio::spawn(bob::run(bob_swap)); let alice_swap = ctx.alice_next_swap().await; - let alice_swap = tokio::spawn(alice::run_until(alice_swap, is_xmr_lock_transaction_sent)); + let alice_swap = tokio::spawn(alice::run_until( + alice_swap, + is_xmr_lock_transaction_sent, + FixedRate::default(), + )); let bob_state = bob_swap.await??; ctx.assert_bob_refunded(bob_state).await; @@ -27,7 +32,7 @@ async fn alice_refunds_after_restart_if_bob_already_refunded() { ctx.restart_alice().await; let alice_swap = ctx.alice_next_swap().await; - let alice_swap = tokio::spawn(alice::run(alice_swap)); + let alice_swap = tokio::spawn(alice::run(alice_swap, FixedRate::default())); let alice_state = alice_swap.await??; ctx.assert_alice_refunded(alice_state).await; diff --git a/swap/tests/bob_refunds_using_cancel_and_refund_command_timelock_not_expired.rs b/swap/tests/bob_refunds_using_cancel_and_refund_command_timelock_not_expired.rs new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/swap/tests/bob_refunds_using_cancel_and_refund_command_timelock_not_expired.rs @@ -0,0 +1 @@ + diff --git a/swap/tests/bob_refunds_using_cancel_and_refund_command_timelock_not_expired_force.rs b/swap/tests/bob_refunds_using_cancel_and_refund_command_timelock_not_expired_force.rs new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/swap/tests/bob_refunds_using_cancel_and_refund_command_timelock_not_expired_force.rs @@ -0,0 +1 @@ + diff --git a/swap/tests/concurrent_bobs_after_xmr_lock_proof_sent.rs b/swap/tests/concurrent_bobs_after_xmr_lock_proof_sent.rs index a580a6be..e756fd9e 100644 --- a/swap/tests/concurrent_bobs_after_xmr_lock_proof_sent.rs +++ b/swap/tests/concurrent_bobs_after_xmr_lock_proof_sent.rs @@ -2,6 +2,7 @@ pub mod harness; use harness::bob_run_until::is_xmr_locked; use harness::SlowCancelConfig; +use swap::protocol::alice::event_loop::FixedRate; use swap::protocol::alice::AliceState; use swap::protocol::bob::BobState; use swap::protocol::{alice, bob}; @@ -16,7 +17,7 @@ async fn concurrent_bobs_after_xmr_lock_proof_sent() { let bob_swap_1 = tokio::spawn(bob::run_until(bob_swap_1, is_xmr_locked)); let alice_swap_1 = ctx.alice_next_swap().await; - let alice_swap_1 = tokio::spawn(alice::run(alice_swap_1)); + let alice_swap_1 = tokio::spawn(alice::run(alice_swap_1, FixedRate::default())); let bob_state_1 = bob_swap_1.await??; assert!(matches!(bob_state_1, BobState::XmrLocked { .. })); @@ -28,7 +29,7 @@ async fn concurrent_bobs_after_xmr_lock_proof_sent() { let bob_swap_2 = tokio::spawn(bob::run(bob_swap_2)); let alice_swap_2 = ctx.alice_next_swap().await; - let alice_swap_2 = tokio::spawn(alice::run(alice_swap_2)); + let alice_swap_2 = tokio::spawn(alice::run(alice_swap_2, FixedRate::default())); // The 2nd swap should ALWAYS finish successfully in this // scenario diff --git a/swap/tests/concurrent_bobs_before_xmr_lock_proof_sent.rs b/swap/tests/concurrent_bobs_before_xmr_lock_proof_sent.rs index a15d6cae..420d3cbe 100644 --- a/swap/tests/concurrent_bobs_before_xmr_lock_proof_sent.rs +++ b/swap/tests/concurrent_bobs_before_xmr_lock_proof_sent.rs @@ -2,6 +2,7 @@ pub mod harness; use harness::bob_run_until::is_btc_locked; use harness::SlowCancelConfig; +use swap::protocol::alice::event_loop::FixedRate; use swap::protocol::alice::AliceState; use swap::protocol::bob::BobState; use swap::protocol::{alice, bob}; @@ -16,7 +17,7 @@ async fn concurrent_bobs_before_xmr_lock_proof_sent() { let bob_swap_1 = tokio::spawn(bob::run_until(bob_swap_1, is_btc_locked)); let alice_swap_1 = ctx.alice_next_swap().await; - let alice_swap_1 = tokio::spawn(alice::run(alice_swap_1)); + let alice_swap_1 = tokio::spawn(alice::run(alice_swap_1, FixedRate::default())); let bob_state_1 = bob_swap_1.await??; assert!(matches!(bob_state_1, BobState::BtcLocked(_))); @@ -28,7 +29,7 @@ async fn concurrent_bobs_before_xmr_lock_proof_sent() { let bob_swap_2 = tokio::spawn(bob::run(bob_swap_2)); let alice_swap_2 = ctx.alice_next_swap().await; - let alice_swap_2 = tokio::spawn(alice::run(alice_swap_2)); + let alice_swap_2 = tokio::spawn(alice::run(alice_swap_2, FixedRate::default())); // The 2nd swap ALWAYS finish successfully in this // scenario, but will receive an "unwanted" transfer proof that is ignored in diff --git a/swap/tests/happy_path.rs b/swap/tests/happy_path.rs index 2f50ff14..51e132fa 100644 --- a/swap/tests/happy_path.rs +++ b/swap/tests/happy_path.rs @@ -1,6 +1,7 @@ pub mod harness; use harness::SlowCancelConfig; +use swap::protocol::alice::event_loop::FixedRate; use swap::protocol::{alice, bob}; use tokio::join; @@ -11,7 +12,7 @@ async fn happy_path() { let bob_swap = tokio::spawn(bob::run(bob_swap)); let alice_swap = ctx.alice_next_swap().await; - let alice_swap = tokio::spawn(alice::run(alice_swap)); + let alice_swap = tokio::spawn(alice::run(alice_swap, FixedRate::default())); let (bob_state, alice_state) = join!(bob_swap, alice_swap); diff --git a/swap/tests/happy_path_restart_alice_after_xmr_locked.rs b/swap/tests/happy_path_restart_alice_after_xmr_locked.rs index 97a6f04a..95a68861 100644 --- a/swap/tests/happy_path_restart_alice_after_xmr_locked.rs +++ b/swap/tests/happy_path_restart_alice_after_xmr_locked.rs @@ -2,6 +2,7 @@ pub mod harness; use harness::alice_run_until::is_xmr_lock_transaction_sent; use harness::SlowCancelConfig; +use swap::protocol::alice::event_loop::FixedRate; use swap::protocol::alice::AliceState; use swap::protocol::{alice, bob}; @@ -12,7 +13,11 @@ async fn given_alice_restarts_after_xmr_is_locked_resume_swap() { let bob_swap = tokio::spawn(bob::run(bob_swap)); let alice_swap = ctx.alice_next_swap().await; - let alice_swap = tokio::spawn(alice::run_until(alice_swap, is_xmr_lock_transaction_sent)); + let alice_swap = tokio::spawn(alice::run_until( + alice_swap, + is_xmr_lock_transaction_sent, + FixedRate::default(), + )); let alice_state = alice_swap.await??; @@ -28,7 +33,7 @@ async fn given_alice_restarts_after_xmr_is_locked_resume_swap() { AliceState::XmrLockTransactionSent { .. } )); - let alice_state = alice::run(alice_swap).await?; + let alice_state = alice::run(alice_swap, FixedRate::default()).await?; ctx.assert_alice_redeemed(alice_state).await; let bob_state = bob_swap.await??; diff --git a/swap/tests/happy_path_restart_bob_after_xmr_locked.rs b/swap/tests/happy_path_restart_bob_after_xmr_locked.rs index a07fb2f2..b3a3b1ed 100644 --- a/swap/tests/happy_path_restart_bob_after_xmr_locked.rs +++ b/swap/tests/happy_path_restart_bob_after_xmr_locked.rs @@ -2,6 +2,7 @@ pub mod harness; use harness::bob_run_until::is_xmr_locked; use harness::SlowCancelConfig; +use swap::protocol::alice::event_loop::FixedRate; use swap::protocol::bob::BobState; use swap::protocol::{alice, bob}; @@ -13,7 +14,7 @@ async fn given_bob_restarts_after_xmr_is_locked_resume_swap() { let bob_swap = tokio::spawn(bob::run_until(bob_swap, is_xmr_locked)); let alice_swap = ctx.alice_next_swap().await; - let alice_swap = tokio::spawn(alice::run(alice_swap)); + let alice_swap = tokio::spawn(alice::run(alice_swap, FixedRate::default())); let bob_state = bob_swap.await??; diff --git a/swap/tests/happy_path_restart_bob_before_xmr_locked.rs b/swap/tests/happy_path_restart_bob_before_xmr_locked.rs index a07fb2f2..b3a3b1ed 100644 --- a/swap/tests/happy_path_restart_bob_before_xmr_locked.rs +++ b/swap/tests/happy_path_restart_bob_before_xmr_locked.rs @@ -2,6 +2,7 @@ pub mod harness; use harness::bob_run_until::is_xmr_locked; use harness::SlowCancelConfig; +use swap::protocol::alice::event_loop::FixedRate; use swap::protocol::bob::BobState; use swap::protocol::{alice, bob}; @@ -13,7 +14,7 @@ async fn given_bob_restarts_after_xmr_is_locked_resume_swap() { let bob_swap = tokio::spawn(bob::run_until(bob_swap, is_xmr_locked)); let alice_swap = ctx.alice_next_swap().await; - let alice_swap = tokio::spawn(alice::run(alice_swap)); + let alice_swap = tokio::spawn(alice::run(alice_swap, FixedRate::default())); let bob_state = bob_swap.await??; diff --git a/swap/tests/punish.rs b/swap/tests/punish.rs index ef498d10..61af1f61 100644 --- a/swap/tests/punish.rs +++ b/swap/tests/punish.rs @@ -2,6 +2,7 @@ pub mod harness; use harness::bob_run_until::is_btc_locked; use harness::FastPunishConfig; +use swap::protocol::alice::event_loop::FixedRate; use swap::protocol::bob::BobState; use swap::protocol::{alice, bob}; @@ -15,7 +16,7 @@ async fn alice_punishes_if_bob_never_acts_after_fund() { let bob_swap = tokio::spawn(bob::run_until(bob_swap, is_btc_locked)); let alice_swap = ctx.alice_next_swap().await; - let alice_swap = tokio::spawn(alice::run(alice_swap)); + let alice_swap = tokio::spawn(alice::run(alice_swap, FixedRate::default())); let bob_state = bob_swap.await??; assert!(matches!(bob_state, BobState::BtcLocked { .. }));