mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2025-01-11 15:39:37 -05:00
Configuration for RPC urls and Bitcoin wallet name
This commit is contained in:
parent
9eae0db9ac
commit
802dc61e7e
549
Cargo.lock
generated
549
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -14,10 +14,13 @@ backoff = { git = "https://github.com/ihrwein/backoff", rev = "9d03992a83dfdc596
|
|||||||
base64 = "0.12"
|
base64 = "0.12"
|
||||||
bitcoin = { version = "0.25", features = ["rand", "use-serde"] }
|
bitcoin = { version = "0.25", features = ["rand", "use-serde"] }
|
||||||
bitcoin-harness = { git = "https://github.com/coblox/bitcoin-harness-rs", rev = "ae2f6cd547496e680941c0910018bbe884128799" }
|
bitcoin-harness = { git = "https://github.com/coblox/bitcoin-harness-rs", rev = "ae2f6cd547496e680941c0910018bbe884128799" }
|
||||||
|
config = { version = "0.10", default-features = false, features = ["toml"] }
|
||||||
conquer-once = "0.3"
|
conquer-once = "0.3"
|
||||||
cross-curve-dleq = { git = "https://github.com/comit-network/cross-curve-dleq", rev = "eddcdea1d1f16fa33ef581d1744014ece535c920", features = ["serde"] }
|
cross-curve-dleq = { git = "https://github.com/comit-network/cross-curve-dleq", rev = "eddcdea1d1f16fa33ef581d1744014ece535c920", features = ["serde"] }
|
||||||
curve25519-dalek = "2"
|
curve25519-dalek = "2"
|
||||||
derivative = "2"
|
derivative = "2"
|
||||||
|
dialoguer = "0.7"
|
||||||
|
directories-next = "2"
|
||||||
ecdsa_fun = { git = "https://github.com/LLFourn/secp256kfun", rev = "cdfbc766045ea678a41780919d6228dd5acee3be", features = ["libsecp_compat", "serde"] }
|
ecdsa_fun = { git = "https://github.com/LLFourn/secp256kfun", rev = "cdfbc766045ea678a41780919d6228dd5acee3be", features = ["libsecp_compat", "serde"] }
|
||||||
ed25519-dalek = { version = "1.0.0-pre.4", features = ["serde"] }# Cannot be 1 because they depend on curve25519-dalek version 3
|
ed25519-dalek = { version = "1.0.0-pre.4", features = ["serde"] }# Cannot be 1 because they depend on curve25519-dalek version 3
|
||||||
futures = { version = "0.3", default-features = false }
|
futures = { version = "0.3", default-features = false }
|
||||||
@ -43,12 +46,13 @@ tempfile = "3"
|
|||||||
thiserror = "1"
|
thiserror = "1"
|
||||||
time = "0.2"
|
time = "0.2"
|
||||||
tokio = { version = "1.0", features = ["rt-multi-thread", "time", "macros", "sync"] }
|
tokio = { version = "1.0", features = ["rt-multi-thread", "time", "macros", "sync"] }
|
||||||
|
toml = "0.5"
|
||||||
tracing = { version = "0.1", features = ["attributes"] }
|
tracing = { version = "0.1", features = ["attributes"] }
|
||||||
tracing-core = "0.1"
|
tracing-core = "0.1"
|
||||||
tracing-futures = { version = "0.2", features = ["std-future", "futures-03"] }
|
tracing-futures = { version = "0.2", features = ["std-future", "futures-03"] }
|
||||||
tracing-log = "0.1"
|
tracing-log = "0.1"
|
||||||
tracing-subscriber = { version = "0.2", default-features = false, features = ["fmt", "ansi", "env-filter"] }
|
tracing-subscriber = { version = "0.2", default-features = false, features = ["fmt", "ansi", "env-filter"] }
|
||||||
url = "2.1"
|
url = { version = "2.1", features = ["serde"] }
|
||||||
uuid = { version = "0.8", features = ["serde", "v4"] }
|
uuid = { version = "0.8", features = ["serde", "v4"] }
|
||||||
void = "1"
|
void = "1"
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ pub use ::bitcoin::{util::amount::Amount, Address, Network, Transaction, Txid};
|
|||||||
pub use ecdsa_fun::{adaptor::EncryptedSignature, fun::Scalar, Signature};
|
pub use ecdsa_fun::{adaptor::EncryptedSignature, fun::Scalar, Signature};
|
||||||
pub use wallet::Wallet;
|
pub use wallet::Wallet;
|
||||||
|
|
||||||
use crate::{bitcoin::timelocks::BlockHeight, config::Config};
|
use crate::{bitcoin::timelocks::BlockHeight, config::ExecutionParams};
|
||||||
use ::bitcoin::{
|
use ::bitcoin::{
|
||||||
hashes::{hex::ToHex, Hash},
|
hashes::{hex::ToHex, Hash},
|
||||||
secp256k1,
|
secp256k1,
|
||||||
@ -208,7 +208,11 @@ pub trait WatchForRawTransaction {
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait WaitForTransactionFinality {
|
pub trait WaitForTransactionFinality {
|
||||||
async fn wait_for_transaction_finality(&self, txid: Txid, config: Config) -> Result<()>;
|
async fn wait_for_transaction_finality(
|
||||||
|
&self,
|
||||||
|
txid: Txid,
|
||||||
|
execution_params: ExecutionParams,
|
||||||
|
) -> Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
|
@ -4,7 +4,7 @@ use crate::{
|
|||||||
GetBlockHeight, GetNetwork, GetRawTransaction, SignTxLock, Transaction,
|
GetBlockHeight, GetNetwork, GetRawTransaction, SignTxLock, Transaction,
|
||||||
TransactionBlockHeight, TxLock, WaitForTransactionFinality, WatchForRawTransaction,
|
TransactionBlockHeight, TxLock, WaitForTransactionFinality, WatchForRawTransaction,
|
||||||
},
|
},
|
||||||
config::Config,
|
config::ExecutionParams,
|
||||||
};
|
};
|
||||||
use ::bitcoin::{util::psbt::PartiallySignedTransaction, Txid};
|
use ::bitcoin::{util::psbt::PartiallySignedTransaction, Txid};
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
@ -171,17 +171,21 @@ impl TransactionBlockHeight for Wallet {
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl WaitForTransactionFinality for Wallet {
|
impl WaitForTransactionFinality for Wallet {
|
||||||
async fn wait_for_transaction_finality(&self, txid: Txid, config: Config) -> Result<()> {
|
async fn wait_for_transaction_finality(
|
||||||
|
&self,
|
||||||
|
txid: Txid,
|
||||||
|
execution_params: ExecutionParams,
|
||||||
|
) -> Result<()> {
|
||||||
// TODO(Franck): This assumes that bitcoind runs with txindex=1
|
// TODO(Franck): This assumes that bitcoind runs with txindex=1
|
||||||
|
|
||||||
// Divide by 4 to not check too often yet still be aware of the new block early
|
// Divide by 4 to not check too often yet still be aware of the new block early
|
||||||
// on.
|
// on.
|
||||||
let mut interval = interval(config.bitcoin_avg_block_time / 4);
|
let mut interval = interval(execution_params.bitcoin_avg_block_time / 4);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let tx = self.inner.client.get_raw_transaction_verbose(txid).await?;
|
let tx = self.inner.client.get_raw_transaction_verbose(txid).await?;
|
||||||
if let Some(confirmations) = tx.confirmations {
|
if let Some(confirmations) = tx.confirmations {
|
||||||
if confirmations >= config.bitcoin_finality_confirmations {
|
if confirmations >= execution_params.bitcoin_finality_confirmations {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,16 @@
|
|||||||
use crate::{bitcoin, monero};
|
use crate::{bitcoin, monero};
|
||||||
use libp2p::{core::Multiaddr, PeerId};
|
use libp2p::{core::Multiaddr, PeerId};
|
||||||
use url::Url;
|
use std::path::PathBuf;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
#[derive(structopt::StructOpt, Debug)]
|
#[derive(structopt::StructOpt, Debug)]
|
||||||
pub struct Options {
|
pub struct Options {
|
||||||
// TODO: Default value should points to proper configuration folder in home folder
|
#[structopt(
|
||||||
#[structopt(long = "data-dir", default_value = "./.swap-data/")]
|
long = "data-dir",
|
||||||
pub data_dir: String,
|
help = "Provide a custom path to the data directory.",
|
||||||
|
parse(from_os_str)
|
||||||
|
)]
|
||||||
|
pub data_dir: Option<PathBuf>,
|
||||||
|
|
||||||
#[structopt(subcommand)]
|
#[structopt(subcommand)]
|
||||||
pub cmd: Command,
|
pub cmd: Command,
|
||||||
@ -17,18 +20,6 @@ pub struct Options {
|
|||||||
#[structopt(name = "xmr_btc-swap", about = "XMR BTC atomic swap")]
|
#[structopt(name = "xmr_btc-swap", about = "XMR BTC atomic swap")]
|
||||||
pub enum Command {
|
pub enum Command {
|
||||||
SellXmr {
|
SellXmr {
|
||||||
#[structopt(long = "bitcoind-rpc", default_value = "http://127.0.0.1:8332")]
|
|
||||||
bitcoind_url: Url,
|
|
||||||
|
|
||||||
#[structopt(long = "bitcoin-wallet-name")]
|
|
||||||
bitcoin_wallet_name: String,
|
|
||||||
|
|
||||||
#[structopt(
|
|
||||||
long = "monero-wallet-rpc",
|
|
||||||
default_value = "http://127.0.0.1:18083/json_rpc"
|
|
||||||
)]
|
|
||||||
monero_wallet_rpc_url: Url,
|
|
||||||
|
|
||||||
#[structopt(long = "p2p-address", default_value = "/ip4/0.0.0.0/tcp/9876")]
|
#[structopt(long = "p2p-address", default_value = "/ip4/0.0.0.0/tcp/9876")]
|
||||||
listen_addr: Multiaddr,
|
listen_addr: Multiaddr,
|
||||||
|
|
||||||
@ -37,6 +28,9 @@ pub enum Command {
|
|||||||
|
|
||||||
#[structopt(long = "receive-btc", help = "Bitcoin amount as floating point nr without denomination (e.g. 1.25)", parse(try_from_str = parse_btc))]
|
#[structopt(long = "receive-btc", help = "Bitcoin amount as floating point nr without denomination (e.g. 1.25)", parse(try_from_str = parse_btc))]
|
||||||
receive_bitcoin: bitcoin::Amount,
|
receive_bitcoin: bitcoin::Amount,
|
||||||
|
|
||||||
|
#[structopt(flatten)]
|
||||||
|
config: Config,
|
||||||
},
|
},
|
||||||
BuyXmr {
|
BuyXmr {
|
||||||
#[structopt(long = "connect-peer-id")]
|
#[structopt(long = "connect-peer-id")]
|
||||||
@ -45,23 +39,14 @@ pub enum Command {
|
|||||||
#[structopt(long = "connect-addr")]
|
#[structopt(long = "connect-addr")]
|
||||||
alice_addr: Multiaddr,
|
alice_addr: Multiaddr,
|
||||||
|
|
||||||
#[structopt(long = "bitcoind-rpc", default_value = "http://127.0.0.1:8332")]
|
|
||||||
bitcoind_url: Url,
|
|
||||||
|
|
||||||
#[structopt(long = "bitcoin-wallet-name")]
|
|
||||||
bitcoin_wallet_name: String,
|
|
||||||
|
|
||||||
#[structopt(
|
|
||||||
long = "monero-wallet-rpc",
|
|
||||||
default_value = "http://127.0.0.1:18083/json_rpc"
|
|
||||||
)]
|
|
||||||
monero_wallet_rpc_url: Url,
|
|
||||||
|
|
||||||
#[structopt(long = "send-btc", help = "Bitcoin amount as floating point nr without denomination (e.g. 1.25)", parse(try_from_str = parse_btc))]
|
#[structopt(long = "send-btc", help = "Bitcoin amount as floating point nr without denomination (e.g. 1.25)", parse(try_from_str = parse_btc))]
|
||||||
send_bitcoin: bitcoin::Amount,
|
send_bitcoin: bitcoin::Amount,
|
||||||
|
|
||||||
#[structopt(long = "receive-xmr", help = "Monero amount as floating point nr without denomination (e.g. 125.1)", parse(try_from_str = parse_xmr))]
|
#[structopt(long = "receive-xmr", help = "Monero amount as floating point nr without denomination (e.g. 125.1)", parse(try_from_str = parse_xmr))]
|
||||||
receive_monero: monero::Amount,
|
receive_monero: monero::Amount,
|
||||||
|
|
||||||
|
#[structopt(flatten)]
|
||||||
|
config: Config,
|
||||||
},
|
},
|
||||||
History,
|
History,
|
||||||
Resume(Resume),
|
Resume(Resume),
|
||||||
@ -73,20 +58,11 @@ pub enum Resume {
|
|||||||
#[structopt(long = "swap-id")]
|
#[structopt(long = "swap-id")]
|
||||||
swap_id: Uuid,
|
swap_id: Uuid,
|
||||||
|
|
||||||
#[structopt(long = "bitcoind-rpc", default_value = "http://127.0.0.1:8332")]
|
|
||||||
bitcoind_url: Url,
|
|
||||||
|
|
||||||
#[structopt(long = "bitcoin-wallet-name")]
|
|
||||||
bitcoin_wallet_name: String,
|
|
||||||
|
|
||||||
#[structopt(
|
|
||||||
long = "monero-wallet-rpc",
|
|
||||||
default_value = "http://127.0.0.1:18083/json_rpc"
|
|
||||||
)]
|
|
||||||
monero_wallet_rpc_url: Url,
|
|
||||||
|
|
||||||
#[structopt(long = "listen-address", default_value = "/ip4/127.0.0.1/tcp/9876")]
|
#[structopt(long = "listen-address", default_value = "/ip4/127.0.0.1/tcp/9876")]
|
||||||
listen_addr: Multiaddr,
|
listen_addr: Multiaddr,
|
||||||
|
|
||||||
|
#[structopt(flatten)]
|
||||||
|
config: Config,
|
||||||
},
|
},
|
||||||
BuyXmr {
|
BuyXmr {
|
||||||
#[structopt(long = "swap-id")]
|
#[structopt(long = "swap-id")]
|
||||||
@ -98,20 +74,21 @@ pub enum Resume {
|
|||||||
#[structopt(long = "counterpart-addr")]
|
#[structopt(long = "counterpart-addr")]
|
||||||
alice_addr: Multiaddr,
|
alice_addr: Multiaddr,
|
||||||
|
|
||||||
#[structopt(long = "bitcoind-rpc", default_value = "http://127.0.0.1:8332")]
|
#[structopt(flatten)]
|
||||||
bitcoind_url: Url,
|
config: Config,
|
||||||
|
|
||||||
#[structopt(long = "bitcoin-wallet-name")]
|
|
||||||
bitcoin_wallet_name: String,
|
|
||||||
|
|
||||||
#[structopt(
|
|
||||||
long = "monero-wallet-rpc",
|
|
||||||
default_value = "http://127.0.0.1:18083/json_rpc"
|
|
||||||
)]
|
|
||||||
monero_wallet_rpc_url: Url,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(structopt::StructOpt, Debug)]
|
||||||
|
pub struct Config {
|
||||||
|
#[structopt(
|
||||||
|
long = "config",
|
||||||
|
help = "Provide a custom path to the configuration file. The configuration file must be a toml file.",
|
||||||
|
parse(from_os_str)
|
||||||
|
)]
|
||||||
|
pub path: Option<PathBuf>,
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_btc(str: &str) -> anyhow::Result<bitcoin::Amount> {
|
fn parse_btc(str: &str) -> anyhow::Result<bitcoin::Amount> {
|
||||||
let amount = bitcoin::Amount::from_str_in(str, ::bitcoin::Denomination::Bitcoin)?;
|
let amount = bitcoin::Amount::from_str_in(str, ::bitcoin::Denomination::Bitcoin)?;
|
||||||
Ok(amount)
|
Ok(amount)
|
||||||
|
@ -1,23 +1,19 @@
|
|||||||
pub mod seed;
|
|
||||||
|
|
||||||
use crate::bitcoin::Timelock;
|
use crate::bitcoin::Timelock;
|
||||||
use conquer_once::Lazy;
|
use conquer_once::Lazy;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct Config {
|
pub struct ExecutionParams {
|
||||||
pub bob_time_to_act: Duration,
|
pub bob_time_to_act: Duration,
|
||||||
pub bitcoin_finality_confirmations: u32,
|
pub bitcoin_finality_confirmations: u32,
|
||||||
pub bitcoin_avg_block_time: Duration,
|
pub bitcoin_avg_block_time: Duration,
|
||||||
pub monero_finality_confirmations: u32,
|
pub monero_finality_confirmations: u32,
|
||||||
pub bitcoin_cancel_timelock: Timelock,
|
pub bitcoin_cancel_timelock: Timelock,
|
||||||
pub bitcoin_punish_timelock: Timelock,
|
pub bitcoin_punish_timelock: Timelock,
|
||||||
pub bitcoin_network: bitcoin::Network,
|
|
||||||
pub monero_network: monero::Network,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait GetConfig {
|
pub trait GetExecutionParams {
|
||||||
fn get_config() -> Config;
|
fn get_execution_params() -> ExecutionParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
@ -29,53 +25,47 @@ pub struct Testnet;
|
|||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct Regtest;
|
pub struct Regtest;
|
||||||
|
|
||||||
impl GetConfig for Mainnet {
|
impl GetExecutionParams for Mainnet {
|
||||||
fn get_config() -> Config {
|
fn get_execution_params() -> ExecutionParams {
|
||||||
Config {
|
ExecutionParams {
|
||||||
bob_time_to_act: *mainnet::BOB_TIME_TO_ACT,
|
bob_time_to_act: *mainnet::BOB_TIME_TO_ACT,
|
||||||
bitcoin_finality_confirmations: mainnet::BITCOIN_FINALITY_CONFIRMATIONS,
|
bitcoin_finality_confirmations: mainnet::BITCOIN_FINALITY_CONFIRMATIONS,
|
||||||
bitcoin_avg_block_time: *mainnet::BITCOIN_AVG_BLOCK_TIME,
|
bitcoin_avg_block_time: *mainnet::BITCOIN_AVG_BLOCK_TIME,
|
||||||
monero_finality_confirmations: mainnet::MONERO_FINALITY_CONFIRMATIONS,
|
monero_finality_confirmations: mainnet::MONERO_FINALITY_CONFIRMATIONS,
|
||||||
bitcoin_cancel_timelock: mainnet::BITCOIN_CANCEL_TIMELOCK,
|
bitcoin_cancel_timelock: mainnet::BITCOIN_CANCEL_TIMELOCK,
|
||||||
bitcoin_punish_timelock: mainnet::BITCOIN_PUNISH_TIMELOCK,
|
bitcoin_punish_timelock: mainnet::BITCOIN_PUNISH_TIMELOCK,
|
||||||
bitcoin_network: bitcoin::Network::Bitcoin,
|
|
||||||
monero_network: monero::Network::Mainnet,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GetConfig for Testnet {
|
impl GetExecutionParams for Testnet {
|
||||||
fn get_config() -> Config {
|
fn get_execution_params() -> ExecutionParams {
|
||||||
Config {
|
ExecutionParams {
|
||||||
bob_time_to_act: *testnet::BOB_TIME_TO_ACT,
|
bob_time_to_act: *testnet::BOB_TIME_TO_ACT,
|
||||||
bitcoin_finality_confirmations: testnet::BITCOIN_FINALITY_CONFIRMATIONS,
|
bitcoin_finality_confirmations: testnet::BITCOIN_FINALITY_CONFIRMATIONS,
|
||||||
bitcoin_avg_block_time: *testnet::BITCOIN_AVG_BLOCK_TIME,
|
bitcoin_avg_block_time: *testnet::BITCOIN_AVG_BLOCK_TIME,
|
||||||
monero_finality_confirmations: testnet::MONERO_FINALITY_CONFIRMATIONS,
|
monero_finality_confirmations: testnet::MONERO_FINALITY_CONFIRMATIONS,
|
||||||
bitcoin_cancel_timelock: testnet::BITCOIN_CANCEL_TIMELOCK,
|
bitcoin_cancel_timelock: testnet::BITCOIN_CANCEL_TIMELOCK,
|
||||||
bitcoin_punish_timelock: testnet::BITCOIN_PUNISH_TIMELOCK,
|
bitcoin_punish_timelock: testnet::BITCOIN_PUNISH_TIMELOCK,
|
||||||
bitcoin_network: bitcoin::Network::Testnet,
|
|
||||||
monero_network: monero::Network::Stagenet,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GetConfig for Regtest {
|
impl GetExecutionParams for Regtest {
|
||||||
fn get_config() -> Config {
|
fn get_execution_params() -> ExecutionParams {
|
||||||
Config {
|
ExecutionParams {
|
||||||
bob_time_to_act: *regtest::BOB_TIME_TO_ACT,
|
bob_time_to_act: *regtest::BOB_TIME_TO_ACT,
|
||||||
bitcoin_finality_confirmations: regtest::BITCOIN_FINALITY_CONFIRMATIONS,
|
bitcoin_finality_confirmations: regtest::BITCOIN_FINALITY_CONFIRMATIONS,
|
||||||
bitcoin_avg_block_time: *regtest::BITCOIN_AVG_BLOCK_TIME,
|
bitcoin_avg_block_time: *regtest::BITCOIN_AVG_BLOCK_TIME,
|
||||||
monero_finality_confirmations: regtest::MONERO_FINALITY_CONFIRMATIONS,
|
monero_finality_confirmations: regtest::MONERO_FINALITY_CONFIRMATIONS,
|
||||||
bitcoin_cancel_timelock: regtest::BITCOIN_CANCEL_TIMELOCK,
|
bitcoin_cancel_timelock: regtest::BITCOIN_CANCEL_TIMELOCK,
|
||||||
bitcoin_punish_timelock: regtest::BITCOIN_PUNISH_TIMELOCK,
|
bitcoin_punish_timelock: regtest::BITCOIN_PUNISH_TIMELOCK,
|
||||||
bitcoin_network: bitcoin::Network::Regtest,
|
|
||||||
monero_network: monero::Network::default(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mod mainnet {
|
mod mainnet {
|
||||||
use super::*;
|
use crate::config::*;
|
||||||
|
|
||||||
// For each step, we are giving Bob 10 minutes to act.
|
// For each step, we are giving Bob 10 minutes to act.
|
||||||
pub static BOB_TIME_TO_ACT: Lazy<Duration> = Lazy::new(|| Duration::from_secs(10 * 60));
|
pub static BOB_TIME_TO_ACT: Lazy<Duration> = Lazy::new(|| Duration::from_secs(10 * 60));
|
||||||
@ -92,7 +82,7 @@ mod mainnet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mod testnet {
|
mod testnet {
|
||||||
use super::*;
|
use crate::config::*;
|
||||||
|
|
||||||
pub static BOB_TIME_TO_ACT: Lazy<Duration> = Lazy::new(|| Duration::from_secs(60 * 60));
|
pub static BOB_TIME_TO_ACT: Lazy<Duration> = Lazy::new(|| Duration::from_secs(60 * 60));
|
||||||
|
|
||||||
@ -110,7 +100,7 @@ mod testnet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mod regtest {
|
mod regtest {
|
||||||
use super::*;
|
use crate::config::*;
|
||||||
|
|
||||||
// In test, we set a shorter time to fail fast
|
// In test, we set a shorter time to fail fast
|
||||||
pub static BOB_TIME_TO_ACT: Lazy<Duration> = Lazy::new(|| Duration::from_secs(30));
|
pub static BOB_TIME_TO_ACT: Lazy<Duration> = Lazy::new(|| Duration::from_secs(30));
|
||||||
|
145
swap/src/configuration.rs
Normal file
145
swap/src/configuration.rs
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
use crate::fs::ensure_directory_exists;
|
||||||
|
use anyhow::{Context, Result};
|
||||||
|
use config::{Config, ConfigError};
|
||||||
|
use dialoguer::{theme::ColorfulTheme, Input};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::{
|
||||||
|
ffi::OsStr,
|
||||||
|
fs,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
};
|
||||||
|
use tracing::info;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
|
pub mod seed;
|
||||||
|
|
||||||
|
const DEFAULT_BITCOIND_TESTNET_URL: &str = "http://127.0.0.1:18332";
|
||||||
|
const DEFAULT_MONERO_WALLET_RPC_TESTNET_URL: &str = "http://127.0.0.1:38083/json_rpc";
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, PartialEq)]
|
||||||
|
pub struct File {
|
||||||
|
pub bitcoin: Bitcoin,
|
||||||
|
pub monero: Monero,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl File {
|
||||||
|
pub fn read<D>(config_file: D) -> Result<Self, ConfigError>
|
||||||
|
where
|
||||||
|
D: AsRef<OsStr>,
|
||||||
|
{
|
||||||
|
let config_file = Path::new(&config_file);
|
||||||
|
|
||||||
|
let mut config = Config::new();
|
||||||
|
config.merge(config::File::from(config_file))?;
|
||||||
|
config.try_into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
pub struct Bitcoin {
|
||||||
|
pub bitcoind_url: Url,
|
||||||
|
pub wallet_name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
pub struct Monero {
|
||||||
|
pub wallet_rpc_url: Url,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(thiserror::Error, Debug, Clone, Copy)]
|
||||||
|
#[error("config not initialized")]
|
||||||
|
pub struct ConfigNotInitialized {}
|
||||||
|
|
||||||
|
pub fn read_config(config_path: PathBuf) -> Result<Result<File, ConfigNotInitialized>> {
|
||||||
|
if config_path.exists() {
|
||||||
|
info!(
|
||||||
|
"Using config file at default path: {}",
|
||||||
|
config_path.display()
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return Ok(Err(ConfigNotInitialized {}));
|
||||||
|
}
|
||||||
|
|
||||||
|
let file = File::read(&config_path)
|
||||||
|
.with_context(|| format!("failed to read config file {}", config_path.display()))?;
|
||||||
|
|
||||||
|
Ok(Ok(file))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn initial_setup<F>(config_path: PathBuf, config_file: F) -> Result<()>
|
||||||
|
where
|
||||||
|
F: Fn() -> Result<File>,
|
||||||
|
{
|
||||||
|
info!("Config file not found, running initial setup...");
|
||||||
|
ensure_directory_exists(config_path.as_path())?;
|
||||||
|
let initial_config = config_file()?;
|
||||||
|
|
||||||
|
let toml = toml::to_string(&initial_config)?;
|
||||||
|
fs::write(&config_path, toml)?;
|
||||||
|
|
||||||
|
info!(
|
||||||
|
"Initial setup complete, config file created at {} ",
|
||||||
|
config_path.as_path().display()
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn query_user_for_initial_testnet_config() -> Result<File> {
|
||||||
|
println!();
|
||||||
|
let bitcoind_url: String = Input::with_theme(&ColorfulTheme::default())
|
||||||
|
.with_prompt("Enter Bitcoind URL (including username and password if applicable) or hit return to use default")
|
||||||
|
.default(DEFAULT_BITCOIND_TESTNET_URL.to_owned())
|
||||||
|
.interact_text()?;
|
||||||
|
let bitcoind_url = Url::parse(bitcoind_url.as_str())?;
|
||||||
|
|
||||||
|
let bitcoin_wallet_name: String = Input::with_theme(&ColorfulTheme::default())
|
||||||
|
.with_prompt("Enter Bitcoind wallet name")
|
||||||
|
.interact_text()?;
|
||||||
|
|
||||||
|
let monero_wallet_rpc_url: String = Input::with_theme(&ColorfulTheme::default())
|
||||||
|
.with_prompt("Enter Monero Wallet RPC URL or hit enter to use default")
|
||||||
|
.default(DEFAULT_MONERO_WALLET_RPC_TESTNET_URL.to_owned())
|
||||||
|
.interact_text()?;
|
||||||
|
let monero_wallet_rpc_url = Url::parse(monero_wallet_rpc_url.as_str())?;
|
||||||
|
println!();
|
||||||
|
|
||||||
|
Ok(File {
|
||||||
|
bitcoin: Bitcoin {
|
||||||
|
bitcoind_url,
|
||||||
|
wallet_name: bitcoin_wallet_name,
|
||||||
|
},
|
||||||
|
monero: Monero {
|
||||||
|
wallet_rpc_url: monero_wallet_rpc_url,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use std::str::FromStr;
|
||||||
|
use tempfile::tempdir;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn config_roundtrip() {
|
||||||
|
let temp_dir = tempdir().unwrap().path().to_path_buf();
|
||||||
|
let config_path = Path::join(&temp_dir, "config.toml");
|
||||||
|
|
||||||
|
let expected = File {
|
||||||
|
bitcoin: Bitcoin {
|
||||||
|
bitcoind_url: Url::from_str("http://127.0.0.1:18332").unwrap(),
|
||||||
|
wallet_name: "alice".to_string(),
|
||||||
|
},
|
||||||
|
monero: Monero {
|
||||||
|
wallet_rpc_url: Url::from_str("http://127.0.0.1:38083/json_rpc").unwrap(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
initial_setup(config_path.clone(), || Ok(expected.clone())).unwrap();
|
||||||
|
let actual = read_config(config_path).unwrap().unwrap();
|
||||||
|
|
||||||
|
assert_eq!(expected, actual);
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,26 @@
|
|||||||
use std::path::Path;
|
use anyhow::Context;
|
||||||
|
use directories_next::ProjectDirs;
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
/// This is to store the configuration and seed files
|
||||||
|
// Linux: /home/<user>/.config/xmr-btc-swap/
|
||||||
|
// OSX: /Users/<user>/Library/Preferences/xmr-btc-swap/
|
||||||
|
fn default_config_dir() -> Option<PathBuf> {
|
||||||
|
ProjectDirs::from("", "", "xmr-btc-swap").map(|proj_dirs| proj_dirs.config_dir().to_path_buf())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn default_config_path() -> anyhow::Result<PathBuf> {
|
||||||
|
default_config_dir()
|
||||||
|
.map(|dir| Path::join(&dir, "config.toml"))
|
||||||
|
.context("Could not generate default configuration path")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This is to store the DB
|
||||||
|
// Linux: /home/<user>/.local/share/nectar/
|
||||||
|
// OSX: /Users/<user>/Library/Application Support/nectar/
|
||||||
|
pub fn default_data_dir() -> Option<std::path::PathBuf> {
|
||||||
|
ProjectDirs::from("", "", "nectar").map(|proj_dirs| proj_dirs.data_dir().to_path_buf())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn ensure_directory_exists(file: &Path) -> Result<(), std::io::Error> {
|
pub fn ensure_directory_exists(file: &Path) -> Result<(), std::io::Error> {
|
||||||
if let Some(path) = file.parent() {
|
if let Some(path) = file.parent() {
|
||||||
|
@ -25,5 +25,4 @@ pub mod protocol;
|
|||||||
pub mod seed;
|
pub mod seed;
|
||||||
pub mod trace;
|
pub mod trace;
|
||||||
|
|
||||||
mod fs;
|
|
||||||
mod serde_peer_id;
|
mod serde_peer_id;
|
||||||
|
125
swap/src/main.rs
125
swap/src/main.rs
@ -12,14 +12,20 @@
|
|||||||
#![forbid(unsafe_code)]
|
#![forbid(unsafe_code)]
|
||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
use crate::cli::{Command, Options, Resume};
|
use crate::{
|
||||||
|
cli::{Command, Options, Resume},
|
||||||
|
config::GetExecutionParams,
|
||||||
|
configuration::{
|
||||||
|
initial_setup, query_user_for_initial_testnet_config, read_config, ConfigNotInitialized,
|
||||||
|
},
|
||||||
|
};
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use config::{Config, GetConfig};
|
|
||||||
use database::Database;
|
use database::Database;
|
||||||
|
use fs::{default_config_path, default_data_dir};
|
||||||
use log::LevelFilter;
|
use log::LevelFilter;
|
||||||
use prettytable::{row, Table};
|
use prettytable::{row, Table};
|
||||||
use protocol::{alice, bob, bob::Builder, SwapAmounts};
|
use protocol::{alice, bob, bob::Builder, SwapAmounts};
|
||||||
use std::sync::Arc;
|
use std::{path::PathBuf, sync::Arc};
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
use trace::init_tracing;
|
use trace::init_tracing;
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
@ -27,6 +33,7 @@ use uuid::Uuid;
|
|||||||
|
|
||||||
pub mod bitcoin;
|
pub mod bitcoin;
|
||||||
pub mod config;
|
pub mod config;
|
||||||
|
pub mod configuration;
|
||||||
pub mod database;
|
pub mod database;
|
||||||
pub mod monero;
|
pub mod monero;
|
||||||
pub mod network;
|
pub mod network;
|
||||||
@ -46,40 +53,42 @@ async fn main() -> Result<()> {
|
|||||||
init_tracing(LevelFilter::Info).expect("initialize tracing");
|
init_tracing(LevelFilter::Info).expect("initialize tracing");
|
||||||
|
|
||||||
let opt = Options::from_args();
|
let opt = Options::from_args();
|
||||||
let config = config::Testnet::get_config();
|
|
||||||
|
let data_dir = if let Some(data_dir) = opt.data_dir {
|
||||||
|
data_dir
|
||||||
|
} else {
|
||||||
|
default_data_dir().context("unable to determine default data path")?
|
||||||
|
};
|
||||||
|
|
||||||
info!(
|
info!(
|
||||||
"Database and Seed will be stored in directory: {}",
|
"Database and Seed will be stored in directory: {}",
|
||||||
opt.data_dir
|
data_dir.display()
|
||||||
);
|
);
|
||||||
let data_dir = std::path::Path::new(opt.data_dir.as_str()).to_path_buf();
|
|
||||||
let db_path = data_dir.join("database");
|
|
||||||
|
|
||||||
let seed = config::seed::Seed::from_file_or_generate(&data_dir)
|
let db_path = data_dir.join("database");
|
||||||
|
let seed = configuration::seed::Seed::from_file_or_generate(&data_dir)
|
||||||
.expect("Could not retrieve/initialize seed")
|
.expect("Could not retrieve/initialize seed")
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
|
// hardcode to testnet/stagenet
|
||||||
|
let bitcoin_network = bitcoin::Network::Testnet;
|
||||||
|
let monero_network = monero::Network::Stagenet;
|
||||||
|
let execution_params = config::Testnet::get_execution_params();
|
||||||
|
|
||||||
match opt.cmd {
|
match opt.cmd {
|
||||||
Command::SellXmr {
|
Command::SellXmr {
|
||||||
bitcoind_url,
|
|
||||||
bitcoin_wallet_name,
|
|
||||||
monero_wallet_rpc_url,
|
|
||||||
listen_addr,
|
listen_addr,
|
||||||
send_monero,
|
send_monero,
|
||||||
receive_bitcoin,
|
receive_bitcoin,
|
||||||
|
config,
|
||||||
} => {
|
} => {
|
||||||
let swap_amounts = SwapAmounts {
|
let swap_amounts = SwapAmounts {
|
||||||
xmr: send_monero,
|
xmr: send_monero,
|
||||||
btc: receive_bitcoin,
|
btc: receive_bitcoin,
|
||||||
};
|
};
|
||||||
|
|
||||||
let (bitcoin_wallet, monero_wallet) = setup_wallets(
|
let (bitcoin_wallet, monero_wallet) =
|
||||||
bitcoind_url,
|
init_wallets(config.path, bitcoin_network, monero_network).await?;
|
||||||
bitcoin_wallet_name.as_str(),
|
|
||||||
monero_wallet_rpc_url,
|
|
||||||
config,
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let swap_id = Uuid::new_v4();
|
let swap_id = Uuid::new_v4();
|
||||||
|
|
||||||
@ -90,7 +99,7 @@ async fn main() -> Result<()> {
|
|||||||
|
|
||||||
let alice_factory = alice::Builder::new(
|
let alice_factory = alice::Builder::new(
|
||||||
seed,
|
seed,
|
||||||
config,
|
execution_params,
|
||||||
swap_id,
|
swap_id,
|
||||||
Arc::new(bitcoin_wallet),
|
Arc::new(bitcoin_wallet),
|
||||||
Arc::new(monero_wallet),
|
Arc::new(monero_wallet),
|
||||||
@ -106,24 +115,17 @@ async fn main() -> Result<()> {
|
|||||||
Command::BuyXmr {
|
Command::BuyXmr {
|
||||||
alice_peer_id,
|
alice_peer_id,
|
||||||
alice_addr,
|
alice_addr,
|
||||||
bitcoind_url,
|
|
||||||
bitcoin_wallet_name,
|
|
||||||
monero_wallet_rpc_url,
|
|
||||||
send_bitcoin,
|
send_bitcoin,
|
||||||
receive_monero,
|
receive_monero,
|
||||||
|
config,
|
||||||
} => {
|
} => {
|
||||||
let swap_amounts = SwapAmounts {
|
let swap_amounts = SwapAmounts {
|
||||||
btc: send_bitcoin,
|
btc: send_bitcoin,
|
||||||
xmr: receive_monero,
|
xmr: receive_monero,
|
||||||
};
|
};
|
||||||
|
|
||||||
let (bitcoin_wallet, monero_wallet) = setup_wallets(
|
let (bitcoin_wallet, monero_wallet) =
|
||||||
bitcoind_url,
|
init_wallets(config.path, bitcoin_network, monero_network).await?;
|
||||||
bitcoin_wallet_name.as_str(),
|
|
||||||
monero_wallet_rpc_url,
|
|
||||||
config,
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let swap_id = Uuid::new_v4();
|
let swap_id = Uuid::new_v4();
|
||||||
|
|
||||||
@ -140,7 +142,7 @@ async fn main() -> Result<()> {
|
|||||||
Arc::new(monero_wallet),
|
Arc::new(monero_wallet),
|
||||||
alice_addr,
|
alice_addr,
|
||||||
alice_peer_id,
|
alice_peer_id,
|
||||||
config,
|
execution_params,
|
||||||
);
|
);
|
||||||
let (swap, event_loop) = bob_factory.with_init_params(swap_amounts).build().await?;
|
let (swap, event_loop) = bob_factory.with_init_params(swap_amounts).build().await?;
|
||||||
|
|
||||||
@ -163,22 +165,15 @@ async fn main() -> Result<()> {
|
|||||||
}
|
}
|
||||||
Command::Resume(Resume::SellXmr {
|
Command::Resume(Resume::SellXmr {
|
||||||
swap_id,
|
swap_id,
|
||||||
bitcoind_url,
|
|
||||||
bitcoin_wallet_name,
|
|
||||||
monero_wallet_rpc_url,
|
|
||||||
listen_addr,
|
listen_addr,
|
||||||
}) => {
|
|
||||||
let (bitcoin_wallet, monero_wallet) = setup_wallets(
|
|
||||||
bitcoind_url,
|
|
||||||
bitcoin_wallet_name.as_str(),
|
|
||||||
monero_wallet_rpc_url,
|
|
||||||
config,
|
config,
|
||||||
)
|
}) => {
|
||||||
.await?;
|
let (bitcoin_wallet, monero_wallet) =
|
||||||
|
init_wallets(config.path, bitcoin_network, monero_network).await?;
|
||||||
|
|
||||||
let alice_factory = alice::Builder::new(
|
let alice_factory = alice::Builder::new(
|
||||||
seed,
|
seed,
|
||||||
config,
|
execution_params,
|
||||||
swap_id,
|
swap_id,
|
||||||
Arc::new(bitcoin_wallet),
|
Arc::new(bitcoin_wallet),
|
||||||
Arc::new(monero_wallet),
|
Arc::new(monero_wallet),
|
||||||
@ -192,19 +187,12 @@ async fn main() -> Result<()> {
|
|||||||
}
|
}
|
||||||
Command::Resume(Resume::BuyXmr {
|
Command::Resume(Resume::BuyXmr {
|
||||||
swap_id,
|
swap_id,
|
||||||
bitcoind_url,
|
|
||||||
bitcoin_wallet_name,
|
|
||||||
monero_wallet_rpc_url,
|
|
||||||
alice_peer_id,
|
alice_peer_id,
|
||||||
alice_addr,
|
alice_addr,
|
||||||
}) => {
|
|
||||||
let (bitcoin_wallet, monero_wallet) = setup_wallets(
|
|
||||||
bitcoind_url,
|
|
||||||
bitcoin_wallet_name.as_str(),
|
|
||||||
monero_wallet_rpc_url,
|
|
||||||
config,
|
config,
|
||||||
)
|
}) => {
|
||||||
.await?;
|
let (bitcoin_wallet, monero_wallet) =
|
||||||
|
init_wallets(config.path, bitcoin_network, monero_network).await?;
|
||||||
|
|
||||||
let bob_factory = Builder::new(
|
let bob_factory = Builder::new(
|
||||||
seed,
|
seed,
|
||||||
@ -214,7 +202,7 @@ async fn main() -> Result<()> {
|
|||||||
Arc::new(monero_wallet),
|
Arc::new(monero_wallet),
|
||||||
alice_addr,
|
alice_addr,
|
||||||
alice_peer_id,
|
alice_peer_id,
|
||||||
config,
|
execution_params,
|
||||||
);
|
);
|
||||||
let (swap, event_loop) = bob_factory.build().await?;
|
let (swap, event_loop) = bob_factory.build().await?;
|
||||||
|
|
||||||
@ -226,21 +214,38 @@ async fn main() -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn setup_wallets(
|
async fn init_wallets(
|
||||||
bitcoind_url: url::Url,
|
config_path: Option<PathBuf>,
|
||||||
bitcoin_wallet_name: &str,
|
bitcoin_network: bitcoin::Network,
|
||||||
monero_wallet_rpc_url: url::Url,
|
monero_network: monero::Network,
|
||||||
config: Config,
|
|
||||||
) -> Result<(bitcoin::Wallet, monero::Wallet)> {
|
) -> Result<(bitcoin::Wallet, monero::Wallet)> {
|
||||||
let bitcoin_wallet =
|
let config_path = if let Some(config_path) = config_path {
|
||||||
bitcoin::Wallet::new(bitcoin_wallet_name, bitcoind_url, config.bitcoin_network).await?;
|
config_path
|
||||||
|
} else {
|
||||||
|
default_config_path()?
|
||||||
|
};
|
||||||
|
|
||||||
|
let config = match read_config(config_path.clone())? {
|
||||||
|
Ok(config) => config,
|
||||||
|
Err(ConfigNotInitialized {}) => {
|
||||||
|
initial_setup(config_path.clone(), query_user_for_initial_testnet_config)?;
|
||||||
|
read_config(config_path)?.expect("after initial setup config can be read")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let bitcoin_wallet = bitcoin::Wallet::new(
|
||||||
|
config.bitcoin.wallet_name.as_str(),
|
||||||
|
config.bitcoin.bitcoind_url,
|
||||||
|
bitcoin_network,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
let bitcoin_balance = bitcoin_wallet.balance().await?;
|
let bitcoin_balance = bitcoin_wallet.balance().await?;
|
||||||
info!(
|
info!(
|
||||||
"Connection to Bitcoin wallet succeeded, balance: {}",
|
"Connection to Bitcoin wallet succeeded, balance: {}",
|
||||||
bitcoin_balance
|
bitcoin_balance
|
||||||
);
|
);
|
||||||
|
|
||||||
let monero_wallet = monero::Wallet::new(monero_wallet_rpc_url, config.monero_network);
|
let monero_wallet = monero::Wallet::new(config.monero.wallet_rpc_url, monero_network);
|
||||||
let monero_balance = monero_wallet.get_balance().await?;
|
let monero_balance = monero_wallet.get_balance().await?;
|
||||||
info!(
|
info!(
|
||||||
"Connection to Monero wallet succeeded, balance: {}",
|
"Connection to Monero wallet succeeded, balance: {}",
|
||||||
|
@ -11,7 +11,7 @@ pub use self::{
|
|||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
bitcoin,
|
bitcoin,
|
||||||
config::Config,
|
config::ExecutionParams,
|
||||||
database,
|
database,
|
||||||
database::Database,
|
database::Database,
|
||||||
monero,
|
monero,
|
||||||
@ -49,7 +49,7 @@ pub struct Swap {
|
|||||||
pub event_loop_handle: EventLoopHandle,
|
pub event_loop_handle: EventLoopHandle,
|
||||||
pub bitcoin_wallet: Arc<bitcoin::Wallet>,
|
pub bitcoin_wallet: Arc<bitcoin::Wallet>,
|
||||||
pub monero_wallet: Arc<monero::Wallet>,
|
pub monero_wallet: Arc<monero::Wallet>,
|
||||||
pub config: Config,
|
pub execution_params: ExecutionParams,
|
||||||
pub swap_id: Uuid,
|
pub swap_id: Uuid,
|
||||||
pub db: Database,
|
pub db: Database,
|
||||||
}
|
}
|
||||||
@ -59,7 +59,7 @@ pub struct Builder {
|
|||||||
identity: Keypair,
|
identity: Keypair,
|
||||||
peer_id: PeerId,
|
peer_id: PeerId,
|
||||||
db_path: PathBuf,
|
db_path: PathBuf,
|
||||||
config: Config,
|
execution_params: ExecutionParams,
|
||||||
|
|
||||||
listen_address: Multiaddr,
|
listen_address: Multiaddr,
|
||||||
|
|
||||||
@ -77,7 +77,7 @@ enum InitParams {
|
|||||||
impl Builder {
|
impl Builder {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
seed: Seed,
|
seed: Seed,
|
||||||
config: Config,
|
execution_params: ExecutionParams,
|
||||||
swap_id: Uuid,
|
swap_id: Uuid,
|
||||||
bitcoin_wallet: Arc<bitcoin::Wallet>,
|
bitcoin_wallet: Arc<bitcoin::Wallet>,
|
||||||
monero_wallet: Arc<monero::Wallet>,
|
monero_wallet: Arc<monero::Wallet>,
|
||||||
@ -93,7 +93,7 @@ impl Builder {
|
|||||||
identity,
|
identity,
|
||||||
peer_id,
|
peer_id,
|
||||||
db_path,
|
db_path,
|
||||||
config,
|
execution_params,
|
||||||
listen_address,
|
listen_address,
|
||||||
bitcoin_wallet,
|
bitcoin_wallet,
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
@ -124,7 +124,7 @@ impl Builder {
|
|||||||
event_loop_handle,
|
event_loop_handle,
|
||||||
bitcoin_wallet: self.bitcoin_wallet,
|
bitcoin_wallet: self.bitcoin_wallet,
|
||||||
monero_wallet: self.monero_wallet,
|
monero_wallet: self.monero_wallet,
|
||||||
config: self.config,
|
execution_params: self.execution_params,
|
||||||
db,
|
db,
|
||||||
state: initial_state,
|
state: initial_state,
|
||||||
swap_id: self.swap_id,
|
swap_id: self.swap_id,
|
||||||
@ -154,7 +154,7 @@ impl Builder {
|
|||||||
event_loop_handle,
|
event_loop_handle,
|
||||||
bitcoin_wallet: self.bitcoin_wallet,
|
bitcoin_wallet: self.bitcoin_wallet,
|
||||||
monero_wallet: self.monero_wallet,
|
monero_wallet: self.monero_wallet,
|
||||||
config: self.config,
|
execution_params: self.execution_params,
|
||||||
swap_id: self.swap_id,
|
swap_id: self.swap_id,
|
||||||
db,
|
db,
|
||||||
},
|
},
|
||||||
@ -195,8 +195,8 @@ impl Builder {
|
|||||||
v_a,
|
v_a,
|
||||||
amounts.btc,
|
amounts.btc,
|
||||||
amounts.xmr,
|
amounts.xmr,
|
||||||
self.config.bitcoin_cancel_timelock,
|
self.execution_params.bitcoin_cancel_timelock,
|
||||||
self.config.bitcoin_punish_timelock,
|
self.execution_params.bitcoin_punish_timelock,
|
||||||
redeem_address,
|
redeem_address,
|
||||||
punish_address,
|
punish_address,
|
||||||
);
|
);
|
||||||
|
@ -7,7 +7,7 @@ use crate::{
|
|||||||
TransactionBlockHeight, TxCancel, TxLock, TxRefund, WaitForTransactionFinality,
|
TransactionBlockHeight, TxCancel, TxLock, TxRefund, WaitForTransactionFinality,
|
||||||
WatchForRawTransaction,
|
WatchForRawTransaction,
|
||||||
},
|
},
|
||||||
config::Config,
|
config::ExecutionParams,
|
||||||
monero,
|
monero,
|
||||||
monero::Transfer,
|
monero::Transfer,
|
||||||
protocol::{
|
protocol::{
|
||||||
@ -33,19 +33,22 @@ pub async fn negotiate(
|
|||||||
state0: alice::State0,
|
state0: alice::State0,
|
||||||
xmr_amount: monero::Amount,
|
xmr_amount: monero::Amount,
|
||||||
event_loop_handle: &mut EventLoopHandle,
|
event_loop_handle: &mut EventLoopHandle,
|
||||||
config: Config,
|
execution_params: ExecutionParams,
|
||||||
) -> Result<(PeerId, alice::State3)> {
|
) -> Result<(PeerId, alice::State3)> {
|
||||||
trace!("Starting negotiate");
|
trace!("Starting negotiate");
|
||||||
|
|
||||||
// todo: we can move this out, we dont need to timeout here
|
// todo: we can move this out, we dont need to timeout here
|
||||||
let bob_peer_id = timeout(
|
let bob_peer_id = timeout(
|
||||||
config.bob_time_to_act,
|
execution_params.bob_time_to_act,
|
||||||
event_loop_handle.recv_conn_established(),
|
event_loop_handle.recv_conn_established(),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.context("Failed to receive dial connection from Bob")??;
|
.context("Failed to receive dial connection from Bob")??;
|
||||||
|
|
||||||
let event = timeout(config.bob_time_to_act, event_loop_handle.recv_request())
|
let event = timeout(
|
||||||
|
execution_params.bob_time_to_act,
|
||||||
|
event_loop_handle.recv_request(),
|
||||||
|
)
|
||||||
.await
|
.await
|
||||||
.context("Failed to receive swap request from Bob")??;
|
.context("Failed to receive swap request from Bob")??;
|
||||||
|
|
||||||
@ -53,8 +56,11 @@ pub async fn negotiate(
|
|||||||
.send_swap_response(event.channel, SwapResponse { xmr_amount })
|
.send_swap_response(event.channel, SwapResponse { xmr_amount })
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let (bob_message0, channel) =
|
let (bob_message0, channel) = timeout(
|
||||||
timeout(config.bob_time_to_act, event_loop_handle.recv_message0()).await??;
|
execution_params.bob_time_to_act,
|
||||||
|
event_loop_handle.recv_message0(),
|
||||||
|
)
|
||||||
|
.await??;
|
||||||
|
|
||||||
let alice_message0 = state0.next_message(&mut OsRng);
|
let alice_message0 = state0.next_message(&mut OsRng);
|
||||||
event_loop_handle
|
event_loop_handle
|
||||||
@ -63,8 +69,11 @@ pub async fn negotiate(
|
|||||||
|
|
||||||
let state1 = state0.receive(bob_message0)?;
|
let state1 = state0.receive(bob_message0)?;
|
||||||
|
|
||||||
let (bob_message1, channel) =
|
let (bob_message1, channel) = timeout(
|
||||||
timeout(config.bob_time_to_act, event_loop_handle.recv_message1()).await??;
|
execution_params.bob_time_to_act,
|
||||||
|
event_loop_handle.recv_message1(),
|
||||||
|
)
|
||||||
|
.await??;
|
||||||
|
|
||||||
let state2 = state1.receive(bob_message1);
|
let state2 = state1.receive(bob_message1);
|
||||||
|
|
||||||
@ -72,7 +81,11 @@ pub async fn negotiate(
|
|||||||
.send_message1(channel, state2.next_message())
|
.send_message1(channel, state2.next_message())
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let bob_message2 = timeout(config.bob_time_to_act, event_loop_handle.recv_message2()).await??;
|
let bob_message2 = timeout(
|
||||||
|
execution_params.bob_time_to_act,
|
||||||
|
event_loop_handle.recv_message2(),
|
||||||
|
)
|
||||||
|
.await??;
|
||||||
|
|
||||||
let state3 = state2.receive(bob_message2)?;
|
let state3 = state2.receive(bob_message2)?;
|
||||||
|
|
||||||
@ -84,14 +97,14 @@ pub async fn negotiate(
|
|||||||
pub async fn wait_for_locked_bitcoin<W>(
|
pub async fn wait_for_locked_bitcoin<W>(
|
||||||
lock_bitcoin_txid: bitcoin::Txid,
|
lock_bitcoin_txid: bitcoin::Txid,
|
||||||
bitcoin_wallet: Arc<W>,
|
bitcoin_wallet: Arc<W>,
|
||||||
config: Config,
|
execution_params: ExecutionParams,
|
||||||
) -> Result<()>
|
) -> Result<()>
|
||||||
where
|
where
|
||||||
W: WatchForRawTransaction + WaitForTransactionFinality,
|
W: WatchForRawTransaction + WaitForTransactionFinality,
|
||||||
{
|
{
|
||||||
// We assume we will see Bob's transaction in the mempool first.
|
// We assume we will see Bob's transaction in the mempool first.
|
||||||
timeout(
|
timeout(
|
||||||
config.bob_time_to_act,
|
execution_params.bob_time_to_act,
|
||||||
bitcoin_wallet.watch_for_raw_transaction(lock_bitcoin_txid),
|
bitcoin_wallet.watch_for_raw_transaction(lock_bitcoin_txid),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
@ -99,7 +112,7 @@ where
|
|||||||
|
|
||||||
// // We saw the transaction in the mempool, waiting for it to be confirmed.
|
// // We saw the transaction in the mempool, waiting for it to be confirmed.
|
||||||
bitcoin_wallet
|
bitcoin_wallet
|
||||||
.wait_for_transaction_finality(lock_bitcoin_txid, config)
|
.wait_for_transaction_finality(lock_bitcoin_txid, execution_params)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -324,7 +337,7 @@ pub fn build_bitcoin_punish_transaction(
|
|||||||
pub async fn publish_bitcoin_punish_transaction<W>(
|
pub async fn publish_bitcoin_punish_transaction<W>(
|
||||||
punish_tx: bitcoin::Transaction,
|
punish_tx: bitcoin::Transaction,
|
||||||
bitcoin_wallet: Arc<W>,
|
bitcoin_wallet: Arc<W>,
|
||||||
config: Config,
|
execution_params: ExecutionParams,
|
||||||
) -> Result<bitcoin::Txid>
|
) -> Result<bitcoin::Txid>
|
||||||
where
|
where
|
||||||
W: BroadcastSignedTransaction + WaitForTransactionFinality,
|
W: BroadcastSignedTransaction + WaitForTransactionFinality,
|
||||||
@ -334,7 +347,7 @@ where
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
bitcoin_wallet
|
bitcoin_wallet
|
||||||
.wait_for_transaction_finality(txid, config)
|
.wait_for_transaction_finality(txid, execution_params)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(txid)
|
Ok(txid)
|
||||||
|
@ -6,7 +6,7 @@ use crate::{
|
|||||||
timelocks::ExpiredTimelocks, TransactionBlockHeight, WaitForTransactionFinality,
|
timelocks::ExpiredTimelocks, TransactionBlockHeight, WaitForTransactionFinality,
|
||||||
WatchForRawTransaction,
|
WatchForRawTransaction,
|
||||||
},
|
},
|
||||||
config::Config,
|
config::ExecutionParams,
|
||||||
database,
|
database,
|
||||||
database::Database,
|
database::Database,
|
||||||
monero,
|
monero,
|
||||||
@ -66,7 +66,7 @@ pub async fn run_until(
|
|||||||
swap.event_loop_handle,
|
swap.event_loop_handle,
|
||||||
swap.bitcoin_wallet,
|
swap.bitcoin_wallet,
|
||||||
swap.monero_wallet,
|
swap.monero_wallet,
|
||||||
swap.config,
|
swap.execution_params,
|
||||||
swap.swap_id,
|
swap.swap_id,
|
||||||
swap.db,
|
swap.db,
|
||||||
)
|
)
|
||||||
@ -82,7 +82,7 @@ async fn run_until_internal(
|
|||||||
mut event_loop_handle: EventLoopHandle,
|
mut event_loop_handle: EventLoopHandle,
|
||||||
bitcoin_wallet: Arc<bitcoin::Wallet>,
|
bitcoin_wallet: Arc<bitcoin::Wallet>,
|
||||||
monero_wallet: Arc<monero::Wallet>,
|
monero_wallet: Arc<monero::Wallet>,
|
||||||
config: Config,
|
execution_params: ExecutionParams,
|
||||||
swap_id: Uuid,
|
swap_id: Uuid,
|
||||||
db: Database,
|
db: Database,
|
||||||
) -> Result<AliceState> {
|
) -> Result<AliceState> {
|
||||||
@ -92,8 +92,13 @@ async fn run_until_internal(
|
|||||||
} else {
|
} else {
|
||||||
match state {
|
match state {
|
||||||
AliceState::Started { amounts, state0 } => {
|
AliceState::Started { amounts, state0 } => {
|
||||||
let (bob_peer_id, state3) =
|
let (bob_peer_id, state3) = negotiate(
|
||||||
negotiate(state0, amounts.xmr, &mut event_loop_handle, config).await?;
|
state0,
|
||||||
|
amounts.xmr,
|
||||||
|
&mut event_loop_handle,
|
||||||
|
execution_params,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let state = AliceState::Negotiated {
|
let state = AliceState::Negotiated {
|
||||||
bob_peer_id,
|
bob_peer_id,
|
||||||
@ -110,7 +115,7 @@ async fn run_until_internal(
|
|||||||
event_loop_handle,
|
event_loop_handle,
|
||||||
bitcoin_wallet,
|
bitcoin_wallet,
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
config,
|
execution_params,
|
||||||
swap_id,
|
swap_id,
|
||||||
db,
|
db,
|
||||||
)
|
)
|
||||||
@ -121,8 +126,11 @@ async fn run_until_internal(
|
|||||||
bob_peer_id,
|
bob_peer_id,
|
||||||
amounts,
|
amounts,
|
||||||
} => {
|
} => {
|
||||||
let _ =
|
let _ = wait_for_locked_bitcoin(
|
||||||
wait_for_locked_bitcoin(state3.tx_lock.txid(), bitcoin_wallet.clone(), config)
|
state3.tx_lock.txid(),
|
||||||
|
bitcoin_wallet.clone(),
|
||||||
|
execution_params,
|
||||||
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let state = AliceState::BtcLocked {
|
let state = AliceState::BtcLocked {
|
||||||
@ -140,7 +148,7 @@ async fn run_until_internal(
|
|||||||
event_loop_handle,
|
event_loop_handle,
|
||||||
bitcoin_wallet,
|
bitcoin_wallet,
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
config,
|
execution_params,
|
||||||
swap_id,
|
swap_id,
|
||||||
db,
|
db,
|
||||||
)
|
)
|
||||||
@ -171,7 +179,7 @@ async fn run_until_internal(
|
|||||||
event_loop_handle,
|
event_loop_handle,
|
||||||
bitcoin_wallet,
|
bitcoin_wallet,
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
config,
|
execution_params,
|
||||||
swap_id,
|
swap_id,
|
||||||
db,
|
db,
|
||||||
)
|
)
|
||||||
@ -209,7 +217,7 @@ async fn run_until_internal(
|
|||||||
event_loop_handle,
|
event_loop_handle,
|
||||||
bitcoin_wallet.clone(),
|
bitcoin_wallet.clone(),
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
config,
|
execution_params,
|
||||||
swap_id,
|
swap_id,
|
||||||
db,
|
db,
|
||||||
)
|
)
|
||||||
@ -235,7 +243,7 @@ async fn run_until_internal(
|
|||||||
{
|
{
|
||||||
Ok(txid) => {
|
Ok(txid) => {
|
||||||
let publishded_redeem_tx = bitcoin_wallet
|
let publishded_redeem_tx = bitcoin_wallet
|
||||||
.wait_for_transaction_finality(txid, config)
|
.wait_for_transaction_finality(txid, execution_params)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
match publishded_redeem_tx {
|
match publishded_redeem_tx {
|
||||||
@ -281,7 +289,7 @@ async fn run_until_internal(
|
|||||||
event_loop_handle,
|
event_loop_handle,
|
||||||
bitcoin_wallet,
|
bitcoin_wallet,
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
config,
|
execution_params,
|
||||||
swap_id,
|
swap_id,
|
||||||
db,
|
db,
|
||||||
)
|
)
|
||||||
@ -308,7 +316,7 @@ async fn run_until_internal(
|
|||||||
event_loop_handle,
|
event_loop_handle,
|
||||||
bitcoin_wallet,
|
bitcoin_wallet,
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
config,
|
execution_params,
|
||||||
swap_id,
|
swap_id,
|
||||||
db,
|
db,
|
||||||
)
|
)
|
||||||
@ -342,7 +350,7 @@ async fn run_until_internal(
|
|||||||
event_loop_handle,
|
event_loop_handle,
|
||||||
bitcoin_wallet.clone(),
|
bitcoin_wallet.clone(),
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
config,
|
execution_params,
|
||||||
swap_id,
|
swap_id,
|
||||||
db,
|
db,
|
||||||
)
|
)
|
||||||
@ -367,7 +375,7 @@ async fn run_until_internal(
|
|||||||
event_loop_handle,
|
event_loop_handle,
|
||||||
bitcoin_wallet.clone(),
|
bitcoin_wallet.clone(),
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
config,
|
execution_params,
|
||||||
swap_id,
|
swap_id,
|
||||||
db,
|
db,
|
||||||
)
|
)
|
||||||
@ -402,7 +410,7 @@ async fn run_until_internal(
|
|||||||
let punish_tx_finalised = publish_bitcoin_punish_transaction(
|
let punish_tx_finalised = publish_bitcoin_punish_transaction(
|
||||||
signed_tx_punish,
|
signed_tx_punish,
|
||||||
bitcoin_wallet.clone(),
|
bitcoin_wallet.clone(),
|
||||||
config,
|
execution_params,
|
||||||
);
|
);
|
||||||
|
|
||||||
let refund_tx_seen = bitcoin_wallet.watch_for_raw_transaction(tx_refund.txid());
|
let refund_tx_seen = bitcoin_wallet.watch_for_raw_transaction(tx_refund.txid());
|
||||||
@ -422,7 +430,7 @@ async fn run_until_internal(
|
|||||||
event_loop_handle,
|
event_loop_handle,
|
||||||
bitcoin_wallet.clone(),
|
bitcoin_wallet.clone(),
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
config,
|
execution_params,
|
||||||
swap_id,
|
swap_id,
|
||||||
db,
|
db,
|
||||||
)
|
)
|
||||||
@ -446,7 +454,7 @@ async fn run_until_internal(
|
|||||||
event_loop_handle,
|
event_loop_handle,
|
||||||
bitcoin_wallet.clone(),
|
bitcoin_wallet.clone(),
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
config,
|
execution_params,
|
||||||
swap_id,
|
swap_id,
|
||||||
db,
|
db,
|
||||||
)
|
)
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
//! Run an XMR/BTC swap in the role of Bob.
|
//! Run an XMR/BTC swap in the role of Bob.
|
||||||
//! Bob holds BTC and wishes receive XMR.
|
//! Bob holds BTC and wishes receive XMR.
|
||||||
use crate::{
|
use crate::{
|
||||||
bitcoin,
|
bitcoin, database,
|
||||||
config::Config,
|
|
||||||
database,
|
|
||||||
database::Database,
|
database::Database,
|
||||||
monero, network,
|
monero, network,
|
||||||
network::{
|
network::{
|
||||||
@ -30,7 +28,7 @@ pub use self::{
|
|||||||
swap::{run, run_until},
|
swap::{run, run_until},
|
||||||
swap_request::*,
|
swap_request::*,
|
||||||
};
|
};
|
||||||
use crate::protocol::alice::TransferProof;
|
use crate::{config::ExecutionParams, protocol::alice::TransferProof};
|
||||||
|
|
||||||
mod encrypted_signature;
|
mod encrypted_signature;
|
||||||
pub mod event_loop;
|
pub mod event_loop;
|
||||||
@ -48,7 +46,7 @@ pub struct Swap {
|
|||||||
pub db: Database,
|
pub db: Database,
|
||||||
pub bitcoin_wallet: Arc<bitcoin::Wallet>,
|
pub bitcoin_wallet: Arc<bitcoin::Wallet>,
|
||||||
pub monero_wallet: Arc<monero::Wallet>,
|
pub monero_wallet: Arc<monero::Wallet>,
|
||||||
pub config: Config,
|
pub execution_params: ExecutionParams,
|
||||||
pub swap_id: Uuid,
|
pub swap_id: Uuid,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +63,7 @@ pub struct Builder {
|
|||||||
monero_wallet: Arc<monero::Wallet>,
|
monero_wallet: Arc<monero::Wallet>,
|
||||||
|
|
||||||
init_params: InitParams,
|
init_params: InitParams,
|
||||||
config: Config,
|
execution_params: ExecutionParams,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum InitParams {
|
enum InitParams {
|
||||||
@ -83,7 +81,7 @@ impl Builder {
|
|||||||
monero_wallet: Arc<monero::Wallet>,
|
monero_wallet: Arc<monero::Wallet>,
|
||||||
alice_address: Multiaddr,
|
alice_address: Multiaddr,
|
||||||
alice_peer_id: PeerId,
|
alice_peer_id: PeerId,
|
||||||
config: Config,
|
execution_params: ExecutionParams,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let identity = network::Seed::new(seed).derive_libp2p_identity();
|
let identity = network::Seed::new(seed).derive_libp2p_identity();
|
||||||
let peer_id = identity.public().into_peer_id();
|
let peer_id = identity.public().into_peer_id();
|
||||||
@ -98,7 +96,7 @@ impl Builder {
|
|||||||
bitcoin_wallet,
|
bitcoin_wallet,
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
init_params: InitParams::None,
|
init_params: InitParams::None,
|
||||||
config,
|
execution_params,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,7 +111,7 @@ impl Builder {
|
|||||||
match self.init_params {
|
match self.init_params {
|
||||||
InitParams::New { swap_amounts } => {
|
InitParams::New { swap_amounts } => {
|
||||||
let initial_state = self
|
let initial_state = self
|
||||||
.make_initial_state(swap_amounts.btc, swap_amounts.xmr, self.config)
|
.make_initial_state(swap_amounts.btc, swap_amounts.xmr, self.execution_params)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let (event_loop, event_loop_handle) = self.init_event_loop()?;
|
let (event_loop, event_loop_handle) = self.init_event_loop()?;
|
||||||
@ -128,7 +126,7 @@ impl Builder {
|
|||||||
bitcoin_wallet: self.bitcoin_wallet.clone(),
|
bitcoin_wallet: self.bitcoin_wallet.clone(),
|
||||||
monero_wallet: self.monero_wallet.clone(),
|
monero_wallet: self.monero_wallet.clone(),
|
||||||
swap_id: self.swap_id,
|
swap_id: self.swap_id,
|
||||||
config: self.config,
|
execution_params: self.execution_params,
|
||||||
},
|
},
|
||||||
event_loop,
|
event_loop,
|
||||||
))
|
))
|
||||||
@ -157,7 +155,7 @@ impl Builder {
|
|||||||
bitcoin_wallet: self.bitcoin_wallet.clone(),
|
bitcoin_wallet: self.bitcoin_wallet.clone(),
|
||||||
monero_wallet: self.monero_wallet.clone(),
|
monero_wallet: self.monero_wallet.clone(),
|
||||||
swap_id: self.swap_id,
|
swap_id: self.swap_id,
|
||||||
config: self.config,
|
execution_params: self.execution_params,
|
||||||
},
|
},
|
||||||
event_loop,
|
event_loop,
|
||||||
))
|
))
|
||||||
@ -183,7 +181,7 @@ impl Builder {
|
|||||||
&self,
|
&self,
|
||||||
btc_to_swap: bitcoin::Amount,
|
btc_to_swap: bitcoin::Amount,
|
||||||
xmr_to_swap: monero::Amount,
|
xmr_to_swap: monero::Amount,
|
||||||
config: Config,
|
execution_params: ExecutionParams,
|
||||||
) -> Result<BobState> {
|
) -> Result<BobState> {
|
||||||
let amounts = SwapAmounts {
|
let amounts = SwapAmounts {
|
||||||
btc: btc_to_swap,
|
btc: btc_to_swap,
|
||||||
@ -195,10 +193,10 @@ impl Builder {
|
|||||||
&mut OsRng,
|
&mut OsRng,
|
||||||
btc_to_swap,
|
btc_to_swap,
|
||||||
xmr_to_swap,
|
xmr_to_swap,
|
||||||
config.bitcoin_cancel_timelock,
|
execution_params.bitcoin_cancel_timelock,
|
||||||
config.bitcoin_punish_timelock,
|
execution_params.bitcoin_punish_timelock,
|
||||||
refund_address,
|
refund_address,
|
||||||
config.monero_finality_confirmations,
|
execution_params.monero_finality_confirmations,
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(BobState::Started { state0, amounts })
|
Ok(BobState::Started { state0, amounts })
|
||||||
|
@ -6,7 +6,7 @@ use crate::{
|
|||||||
GetBlockHeight, GetNetwork, GetRawTransaction, Transaction, TransactionBlockHeight,
|
GetBlockHeight, GetNetwork, GetRawTransaction, Transaction, TransactionBlockHeight,
|
||||||
TxCancel, Txid, WatchForRawTransaction,
|
TxCancel, Txid, WatchForRawTransaction,
|
||||||
},
|
},
|
||||||
config::Config,
|
config::ExecutionParams,
|
||||||
monero,
|
monero,
|
||||||
monero::{monero_private_key, TransferProof},
|
monero::{monero_private_key, TransferProof},
|
||||||
protocol::{alice, bob, bob::EncryptedSignature, SwapAmounts},
|
protocol::{alice, bob, bob::EncryptedSignature, SwapAmounts},
|
||||||
@ -556,7 +556,11 @@ impl State4 {
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn refund_btc<W>(&self, bitcoin_wallet: &W, config: Config) -> Result<()>
|
pub async fn refund_btc<W>(
|
||||||
|
&self,
|
||||||
|
bitcoin_wallet: &W,
|
||||||
|
execution_params: ExecutionParams,
|
||||||
|
) -> Result<()>
|
||||||
where
|
where
|
||||||
W: bitcoin::BroadcastSignedTransaction + bitcoin::WaitForTransactionFinality,
|
W: bitcoin::BroadcastSignedTransaction + bitcoin::WaitForTransactionFinality,
|
||||||
{
|
{
|
||||||
@ -581,7 +585,7 @@ impl State4 {
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
bitcoin_wallet
|
bitcoin_wallet
|
||||||
.wait_for_transaction_finality(txid, config)
|
.wait_for_transaction_finality(txid, execution_params)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
bitcoin,
|
bitcoin,
|
||||||
bitcoin::timelocks::ExpiredTimelocks,
|
bitcoin::timelocks::ExpiredTimelocks,
|
||||||
config::Config,
|
config::ExecutionParams,
|
||||||
database::{Database, Swap},
|
database::{Database, Swap},
|
||||||
monero,
|
monero,
|
||||||
protocol::{
|
protocol::{
|
||||||
@ -46,7 +46,7 @@ pub async fn run_until(
|
|||||||
swap.monero_wallet,
|
swap.monero_wallet,
|
||||||
OsRng,
|
OsRng,
|
||||||
swap.swap_id,
|
swap.swap_id,
|
||||||
swap.config,
|
swap.execution_params,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -63,7 +63,7 @@ async fn run_until_internal<R>(
|
|||||||
monero_wallet: Arc<monero::Wallet>,
|
monero_wallet: Arc<monero::Wallet>,
|
||||||
mut rng: R,
|
mut rng: R,
|
||||||
swap_id: Uuid,
|
swap_id: Uuid,
|
||||||
config: Config,
|
execution_params: ExecutionParams,
|
||||||
) -> Result<BobState>
|
) -> Result<BobState>
|
||||||
where
|
where
|
||||||
R: RngCore + CryptoRng + Send,
|
R: RngCore + CryptoRng + Send,
|
||||||
@ -97,7 +97,7 @@ where
|
|||||||
monero_wallet,
|
monero_wallet,
|
||||||
rng,
|
rng,
|
||||||
swap_id,
|
swap_id,
|
||||||
config,
|
execution_params,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -119,7 +119,7 @@ where
|
|||||||
monero_wallet,
|
monero_wallet,
|
||||||
rng,
|
rng,
|
||||||
swap_id,
|
swap_id,
|
||||||
config,
|
execution_params,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -172,7 +172,7 @@ where
|
|||||||
monero_wallet,
|
monero_wallet,
|
||||||
rng,
|
rng,
|
||||||
swap_id,
|
swap_id,
|
||||||
config,
|
execution_params,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -219,7 +219,7 @@ where
|
|||||||
monero_wallet,
|
monero_wallet,
|
||||||
rng,
|
rng,
|
||||||
swap_id,
|
swap_id,
|
||||||
config,
|
execution_params,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -262,7 +262,7 @@ where
|
|||||||
monero_wallet,
|
monero_wallet,
|
||||||
rng,
|
rng,
|
||||||
swap_id,
|
swap_id,
|
||||||
config,
|
execution_params,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -298,7 +298,7 @@ where
|
|||||||
monero_wallet,
|
monero_wallet,
|
||||||
rng,
|
rng,
|
||||||
swap_id,
|
swap_id,
|
||||||
config,
|
execution_params,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -320,7 +320,7 @@ where
|
|||||||
monero_wallet,
|
monero_wallet,
|
||||||
rng,
|
rng,
|
||||||
swap_id,
|
swap_id,
|
||||||
config,
|
execution_params,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -346,7 +346,7 @@ where
|
|||||||
monero_wallet,
|
monero_wallet,
|
||||||
rng,
|
rng,
|
||||||
swap_id,
|
swap_id,
|
||||||
config,
|
execution_params,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -357,7 +357,9 @@ where
|
|||||||
bail!("Internal error: canceled state reached before cancel timelock was expired");
|
bail!("Internal error: canceled state reached before cancel timelock was expired");
|
||||||
}
|
}
|
||||||
ExpiredTimelocks::Cancel => {
|
ExpiredTimelocks::Cancel => {
|
||||||
state.refund_btc(bitcoin_wallet.as_ref(), config).await?;
|
state
|
||||||
|
.refund_btc(bitcoin_wallet.as_ref(), execution_params)
|
||||||
|
.await?;
|
||||||
BobState::BtcRefunded(state)
|
BobState::BtcRefunded(state)
|
||||||
}
|
}
|
||||||
ExpiredTimelocks::Punish => BobState::BtcPunished {
|
ExpiredTimelocks::Punish => BobState::BtcPunished {
|
||||||
@ -376,7 +378,7 @@ where
|
|||||||
monero_wallet,
|
monero_wallet,
|
||||||
rng,
|
rng,
|
||||||
swap_id,
|
swap_id,
|
||||||
config,
|
execution_params,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ use swap::{
|
|||||||
bitcoin,
|
bitcoin,
|
||||||
bitcoin::Timelock,
|
bitcoin::Timelock,
|
||||||
config,
|
config,
|
||||||
config::{Config, GetConfig},
|
config::{ExecutionParams, GetExecutionParams},
|
||||||
monero,
|
monero,
|
||||||
protocol::{alice, alice::AliceState, bob, bob::BobState, SwapAmounts},
|
protocol::{alice, alice::AliceState, bob, bob::BobState, SwapAmounts},
|
||||||
seed::Seed,
|
seed::Seed,
|
||||||
@ -29,7 +29,7 @@ pub struct StartingBalances {
|
|||||||
|
|
||||||
struct AliceParams {
|
struct AliceParams {
|
||||||
seed: Seed,
|
seed: Seed,
|
||||||
config: Config,
|
execution_params: ExecutionParams,
|
||||||
swap_id: Uuid,
|
swap_id: Uuid,
|
||||||
bitcoin_wallet: Arc<bitcoin::Wallet>,
|
bitcoin_wallet: Arc<bitcoin::Wallet>,
|
||||||
monero_wallet: Arc<monero::Wallet>,
|
monero_wallet: Arc<monero::Wallet>,
|
||||||
@ -41,7 +41,7 @@ impl AliceParams {
|
|||||||
pub fn builder(&self) -> alice::Builder {
|
pub fn builder(&self) -> alice::Builder {
|
||||||
alice::Builder::new(
|
alice::Builder::new(
|
||||||
self.seed,
|
self.seed,
|
||||||
self.config,
|
self.execution_params,
|
||||||
self.swap_id,
|
self.swap_id,
|
||||||
self.bitcoin_wallet.clone(),
|
self.bitcoin_wallet.clone(),
|
||||||
self.monero_wallet.clone(),
|
self.monero_wallet.clone(),
|
||||||
@ -64,7 +64,7 @@ struct BobParams {
|
|||||||
monero_wallet: Arc<monero::Wallet>,
|
monero_wallet: Arc<monero::Wallet>,
|
||||||
alice_address: Multiaddr,
|
alice_address: Multiaddr,
|
||||||
alice_peer_id: PeerId,
|
alice_peer_id: PeerId,
|
||||||
config: Config,
|
execution_params: ExecutionParams,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BobParams {
|
impl BobParams {
|
||||||
@ -77,7 +77,7 @@ impl BobParams {
|
|||||||
self.monero_wallet.clone(),
|
self.monero_wallet.clone(),
|
||||||
self.alice_address.clone(),
|
self.alice_address.clone(),
|
||||||
self.alice_peer_id,
|
self.alice_peer_id,
|
||||||
self.config,
|
self.execution_params,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -308,13 +308,13 @@ pub async fn setup_test<T, F, C>(_config: C, testfn: T)
|
|||||||
where
|
where
|
||||||
T: Fn(TestContext) -> F,
|
T: Fn(TestContext) -> F,
|
||||||
F: Future<Output = ()>,
|
F: Future<Output = ()>,
|
||||||
C: GetConfig,
|
C: GetExecutionParams,
|
||||||
{
|
{
|
||||||
let cli = Cli::default();
|
let cli = Cli::default();
|
||||||
|
|
||||||
let _guard = init_tracing();
|
let _guard = init_tracing();
|
||||||
|
|
||||||
let config = C::get_config();
|
let execution_params = C::get_execution_params();
|
||||||
|
|
||||||
let (monero, containers) = testutils::init_containers(&cli).await;
|
let (monero, containers) = testutils::init_containers(&cli).await;
|
||||||
|
|
||||||
@ -334,18 +334,17 @@ where
|
|||||||
.parse()
|
.parse()
|
||||||
.expect("failed to parse Alice's address");
|
.expect("failed to parse Alice's address");
|
||||||
|
|
||||||
let (alice_bitcoin_wallet, alice_monero_wallet) = init_wallets(
|
let (alice_bitcoin_wallet, alice_monero_wallet) = init_test_wallets(
|
||||||
"alice",
|
"alice",
|
||||||
&containers.bitcoind,
|
&containers.bitcoind,
|
||||||
&monero,
|
&monero,
|
||||||
alice_starting_balances.clone(),
|
alice_starting_balances.clone(),
|
||||||
config,
|
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let alice_params = AliceParams {
|
let alice_params = AliceParams {
|
||||||
seed: Seed::random().unwrap(),
|
seed: Seed::random().unwrap(),
|
||||||
config,
|
execution_params,
|
||||||
swap_id: Uuid::new_v4(),
|
swap_id: Uuid::new_v4(),
|
||||||
bitcoin_wallet: alice_bitcoin_wallet.clone(),
|
bitcoin_wallet: alice_bitcoin_wallet.clone(),
|
||||||
monero_wallet: alice_monero_wallet.clone(),
|
monero_wallet: alice_monero_wallet.clone(),
|
||||||
@ -358,12 +357,11 @@ where
|
|||||||
btc: swap_amounts.btc * 10,
|
btc: swap_amounts.btc * 10,
|
||||||
};
|
};
|
||||||
|
|
||||||
let (bob_bitcoin_wallet, bob_monero_wallet) = init_wallets(
|
let (bob_bitcoin_wallet, bob_monero_wallet) = init_test_wallets(
|
||||||
"bob",
|
"bob",
|
||||||
&containers.bitcoind,
|
&containers.bitcoind,
|
||||||
&monero,
|
&monero,
|
||||||
bob_starting_balances.clone(),
|
bob_starting_balances.clone(),
|
||||||
config,
|
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
@ -375,7 +373,7 @@ where
|
|||||||
monero_wallet: bob_monero_wallet.clone(),
|
monero_wallet: bob_monero_wallet.clone(),
|
||||||
alice_address: alice_params.listen_address.clone(),
|
alice_address: alice_params.listen_address.clone(),
|
||||||
alice_peer_id: alice_params.peer_id(),
|
alice_peer_id: alice_params.peer_id(),
|
||||||
config,
|
execution_params,
|
||||||
};
|
};
|
||||||
|
|
||||||
let test = TestContext {
|
let test = TestContext {
|
||||||
@ -403,12 +401,11 @@ async fn init_containers(cli: &Cli) -> (Monero, Containers<'_>) {
|
|||||||
(monero, Containers { bitcoind, monerods })
|
(monero, Containers { bitcoind, monerods })
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn init_wallets(
|
async fn init_test_wallets(
|
||||||
name: &str,
|
name: &str,
|
||||||
bitcoind: &Bitcoind<'_>,
|
bitcoind: &Bitcoind<'_>,
|
||||||
monero: &Monero,
|
monero: &Monero,
|
||||||
starting_balances: StartingBalances,
|
starting_balances: StartingBalances,
|
||||||
config: Config,
|
|
||||||
) -> (Arc<bitcoin::Wallet>, Arc<monero::Wallet>) {
|
) -> (Arc<bitcoin::Wallet>, Arc<monero::Wallet>) {
|
||||||
monero
|
monero
|
||||||
.init(vec![(name, starting_balances.xmr.as_piconero())])
|
.init(vec![(name, starting_balances.xmr.as_piconero())])
|
||||||
@ -417,11 +414,11 @@ async fn init_wallets(
|
|||||||
|
|
||||||
let xmr_wallet = Arc::new(swap::monero::Wallet {
|
let xmr_wallet = Arc::new(swap::monero::Wallet {
|
||||||
inner: monero.wallet(name).unwrap().client(),
|
inner: monero.wallet(name).unwrap().client(),
|
||||||
network: config.monero_network,
|
network: monero::Network::default(),
|
||||||
});
|
});
|
||||||
|
|
||||||
let btc_wallet = Arc::new(
|
let btc_wallet = Arc::new(
|
||||||
swap::bitcoin::Wallet::new(name, bitcoind.node_url.clone(), config.bitcoin_network)
|
swap::bitcoin::Wallet::new(name, bitcoind.node_url.clone(), bitcoin::Network::Regtest)
|
||||||
.await
|
.await
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
);
|
);
|
||||||
@ -517,34 +514,34 @@ pub mod bob_run_until {
|
|||||||
|
|
||||||
pub struct SlowCancelConfig;
|
pub struct SlowCancelConfig;
|
||||||
|
|
||||||
impl GetConfig for SlowCancelConfig {
|
impl GetExecutionParams for SlowCancelConfig {
|
||||||
fn get_config() -> Config {
|
fn get_execution_params() -> ExecutionParams {
|
||||||
Config {
|
ExecutionParams {
|
||||||
bitcoin_cancel_timelock: Timelock::new(180),
|
bitcoin_cancel_timelock: Timelock::new(180),
|
||||||
..config::Regtest::get_config()
|
..config::Regtest::get_execution_params()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FastCancelConfig;
|
pub struct FastCancelConfig;
|
||||||
|
|
||||||
impl GetConfig for FastCancelConfig {
|
impl GetExecutionParams for FastCancelConfig {
|
||||||
fn get_config() -> Config {
|
fn get_execution_params() -> ExecutionParams {
|
||||||
Config {
|
ExecutionParams {
|
||||||
bitcoin_cancel_timelock: Timelock::new(1),
|
bitcoin_cancel_timelock: Timelock::new(1),
|
||||||
..config::Regtest::get_config()
|
..config::Regtest::get_execution_params()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FastPunishConfig;
|
pub struct FastPunishConfig;
|
||||||
|
|
||||||
impl GetConfig for FastPunishConfig {
|
impl GetExecutionParams for FastPunishConfig {
|
||||||
fn get_config() -> Config {
|
fn get_execution_params() -> ExecutionParams {
|
||||||
Config {
|
ExecutionParams {
|
||||||
bitcoin_cancel_timelock: Timelock::new(1),
|
bitcoin_cancel_timelock: Timelock::new(1),
|
||||||
bitcoin_punish_timelock: Timelock::new(1),
|
bitcoin_punish_timelock: Timelock::new(1),
|
||||||
..config::Regtest::get_config()
|
..config::Regtest::get_execution_params()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user