|
|
@ -16,18 +16,20 @@ use monero_harness::Monero;
|
|
|
|
use rand::rngs::OsRng;
|
|
|
|
use rand::rngs::OsRng;
|
|
|
|
use std::{convert::TryInto, sync::Arc};
|
|
|
|
use std::{convert::TryInto, sync::Arc};
|
|
|
|
use testcontainers::clients::Cli;
|
|
|
|
use testcontainers::clients::Cli;
|
|
|
|
|
|
|
|
use tokio::sync::Mutex;
|
|
|
|
use tracing::info;
|
|
|
|
use tracing::info;
|
|
|
|
use xmr_btc::{
|
|
|
|
use xmr_btc::{
|
|
|
|
alice::{self, ReceiveBitcoinRedeemEncsig},
|
|
|
|
alice::{self, ReceiveBitcoinRedeemEncsig},
|
|
|
|
bitcoin::{self, BroadcastSignedTransaction, EncryptedSignature, SignTxLock},
|
|
|
|
bitcoin::{self, BroadcastSignedTransaction, EncryptedSignature, SignTxLock},
|
|
|
|
bob,
|
|
|
|
bob::{self, ReceiveTransferProof},
|
|
|
|
monero::{CreateWalletForOutput, Transfer},
|
|
|
|
monero::{CreateWalletForOutput, Transfer, TransferProof},
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/// Time given to Bob to get the Bitcoin lock transaction included in a block.
|
|
|
|
/// Time given to Bob to get the Bitcoin lock transaction included in a block.
|
|
|
|
const BITCOIN_TX_LOCK_TIMEOUT: u64 = 5;
|
|
|
|
const BITCOIN_TX_LOCK_TIMEOUT: u64 = 5;
|
|
|
|
|
|
|
|
|
|
|
|
type AliceNetwork = Network<EncryptedSignature>;
|
|
|
|
type AliceNetwork = Network<EncryptedSignature>;
|
|
|
|
|
|
|
|
type BobNetwork = Network<TransferProof>;
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
#[derive(Debug)]
|
|
|
|
struct Network<M> {
|
|
|
|
struct Network<M> {
|
|
|
@ -44,6 +46,13 @@ impl<M> Network<M> {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[async_trait]
|
|
|
|
|
|
|
|
impl ReceiveTransferProof for BobNetwork {
|
|
|
|
|
|
|
|
async fn receive_transfer_proof(&mut self) -> TransferProof {
|
|
|
|
|
|
|
|
self.receiver.next().await.unwrap()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[async_trait]
|
|
|
|
#[async_trait]
|
|
|
|
impl ReceiveBitcoinRedeemEncsig for AliceNetwork {
|
|
|
|
impl ReceiveBitcoinRedeemEncsig for AliceNetwork {
|
|
|
|
async fn receive_bitcoin_redeem_encsig(&mut self) -> EncryptedSignature {
|
|
|
|
async fn receive_bitcoin_redeem_encsig(&mut self) -> EncryptedSignature {
|
|
|
@ -92,7 +101,10 @@ impl Default for BobBehaviour {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async fn swap_as_alice(
|
|
|
|
async fn swap_as_alice(
|
|
|
|
network: AliceNetwork,
|
|
|
|
network: Arc<Mutex<AliceNetwork>>,
|
|
|
|
|
|
|
|
// FIXME: It would be more intuitive to have a single network/transport struct instead of
|
|
|
|
|
|
|
|
// splitting into two, but Rust ownership rules make this tedious
|
|
|
|
|
|
|
|
mut sender: Sender<TransferProof>,
|
|
|
|
monero_wallet: Arc<harness::wallet::monero::Wallet>,
|
|
|
|
monero_wallet: Arc<harness::wallet::monero::Wallet>,
|
|
|
|
bitcoin_wallet: Arc<harness::wallet::bitcoin::Wallet>,
|
|
|
|
bitcoin_wallet: Arc<harness::wallet::bitcoin::Wallet>,
|
|
|
|
behaviour: AliceBehaviour,
|
|
|
|
behaviour: AliceBehaviour,
|
|
|
@ -101,7 +113,6 @@ async fn swap_as_alice(
|
|
|
|
let mut action_generator = alice::action_generator(
|
|
|
|
let mut action_generator = alice::action_generator(
|
|
|
|
network,
|
|
|
|
network,
|
|
|
|
bitcoin_wallet.clone(),
|
|
|
|
bitcoin_wallet.clone(),
|
|
|
|
monero_wallet.clone(),
|
|
|
|
|
|
|
|
state,
|
|
|
|
state,
|
|
|
|
BITCOIN_TX_LOCK_TIMEOUT,
|
|
|
|
BITCOIN_TX_LOCK_TIMEOUT,
|
|
|
|
);
|
|
|
|
);
|
|
|
@ -118,9 +129,11 @@ async fn swap_as_alice(
|
|
|
|
public_view_key,
|
|
|
|
public_view_key,
|
|
|
|
}) => {
|
|
|
|
}) => {
|
|
|
|
if behaviour.lock_xmr {
|
|
|
|
if behaviour.lock_xmr {
|
|
|
|
let _ = monero_wallet
|
|
|
|
let (transfer_proof, _) = monero_wallet
|
|
|
|
.transfer(public_spend_key, public_view_key, amount)
|
|
|
|
.transfer(public_spend_key, public_view_key, amount)
|
|
|
|
.await?;
|
|
|
|
.await?;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sender.send(transfer_proof).await?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
GeneratorState::Yielded(alice::Action::RedeemBtc(tx)) => {
|
|
|
|
GeneratorState::Yielded(alice::Action::RedeemBtc(tx)) => {
|
|
|
@ -154,6 +167,7 @@ async fn swap_as_alice(
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async fn swap_as_bob(
|
|
|
|
async fn swap_as_bob(
|
|
|
|
|
|
|
|
network: Arc<Mutex<BobNetwork>>,
|
|
|
|
mut sender: Sender<EncryptedSignature>,
|
|
|
|
mut sender: Sender<EncryptedSignature>,
|
|
|
|
monero_wallet: Arc<harness::wallet::monero::Wallet>,
|
|
|
|
monero_wallet: Arc<harness::wallet::monero::Wallet>,
|
|
|
|
bitcoin_wallet: Arc<harness::wallet::bitcoin::Wallet>,
|
|
|
|
bitcoin_wallet: Arc<harness::wallet::bitcoin::Wallet>,
|
|
|
@ -161,6 +175,7 @@ async fn swap_as_bob(
|
|
|
|
state: bob::State2,
|
|
|
|
state: bob::State2,
|
|
|
|
) -> Result<()> {
|
|
|
|
) -> Result<()> {
|
|
|
|
let mut action_generator = bob::action_generator(
|
|
|
|
let mut action_generator = bob::action_generator(
|
|
|
|
|
|
|
|
network,
|
|
|
|
monero_wallet.clone(),
|
|
|
|
monero_wallet.clone(),
|
|
|
|
bitcoin_wallet.clone(),
|
|
|
|
bitcoin_wallet.clone(),
|
|
|
|
state,
|
|
|
|
state,
|
|
|
@ -218,11 +233,9 @@ async fn swap_as_bob(
|
|
|
|
#[tokio::test]
|
|
|
|
#[tokio::test]
|
|
|
|
async fn on_chain_happy_path() {
|
|
|
|
async fn on_chain_happy_path() {
|
|
|
|
let cli = Cli::default();
|
|
|
|
let cli = Cli::default();
|
|
|
|
let (monero, _container) = Monero::new(&cli, None, vec![
|
|
|
|
let (monero, _container) = Monero::new(&cli, Some("ochp".to_string()), vec![
|
|
|
|
"alice".to_string(),
|
|
|
|
"alice".to_string(),
|
|
|
|
"alice-watch-only".to_string(),
|
|
|
|
|
|
|
|
"bob".to_string(),
|
|
|
|
"bob".to_string(),
|
|
|
|
"bob-watch-only".to_string(),
|
|
|
|
|
|
|
|
])
|
|
|
|
])
|
|
|
|
.await
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
.unwrap();
|
|
|
@ -258,16 +271,19 @@ async fn on_chain_happy_path() {
|
|
|
|
let bob_monero_wallet = Arc::new(bob_node.monero_wallet);
|
|
|
|
let bob_monero_wallet = Arc::new(bob_node.monero_wallet);
|
|
|
|
|
|
|
|
|
|
|
|
let (alice_network, bob_sender) = Network::<EncryptedSignature>::new();
|
|
|
|
let (alice_network, bob_sender) = Network::<EncryptedSignature>::new();
|
|
|
|
|
|
|
|
let (bob_network, alice_sender) = Network::<TransferProof>::new();
|
|
|
|
|
|
|
|
|
|
|
|
try_join(
|
|
|
|
try_join(
|
|
|
|
swap_as_alice(
|
|
|
|
swap_as_alice(
|
|
|
|
alice_network,
|
|
|
|
Arc::new(Mutex::new(alice_network)),
|
|
|
|
|
|
|
|
alice_sender,
|
|
|
|
alice_monero_wallet.clone(),
|
|
|
|
alice_monero_wallet.clone(),
|
|
|
|
alice_bitcoin_wallet.clone(),
|
|
|
|
alice_bitcoin_wallet.clone(),
|
|
|
|
AliceBehaviour::default(),
|
|
|
|
AliceBehaviour::default(),
|
|
|
|
alice,
|
|
|
|
alice,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
swap_as_bob(
|
|
|
|
swap_as_bob(
|
|
|
|
|
|
|
|
Arc::new(Mutex::new(bob_network)),
|
|
|
|
bob_sender,
|
|
|
|
bob_sender,
|
|
|
|
bob_monero_wallet.clone(),
|
|
|
|
bob_monero_wallet.clone(),
|
|
|
|
bob_bitcoin_wallet.clone(),
|
|
|
|
bob_bitcoin_wallet.clone(),
|
|
|
@ -312,11 +328,9 @@ async fn on_chain_happy_path() {
|
|
|
|
#[tokio::test]
|
|
|
|
#[tokio::test]
|
|
|
|
async fn on_chain_both_refund_if_alice_never_redeems() {
|
|
|
|
async fn on_chain_both_refund_if_alice_never_redeems() {
|
|
|
|
let cli = Cli::default();
|
|
|
|
let cli = Cli::default();
|
|
|
|
let (monero, _container) = Monero::new(&cli, None, vec![
|
|
|
|
let (monero, _container) = Monero::new(&cli, Some("ocbr".to_string()), vec![
|
|
|
|
"alice".to_string(),
|
|
|
|
"alice".to_string(),
|
|
|
|
"alice-watch-only".to_string(),
|
|
|
|
|
|
|
|
"bob".to_string(),
|
|
|
|
"bob".to_string(),
|
|
|
|
"bob-watch-only".to_string(),
|
|
|
|
|
|
|
|
])
|
|
|
|
])
|
|
|
|
.await
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
.unwrap();
|
|
|
@ -352,10 +366,12 @@ async fn on_chain_both_refund_if_alice_never_redeems() {
|
|
|
|
let bob_monero_wallet = Arc::new(bob_node.monero_wallet);
|
|
|
|
let bob_monero_wallet = Arc::new(bob_node.monero_wallet);
|
|
|
|
|
|
|
|
|
|
|
|
let (alice_network, bob_sender) = Network::<EncryptedSignature>::new();
|
|
|
|
let (alice_network, bob_sender) = Network::<EncryptedSignature>::new();
|
|
|
|
|
|
|
|
let (bob_network, alice_sender) = Network::<TransferProof>::new();
|
|
|
|
|
|
|
|
|
|
|
|
try_join(
|
|
|
|
try_join(
|
|
|
|
swap_as_alice(
|
|
|
|
swap_as_alice(
|
|
|
|
alice_network,
|
|
|
|
Arc::new(Mutex::new(alice_network)),
|
|
|
|
|
|
|
|
alice_sender,
|
|
|
|
alice_monero_wallet.clone(),
|
|
|
|
alice_monero_wallet.clone(),
|
|
|
|
alice_bitcoin_wallet.clone(),
|
|
|
|
alice_bitcoin_wallet.clone(),
|
|
|
|
AliceBehaviour {
|
|
|
|
AliceBehaviour {
|
|
|
@ -365,6 +381,7 @@ async fn on_chain_both_refund_if_alice_never_redeems() {
|
|
|
|
alice,
|
|
|
|
alice,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
swap_as_bob(
|
|
|
|
swap_as_bob(
|
|
|
|
|
|
|
|
Arc::new(Mutex::new(bob_network)),
|
|
|
|
bob_sender,
|
|
|
|
bob_sender,
|
|
|
|
bob_monero_wallet.clone(),
|
|
|
|
bob_monero_wallet.clone(),
|
|
|
|
bob_bitcoin_wallet.clone(),
|
|
|
|
bob_bitcoin_wallet.clone(),
|
|
|
@ -406,11 +423,9 @@ async fn on_chain_both_refund_if_alice_never_redeems() {
|
|
|
|
#[tokio::test]
|
|
|
|
#[tokio::test]
|
|
|
|
async fn on_chain_alice_punishes_if_bob_never_acts_after_fund() {
|
|
|
|
async fn on_chain_alice_punishes_if_bob_never_acts_after_fund() {
|
|
|
|
let cli = Cli::default();
|
|
|
|
let cli = Cli::default();
|
|
|
|
let (monero, _container) = Monero::new(&cli, None, vec![
|
|
|
|
let (monero, _container) = Monero::new(&cli, Some("ocap".to_string()), vec![
|
|
|
|
"alice".to_string(),
|
|
|
|
"alice".to_string(),
|
|
|
|
"alice-watch-only".to_string(),
|
|
|
|
|
|
|
|
"bob".to_string(),
|
|
|
|
"bob".to_string(),
|
|
|
|
"bob-watch-only".to_string(),
|
|
|
|
|
|
|
|
])
|
|
|
|
])
|
|
|
|
.await
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
.unwrap();
|
|
|
@ -446,15 +461,18 @@ async fn on_chain_alice_punishes_if_bob_never_acts_after_fund() {
|
|
|
|
let bob_monero_wallet = Arc::new(bob_node.monero_wallet);
|
|
|
|
let bob_monero_wallet = Arc::new(bob_node.monero_wallet);
|
|
|
|
|
|
|
|
|
|
|
|
let (alice_network, bob_sender) = Network::<EncryptedSignature>::new();
|
|
|
|
let (alice_network, bob_sender) = Network::<EncryptedSignature>::new();
|
|
|
|
|
|
|
|
let (bob_network, alice_sender) = Network::<TransferProof>::new();
|
|
|
|
|
|
|
|
|
|
|
|
let alice_swap = swap_as_alice(
|
|
|
|
let alice_swap = swap_as_alice(
|
|
|
|
alice_network,
|
|
|
|
Arc::new(Mutex::new(alice_network)),
|
|
|
|
|
|
|
|
alice_sender,
|
|
|
|
alice_monero_wallet.clone(),
|
|
|
|
alice_monero_wallet.clone(),
|
|
|
|
alice_bitcoin_wallet.clone(),
|
|
|
|
alice_bitcoin_wallet.clone(),
|
|
|
|
AliceBehaviour::default(),
|
|
|
|
AliceBehaviour::default(),
|
|
|
|
alice,
|
|
|
|
alice,
|
|
|
|
);
|
|
|
|
);
|
|
|
|
let bob_swap = swap_as_bob(
|
|
|
|
let bob_swap = swap_as_bob(
|
|
|
|
|
|
|
|
Arc::new(Mutex::new(bob_network)),
|
|
|
|
bob_sender,
|
|
|
|
bob_sender,
|
|
|
|
bob_monero_wallet.clone(),
|
|
|
|
bob_monero_wallet.clone(),
|
|
|
|
bob_bitcoin_wallet.clone(),
|
|
|
|
bob_bitcoin_wallet.clone(),
|
|
|
|