mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2024-10-01 01:45:40 -04:00
Merge #115
115: Monero wallet network, Testnet r=da-kami a=da-kami Add network for monero and switch application to run on Bitcoin `testnet3` and Monero `stagenet`. Co-authored-by: Daniel Karzel <daniel@comit.network>
This commit is contained in:
commit
184f179044
@ -105,9 +105,9 @@ where
|
||||
.context("Failed to find lock Bitcoin tx")?;
|
||||
|
||||
// // We saw the transaction in the mempool, waiting for it to be confirmed.
|
||||
// bitcoin_wallet
|
||||
// .wait_for_transaction_finality(lock_bitcoin_txid, config)
|
||||
// .await;
|
||||
bitcoin_wallet
|
||||
.wait_for_transaction_finality(lock_bitcoin_txid, config)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ impl SignTxLock for Wallet {
|
||||
impl BroadcastSignedTransaction for Wallet {
|
||||
async fn broadcast_signed_transaction(&self, transaction: Transaction) -> Result<Txid> {
|
||||
let txid = self.inner.send_raw_transaction(transaction).await?;
|
||||
tracing::debug!("Bitcoin tx broadcasted! TXID = {}", txid);
|
||||
tracing::info!("Bitcoin tx broadcasted! TXID = {}", txid);
|
||||
Ok(txid)
|
||||
}
|
||||
}
|
||||
|
@ -50,7 +50,10 @@ pub enum Command {
|
||||
#[structopt(long = "bitcoin-wallet-name")]
|
||||
bitcoin_wallet_name: String,
|
||||
|
||||
#[structopt(long = "monerod", default_value = "http://127.0.0.1:18083/json_rpc")]
|
||||
#[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))]
|
||||
|
@ -40,11 +40,11 @@ extern crate prettytable;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
init_tracing(LevelFilter::Trace).expect("initialize tracing");
|
||||
init_tracing(LevelFilter::Info).expect("initialize tracing");
|
||||
|
||||
let opt = Options::from_args();
|
||||
|
||||
let config = Config::mainnet();
|
||||
let config = Config::testnet();
|
||||
|
||||
info!("Database: {}", opt.db_path);
|
||||
let db = Database::open(std::path::Path::new(opt.db_path.as_str()))
|
||||
@ -257,7 +257,7 @@ async fn setup_wallets(
|
||||
);
|
||||
let bitcoin_wallet = Arc::new(bitcoin_wallet);
|
||||
|
||||
let monero_wallet = monero::Wallet::new(monero_wallet_rpc_url);
|
||||
let monero_wallet = monero::Wallet::new(monero_wallet_rpc_url, config.monero_network);
|
||||
let monero_balance = monero_wallet.get_balance().await?;
|
||||
info!(
|
||||
"Connection to Monero wallet succeeded, balance: {}",
|
||||
|
@ -8,16 +8,22 @@ use url::Url;
|
||||
pub use xmr_btc::monero::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Wallet(pub wallet::Client);
|
||||
pub struct Wallet {
|
||||
pub inner: wallet::Client,
|
||||
pub network: Network,
|
||||
}
|
||||
|
||||
impl Wallet {
|
||||
pub fn new(url: Url) -> Self {
|
||||
Self(wallet::Client::new(url))
|
||||
pub fn new(url: Url, network: Network) -> Self {
|
||||
Self {
|
||||
inner: wallet::Client::new(url),
|
||||
network,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the balance of the primary account.
|
||||
pub async fn get_balance(&self) -> Result<Amount> {
|
||||
let amount = self.0.get_balance(0).await?;
|
||||
let amount = self.inner.get_balance(0).await?;
|
||||
|
||||
Ok(Amount::from_piconero(amount))
|
||||
}
|
||||
@ -32,15 +38,15 @@ impl Transfer for Wallet {
|
||||
amount: Amount,
|
||||
) -> Result<(TransferProof, Amount)> {
|
||||
let destination_address =
|
||||
Address::standard(Network::Mainnet, public_spend_key, public_view_key.into());
|
||||
Address::standard(self.network, public_spend_key, public_view_key.into());
|
||||
|
||||
let res = self
|
||||
.0
|
||||
.inner
|
||||
.transfer(0, amount.as_piconero(), &destination_address.to_string())
|
||||
.await?;
|
||||
|
||||
let tx_hash = TxHash(res.tx_hash);
|
||||
tracing::debug!("Monero tx broadcasted!, tx hash: {:?}", tx_hash);
|
||||
tracing::info!("Monero tx broadcasted!, tx hash: {:?}", tx_hash);
|
||||
let tx_key = PrivateKey::from_str(&res.tx_key)?;
|
||||
|
||||
let fee = Amount::from_piconero(res.fee);
|
||||
@ -62,10 +68,10 @@ impl CreateWalletForOutput for Wallet {
|
||||
let public_spend_key = PublicKey::from_private_key(&private_spend_key);
|
||||
let public_view_key = PublicKey::from_private_key(&private_view_key.into());
|
||||
|
||||
let address = Address::standard(Network::Mainnet, public_spend_key, public_view_key);
|
||||
let address = Address::standard(self.network, public_spend_key, public_view_key);
|
||||
|
||||
let _ = self
|
||||
.0
|
||||
.inner
|
||||
.generate_from_keys(
|
||||
&address.to_string(),
|
||||
&private_spend_key.to_string(),
|
||||
@ -96,14 +102,14 @@ impl WatchForTransfer for Wallet {
|
||||
InsufficientFunds { expected: Amount, actual: Amount },
|
||||
}
|
||||
|
||||
let address = Address::standard(Network::Mainnet, public_spend_key, public_view_key.into());
|
||||
let address = Address::standard(self.network, public_spend_key, public_view_key.into());
|
||||
|
||||
let res = (|| async {
|
||||
// NOTE: Currently, this is conflating IO errors with the transaction not being
|
||||
// in the blockchain yet, or not having enough confirmations on it. All these
|
||||
// errors warrant a retry, but the strategy should probably differ per case
|
||||
let proof = self
|
||||
.0
|
||||
.inner
|
||||
.check_tx_key(
|
||||
&String::from(transfer_proof.tx_hash()),
|
||||
&transfer_proof.tx_key().to_string(),
|
||||
|
@ -15,8 +15,8 @@ pub fn init_tracing(level: log::LevelFilter) -> anyhow::Result<()> {
|
||||
let is_terminal = atty::is(atty::Stream::Stderr);
|
||||
let subscriber = FmtSubscriber::builder()
|
||||
.with_env_filter(format!(
|
||||
"swap={},xmr_btc={},http=warn,warp=warn",
|
||||
level, level
|
||||
"swap={},xmr_btc={},monero_harness={},bitcoin_harness={},http=warn,warp=warn",
|
||||
level, level, level, level
|
||||
))
|
||||
.with_writer(std::io::stderr)
|
||||
.with_ansi(is_terminal)
|
||||
|
@ -110,7 +110,7 @@ async fn happy_path() {
|
||||
|
||||
let xmr_alice_final = alice_xmr_wallet.as_ref().get_balance().await.unwrap();
|
||||
|
||||
bob_xmr_wallet.as_ref().0.refresh().await.unwrap();
|
||||
bob_xmr_wallet.as_ref().inner.refresh().await.unwrap();
|
||||
let xmr_bob_final = bob_xmr_wallet.as_ref().get_balance().await.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
|
@ -150,7 +150,7 @@ async fn given_alice_restarts_after_encsig_is_learned_resume_swap() {
|
||||
assert!(btc_bob_final <= bob_btc_starting_balance - btc_to_swap);
|
||||
|
||||
let xmr_alice_final = alice_xmr_wallet.as_ref().get_balance().await.unwrap();
|
||||
bob_xmr_wallet_clone.as_ref().0.refresh().await.unwrap();
|
||||
bob_xmr_wallet_clone.as_ref().inner.refresh().await.unwrap();
|
||||
let xmr_bob_final = bob_xmr_wallet_clone.as_ref().get_balance().await.unwrap();
|
||||
|
||||
assert!(xmr_alice_final <= alice_xmr_starting_balance - xmr_to_swap);
|
||||
|
@ -153,7 +153,7 @@ async fn given_bob_restarts_after_encsig_is_sent_resume_swap() {
|
||||
assert!(btc_bob_final <= bob_btc_starting_balance - btc_to_swap);
|
||||
|
||||
let xmr_alice_final = alice_xmr_wallet_clone.as_ref().get_balance().await.unwrap();
|
||||
bob_xmr_wallet_clone.as_ref().0.refresh().await.unwrap();
|
||||
bob_xmr_wallet_clone.as_ref().inner.refresh().await.unwrap();
|
||||
let xmr_bob_final = bob_xmr_wallet_clone.as_ref().get_balance().await.unwrap();
|
||||
|
||||
assert!(xmr_alice_final <= alice_xmr_starting_balance - xmr_to_swap);
|
||||
|
@ -138,7 +138,7 @@ async fn given_bob_restarts_after_xmr_is_locked_resume_swap() {
|
||||
|
||||
let xmr_alice_final = alice_xmr_wallet.as_ref().get_balance().await.unwrap();
|
||||
|
||||
bob_xmr_wallet.as_ref().0.refresh().await.unwrap();
|
||||
bob_xmr_wallet.as_ref().inner.refresh().await.unwrap();
|
||||
let xmr_bob_final = bob_xmr_wallet.as_ref().get_balance().await.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
|
@ -156,11 +156,11 @@ async fn given_alice_restarts_after_xmr_is_locked_abort_swap() {
|
||||
- bitcoin::Amount::from_sat(2 * bitcoin::TX_FEE);
|
||||
assert!(btc_bob_final_alice_submitted_cancel || btc_bob_final_bob_submitted_cancel);
|
||||
|
||||
alice_xmr_wallet.as_ref().0.refresh().await.unwrap();
|
||||
alice_xmr_wallet.as_ref().inner.refresh().await.unwrap();
|
||||
let xmr_alice_final = alice_xmr_wallet.as_ref().get_balance().await.unwrap();
|
||||
assert_eq!(xmr_alice_final, xmr_to_swap);
|
||||
|
||||
bob_xmr_wallet.as_ref().0.refresh().await.unwrap();
|
||||
bob_xmr_wallet.as_ref().inner.refresh().await.unwrap();
|
||||
let xmr_bob_final = bob_xmr_wallet.as_ref().get_balance().await.unwrap();
|
||||
assert_eq!(xmr_bob_final, bob_xmr_starting_balance);
|
||||
}
|
||||
|
@ -46,7 +46,10 @@ pub async fn init_wallets(
|
||||
}
|
||||
};
|
||||
|
||||
let xmr_wallet = Arc::new(swap::monero::Wallet(monero.wallet(name).unwrap().client()));
|
||||
let xmr_wallet = Arc::new(swap::monero::Wallet {
|
||||
inner: monero.wallet(name).unwrap().client(),
|
||||
network: config.monero_network,
|
||||
});
|
||||
|
||||
let btc_wallet = Arc::new(
|
||||
swap::bitcoin::Wallet::new(name, bitcoind.node_url.clone(), config.bitcoin_network)
|
||||
|
@ -11,6 +11,7 @@ pub struct Config {
|
||||
pub bitcoin_cancel_timelock: Timelock,
|
||||
pub bitcoin_punish_timelock: Timelock,
|
||||
pub bitcoin_network: ::bitcoin::Network,
|
||||
pub monero_network: ::monero::Network,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
@ -26,6 +27,23 @@ impl Config {
|
||||
bitcoin_cancel_timelock: mainnet::BITCOIN_CANCEL_TIMELOCK,
|
||||
bitcoin_punish_timelock: mainnet::BITCOIN_PUNISH_TIMELOCK,
|
||||
bitcoin_network: ::bitcoin::Network::Bitcoin,
|
||||
monero_network: ::monero::Network::Mainnet,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn testnet() -> Self {
|
||||
Self {
|
||||
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,
|
||||
// We apply a scaling factor (1.5) so that the swap is not aborted when the
|
||||
// blockchain is slow
|
||||
monero_max_finality_time: (*testnet::MONERO_AVG_BLOCK_TIME).mul_f64(1.5)
|
||||
* 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,
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,6 +59,7 @@ impl Config {
|
||||
bitcoin_cancel_timelock: regtest::BITCOIN_CANCEL_TIMELOCK,
|
||||
bitcoin_punish_timelock: regtest::BITCOIN_PUNISH_TIMELOCK,
|
||||
bitcoin_network: ::bitcoin::Network::Regtest,
|
||||
monero_network: ::monero::Network::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -64,6 +83,26 @@ mod mainnet {
|
||||
pub static BITCOIN_PUNISH_TIMELOCK: Timelock = Timelock::new(72);
|
||||
}
|
||||
|
||||
mod testnet {
|
||||
use super::*;
|
||||
|
||||
pub static BOB_TIME_TO_ACT: Lazy<Duration> = Lazy::new(|| Duration::from_secs(5 * 60));
|
||||
|
||||
// This does not reflect recommended values for mainnet!
|
||||
pub static BITCOIN_FINALITY_CONFIRMATIONS: u32 = 1;
|
||||
|
||||
pub static BITCOIN_AVG_BLOCK_TIME: Lazy<Duration> = Lazy::new(|| Duration::from_secs(5 * 60));
|
||||
|
||||
// This does not reflect recommended values for mainnet!
|
||||
pub static MONERO_FINALITY_CONFIRMATIONS: u32 = 5;
|
||||
|
||||
pub static MONERO_AVG_BLOCK_TIME: Lazy<Duration> = Lazy::new(|| Duration::from_secs(2 * 60));
|
||||
|
||||
// This does not reflect recommended values for mainnet!
|
||||
pub static BITCOIN_CANCEL_TIMELOCK: Timelock = Timelock::new(6);
|
||||
pub static BITCOIN_PUNISH_TIMELOCK: Timelock = Timelock::new(6);
|
||||
}
|
||||
|
||||
mod regtest {
|
||||
use super::*;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user