2020-10-15 06:53:55 -04:00
|
|
|
pub mod harness;
|
2020-10-12 02:17:22 -04:00
|
|
|
|
|
|
|
use anyhow::Result;
|
2020-10-15 19:49:34 -04:00
|
|
|
use async_trait::async_trait;
|
2020-10-18 19:44:25 -04:00
|
|
|
use futures::{
|
|
|
|
channel::mpsc::{Receiver, Sender},
|
|
|
|
SinkExt, StreamExt,
|
|
|
|
};
|
2020-10-12 02:17:22 -04:00
|
|
|
use genawaiter::GeneratorState;
|
|
|
|
use harness::wallet::{bitcoin, monero};
|
|
|
|
use xmr_btc::{
|
2020-10-18 19:44:25 -04:00
|
|
|
action_generator_alice, action_generator_bob, alice,
|
|
|
|
bitcoin::{BroadcastSignedTransaction, EncryptedSignature, SignTxLock},
|
2020-10-12 02:17:22 -04:00
|
|
|
bob,
|
2020-10-18 19:44:25 -04:00
|
|
|
monero::{CreateWalletForOutput, Transfer, TransferProof},
|
|
|
|
AliceAction, BobAction, ReceiveBitcoinRedeemEncsig, ReceiveTransferProof,
|
2020-10-12 02:17:22 -04:00
|
|
|
};
|
|
|
|
|
2020-10-18 19:44:25 -04:00
|
|
|
type AliceNetwork = Network<EncryptedSignature>;
|
|
|
|
type BobNetwork = Network<TransferProof>;
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
struct Network<RecvMsg> {
|
|
|
|
// TODO: It is weird to use mpsc's in a situation where only one message is expected, but the
|
|
|
|
// ownership rules of Rust are making this painful
|
|
|
|
pub receiver: Receiver<RecvMsg>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[async_trait]
|
|
|
|
impl ReceiveTransferProof for BobNetwork {
|
|
|
|
async fn receive_transfer_proof(&mut self) -> TransferProof {
|
|
|
|
self.receiver.next().await.unwrap()
|
|
|
|
}
|
|
|
|
}
|
2020-10-12 02:17:22 -04:00
|
|
|
|
2020-10-15 19:49:34 -04:00
|
|
|
#[async_trait]
|
2020-10-18 19:44:25 -04:00
|
|
|
impl ReceiveBitcoinRedeemEncsig for AliceNetwork {
|
|
|
|
async fn receive_bitcoin_redeem_encsig(&mut self) -> EncryptedSignature {
|
|
|
|
self.receiver.next().await.unwrap()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn swap_as_alice(
|
|
|
|
network: &'static mut 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>,
|
2020-10-19 21:18:27 -04:00
|
|
|
monero_wallet: &'static monero::Wallet,
|
2020-10-18 19:44:25 -04:00
|
|
|
bitcoin_wallet: &'static bitcoin::Wallet,
|
|
|
|
state: alice::State3,
|
|
|
|
) -> Result<()> {
|
|
|
|
let mut action_generator =
|
|
|
|
action_generator_alice(network, monero_wallet, bitcoin_wallet, state);
|
|
|
|
|
|
|
|
loop {
|
|
|
|
match action_generator.async_resume().await {
|
|
|
|
GeneratorState::Yielded(AliceAction::LockXmr {
|
|
|
|
amount,
|
|
|
|
public_spend_key,
|
|
|
|
public_view_key,
|
|
|
|
}) => {
|
|
|
|
let (transfer_proof, _) = monero_wallet
|
|
|
|
.transfer(public_spend_key, public_view_key, amount)
|
|
|
|
.await?;
|
|
|
|
|
|
|
|
sender.send(transfer_proof).await.unwrap();
|
|
|
|
}
|
|
|
|
GeneratorState::Yielded(AliceAction::RedeemBtc(tx))
|
|
|
|
| GeneratorState::Yielded(AliceAction::CancelBtc(tx))
|
|
|
|
| GeneratorState::Yielded(AliceAction::PunishBtc(tx)) => {
|
|
|
|
let _ = bitcoin_wallet.broadcast_signed_transaction(tx).await?;
|
|
|
|
}
|
|
|
|
GeneratorState::Yielded(AliceAction::CreateMoneroWalletForOutput {
|
|
|
|
spend_key,
|
|
|
|
view_key,
|
|
|
|
}) => {
|
|
|
|
monero_wallet
|
|
|
|
.create_and_load_wallet_for_output(spend_key, view_key)
|
|
|
|
.await?;
|
|
|
|
}
|
|
|
|
GeneratorState::Complete(()) => return Ok(()),
|
|
|
|
}
|
2020-10-12 02:17:22 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn swap_as_bob(
|
2020-10-18 19:44:25 -04:00
|
|
|
network: &'static mut BobNetwork,
|
|
|
|
mut sender: Sender<EncryptedSignature>,
|
2020-10-19 21:18:27 -04:00
|
|
|
monero_wallet: &'static monero::Wallet,
|
2020-10-12 02:17:22 -04:00
|
|
|
bitcoin_wallet: &'static bitcoin::Wallet,
|
|
|
|
state: bob::State2,
|
|
|
|
) -> Result<()> {
|
|
|
|
let mut action_generator = action_generator_bob(network, monero_wallet, bitcoin_wallet, state);
|
|
|
|
|
|
|
|
loop {
|
|
|
|
match action_generator.async_resume().await {
|
2020-10-16 02:04:03 -04:00
|
|
|
GeneratorState::Yielded(BobAction::LockBitcoin(tx_lock)) => {
|
2020-10-12 02:17:22 -04:00
|
|
|
let signed_tx_lock = bitcoin_wallet.sign_tx_lock(tx_lock).await?;
|
|
|
|
let _ = bitcoin_wallet
|
|
|
|
.broadcast_signed_transaction(signed_tx_lock)
|
|
|
|
.await?;
|
|
|
|
}
|
2020-10-18 19:44:25 -04:00
|
|
|
GeneratorState::Yielded(BobAction::SendBitcoinRedeemEncsig(tx_redeem_encsig)) => {
|
|
|
|
sender.send(tx_redeem_encsig).await.unwrap();
|
2020-10-12 02:17:22 -04:00
|
|
|
}
|
2020-10-16 02:04:03 -04:00
|
|
|
GeneratorState::Yielded(BobAction::CreateMoneroWalletForOutput {
|
2020-10-12 02:17:22 -04:00
|
|
|
spend_key,
|
|
|
|
view_key,
|
|
|
|
}) => {
|
|
|
|
monero_wallet
|
|
|
|
.create_and_load_wallet_for_output(spend_key, view_key)
|
|
|
|
.await?;
|
|
|
|
}
|
2020-10-16 02:04:03 -04:00
|
|
|
GeneratorState::Yielded(BobAction::CancelBitcoin(tx_cancel)) => {
|
2020-10-12 02:17:22 -04:00
|
|
|
let _ = bitcoin_wallet
|
|
|
|
.broadcast_signed_transaction(tx_cancel)
|
|
|
|
.await?;
|
2020-10-15 23:06:25 -04:00
|
|
|
}
|
2020-10-16 02:04:03 -04:00
|
|
|
GeneratorState::Yielded(BobAction::RefundBitcoin(tx_refund)) => {
|
2020-10-12 02:17:22 -04:00
|
|
|
let _ = bitcoin_wallet
|
|
|
|
.broadcast_signed_transaction(tx_refund)
|
|
|
|
.await?;
|
|
|
|
}
|
|
|
|
GeneratorState::Complete(()) => return Ok(()),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn on_chain_happy_path() {}
|