From 7aabc8703d4423aac02b4b09b078786e09e9712e Mon Sep 17 00:00:00 2001 From: rishflab Date: Tue, 25 May 2021 10:16:32 +1000 Subject: [PATCH] WIP: cleanup happy path, monero signing broken --- Cargo.lock | 10 +- swap/src/xmr_first_protocol.rs | 2 - swap/src/xmr_first_protocol/alice.rs | 1 - swap/src/xmr_first_protocol/bob.rs | 37 +-- .../transactions/btc_emergency_refund.rs | 109 ------- .../transactions/btc_redeem.rs | 41 ++- .../xmr_first_protocol/transactions/mod.rs | 2 - .../transactions/xmr_refund.rs | 43 --- ...mr_first_bob_fails_to_act_alice_refunds.rs | 130 -------- swap/tests/xmr_first_happy_path.rs | 306 +++++++++--------- 10 files changed, 187 insertions(+), 494 deletions(-) delete mode 100644 swap/src/xmr_first_protocol/transactions/btc_emergency_refund.rs delete mode 100644 swap/src/xmr_first_protocol/transactions/xmr_refund.rs delete mode 100644 swap/tests/xmr_first_bob_fails_to_act_alice_refunds.rs diff --git a/Cargo.lock b/Cargo.lock index 0ea97a7b..c5e88980 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3777,11 +3777,11 @@ dependencies = [ "tracing", "tracing-appender", "tracing-futures", - "tracing-subscriber", - "url 2.2.1", - "uuid", - "void", - "zip", + "tracing-subscriber", + "url 2.2.1", + "uuid", + "void", + "zip", ] [[package]] diff --git a/swap/src/xmr_first_protocol.rs b/swap/src/xmr_first_protocol.rs index 5cbe3f06..da3dada1 100644 --- a/swap/src/xmr_first_protocol.rs +++ b/swap/src/xmr_first_protocol.rs @@ -1,11 +1,9 @@ -use crate::bitcoin::Txid; use crate::protocol::CROSS_CURVE_PROOF_SYSTEM; use curve25519_dalek::constants::ED25519_BASEPOINT_POINT; use curve25519_dalek::edwards::EdwardsPoint; use curve25519_dalek::scalar::Scalar; use ecdsa_fun::fun::Point; use hash_edwards_to_edwards::hash_point_to_point; -use monero_adaptor::AdaptorSignature; use rand::rngs::OsRng; pub mod alice; diff --git a/swap/src/xmr_first_protocol/alice.rs b/swap/src/xmr_first_protocol/alice.rs index 3a69778f..12d9e109 100644 --- a/swap/src/xmr_first_protocol/alice.rs +++ b/swap/src/xmr_first_protocol/alice.rs @@ -6,7 +6,6 @@ use crate::monero::{Scalar, TransferProof, TransferRequest}; use crate::monero_ext::ScalarExt; use crate::xmr_first_protocol::transactions::btc_lock::BtcLock; use crate::xmr_first_protocol::transactions::btc_redeem::BtcRedeem; -use crate::xmr_first_protocol::transactions::xmr_refund::XmrRefund; // start pub struct Alice3 { diff --git a/swap/src/xmr_first_protocol/bob.rs b/swap/src/xmr_first_protocol/bob.rs index ee1c9d5c..a52eacc9 100644 --- a/swap/src/xmr_first_protocol/bob.rs +++ b/swap/src/xmr_first_protocol/bob.rs @@ -1,9 +1,8 @@ -use crate::monero::wallet::{TransferRequest, WatchRequest}; +use crate::monero::wallet::WatchRequest; use crate::monero::TransferProof; use crate::xmr_first_protocol::transactions::btc_lock::BtcLock; use crate::xmr_first_protocol::transactions::btc_redeem::BtcRedeem; use anyhow::Result; -use monero_rpc::wallet::BlockHeight; use uuid::Uuid; // watching for xmr_lock @@ -56,40 +55,6 @@ impl Bob3 { v: self.v, }) } - - pub async fn emergency_refund_if_refund_xmr_seen( - &self, - xmr_wallet: &crate::monero::Wallet, - btc_wallet: &crate::bitcoin::Wallet, - transfer_proof: TransferProof, - ) -> Result { - let req = WatchRequest { - public_spend_key: todo!(), - public_view_key: todo!(), - transfer_proof, - conf_target: 1, - expected: self.xmr_swap_amount, - }; - let _ = xmr_wallet.watch_for_transfer(req).await?; - - let emergency_refund = btc_wallet - .sign_and_finalize(self.tx_lock.clone().into()) - .await?; - - let (_txid, sub) = btc_wallet.broadcast(emergency_refund, "lock").await?; - - let _ = sub.wait_until_confirmed_with(1).await?; - - Ok(Bob4 { - b: self.b.clone(), - A: self.A, - s_b: self.s_b, - S_a_bitcoin: self.S_a_bitcoin, - tx_lock: self.tx_lock.clone(), - alice_redeem_address: self.alice_redeem_address.clone(), - v: self.v, - }) - } } // published btc_lock, watching for btc_redeem diff --git a/swap/src/xmr_first_protocol/transactions/btc_emergency_refund.rs b/swap/src/xmr_first_protocol/transactions/btc_emergency_refund.rs deleted file mode 100644 index 81c8581b..00000000 --- a/swap/src/xmr_first_protocol/transactions/btc_emergency_refund.rs +++ /dev/null @@ -1,109 +0,0 @@ -use crate::bitcoin::wallet::Watchable; -use crate::bitcoin::{ - verify_encsig, verify_sig, Address, EmptyWitnessStack, EncryptedSignature, NoInputs, - NotThreeWitnesses, PublicKey, SecretKey, TooManyInputs, Transaction, -}; -use crate::xmr_first_protocol::transactions::btc_lock::BtcLock; -use crate::xmr_first_protocol::transactions::btc_redeem::BtcRedeem; -use ::bitcoin::util::bip143::SigHashCache; -use ::bitcoin::{SigHash, SigHashType, Txid}; -use anyhow::{bail, Context, Result}; -use bitcoin::Script; -use ecdsa_fun::adaptor::{Adaptor, HashTranscript}; -use ecdsa_fun::fun::Scalar; -use ecdsa_fun::nonce::Deterministic; -use ecdsa_fun::Signature; -use miniscript::{Descriptor, DescriptorTrait}; -use sha2::Sha256; -use std::collections::HashMap; - -#[derive(Clone, Debug)] -pub struct BtcEmergencyRefund { - inner: Transaction, - digest: SigHash, - lock_output_descriptor: Descriptor<::bitcoin::PublicKey>, - watch_script: Script, -} - -impl BtcEmergencyRefund { - pub fn new(tx_redeem: &BtcRedeem, redeem_address: &Address) -> Self { - let tx_refund = tx_redeem.build_take_transaction(redeem_address, None); - - let digest = SigHashCache::new(&tx_refund).signature_hash( - 0, // Only one input: lock_input (lock transaction) - &tx_refund.output_descriptor.script_code(), - tx_refund.lock_amount().as_sat(), - SigHashType::All, - ); - - Self { - inner: tx_refund, - digest, - lock_output_descriptor: tx_refund.output_descriptor.clone(), - watch_script: redeem_address.script_pubkey(), - } - } - - pub fn txid(&self) -> Txid { - self.inner.txid() - } - - pub fn digest(&self) -> SigHash { - self.digest - } - - pub fn complete( - mut self, - a: SecretKey, - s_a: Scalar, - B: PublicKey, - encrypted_signature: EncryptedSignature, - ) -> Result { - verify_encsig( - B, - PublicKey::from(s_a.clone()), - &self.digest(), - &encrypted_signature, - ) - .context("Invalid encrypted signature received")?; - - let sig_a = a.sign(self.digest()); - let adaptor = Adaptor::, Deterministic>::default(); - let sig_b = adaptor.decrypt_signature(&s_a, encrypted_signature); - - let satisfier = { - let mut satisfier = HashMap::with_capacity(2); - - let A = ::bitcoin::PublicKey { - compressed: true, - key: a.public.into(), - }; - let B = ::bitcoin::PublicKey { - compressed: true, - key: B.0.into(), - }; - - // The order in which these are inserted doesn't matter - satisfier.insert(A, (sig_a.into(), ::bitcoin::SigHashType::All)); - satisfier.insert(B, (sig_b.into(), ::bitcoin::SigHashType::All)); - - satisfier - }; - - self.lock_output_descriptor - .satisfy(&mut self.inner.input[0], satisfier) - .context("Failed to sign Bitcoin redeem transaction")?; - - Ok(self.inner) - } -} - -impl Watchable for BtcEmergencyRefund { - fn id(&self) -> Txid { - self.txid() - } - - fn script(&self) -> Script { - self.watch_script.clone() - } -} diff --git a/swap/src/xmr_first_protocol/transactions/btc_redeem.rs b/swap/src/xmr_first_protocol/transactions/btc_redeem.rs index 5f72d899..726a0d00 100644 --- a/swap/src/xmr_first_protocol/transactions/btc_redeem.rs +++ b/swap/src/xmr_first_protocol/transactions/btc_redeem.rs @@ -7,7 +7,7 @@ use crate::xmr_first_protocol::transactions::btc_lock::BtcLock; use ::bitcoin::util::bip143::SigHashCache; use ::bitcoin::{SigHash, SigHashType, Txid}; use anyhow::{bail, Context, Result}; -use bdk::bitcoin::Script; +use bdk::bitcoin::{OutPoint, Script}; use bitcoin::{PrivateKey, TxIn, TxOut}; use ecdsa_fun::adaptor::{Adaptor, HashTranscript}; use ecdsa_fun::fun::Scalar; @@ -50,6 +50,25 @@ impl BtcRedeem { self.inner.txid() } + pub fn as_outpoint(&self) -> OutPoint { + // This is fine because a transaction that has that many outputs is not + // realistic + #[allow(clippy::cast_possible_truncation)] + OutPoint::new(self.txid(), self.lock_output_vout() as u32) + } + + /// Retreive the index of the locked output in the transaction outputs + /// vector + fn lock_output_vout(&self) -> usize { + self.inner + .clone() + .extract_tx() + .output + .iter() + .position(|output| output.script_pubkey == self.output_descriptor.script_pubkey()) + .expect("transaction contains lock output") + } + pub fn digest(&self) -> SigHash { self.digest } @@ -144,16 +163,16 @@ impl BtcRedeem { Ok(sig) } - pub fn build_transaction( - &self, - a: SecretKey, - s_a: Scalar, - B: PublicKey, - encsig: EncryptedSignature, - ) -> Transaction { - let signed_tx_redeem = self.complete(a, s_a, B, encsig)?; - signed_tx_redeem - } + // pub fn build_transaction( + // &self, + // a: SecretKey, + // s_a: Scalar, + // B: PublicKey, + // encsig: EncryptedSignature, + // ) -> Transaction { + // let signed_tx_redeem = self.complete(a, s_a, B, encsig)?; + // signed_tx_redeem + // } pub fn build_take_transaction( &self, diff --git a/swap/src/xmr_first_protocol/transactions/mod.rs b/swap/src/xmr_first_protocol/transactions/mod.rs index f1de8920..bd2124d2 100644 --- a/swap/src/xmr_first_protocol/transactions/mod.rs +++ b/swap/src/xmr_first_protocol/transactions/mod.rs @@ -1,6 +1,4 @@ -pub mod btc_emergency_refund; pub mod btc_lock; pub mod btc_redeem; pub mod xmr_lock; pub mod xmr_redeem; -pub mod xmr_refund; diff --git a/swap/src/xmr_first_protocol/transactions/xmr_refund.rs b/swap/src/xmr_first_protocol/transactions/xmr_refund.rs deleted file mode 100644 index fafa530b..00000000 --- a/swap/src/xmr_first_protocol/transactions/xmr_refund.rs +++ /dev/null @@ -1,43 +0,0 @@ -use crate::monero::wallet::WatchRequest; -use crate::monero::{Amount, PrivateViewKey, Scalar}; -use crate::xmr_first_protocol::alice::Alice4; -use anyhow::Result; -use monero_adaptor::Signature; - -pub struct XmrRefund { - signature: Signature, - amount: Amount, -} - -struct TransferRequest; - -impl XmrRefund { - pub fn new(signature: Signature, amount: Amount) -> Self { - XmrRefund { - signature, - amount: xmr_swap_amount, - } - } - pub fn transfer_request(&self) -> TransferRequest { - todo!(); - TransferRequest - } - // pub fn watch_request(&self) -> WatchRequest { - // let S_a = monero::PublicKey::from_private_key(&monero::PrivateKey { - // scalar: self.s_a }); - // - // let public_spend_key = S_a + self.S_b_monero; - // let public_view_key = self.v_a.public(); - // - // WatchRequest { - // public_spend_key, - // public_view_key, - // transfer_proof: todo!("xfer without broadcasting to get xfer proof"), - // conf_target: 1, - // expected: self.amount, - // } - // } - pub fn extract_r_a(&self) -> Scalar { - self.signature.extract() - } -} diff --git a/swap/tests/xmr_first_bob_fails_to_act_alice_refunds.rs b/swap/tests/xmr_first_bob_fails_to_act_alice_refunds.rs deleted file mode 100644 index a28941eb..00000000 --- a/swap/tests/xmr_first_bob_fails_to_act_alice_refunds.rs +++ /dev/null @@ -1,130 +0,0 @@ -pub mod harness; - -use rand::rngs::OsRng; -use swap::bitcoin::BtcLock; -use swap::env::GetConfig; -use swap::monero; -use swap::monero::TransferRequest; -use swap::protocol::alice::event_loop::FixedRate; -use swap::protocol::CROSS_CURVE_PROOF_SYSTEM; -use swap::seed::Seed; -use swap::xmr_first_protocol::alice::{publish_xmr_refund, Alice3}; -use swap::xmr_first_protocol::bob::Bob3; -use swap::xmr_first_protocol::transactions::btc_lock::BtcLock; -use swap::xmr_first_protocol::transactions::xmr_lock::XmrLock; -use swap::xmr_first_protocol::transactions::xmr_refund::XmrRefund; -use tempfile::tempdir; -use testcontainers::clients::Cli; -use swap::xmr_first_protocol::transactions::btc_redeem::BtcRedeem; -use monero::{PublicKey, PrivateKey}; -use swap::xmr_first_protocol::setup; -use swap::xmr_first_protocol::transactions::xmr_redeem::XmrRedeem; - -#[tokio::test] -async fn refund() { - let cli = Cli::default(); - - let env_config = harness::SlowCancelConfig::get_config(); - - let (monero, containers) = harness::init_containers(&cli).await; - - let btc_swap_amount = bitcoin::Amount::from_sat(1_000_000); - let xmr_swap_amount = - monero::Amount::from_monero(btc_swap_amount.as_btc() / FixedRate::RATE).unwrap(); - - let alice_starting_balances = harness::StartingBalances { - xmr: xmr_swap_amount * 10, - btc: bitcoin::Amount::ZERO, - }; - - let electrs_rpc_port = containers - .electrs - .get_host_port(harness::electrs::RPC_PORT) - .expect("Could not map electrs rpc port"); - - let alice_seed = Seed::random().unwrap(); - let (alice_bitcoin_wallet, alice_monero_wallet) = harness::init_test_wallets( - "Alice", - containers.bitcoind_url.clone(), - &monero, - alice_starting_balances.clone(), - tempdir().unwrap().path(), - electrs_rpc_port, - &alice_seed, - env_config.clone(), - ) - .await; - - let bob_seed = Seed::random().unwrap(); - let bob_starting_balances = harness::StartingBalances { - xmr: monero::Amount::ZERO, - btc: btc_swap_amount * 10, - }; - - let (bob_bitcoin_wallet, bob_monero_wallet) = harness::init_test_wallets( - "Bob", - containers.bitcoind_url, - &monero, - bob_starting_balances.clone(), - tempdir().unwrap().path(), - electrs_rpc_port, - &bob_seed, - env_config, - ) - .await; - - let (alice, bob) = setup(); - - let btc_redeem_address = alice_bitcoin_wallet.new_address().await.unwrap(); - - // transactions - let btc_lock = - BtcLock::new(&bob_bitcoin_wallet, btc_swap_amount, a.public(), b.public()).await?; - let btc_redeem = BtcRedeem::new(&btc_lock, &btc_redeem_address); - let xmr_lock = XmrLock::new(alice.S_a.into(), alice.S_b, alice.v_a, alice.v_b, xmr_swap_amount); - //let xmr_redeem = XmrRedeem::new(s_a, PrivateKey::from_scalar(bob.s_b), alice.v_a, alice.v_b, xmr_swap_amount); - let xmr_refund = XmrRefund::new(sig, xmr_swap_amount); - - // Alice publishes xmr_lock - let xmr_lock_transfer_proof = alice_monero_wallet - .transfer(xmr_lock.transfer_request()) - .await - .unwrap(); - - // Bob waits until xmr_lock is seen - let _ = bob_monero_wallet - .watch_for_transfer(xmr_lock.watch_request(xmr_lock_transfer_proof)) - .await - .unwrap(); - - // Bob publishes btc_lock - let signed_tx_lock = bob_bitcoin_wallet - .sign_and_finalize(btc_lock.clone().into()) - .await?; - let (_txid, sub) = bob_bitcoin_wallet.broadcast(signed_tx_lock, "lock").await.unwrap(); - let _ = sub.wait_until_confirmed_with(1).await?; - - // alice publishes xmr_refund - // let xmr_refund_transfer_proof = alice_monero_wallet - // .transfer(xmr_refund.transfer_request()) - // .await - // .unwrap(); - - // alice publishes btc_redeem - btc_redeem.encsig((), ()); - let (_, btc_redeem_sub) = alice_bitcoin_wallet.broadcast(btc_redeem.build_transaction(alice.a, alice.s_a, alice.pk_b, btc_lock.), "redeem") - .await - .unwrap(); - - // bob sees xmr_refund and btc_redeem - let _ = bob_monero_wallet - .watch_for_transfer(xmr_lock.watch_request(xmr_refund_transfer_proof)) - .await - .unwrap(); - let _ = btc_redeem_sub.wait_until_seen() - .await - .unwrap(); - - // extract r_a from xmr_refund - let _ = bob_bitcoin_wallet.broadcast("redeem") -} diff --git a/swap/tests/xmr_first_happy_path.rs b/swap/tests/xmr_first_happy_path.rs index 78c4e552..416129e4 100644 --- a/swap/tests/xmr_first_happy_path.rs +++ b/swap/tests/xmr_first_happy_path.rs @@ -1,155 +1,151 @@ -// pub mod harness; -// -// use rand::rngs::OsRng; -// use swap::env::GetConfig; -// use swap::monero; -// use swap::protocol::alice::event_loop::FixedRate; -// use swap::protocol::CROSS_CURVE_PROOF_SYSTEM; -// use swap::seed::Seed; -// use swap::xmr_first_protocol::alice::Alice3; -// use swap::xmr_first_protocol::bob::Bob3; -// use swap::xmr_first_protocol::transactions::btc_lock::BtcLock; -// use swap::xmr_first_protocol::transactions::btc_redeem::BtcRedeem; -// use tempfile::tempdir; -// use testcontainers::clients::Cli; -// use uuid::Uuid; -// -// #[tokio::test] -// async fn happy_path() { -// let cli = Cli::default(); -// -// let env_config = harness::SlowCancelConfig::get_config(); -// -// let (monero, containers) = harness::init_containers(&cli).await; -// -// let btc_swap_amount = bitcoin::Amount::from_sat(1_000_000); -// let xmr_swap_amount = -// monero::Amount::from_monero(btc_swap_amount.as_btc() / -// FixedRate::RATE).unwrap(); -// -// let alice_starting_balances = harness::StartingBalances { -// xmr: xmr_swap_amount * 10, -// btc: bitcoin::Amount::ZERO, -// }; -// -// let electrs_rpc_port = containers -// .electrs -// .get_host_port(harness::electrs::RPC_PORT) -// .expect("Could not map electrs rpc port"); -// -// let alice_seed = Seed::random().unwrap(); -// let (alice_bitcoin_wallet, alice_monero_wallet) = -// harness::init_test_wallets( "Alice", -// containers.bitcoind_url.clone(), -// &monero, -// alice_starting_balances.clone(), -// tempdir().unwrap().path(), -// electrs_rpc_port, -// &alice_seed, -// env_config.clone(), -// ) -// .await; -// -// let bob_seed = Seed::random().unwrap(); -// let bob_starting_balances = harness::StartingBalances { -// xmr: monero::Amount::ZERO, -// btc: btc_swap_amount * 10, -// }; -// -// let (bob_bitcoin_wallet, bob_monero_wallet) = harness::init_test_wallets( -// "Bob", -// containers.bitcoind_url, -// &monero, -// bob_starting_balances.clone(), -// tempdir().unwrap().path(), -// electrs_rpc_port, -// &bob_seed, -// env_config, -// ) -// .await; -// -// let a = swap::bitcoin::SecretKey::new_random(&mut OsRng); -// let b = swap::bitcoin::SecretKey::new_random(&mut OsRng); -// -// let s_a = monero::Scalar::random(&mut OsRng); -// let S_a = monero::PublicKey::from_private_key(&monero::PrivateKey { -// scalar: s_a }); -// -// let s_b = monero::Scalar::random(&mut OsRng); -// let S_b = monero::PublicKey::from_private_key(&monero::PrivateKey { -// scalar: s_b }); -// -// let (dleq_proof_s_b, (S_b_bitcoin, S_b_monero)) = -// CROSS_CURVE_PROOF_SYSTEM.prove(&s_b, &mut OsRng); -// -// let (dleq_proof_s_b, (S_a_bitcoin, S_a_monero)) = -// CROSS_CURVE_PROOF_SYSTEM.prove(&s_a, &mut OsRng); -// -// let v_a = monero::PrivateViewKey::new_random(&mut OsRng); -// let v_b = monero::PrivateViewKey::new_random(&mut OsRng); -// -// let btc_redeem_address = bob_bitcoin_wallet.new_address().await.unwrap(); -// -// let tx_lock = BtcLock::new(&bob_bitcoin_wallet, btc_swap_amount, -// a.public(), b.public()) .await -// .unwrap(); -// -// let tx_redeem = BtcRedeem::new(&tx_lock, &btc_redeem_address); -// -// let encsig = tx_redeem.encsig(b.clone(), -// swap::bitcoin::PublicKey::from(S_a_bitcoin)); -// -// let alice = Alice3 { -// xmr_swap_amount, -// btc_swap_amount, -// a: a.clone(), -// B: b.public(), -// s_a, -// S_b_monero: monero::PublicKey { -// point: S_b_monero.compress(), -// }, -// v_a, -// redeem_address: alice_bitcoin_wallet.new_address().await.unwrap(), -// }; -// -// let bob = Bob3 { -// b, -// A: a.public(), -// s_b, -// xmr_swap_amount, -// btc_swap_amount, -// tx_lock, -// S: S_b, -// S_a_bitcoin: swap::bitcoin::PublicKey::from(S_b_bitcoin), -// alice_redeem_address: -// bob_bitcoin_wallet.new_address().await.unwrap(), v: v_b, -// }; -// -// let alice = alice.publish_xmr_lock(&alice_monero_wallet).await.unwrap(); -// -// // also publishes lock btc -// let bob = bob -// .watch_for_lock_xmr( -// &bob_monero_wallet, -// &bob_bitcoin_wallet, -// alice.transfer_proof.clone(), -// btc_redeem_address, -// ) -// .await -// .unwrap(); -// -// let alice = alice -// .watch_for_btc_lock(&alice_bitcoin_wallet) -// .await -// .unwrap(); -// -// let _ = alice -// .publish_btc_redeem(&alice_bitcoin_wallet, encsig) -// .await -// .unwrap(); -// -// let swap_id = Uuid::new_v4(); -// bob.redeem_xmr_when_btc_redeem_seen(&bob_bitcoin_wallet, -// &bob_monero_wallet, swap_id) .await -// .unwrap(); -// } +pub mod harness; + +use rand::rngs::OsRng; +use swap::env::GetConfig; +use swap::monero; +use swap::protocol::alice::event_loop::FixedRate; +use swap::protocol::CROSS_CURVE_PROOF_SYSTEM; +use swap::seed::Seed; +use swap::xmr_first_protocol::alice::Alice3; +use swap::xmr_first_protocol::bob::Bob3; +use swap::xmr_first_protocol::transactions::btc_lock::BtcLock; +use swap::xmr_first_protocol::transactions::btc_redeem::BtcRedeem; +use tempfile::tempdir; +use testcontainers::clients::Cli; +use uuid::Uuid; + +#[tokio::test] +async fn happy_path() { + let cli = Cli::default(); + + let env_config = harness::SlowCancelConfig::get_config(); + + let (monero, containers) = harness::init_containers(&cli).await; + + let btc_swap_amount = bitcoin::Amount::from_sat(1_000_000); + let xmr_swap_amount = + monero::Amount::from_monero(btc_swap_amount.as_btc() / FixedRate::RATE).unwrap(); + + let alice_starting_balances = harness::StartingBalances { + xmr: xmr_swap_amount * 10, + btc: bitcoin::Amount::ZERO, + }; + + let electrs_rpc_port = containers + .electrs + .get_host_port(harness::electrs::RPC_PORT) + .expect("Could not map electrs rpc port"); + + let alice_seed = Seed::random().unwrap(); + let (alice_bitcoin_wallet, alice_monero_wallet) = harness::init_test_wallets( + "Alice", + containers.bitcoind_url.clone(), + &monero, + alice_starting_balances.clone(), + tempdir().unwrap().path(), + electrs_rpc_port, + &alice_seed, + env_config.clone(), + ) + .await; + + let bob_seed = Seed::random().unwrap(); + let bob_starting_balances = harness::StartingBalances { + xmr: monero::Amount::ZERO, + btc: btc_swap_amount * 10, + }; + + let (bob_bitcoin_wallet, bob_monero_wallet) = harness::init_test_wallets( + "Bob", + containers.bitcoind_url, + &monero, + bob_starting_balances.clone(), + tempdir().unwrap().path(), + electrs_rpc_port, + &bob_seed, + env_config, + ) + .await; + + let a = swap::bitcoin::SecretKey::new_random(&mut OsRng); + let b = swap::bitcoin::SecretKey::new_random(&mut OsRng); + + let s_a = monero::Scalar::random(&mut OsRng); + let S_a = monero::PublicKey::from_private_key(&monero::PrivateKey { scalar: s_a }); + + let s_b = monero::Scalar::random(&mut OsRng); + let S_b = monero::PublicKey::from_private_key(&monero::PrivateKey { scalar: s_b }); + + let (dleq_proof_s_b, (S_b_bitcoin, S_b_monero)) = + CROSS_CURVE_PROOF_SYSTEM.prove(&s_b, &mut OsRng); + + let (dleq_proof_s_b, (S_a_bitcoin, S_a_monero)) = + CROSS_CURVE_PROOF_SYSTEM.prove(&s_a, &mut OsRng); + + let v_a = monero::PrivateViewKey::new_random(&mut OsRng); + let v_b = monero::PrivateViewKey::new_random(&mut OsRng); + + let btc_redeem_address = bob_bitcoin_wallet.new_address().await.unwrap(); + + let tx_lock = BtcLock::new(&bob_bitcoin_wallet, btc_swap_amount, a.public(), b.public()) + .await + .unwrap(); + + let tx_redeem = BtcRedeem::new(&tx_lock, &btc_redeem_address); + + let encsig = tx_redeem.encsig(b.clone(), swap::bitcoin::PublicKey::from(S_a_bitcoin)); + + let alice = Alice3 { + xmr_swap_amount, + btc_swap_amount, + a: a.clone(), + B: b.public(), + s_a, + S_b_monero: monero::PublicKey { + point: S_b_monero.compress(), + }, + v_a, + redeem_address: alice_bitcoin_wallet.new_address().await.unwrap(), + }; + + let bob = Bob3 { + b, + A: a.public(), + s_b, + xmr_swap_amount, + btc_swap_amount, + tx_lock, + S: S_b, + S_a_bitcoin: swap::bitcoin::PublicKey::from(S_b_bitcoin), + alice_redeem_address: bob_bitcoin_wallet.new_address().await.unwrap(), + v: v_b, + }; + + let alice = alice.publish_xmr_lock(&alice_monero_wallet).await.unwrap(); + + // also publishes lock btc + let bob = bob + .watch_for_lock_xmr( + &bob_monero_wallet, + &bob_bitcoin_wallet, + alice.transfer_proof.clone(), + btc_redeem_address, + ) + .await + .unwrap(); + + let alice = alice + .watch_for_btc_lock(&alice_bitcoin_wallet) + .await + .unwrap(); + + let _ = alice + .publish_btc_redeem(&alice_bitcoin_wallet, encsig) + .await + .unwrap(); + + let swap_id = Uuid::new_v4(); + bob.redeem_xmr_when_btc_redeem_seen(&bob_bitcoin_wallet, &bob_monero_wallet, swap_id) + .await + .unwrap(); +}