mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2025-01-11 07:29:39 -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"
|
||||
bitcoin = { version = "0.25", features = ["rand", "use-serde"] }
|
||||
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"
|
||||
cross-curve-dleq = { git = "https://github.com/comit-network/cross-curve-dleq", rev = "eddcdea1d1f16fa33ef581d1744014ece535c920", features = ["serde"] }
|
||||
curve25519-dalek = "2"
|
||||
derivative = "2"
|
||||
dialoguer = "0.7"
|
||||
directories-next = "2"
|
||||
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
|
||||
futures = { version = "0.3", default-features = false }
|
||||
@ -43,12 +46,13 @@ tempfile = "3"
|
||||
thiserror = "1"
|
||||
time = "0.2"
|
||||
tokio = { version = "1.0", features = ["rt-multi-thread", "time", "macros", "sync"] }
|
||||
toml = "0.5"
|
||||
tracing = { version = "0.1", features = ["attributes"] }
|
||||
tracing-core = "0.1"
|
||||
tracing-futures = { version = "0.2", features = ["std-future", "futures-03"] }
|
||||
tracing-log = "0.1"
|
||||
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"] }
|
||||
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 wallet::Wallet;
|
||||
|
||||
use crate::{bitcoin::timelocks::BlockHeight, config::Config};
|
||||
use crate::{bitcoin::timelocks::BlockHeight, config::ExecutionParams};
|
||||
use ::bitcoin::{
|
||||
hashes::{hex::ToHex, Hash},
|
||||
secp256k1,
|
||||
@ -208,7 +208,11 @@ pub trait WatchForRawTransaction {
|
||||
|
||||
#[async_trait]
|
||||
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]
|
||||
|
@ -4,7 +4,7 @@ use crate::{
|
||||
GetBlockHeight, GetNetwork, GetRawTransaction, SignTxLock, Transaction,
|
||||
TransactionBlockHeight, TxLock, WaitForTransactionFinality, WatchForRawTransaction,
|
||||
},
|
||||
config::Config,
|
||||
config::ExecutionParams,
|
||||
};
|
||||
use ::bitcoin::{util::psbt::PartiallySignedTransaction, Txid};
|
||||
use anyhow::{Context, Result};
|
||||
@ -171,17 +171,21 @@ impl TransactionBlockHeight for Wallet {
|
||||
|
||||
#[async_trait]
|
||||
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
|
||||
|
||||
// Divide by 4 to not check too often yet still be aware of the new block early
|
||||
// on.
|
||||
let mut interval = interval(config.bitcoin_avg_block_time / 4);
|
||||
let mut interval = interval(execution_params.bitcoin_avg_block_time / 4);
|
||||
|
||||
loop {
|
||||
let tx = self.inner.client.get_raw_transaction_verbose(txid).await?;
|
||||
if let Some(confirmations) = tx.confirmations {
|
||||
if confirmations >= config.bitcoin_finality_confirmations {
|
||||
if confirmations >= execution_params.bitcoin_finality_confirmations {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,16 @@
|
||||
use crate::{bitcoin, monero};
|
||||
use libp2p::{core::Multiaddr, PeerId};
|
||||
use url::Url;
|
||||
use std::path::PathBuf;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(structopt::StructOpt, Debug)]
|
||||
pub struct Options {
|
||||
// TODO: Default value should points to proper configuration folder in home folder
|
||||
#[structopt(long = "data-dir", default_value = "./.swap-data/")]
|
||||
pub data_dir: String,
|
||||
#[structopt(
|
||||
long = "data-dir",
|
||||
help = "Provide a custom path to the data directory.",
|
||||
parse(from_os_str)
|
||||
)]
|
||||
pub data_dir: Option<PathBuf>,
|
||||
|
||||
#[structopt(subcommand)]
|
||||
pub cmd: Command,
|
||||
@ -17,18 +20,6 @@ pub struct Options {
|
||||
#[structopt(name = "xmr_btc-swap", about = "XMR BTC atomic swap")]
|
||||
pub enum Command {
|
||||
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")]
|
||||
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))]
|
||||
receive_bitcoin: bitcoin::Amount,
|
||||
|
||||
#[structopt(flatten)]
|
||||
config: Config,
|
||||
},
|
||||
BuyXmr {
|
||||
#[structopt(long = "connect-peer-id")]
|
||||
@ -45,23 +39,14 @@ pub enum Command {
|
||||
#[structopt(long = "connect-addr")]
|
||||
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))]
|
||||
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))]
|
||||
receive_monero: monero::Amount,
|
||||
|
||||
#[structopt(flatten)]
|
||||
config: Config,
|
||||
},
|
||||
History,
|
||||
Resume(Resume),
|
||||
@ -73,20 +58,11 @@ pub enum Resume {
|
||||
#[structopt(long = "swap-id")]
|
||||
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")]
|
||||
listen_addr: Multiaddr,
|
||||
|
||||
#[structopt(flatten)]
|
||||
config: Config,
|
||||
},
|
||||
BuyXmr {
|
||||
#[structopt(long = "swap-id")]
|
||||
@ -98,20 +74,21 @@ pub enum Resume {
|
||||
#[structopt(long = "counterpart-addr")]
|
||||
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(flatten)]
|
||||
config: Config,
|
||||
},
|
||||
}
|
||||
|
||||
#[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> {
|
||||
let amount = bitcoin::Amount::from_str_in(str, ::bitcoin::Denomination::Bitcoin)?;
|
||||
Ok(amount)
|
||||
|
@ -1,23 +1,19 @@
|
||||
pub mod seed;
|
||||
|
||||
use crate::bitcoin::Timelock;
|
||||
use conquer_once::Lazy;
|
||||
use std::time::Duration;
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct Config {
|
||||
pub struct ExecutionParams {
|
||||
pub bob_time_to_act: Duration,
|
||||
pub bitcoin_finality_confirmations: u32,
|
||||
pub bitcoin_avg_block_time: Duration,
|
||||
pub monero_finality_confirmations: u32,
|
||||
pub bitcoin_cancel_timelock: Timelock,
|
||||
pub bitcoin_punish_timelock: Timelock,
|
||||
pub bitcoin_network: bitcoin::Network,
|
||||
pub monero_network: monero::Network,
|
||||
}
|
||||
|
||||
pub trait GetConfig {
|
||||
fn get_config() -> Config;
|
||||
pub trait GetExecutionParams {
|
||||
fn get_execution_params() -> ExecutionParams;
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
@ -29,53 +25,47 @@ pub struct Testnet;
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Regtest;
|
||||
|
||||
impl GetConfig for Mainnet {
|
||||
fn get_config() -> Config {
|
||||
Config {
|
||||
impl GetExecutionParams for Mainnet {
|
||||
fn get_execution_params() -> ExecutionParams {
|
||||
ExecutionParams {
|
||||
bob_time_to_act: *mainnet::BOB_TIME_TO_ACT,
|
||||
bitcoin_finality_confirmations: mainnet::BITCOIN_FINALITY_CONFIRMATIONS,
|
||||
bitcoin_avg_block_time: *mainnet::BITCOIN_AVG_BLOCK_TIME,
|
||||
monero_finality_confirmations: mainnet::MONERO_FINALITY_CONFIRMATIONS,
|
||||
bitcoin_cancel_timelock: mainnet::BITCOIN_CANCEL_TIMELOCK,
|
||||
bitcoin_punish_timelock: mainnet::BITCOIN_PUNISH_TIMELOCK,
|
||||
bitcoin_network: bitcoin::Network::Bitcoin,
|
||||
monero_network: monero::Network::Mainnet,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GetConfig for Testnet {
|
||||
fn get_config() -> Config {
|
||||
Config {
|
||||
impl GetExecutionParams for Testnet {
|
||||
fn get_execution_params() -> ExecutionParams {
|
||||
ExecutionParams {
|
||||
bob_time_to_act: *testnet::BOB_TIME_TO_ACT,
|
||||
bitcoin_finality_confirmations: testnet::BITCOIN_FINALITY_CONFIRMATIONS,
|
||||
bitcoin_avg_block_time: *testnet::BITCOIN_AVG_BLOCK_TIME,
|
||||
monero_finality_confirmations: testnet::MONERO_FINALITY_CONFIRMATIONS,
|
||||
bitcoin_cancel_timelock: testnet::BITCOIN_CANCEL_TIMELOCK,
|
||||
bitcoin_punish_timelock: testnet::BITCOIN_PUNISH_TIMELOCK,
|
||||
bitcoin_network: bitcoin::Network::Testnet,
|
||||
monero_network: monero::Network::Stagenet,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GetConfig for Regtest {
|
||||
fn get_config() -> Config {
|
||||
Config {
|
||||
impl GetExecutionParams for Regtest {
|
||||
fn get_execution_params() -> ExecutionParams {
|
||||
ExecutionParams {
|
||||
bob_time_to_act: *regtest::BOB_TIME_TO_ACT,
|
||||
bitcoin_finality_confirmations: regtest::BITCOIN_FINALITY_CONFIRMATIONS,
|
||||
bitcoin_avg_block_time: *regtest::BITCOIN_AVG_BLOCK_TIME,
|
||||
monero_finality_confirmations: regtest::MONERO_FINALITY_CONFIRMATIONS,
|
||||
bitcoin_cancel_timelock: regtest::BITCOIN_CANCEL_TIMELOCK,
|
||||
bitcoin_punish_timelock: regtest::BITCOIN_PUNISH_TIMELOCK,
|
||||
bitcoin_network: bitcoin::Network::Regtest,
|
||||
monero_network: monero::Network::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod mainnet {
|
||||
use super::*;
|
||||
use crate::config::*;
|
||||
|
||||
// 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));
|
||||
@ -92,7 +82,7 @@ mod mainnet {
|
||||
}
|
||||
|
||||
mod testnet {
|
||||
use super::*;
|
||||
use crate::config::*;
|
||||
|
||||
pub static BOB_TIME_TO_ACT: Lazy<Duration> = Lazy::new(|| Duration::from_secs(60 * 60));
|
||||
|
||||
@ -110,7 +100,7 @@ mod testnet {
|
||||
}
|
||||
|
||||
mod regtest {
|
||||
use super::*;
|
||||
use crate::config::*;
|
||||
|
||||
// In test, we set a shorter time to fail fast
|
||||
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> {
|
||||
if let Some(path) = file.parent() {
|
||||
|
@ -25,5 +25,4 @@ pub mod protocol;
|
||||
pub mod seed;
|
||||
pub mod trace;
|
||||
|
||||
mod fs;
|
||||
mod serde_peer_id;
|
||||
|
125
swap/src/main.rs
125
swap/src/main.rs
@ -12,14 +12,20 @@
|
||||
#![forbid(unsafe_code)]
|
||||
#![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 config::{Config, GetConfig};
|
||||
use database::Database;
|
||||
use fs::{default_config_path, default_data_dir};
|
||||
use log::LevelFilter;
|
||||
use prettytable::{row, Table};
|
||||
use protocol::{alice, bob, bob::Builder, SwapAmounts};
|
||||
use std::sync::Arc;
|
||||
use std::{path::PathBuf, sync::Arc};
|
||||
use structopt::StructOpt;
|
||||
use trace::init_tracing;
|
||||
use tracing::info;
|
||||
@ -27,6 +33,7 @@ use uuid::Uuid;
|
||||
|
||||
pub mod bitcoin;
|
||||
pub mod config;
|
||||
pub mod configuration;
|
||||
pub mod database;
|
||||
pub mod monero;
|
||||
pub mod network;
|
||||
@ -46,40 +53,42 @@ async fn main() -> Result<()> {
|
||||
init_tracing(LevelFilter::Info).expect("initialize tracing");
|
||||
|
||||
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!(
|
||||
"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")
|
||||
.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 {
|
||||
Command::SellXmr {
|
||||
bitcoind_url,
|
||||
bitcoin_wallet_name,
|
||||
monero_wallet_rpc_url,
|
||||
listen_addr,
|
||||
send_monero,
|
||||
receive_bitcoin,
|
||||
config,
|
||||
} => {
|
||||
let swap_amounts = SwapAmounts {
|
||||
xmr: send_monero,
|
||||
btc: receive_bitcoin,
|
||||
};
|
||||
|
||||
let (bitcoin_wallet, monero_wallet) = setup_wallets(
|
||||
bitcoind_url,
|
||||
bitcoin_wallet_name.as_str(),
|
||||
monero_wallet_rpc_url,
|
||||
config,
|
||||
)
|
||||
.await?;
|
||||
let (bitcoin_wallet, monero_wallet) =
|
||||
init_wallets(config.path, bitcoin_network, monero_network).await?;
|
||||
|
||||
let swap_id = Uuid::new_v4();
|
||||
|
||||
@ -90,7 +99,7 @@ async fn main() -> Result<()> {
|
||||
|
||||
let alice_factory = alice::Builder::new(
|
||||
seed,
|
||||
config,
|
||||
execution_params,
|
||||
swap_id,
|
||||
Arc::new(bitcoin_wallet),
|
||||
Arc::new(monero_wallet),
|
||||
@ -106,24 +115,17 @@ async fn main() -> Result<()> {
|
||||
Command::BuyXmr {
|
||||
alice_peer_id,
|
||||
alice_addr,
|
||||
bitcoind_url,
|
||||
bitcoin_wallet_name,
|
||||
monero_wallet_rpc_url,
|
||||
send_bitcoin,
|
||||
receive_monero,
|
||||
config,
|
||||
} => {
|
||||
let swap_amounts = SwapAmounts {
|
||||
btc: send_bitcoin,
|
||||
xmr: receive_monero,
|
||||
};
|
||||
|
||||
let (bitcoin_wallet, monero_wallet) = setup_wallets(
|
||||
bitcoind_url,
|
||||
bitcoin_wallet_name.as_str(),
|
||||
monero_wallet_rpc_url,
|
||||
config,
|
||||
)
|
||||
.await?;
|
||||
let (bitcoin_wallet, monero_wallet) =
|
||||
init_wallets(config.path, bitcoin_network, monero_network).await?;
|
||||
|
||||
let swap_id = Uuid::new_v4();
|
||||
|
||||
@ -140,7 +142,7 @@ async fn main() -> Result<()> {
|
||||
Arc::new(monero_wallet),
|
||||
alice_addr,
|
||||
alice_peer_id,
|
||||
config,
|
||||
execution_params,
|
||||
);
|
||||
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 {
|
||||
swap_id,
|
||||
bitcoind_url,
|
||||
bitcoin_wallet_name,
|
||||
monero_wallet_rpc_url,
|
||||
listen_addr,
|
||||
}) => {
|
||||
let (bitcoin_wallet, monero_wallet) = setup_wallets(
|
||||
bitcoind_url,
|
||||
bitcoin_wallet_name.as_str(),
|
||||
monero_wallet_rpc_url,
|
||||
config,
|
||||
)
|
||||
.await?;
|
||||
}) => {
|
||||
let (bitcoin_wallet, monero_wallet) =
|
||||
init_wallets(config.path, bitcoin_network, monero_network).await?;
|
||||
|
||||
let alice_factory = alice::Builder::new(
|
||||
seed,
|
||||
config,
|
||||
execution_params,
|
||||
swap_id,
|
||||
Arc::new(bitcoin_wallet),
|
||||
Arc::new(monero_wallet),
|
||||
@ -192,19 +187,12 @@ async fn main() -> Result<()> {
|
||||
}
|
||||
Command::Resume(Resume::BuyXmr {
|
||||
swap_id,
|
||||
bitcoind_url,
|
||||
bitcoin_wallet_name,
|
||||
monero_wallet_rpc_url,
|
||||
alice_peer_id,
|
||||
alice_addr,
|
||||
}) => {
|
||||
let (bitcoin_wallet, monero_wallet) = setup_wallets(
|
||||
bitcoind_url,
|
||||
bitcoin_wallet_name.as_str(),
|
||||
monero_wallet_rpc_url,
|
||||
config,
|
||||
)
|
||||
.await?;
|
||||
}) => {
|
||||
let (bitcoin_wallet, monero_wallet) =
|
||||
init_wallets(config.path, bitcoin_network, monero_network).await?;
|
||||
|
||||
let bob_factory = Builder::new(
|
||||
seed,
|
||||
@ -214,7 +202,7 @@ async fn main() -> Result<()> {
|
||||
Arc::new(monero_wallet),
|
||||
alice_addr,
|
||||
alice_peer_id,
|
||||
config,
|
||||
execution_params,
|
||||
);
|
||||
let (swap, event_loop) = bob_factory.build().await?;
|
||||
|
||||
@ -226,21 +214,38 @@ async fn main() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn setup_wallets(
|
||||
bitcoind_url: url::Url,
|
||||
bitcoin_wallet_name: &str,
|
||||
monero_wallet_rpc_url: url::Url,
|
||||
config: Config,
|
||||
async fn init_wallets(
|
||||
config_path: Option<PathBuf>,
|
||||
bitcoin_network: bitcoin::Network,
|
||||
monero_network: monero::Network,
|
||||
) -> Result<(bitcoin::Wallet, monero::Wallet)> {
|
||||
let bitcoin_wallet =
|
||||
bitcoin::Wallet::new(bitcoin_wallet_name, bitcoind_url, config.bitcoin_network).await?;
|
||||
let config_path = if let Some(config_path) = config_path {
|
||||
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?;
|
||||
info!(
|
||||
"Connection to Bitcoin wallet succeeded, 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?;
|
||||
info!(
|
||||
"Connection to Monero wallet succeeded, balance: {}",
|
||||
|
@ -11,7 +11,7 @@ pub use self::{
|
||||
};
|
||||
use crate::{
|
||||
bitcoin,
|
||||
config::Config,
|
||||
config::ExecutionParams,
|
||||
database,
|
||||
database::Database,
|
||||
monero,
|
||||
@ -49,7 +49,7 @@ pub struct Swap {
|
||||
pub event_loop_handle: EventLoopHandle,
|
||||
pub bitcoin_wallet: Arc<bitcoin::Wallet>,
|
||||
pub monero_wallet: Arc<monero::Wallet>,
|
||||
pub config: Config,
|
||||
pub execution_params: ExecutionParams,
|
||||
pub swap_id: Uuid,
|
||||
pub db: Database,
|
||||
}
|
||||
@ -59,7 +59,7 @@ pub struct Builder {
|
||||
identity: Keypair,
|
||||
peer_id: PeerId,
|
||||
db_path: PathBuf,
|
||||
config: Config,
|
||||
execution_params: ExecutionParams,
|
||||
|
||||
listen_address: Multiaddr,
|
||||
|
||||
@ -77,7 +77,7 @@ enum InitParams {
|
||||
impl Builder {
|
||||
pub fn new(
|
||||
seed: Seed,
|
||||
config: Config,
|
||||
execution_params: ExecutionParams,
|
||||
swap_id: Uuid,
|
||||
bitcoin_wallet: Arc<bitcoin::Wallet>,
|
||||
monero_wallet: Arc<monero::Wallet>,
|
||||
@ -93,7 +93,7 @@ impl Builder {
|
||||
identity,
|
||||
peer_id,
|
||||
db_path,
|
||||
config,
|
||||
execution_params,
|
||||
listen_address,
|
||||
bitcoin_wallet,
|
||||
monero_wallet,
|
||||
@ -124,7 +124,7 @@ impl Builder {
|
||||
event_loop_handle,
|
||||
bitcoin_wallet: self.bitcoin_wallet,
|
||||
monero_wallet: self.monero_wallet,
|
||||
config: self.config,
|
||||
execution_params: self.execution_params,
|
||||
db,
|
||||
state: initial_state,
|
||||
swap_id: self.swap_id,
|
||||
@ -154,7 +154,7 @@ impl Builder {
|
||||
event_loop_handle,
|
||||
bitcoin_wallet: self.bitcoin_wallet,
|
||||
monero_wallet: self.monero_wallet,
|
||||
config: self.config,
|
||||
execution_params: self.execution_params,
|
||||
swap_id: self.swap_id,
|
||||
db,
|
||||
},
|
||||
@ -195,8 +195,8 @@ impl Builder {
|
||||
v_a,
|
||||
amounts.btc,
|
||||
amounts.xmr,
|
||||
self.config.bitcoin_cancel_timelock,
|
||||
self.config.bitcoin_punish_timelock,
|
||||
self.execution_params.bitcoin_cancel_timelock,
|
||||
self.execution_params.bitcoin_punish_timelock,
|
||||
redeem_address,
|
||||
punish_address,
|
||||
);
|
||||
|
@ -7,7 +7,7 @@ use crate::{
|
||||
TransactionBlockHeight, TxCancel, TxLock, TxRefund, WaitForTransactionFinality,
|
||||
WatchForRawTransaction,
|
||||
},
|
||||
config::Config,
|
||||
config::ExecutionParams,
|
||||
monero,
|
||||
monero::Transfer,
|
||||
protocol::{
|
||||
@ -33,19 +33,22 @@ pub async fn negotiate(
|
||||
state0: alice::State0,
|
||||
xmr_amount: monero::Amount,
|
||||
event_loop_handle: &mut EventLoopHandle,
|
||||
config: Config,
|
||||
execution_params: ExecutionParams,
|
||||
) -> Result<(PeerId, alice::State3)> {
|
||||
trace!("Starting negotiate");
|
||||
|
||||
// todo: we can move this out, we dont need to timeout here
|
||||
let bob_peer_id = timeout(
|
||||
config.bob_time_to_act,
|
||||
execution_params.bob_time_to_act,
|
||||
event_loop_handle.recv_conn_established(),
|
||||
)
|
||||
.await
|
||||
.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
|
||||
.context("Failed to receive swap request from Bob")??;
|
||||
|
||||
@ -53,8 +56,11 @@ pub async fn negotiate(
|
||||
.send_swap_response(event.channel, SwapResponse { xmr_amount })
|
||||
.await?;
|
||||
|
||||
let (bob_message0, channel) =
|
||||
timeout(config.bob_time_to_act, event_loop_handle.recv_message0()).await??;
|
||||
let (bob_message0, channel) = timeout(
|
||||
execution_params.bob_time_to_act,
|
||||
event_loop_handle.recv_message0(),
|
||||
)
|
||||
.await??;
|
||||
|
||||
let alice_message0 = state0.next_message(&mut OsRng);
|
||||
event_loop_handle
|
||||
@ -63,8 +69,11 @@ pub async fn negotiate(
|
||||
|
||||
let state1 = state0.receive(bob_message0)?;
|
||||
|
||||
let (bob_message1, channel) =
|
||||
timeout(config.bob_time_to_act, event_loop_handle.recv_message1()).await??;
|
||||
let (bob_message1, channel) = timeout(
|
||||
execution_params.bob_time_to_act,
|
||||
event_loop_handle.recv_message1(),
|
||||
)
|
||||
.await??;
|
||||
|
||||
let state2 = state1.receive(bob_message1);
|
||||
|
||||
@ -72,7 +81,11 @@ pub async fn negotiate(
|
||||
.send_message1(channel, state2.next_message())
|
||||
.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)?;
|
||||
|
||||
@ -84,14 +97,14 @@ pub async fn negotiate(
|
||||
pub async fn wait_for_locked_bitcoin<W>(
|
||||
lock_bitcoin_txid: bitcoin::Txid,
|
||||
bitcoin_wallet: Arc<W>,
|
||||
config: Config,
|
||||
execution_params: ExecutionParams,
|
||||
) -> Result<()>
|
||||
where
|
||||
W: WatchForRawTransaction + WaitForTransactionFinality,
|
||||
{
|
||||
// We assume we will see Bob's transaction in the mempool first.
|
||||
timeout(
|
||||
config.bob_time_to_act,
|
||||
execution_params.bob_time_to_act,
|
||||
bitcoin_wallet.watch_for_raw_transaction(lock_bitcoin_txid),
|
||||
)
|
||||
.await
|
||||
@ -99,7 +112,7 @@ where
|
||||
|
||||
// // We saw the transaction in the mempool, waiting for it to be confirmed.
|
||||
bitcoin_wallet
|
||||
.wait_for_transaction_finality(lock_bitcoin_txid, config)
|
||||
.wait_for_transaction_finality(lock_bitcoin_txid, execution_params)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
@ -324,7 +337,7 @@ pub fn build_bitcoin_punish_transaction(
|
||||
pub async fn publish_bitcoin_punish_transaction<W>(
|
||||
punish_tx: bitcoin::Transaction,
|
||||
bitcoin_wallet: Arc<W>,
|
||||
config: Config,
|
||||
execution_params: ExecutionParams,
|
||||
) -> Result<bitcoin::Txid>
|
||||
where
|
||||
W: BroadcastSignedTransaction + WaitForTransactionFinality,
|
||||
@ -334,7 +347,7 @@ where
|
||||
.await?;
|
||||
|
||||
bitcoin_wallet
|
||||
.wait_for_transaction_finality(txid, config)
|
||||
.wait_for_transaction_finality(txid, execution_params)
|
||||
.await?;
|
||||
|
||||
Ok(txid)
|
||||
|
@ -6,7 +6,7 @@ use crate::{
|
||||
timelocks::ExpiredTimelocks, TransactionBlockHeight, WaitForTransactionFinality,
|
||||
WatchForRawTransaction,
|
||||
},
|
||||
config::Config,
|
||||
config::ExecutionParams,
|
||||
database,
|
||||
database::Database,
|
||||
monero,
|
||||
@ -66,7 +66,7 @@ pub async fn run_until(
|
||||
swap.event_loop_handle,
|
||||
swap.bitcoin_wallet,
|
||||
swap.monero_wallet,
|
||||
swap.config,
|
||||
swap.execution_params,
|
||||
swap.swap_id,
|
||||
swap.db,
|
||||
)
|
||||
@ -82,7 +82,7 @@ async fn run_until_internal(
|
||||
mut event_loop_handle: EventLoopHandle,
|
||||
bitcoin_wallet: Arc<bitcoin::Wallet>,
|
||||
monero_wallet: Arc<monero::Wallet>,
|
||||
config: Config,
|
||||
execution_params: ExecutionParams,
|
||||
swap_id: Uuid,
|
||||
db: Database,
|
||||
) -> Result<AliceState> {
|
||||
@ -92,8 +92,13 @@ async fn run_until_internal(
|
||||
} else {
|
||||
match state {
|
||||
AliceState::Started { amounts, state0 } => {
|
||||
let (bob_peer_id, state3) =
|
||||
negotiate(state0, amounts.xmr, &mut event_loop_handle, config).await?;
|
||||
let (bob_peer_id, state3) = negotiate(
|
||||
state0,
|
||||
amounts.xmr,
|
||||
&mut event_loop_handle,
|
||||
execution_params,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let state = AliceState::Negotiated {
|
||||
bob_peer_id,
|
||||
@ -110,7 +115,7 @@ async fn run_until_internal(
|
||||
event_loop_handle,
|
||||
bitcoin_wallet,
|
||||
monero_wallet,
|
||||
config,
|
||||
execution_params,
|
||||
swap_id,
|
||||
db,
|
||||
)
|
||||
@ -121,8 +126,11 @@ async fn run_until_internal(
|
||||
bob_peer_id,
|
||||
amounts,
|
||||
} => {
|
||||
let _ =
|
||||
wait_for_locked_bitcoin(state3.tx_lock.txid(), bitcoin_wallet.clone(), config)
|
||||
let _ = wait_for_locked_bitcoin(
|
||||
state3.tx_lock.txid(),
|
||||
bitcoin_wallet.clone(),
|
||||
execution_params,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let state = AliceState::BtcLocked {
|
||||
@ -140,7 +148,7 @@ async fn run_until_internal(
|
||||
event_loop_handle,
|
||||
bitcoin_wallet,
|
||||
monero_wallet,
|
||||
config,
|
||||
execution_params,
|
||||
swap_id,
|
||||
db,
|
||||
)
|
||||
@ -171,7 +179,7 @@ async fn run_until_internal(
|
||||
event_loop_handle,
|
||||
bitcoin_wallet,
|
||||
monero_wallet,
|
||||
config,
|
||||
execution_params,
|
||||
swap_id,
|
||||
db,
|
||||
)
|
||||
@ -209,7 +217,7 @@ async fn run_until_internal(
|
||||
event_loop_handle,
|
||||
bitcoin_wallet.clone(),
|
||||
monero_wallet,
|
||||
config,
|
||||
execution_params,
|
||||
swap_id,
|
||||
db,
|
||||
)
|
||||
@ -235,7 +243,7 @@ async fn run_until_internal(
|
||||
{
|
||||
Ok(txid) => {
|
||||
let publishded_redeem_tx = bitcoin_wallet
|
||||
.wait_for_transaction_finality(txid, config)
|
||||
.wait_for_transaction_finality(txid, execution_params)
|
||||
.await;
|
||||
|
||||
match publishded_redeem_tx {
|
||||
@ -281,7 +289,7 @@ async fn run_until_internal(
|
||||
event_loop_handle,
|
||||
bitcoin_wallet,
|
||||
monero_wallet,
|
||||
config,
|
||||
execution_params,
|
||||
swap_id,
|
||||
db,
|
||||
)
|
||||
@ -308,7 +316,7 @@ async fn run_until_internal(
|
||||
event_loop_handle,
|
||||
bitcoin_wallet,
|
||||
monero_wallet,
|
||||
config,
|
||||
execution_params,
|
||||
swap_id,
|
||||
db,
|
||||
)
|
||||
@ -342,7 +350,7 @@ async fn run_until_internal(
|
||||
event_loop_handle,
|
||||
bitcoin_wallet.clone(),
|
||||
monero_wallet,
|
||||
config,
|
||||
execution_params,
|
||||
swap_id,
|
||||
db,
|
||||
)
|
||||
@ -367,7 +375,7 @@ async fn run_until_internal(
|
||||
event_loop_handle,
|
||||
bitcoin_wallet.clone(),
|
||||
monero_wallet,
|
||||
config,
|
||||
execution_params,
|
||||
swap_id,
|
||||
db,
|
||||
)
|
||||
@ -402,7 +410,7 @@ async fn run_until_internal(
|
||||
let punish_tx_finalised = publish_bitcoin_punish_transaction(
|
||||
signed_tx_punish,
|
||||
bitcoin_wallet.clone(),
|
||||
config,
|
||||
execution_params,
|
||||
);
|
||||
|
||||
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,
|
||||
bitcoin_wallet.clone(),
|
||||
monero_wallet,
|
||||
config,
|
||||
execution_params,
|
||||
swap_id,
|
||||
db,
|
||||
)
|
||||
@ -446,7 +454,7 @@ async fn run_until_internal(
|
||||
event_loop_handle,
|
||||
bitcoin_wallet.clone(),
|
||||
monero_wallet,
|
||||
config,
|
||||
execution_params,
|
||||
swap_id,
|
||||
db,
|
||||
)
|
||||
|
@ -1,9 +1,7 @@
|
||||
//! Run an XMR/BTC swap in the role of Bob.
|
||||
//! Bob holds BTC and wishes receive XMR.
|
||||
use crate::{
|
||||
bitcoin,
|
||||
config::Config,
|
||||
database,
|
||||
bitcoin, database,
|
||||
database::Database,
|
||||
monero, network,
|
||||
network::{
|
||||
@ -30,7 +28,7 @@ pub use self::{
|
||||
swap::{run, run_until},
|
||||
swap_request::*,
|
||||
};
|
||||
use crate::protocol::alice::TransferProof;
|
||||
use crate::{config::ExecutionParams, protocol::alice::TransferProof};
|
||||
|
||||
mod encrypted_signature;
|
||||
pub mod event_loop;
|
||||
@ -48,7 +46,7 @@ pub struct Swap {
|
||||
pub db: Database,
|
||||
pub bitcoin_wallet: Arc<bitcoin::Wallet>,
|
||||
pub monero_wallet: Arc<monero::Wallet>,
|
||||
pub config: Config,
|
||||
pub execution_params: ExecutionParams,
|
||||
pub swap_id: Uuid,
|
||||
}
|
||||
|
||||
@ -65,7 +63,7 @@ pub struct Builder {
|
||||
monero_wallet: Arc<monero::Wallet>,
|
||||
|
||||
init_params: InitParams,
|
||||
config: Config,
|
||||
execution_params: ExecutionParams,
|
||||
}
|
||||
|
||||
enum InitParams {
|
||||
@ -83,7 +81,7 @@ impl Builder {
|
||||
monero_wallet: Arc<monero::Wallet>,
|
||||
alice_address: Multiaddr,
|
||||
alice_peer_id: PeerId,
|
||||
config: Config,
|
||||
execution_params: ExecutionParams,
|
||||
) -> Self {
|
||||
let identity = network::Seed::new(seed).derive_libp2p_identity();
|
||||
let peer_id = identity.public().into_peer_id();
|
||||
@ -98,7 +96,7 @@ impl Builder {
|
||||
bitcoin_wallet,
|
||||
monero_wallet,
|
||||
init_params: InitParams::None,
|
||||
config,
|
||||
execution_params,
|
||||
}
|
||||
}
|
||||
|
||||
@ -113,7 +111,7 @@ impl Builder {
|
||||
match self.init_params {
|
||||
InitParams::New { swap_amounts } => {
|
||||
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?;
|
||||
|
||||
let (event_loop, event_loop_handle) = self.init_event_loop()?;
|
||||
@ -128,7 +126,7 @@ impl Builder {
|
||||
bitcoin_wallet: self.bitcoin_wallet.clone(),
|
||||
monero_wallet: self.monero_wallet.clone(),
|
||||
swap_id: self.swap_id,
|
||||
config: self.config,
|
||||
execution_params: self.execution_params,
|
||||
},
|
||||
event_loop,
|
||||
))
|
||||
@ -157,7 +155,7 @@ impl Builder {
|
||||
bitcoin_wallet: self.bitcoin_wallet.clone(),
|
||||
monero_wallet: self.monero_wallet.clone(),
|
||||
swap_id: self.swap_id,
|
||||
config: self.config,
|
||||
execution_params: self.execution_params,
|
||||
},
|
||||
event_loop,
|
||||
))
|
||||
@ -183,7 +181,7 @@ impl Builder {
|
||||
&self,
|
||||
btc_to_swap: bitcoin::Amount,
|
||||
xmr_to_swap: monero::Amount,
|
||||
config: Config,
|
||||
execution_params: ExecutionParams,
|
||||
) -> Result<BobState> {
|
||||
let amounts = SwapAmounts {
|
||||
btc: btc_to_swap,
|
||||
@ -195,10 +193,10 @@ impl Builder {
|
||||
&mut OsRng,
|
||||
btc_to_swap,
|
||||
xmr_to_swap,
|
||||
config.bitcoin_cancel_timelock,
|
||||
config.bitcoin_punish_timelock,
|
||||
execution_params.bitcoin_cancel_timelock,
|
||||
execution_params.bitcoin_punish_timelock,
|
||||
refund_address,
|
||||
config.monero_finality_confirmations,
|
||||
execution_params.monero_finality_confirmations,
|
||||
);
|
||||
|
||||
Ok(BobState::Started { state0, amounts })
|
||||
|
@ -6,7 +6,7 @@ use crate::{
|
||||
GetBlockHeight, GetNetwork, GetRawTransaction, Transaction, TransactionBlockHeight,
|
||||
TxCancel, Txid, WatchForRawTransaction,
|
||||
},
|
||||
config::Config,
|
||||
config::ExecutionParams,
|
||||
monero,
|
||||
monero::{monero_private_key, TransferProof},
|
||||
protocol::{alice, bob, bob::EncryptedSignature, SwapAmounts},
|
||||
@ -556,7 +556,11 @@ impl State4 {
|
||||
.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
|
||||
W: bitcoin::BroadcastSignedTransaction + bitcoin::WaitForTransactionFinality,
|
||||
{
|
||||
@ -581,7 +585,7 @@ impl State4 {
|
||||
.await?;
|
||||
|
||||
bitcoin_wallet
|
||||
.wait_for_transaction_finality(txid, config)
|
||||
.wait_for_transaction_finality(txid, execution_params)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
bitcoin,
|
||||
bitcoin::timelocks::ExpiredTimelocks,
|
||||
config::Config,
|
||||
config::ExecutionParams,
|
||||
database::{Database, Swap},
|
||||
monero,
|
||||
protocol::{
|
||||
@ -46,7 +46,7 @@ pub async fn run_until(
|
||||
swap.monero_wallet,
|
||||
OsRng,
|
||||
swap.swap_id,
|
||||
swap.config,
|
||||
swap.execution_params,
|
||||
)
|
||||
.await
|
||||
}
|
||||
@ -63,7 +63,7 @@ async fn run_until_internal<R>(
|
||||
monero_wallet: Arc<monero::Wallet>,
|
||||
mut rng: R,
|
||||
swap_id: Uuid,
|
||||
config: Config,
|
||||
execution_params: ExecutionParams,
|
||||
) -> Result<BobState>
|
||||
where
|
||||
R: RngCore + CryptoRng + Send,
|
||||
@ -97,7 +97,7 @@ where
|
||||
monero_wallet,
|
||||
rng,
|
||||
swap_id,
|
||||
config,
|
||||
execution_params,
|
||||
)
|
||||
.await
|
||||
}
|
||||
@ -119,7 +119,7 @@ where
|
||||
monero_wallet,
|
||||
rng,
|
||||
swap_id,
|
||||
config,
|
||||
execution_params,
|
||||
)
|
||||
.await
|
||||
}
|
||||
@ -172,7 +172,7 @@ where
|
||||
monero_wallet,
|
||||
rng,
|
||||
swap_id,
|
||||
config,
|
||||
execution_params,
|
||||
)
|
||||
.await
|
||||
}
|
||||
@ -219,7 +219,7 @@ where
|
||||
monero_wallet,
|
||||
rng,
|
||||
swap_id,
|
||||
config,
|
||||
execution_params,
|
||||
)
|
||||
.await
|
||||
}
|
||||
@ -262,7 +262,7 @@ where
|
||||
monero_wallet,
|
||||
rng,
|
||||
swap_id,
|
||||
config,
|
||||
execution_params,
|
||||
)
|
||||
.await
|
||||
}
|
||||
@ -298,7 +298,7 @@ where
|
||||
monero_wallet,
|
||||
rng,
|
||||
swap_id,
|
||||
config,
|
||||
execution_params,
|
||||
)
|
||||
.await
|
||||
}
|
||||
@ -320,7 +320,7 @@ where
|
||||
monero_wallet,
|
||||
rng,
|
||||
swap_id,
|
||||
config,
|
||||
execution_params,
|
||||
)
|
||||
.await
|
||||
}
|
||||
@ -346,7 +346,7 @@ where
|
||||
monero_wallet,
|
||||
rng,
|
||||
swap_id,
|
||||
config,
|
||||
execution_params,
|
||||
)
|
||||
.await
|
||||
}
|
||||
@ -357,7 +357,9 @@ where
|
||||
bail!("Internal error: canceled state reached before cancel timelock was expired");
|
||||
}
|
||||
ExpiredTimelocks::Cancel => {
|
||||
state.refund_btc(bitcoin_wallet.as_ref(), config).await?;
|
||||
state
|
||||
.refund_btc(bitcoin_wallet.as_ref(), execution_params)
|
||||
.await?;
|
||||
BobState::BtcRefunded(state)
|
||||
}
|
||||
ExpiredTimelocks::Punish => BobState::BtcPunished {
|
||||
@ -376,7 +378,7 @@ where
|
||||
monero_wallet,
|
||||
rng,
|
||||
swap_id,
|
||||
config,
|
||||
execution_params,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ use swap::{
|
||||
bitcoin,
|
||||
bitcoin::Timelock,
|
||||
config,
|
||||
config::{Config, GetConfig},
|
||||
config::{ExecutionParams, GetExecutionParams},
|
||||
monero,
|
||||
protocol::{alice, alice::AliceState, bob, bob::BobState, SwapAmounts},
|
||||
seed::Seed,
|
||||
@ -29,7 +29,7 @@ pub struct StartingBalances {
|
||||
|
||||
struct AliceParams {
|
||||
seed: Seed,
|
||||
config: Config,
|
||||
execution_params: ExecutionParams,
|
||||
swap_id: Uuid,
|
||||
bitcoin_wallet: Arc<bitcoin::Wallet>,
|
||||
monero_wallet: Arc<monero::Wallet>,
|
||||
@ -41,7 +41,7 @@ impl AliceParams {
|
||||
pub fn builder(&self) -> alice::Builder {
|
||||
alice::Builder::new(
|
||||
self.seed,
|
||||
self.config,
|
||||
self.execution_params,
|
||||
self.swap_id,
|
||||
self.bitcoin_wallet.clone(),
|
||||
self.monero_wallet.clone(),
|
||||
@ -64,7 +64,7 @@ struct BobParams {
|
||||
monero_wallet: Arc<monero::Wallet>,
|
||||
alice_address: Multiaddr,
|
||||
alice_peer_id: PeerId,
|
||||
config: Config,
|
||||
execution_params: ExecutionParams,
|
||||
}
|
||||
|
||||
impl BobParams {
|
||||
@ -77,7 +77,7 @@ impl BobParams {
|
||||
self.monero_wallet.clone(),
|
||||
self.alice_address.clone(),
|
||||
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
|
||||
T: Fn(TestContext) -> F,
|
||||
F: Future<Output = ()>,
|
||||
C: GetConfig,
|
||||
C: GetExecutionParams,
|
||||
{
|
||||
let cli = Cli::default();
|
||||
|
||||
let _guard = init_tracing();
|
||||
|
||||
let config = C::get_config();
|
||||
let execution_params = C::get_execution_params();
|
||||
|
||||
let (monero, containers) = testutils::init_containers(&cli).await;
|
||||
|
||||
@ -334,18 +334,17 @@ where
|
||||
.parse()
|
||||
.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",
|
||||
&containers.bitcoind,
|
||||
&monero,
|
||||
alice_starting_balances.clone(),
|
||||
config,
|
||||
)
|
||||
.await;
|
||||
|
||||
let alice_params = AliceParams {
|
||||
seed: Seed::random().unwrap(),
|
||||
config,
|
||||
execution_params,
|
||||
swap_id: Uuid::new_v4(),
|
||||
bitcoin_wallet: alice_bitcoin_wallet.clone(),
|
||||
monero_wallet: alice_monero_wallet.clone(),
|
||||
@ -358,12 +357,11 @@ where
|
||||
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",
|
||||
&containers.bitcoind,
|
||||
&monero,
|
||||
bob_starting_balances.clone(),
|
||||
config,
|
||||
)
|
||||
.await;
|
||||
|
||||
@ -375,7 +373,7 @@ where
|
||||
monero_wallet: bob_monero_wallet.clone(),
|
||||
alice_address: alice_params.listen_address.clone(),
|
||||
alice_peer_id: alice_params.peer_id(),
|
||||
config,
|
||||
execution_params,
|
||||
};
|
||||
|
||||
let test = TestContext {
|
||||
@ -403,12 +401,11 @@ async fn init_containers(cli: &Cli) -> (Monero, Containers<'_>) {
|
||||
(monero, Containers { bitcoind, monerods })
|
||||
}
|
||||
|
||||
async fn init_wallets(
|
||||
async fn init_test_wallets(
|
||||
name: &str,
|
||||
bitcoind: &Bitcoind<'_>,
|
||||
monero: &Monero,
|
||||
starting_balances: StartingBalances,
|
||||
config: Config,
|
||||
) -> (Arc<bitcoin::Wallet>, Arc<monero::Wallet>) {
|
||||
monero
|
||||
.init(vec![(name, starting_balances.xmr.as_piconero())])
|
||||
@ -417,11 +414,11 @@ async fn init_wallets(
|
||||
|
||||
let xmr_wallet = Arc::new(swap::monero::Wallet {
|
||||
inner: monero.wallet(name).unwrap().client(),
|
||||
network: config.monero_network,
|
||||
network: monero::Network::default(),
|
||||
});
|
||||
|
||||
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
|
||||
.unwrap(),
|
||||
);
|
||||
@ -517,34 +514,34 @@ pub mod bob_run_until {
|
||||
|
||||
pub struct SlowCancelConfig;
|
||||
|
||||
impl GetConfig for SlowCancelConfig {
|
||||
fn get_config() -> Config {
|
||||
Config {
|
||||
impl GetExecutionParams for SlowCancelConfig {
|
||||
fn get_execution_params() -> ExecutionParams {
|
||||
ExecutionParams {
|
||||
bitcoin_cancel_timelock: Timelock::new(180),
|
||||
..config::Regtest::get_config()
|
||||
..config::Regtest::get_execution_params()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FastCancelConfig;
|
||||
|
||||
impl GetConfig for FastCancelConfig {
|
||||
fn get_config() -> Config {
|
||||
Config {
|
||||
impl GetExecutionParams for FastCancelConfig {
|
||||
fn get_execution_params() -> ExecutionParams {
|
||||
ExecutionParams {
|
||||
bitcoin_cancel_timelock: Timelock::new(1),
|
||||
..config::Regtest::get_config()
|
||||
..config::Regtest::get_execution_params()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FastPunishConfig;
|
||||
|
||||
impl GetConfig for FastPunishConfig {
|
||||
fn get_config() -> Config {
|
||||
Config {
|
||||
impl GetExecutionParams for FastPunishConfig {
|
||||
fn get_execution_params() -> ExecutionParams {
|
||||
ExecutionParams {
|
||||
bitcoin_cancel_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