Separate settings from config

Settings to be used internally to pass configuration to swap execution.
Config to be used for reading/writing configuration parameters to file.
Eventually the settings can be created from config.
This commit is contained in:
Daniel Karzel 2021-01-27 13:33:32 +11:00
parent 73f89fefda
commit 049b7bc329
13 changed files with 224 additions and 215 deletions

View File

@ -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, settings::Protocol};
use ::bitcoin::{
hashes::{hex::ToHex, Hash},
secp256k1,
@ -208,7 +208,7 @@ 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, settings: Protocol) -> Result<()>;
}
#[async_trait]

View File

@ -4,7 +4,7 @@ use crate::{
GetBlockHeight, GetNetwork, GetRawTransaction, SignTxLock, Transaction,
TransactionBlockHeight, TxLock, WaitForTransactionFinality, WatchForRawTransaction,
},
config::Config,
settings,
};
use ::bitcoin::{util::psbt::PartiallySignedTransaction, Txid};
use anyhow::{Context, Result};
@ -170,17 +170,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,
settings: settings::Protocol,
) -> 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(settings.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 >= settings.bitcoin_finality_confirmations {
break;
}
}

View File

@ -1,110 +1 @@
pub mod seed;
use crate::bitcoin::Timelock;
use conquer_once::Lazy;
use std::time::Duration;
#[derive(Debug, Copy, Clone)]
pub struct Config {
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,
}
impl Config {
pub fn mainnet() -> Self {
Self {
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,
}
}
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,
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,
}
}
pub fn regtest() -> Self {
Self {
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::*;
// 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 BITCOIN_FINALITY_CONFIRMATIONS: u32 = 3;
pub static BITCOIN_AVG_BLOCK_TIME: Lazy<Duration> = Lazy::new(|| Duration::from_secs(10 * 60));
pub static MONERO_FINALITY_CONFIRMATIONS: u32 = 15;
// Set to 12 hours, arbitrary value to be reviewed properly
pub static BITCOIN_CANCEL_TIMELOCK: Timelock = Timelock::new(72);
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(60 * 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;
// This does not reflect recommended values for mainnet!
pub static BITCOIN_CANCEL_TIMELOCK: Timelock = Timelock::new(12);
pub static BITCOIN_PUNISH_TIMELOCK: Timelock = Timelock::new(6);
}
mod regtest {
use super::*;
// 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 BITCOIN_FINALITY_CONFIRMATIONS: u32 = 1;
pub static BITCOIN_AVG_BLOCK_TIME: Lazy<Duration> = Lazy::new(|| Duration::from_secs(5));
pub static MONERO_FINALITY_CONFIRMATIONS: u32 = 1;
pub static BITCOIN_CANCEL_TIMELOCK: Timelock = Timelock::new(50);
pub static BITCOIN_PUNISH_TIMELOCK: Timelock = Timelock::new(50);
}

View File

@ -23,6 +23,7 @@ pub mod monero;
pub mod network;
pub mod protocol;
pub mod seed;
pub mod settings;
pub mod trace;
mod fs;

View File

@ -14,7 +14,6 @@
use crate::cli::{Command, Options, Resume};
use anyhow::{Context, Result};
use config::Config;
use database::Database;
use prettytable::{row, Table};
use protocol::{alice, bob, bob::Builder, SwapAmounts};
@ -31,6 +30,7 @@ pub mod monero;
pub mod network;
pub mod protocol;
pub mod seed;
pub mod settings;
pub mod trace;
mod cli;
@ -45,7 +45,7 @@ async fn main() -> Result<()> {
init_tracing(LevelFilter::Info).expect("initialize tracing");
let opt = Options::from_args();
let config = Config::testnet();
let settings = settings::Protocol::testnet();
info!(
"Database and Seed will be stored in directory: {}",
@ -76,7 +76,7 @@ async fn main() -> Result<()> {
bitcoind_url,
bitcoin_wallet_name.as_str(),
monero_wallet_rpc_url,
config,
settings,
)
.await?;
@ -89,7 +89,7 @@ async fn main() -> Result<()> {
let alice_factory = alice::Builder::new(
seed,
config,
settings,
swap_id,
Arc::new(bitcoin_wallet),
Arc::new(monero_wallet),
@ -121,7 +121,7 @@ async fn main() -> Result<()> {
bitcoind_url,
bitcoin_wallet_name.as_str(),
monero_wallet_rpc_url,
config,
settings,
)
.await?;
@ -140,7 +140,7 @@ async fn main() -> Result<()> {
Arc::new(monero_wallet),
alice_addr,
alice_peer_id,
config,
settings,
);
let (swap, event_loop) = bob_factory.with_init_params(swap_amounts).build().await?;
@ -172,13 +172,13 @@ async fn main() -> Result<()> {
bitcoind_url,
bitcoin_wallet_name.as_str(),
monero_wallet_rpc_url,
config,
settings,
)
.await?;
let alice_factory = alice::Builder::new(
seed,
config,
settings,
swap_id,
Arc::new(bitcoin_wallet),
Arc::new(monero_wallet),
@ -203,7 +203,7 @@ async fn main() -> Result<()> {
bitcoind_url,
bitcoin_wallet_name.as_str(),
monero_wallet_rpc_url,
config,
settings,
)
.await?;
@ -215,7 +215,7 @@ async fn main() -> Result<()> {
Arc::new(monero_wallet),
alice_addr,
alice_peer_id,
config,
settings,
);
let (swap, event_loop) = bob_factory.build().await?;
@ -231,17 +231,17 @@ async fn setup_wallets(
bitcoind_url: url::Url,
bitcoin_wallet_name: &str,
monero_wallet_rpc_url: url::Url,
config: Config,
settings: settings::Protocol,
) -> Result<(bitcoin::Wallet, monero::Wallet)> {
let bitcoin_wallet =
bitcoin::Wallet::new(bitcoin_wallet_name, bitcoind_url, config.bitcoin_network).await?;
bitcoin::Wallet::new(bitcoin_wallet_name, bitcoind_url, settings.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(monero_wallet_rpc_url, settings.monero_network);
let monero_balance = monero_wallet.get_balance().await?;
info!(
"Connection to Monero wallet succeeded, balance: {}",

View File

@ -10,9 +10,7 @@ pub use self::{
transfer_proof::TransferProof,
};
use crate::{
bitcoin,
config::Config,
database,
bitcoin, database,
database::Database,
monero,
network::{
@ -23,6 +21,7 @@ use crate::{
},
protocol::{bob, bob::EncryptedSignature, SwapAmounts},
seed::Seed,
settings,
};
use anyhow::{bail, Result};
use libp2p::{
@ -49,7 +48,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 settings: settings::Protocol,
pub swap_id: Uuid,
pub db: Database,
}
@ -59,7 +58,7 @@ pub struct Builder {
identity: Keypair,
peer_id: PeerId,
db_path: PathBuf,
config: Config,
settings: settings::Protocol,
listen_address: Multiaddr,
@ -77,7 +76,7 @@ enum InitParams {
impl Builder {
pub async fn new(
seed: Seed,
config: Config,
settings: settings::Protocol,
swap_id: Uuid,
bitcoin_wallet: Arc<bitcoin::Wallet>,
monero_wallet: Arc<monero::Wallet>,
@ -93,7 +92,7 @@ impl Builder {
identity,
peer_id,
db_path,
config,
settings,
listen_address,
bitcoin_wallet,
monero_wallet,
@ -124,7 +123,7 @@ impl Builder {
event_loop_handle,
bitcoin_wallet: self.bitcoin_wallet,
monero_wallet: self.monero_wallet,
config: self.config,
settings: self.settings,
db,
state: initial_state,
swap_id: self.swap_id,
@ -154,7 +153,7 @@ impl Builder {
event_loop_handle,
bitcoin_wallet: self.bitcoin_wallet,
monero_wallet: self.monero_wallet,
config: self.config,
settings: self.settings,
swap_id: self.swap_id,
db,
},
@ -195,8 +194,8 @@ impl Builder {
v_a,
amounts.btc,
amounts.xmr,
self.config.bitcoin_cancel_timelock,
self.config.bitcoin_punish_timelock,
self.settings.bitcoin_cancel_timelock,
self.settings.bitcoin_punish_timelock,
redeem_address,
punish_address,
);

View File

@ -7,7 +7,6 @@ use crate::{
TransactionBlockHeight, TxCancel, TxLock, TxRefund, WaitForTransactionFinality,
WatchForRawTransaction,
},
config::Config,
monero,
monero::Transfer,
protocol::{
@ -15,6 +14,7 @@ use crate::{
alice::{event_loop::EventLoopHandle, SwapResponse, TransferProof},
SwapAmounts,
},
settings,
};
use anyhow::{Context, Result};
use ecdsa_fun::{adaptor::Adaptor, nonce::Deterministic};
@ -33,19 +33,19 @@ pub async fn negotiate(
state0: alice::State0,
xmr_amount: monero::Amount,
event_loop_handle: &mut EventLoopHandle,
config: Config,
settings: settings::Protocol,
) -> 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,
settings.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(settings.bob_time_to_act, event_loop_handle.recv_request())
.await
.context("Failed to receive swap request from Bob")??;
@ -54,7 +54,7 @@ pub async fn negotiate(
.await?;
let (bob_message0, channel) =
timeout(config.bob_time_to_act, event_loop_handle.recv_message0()).await??;
timeout(settings.bob_time_to_act, event_loop_handle.recv_message0()).await??;
let alice_message0 = state0.next_message(&mut OsRng);
event_loop_handle
@ -64,7 +64,7 @@ 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??;
timeout(settings.bob_time_to_act, event_loop_handle.recv_message1()).await??;
let state2 = state1.receive(bob_message1);
@ -72,7 +72,8 @@ 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(settings.bob_time_to_act, event_loop_handle.recv_message2()).await??;
let state3 = state2.receive(bob_message2)?;
@ -84,14 +85,14 @@ pub async fn negotiate(
pub async fn wait_for_locked_bitcoin<W>(
lock_bitcoin_txid: bitcoin::Txid,
bitcoin_wallet: Arc<W>,
config: Config,
settings: settings::Protocol,
) -> Result<()>
where
W: WatchForRawTransaction + WaitForTransactionFinality,
{
// We assume we will see Bob's transaction in the mempool first.
timeout(
config.bob_time_to_act,
settings.bob_time_to_act,
bitcoin_wallet.watch_for_raw_transaction(lock_bitcoin_txid),
)
.await
@ -99,7 +100,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, settings)
.await?;
Ok(())
@ -324,7 +325,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,
settings: settings::Protocol,
) -> Result<bitcoin::Txid>
where
W: BroadcastSignedTransaction + WaitForTransactionFinality,
@ -334,7 +335,7 @@ where
.await?;
bitcoin_wallet
.wait_for_transaction_finality(txid, config)
.wait_for_transaction_finality(txid, settings)
.await?;
Ok(txid)

View File

@ -6,7 +6,6 @@ use crate::{
timelocks::ExpiredTimelocks, TransactionBlockHeight, WaitForTransactionFinality,
WatchForRawTransaction,
},
config::Config,
database,
database::Database,
monero,
@ -25,6 +24,7 @@ use crate::{
AliceState,
},
},
settings,
};
use anyhow::{bail, Result};
use async_recursion::async_recursion;
@ -65,7 +65,7 @@ pub async fn run_until(
swap.event_loop_handle,
swap.bitcoin_wallet,
swap.monero_wallet,
swap.config,
swap.settings,
swap.swap_id,
swap.db,
)
@ -81,7 +81,7 @@ async fn run_until_internal(
mut event_loop_handle: EventLoopHandle,
bitcoin_wallet: Arc<bitcoin::Wallet>,
monero_wallet: Arc<monero::Wallet>,
config: Config,
settings: settings::Protocol,
swap_id: Uuid,
db: Database,
) -> Result<AliceState> {
@ -92,7 +92,7 @@ async fn run_until_internal(
match state {
AliceState::Started { amounts, state0 } => {
let (bob_peer_id, state3) =
negotiate(state0, amounts.xmr, &mut event_loop_handle, config).await?;
negotiate(state0, amounts.xmr, &mut event_loop_handle, settings).await?;
let state = AliceState::Negotiated {
bob_peer_id,
@ -109,7 +109,7 @@ async fn run_until_internal(
event_loop_handle,
bitcoin_wallet,
monero_wallet,
config,
settings,
swap_id,
db,
)
@ -120,9 +120,12 @@ async fn run_until_internal(
bob_peer_id,
amounts,
} => {
let _ =
wait_for_locked_bitcoin(state3.tx_lock.txid(), bitcoin_wallet.clone(), config)
.await?;
let _ = wait_for_locked_bitcoin(
state3.tx_lock.txid(),
bitcoin_wallet.clone(),
settings,
)
.await?;
let state = AliceState::BtcLocked {
bob_peer_id,
@ -139,7 +142,7 @@ async fn run_until_internal(
event_loop_handle,
bitcoin_wallet,
monero_wallet,
config,
settings,
swap_id,
db,
)
@ -170,7 +173,7 @@ async fn run_until_internal(
event_loop_handle,
bitcoin_wallet,
monero_wallet,
config,
settings,
swap_id,
db,
)
@ -208,7 +211,7 @@ async fn run_until_internal(
event_loop_handle,
bitcoin_wallet.clone(),
monero_wallet,
config,
settings,
swap_id,
db,
)
@ -234,7 +237,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, settings)
.await;
match publishded_redeem_tx {
@ -280,7 +283,7 @@ async fn run_until_internal(
event_loop_handle,
bitcoin_wallet,
monero_wallet,
config,
settings,
swap_id,
db,
)
@ -307,7 +310,7 @@ async fn run_until_internal(
event_loop_handle,
bitcoin_wallet,
monero_wallet,
config,
settings,
swap_id,
db,
)
@ -341,7 +344,7 @@ async fn run_until_internal(
event_loop_handle,
bitcoin_wallet.clone(),
monero_wallet,
config,
settings,
swap_id,
db,
)
@ -366,7 +369,7 @@ async fn run_until_internal(
event_loop_handle,
bitcoin_wallet.clone(),
monero_wallet,
config,
settings,
swap_id,
db,
)
@ -401,7 +404,7 @@ async fn run_until_internal(
let punish_tx_finalised = publish_bitcoin_punish_transaction(
signed_tx_punish,
bitcoin_wallet.clone(),
config,
settings,
);
let refund_tx_seen = bitcoin_wallet.watch_for_raw_transaction(tx_refund.txid());
@ -421,7 +424,7 @@ async fn run_until_internal(
event_loop_handle,
bitcoin_wallet.clone(),
monero_wallet,
config,
settings,
swap_id,
db,
)
@ -445,7 +448,7 @@ async fn run_until_internal(
event_loop_handle,
bitcoin_wallet.clone(),
monero_wallet,
config,
settings,
swap_id,
db,
)

View File

@ -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::{
@ -12,6 +10,7 @@ use crate::{
},
protocol::{alice, bob, SwapAmounts},
seed::Seed,
settings,
};
use anyhow::{bail, Result};
use libp2p::{core::Multiaddr, identity::Keypair, NetworkBehaviour, PeerId};
@ -48,7 +47,7 @@ pub struct Swap {
pub db: Database,
pub bitcoin_wallet: Arc<bitcoin::Wallet>,
pub monero_wallet: Arc<monero::Wallet>,
pub config: Config,
pub settings: settings::Protocol,
pub swap_id: Uuid,
}
@ -65,7 +64,7 @@ pub struct Builder {
monero_wallet: Arc<monero::Wallet>,
init_params: InitParams,
config: Config,
settings: settings::Protocol,
}
enum InitParams {
@ -83,7 +82,7 @@ impl Builder {
monero_wallet: Arc<monero::Wallet>,
alice_address: Multiaddr,
alice_peer_id: PeerId,
config: Config,
settings: settings::Protocol,
) -> Self {
let identity = network::Seed::new(seed).derive_libp2p_identity();
let peer_id = identity.public().into_peer_id();
@ -98,7 +97,7 @@ impl Builder {
bitcoin_wallet,
monero_wallet,
init_params: InitParams::None,
config,
settings,
}
}
@ -113,7 +112,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.settings)
.await?;
let (event_loop, event_loop_handle) = self.init_event_loop()?;
@ -128,7 +127,7 @@ impl Builder {
bitcoin_wallet: self.bitcoin_wallet.clone(),
monero_wallet: self.monero_wallet.clone(),
swap_id: self.swap_id,
config: self.config,
settings: self.settings,
},
event_loop,
))
@ -157,7 +156,7 @@ impl Builder {
bitcoin_wallet: self.bitcoin_wallet.clone(),
monero_wallet: self.monero_wallet.clone(),
swap_id: self.swap_id,
config: self.config,
settings: self.settings,
},
event_loop,
))
@ -183,7 +182,7 @@ impl Builder {
&self,
btc_to_swap: bitcoin::Amount,
xmr_to_swap: monero::Amount,
config: Config,
settings: settings::Protocol,
) -> Result<BobState> {
let amounts = SwapAmounts {
btc: btc_to_swap,
@ -195,10 +194,10 @@ impl Builder {
&mut OsRng,
btc_to_swap,
xmr_to_swap,
config.bitcoin_cancel_timelock,
config.bitcoin_punish_timelock,
settings.bitcoin_cancel_timelock,
settings.bitcoin_punish_timelock,
refund_address,
config.monero_finality_confirmations,
settings.monero_finality_confirmations,
);
Ok(BobState::Started { state0, amounts })

View File

@ -6,10 +6,10 @@ use crate::{
GetBlockHeight, GetNetwork, GetRawTransaction, Transaction, TransactionBlockHeight,
TxCancel, Txid, WatchForRawTransaction,
},
config::Config,
monero,
monero::{monero_private_key, TransferProof},
protocol::{alice, bob, bob::EncryptedSignature, SwapAmounts},
settings,
};
use anyhow::{anyhow, Result};
use ecdsa_fun::{adaptor::Adaptor, nonce::Deterministic, Signature};
@ -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,
settings: settings::Protocol,
) -> 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, settings)
.await?;
Ok(())

View File

@ -1,13 +1,13 @@
use crate::{
bitcoin,
bitcoin::timelocks::ExpiredTimelocks,
config::Config,
database::{Database, Swap},
monero,
protocol::{
bob::{self, event_loop::EventLoopHandle, state::*, SwapRequest},
SwapAmounts,
},
settings,
};
use anyhow::{bail, Result};
use async_recursion::async_recursion;
@ -45,7 +45,7 @@ pub async fn run_until(
swap.monero_wallet,
OsRng,
swap.swap_id,
swap.config,
swap.settings,
)
.await
}
@ -62,7 +62,7 @@ async fn run_until_internal<R>(
monero_wallet: Arc<monero::Wallet>,
mut rng: R,
swap_id: Uuid,
config: Config,
settings: settings::Protocol,
) -> Result<BobState>
where
R: RngCore + CryptoRng + Send,
@ -96,7 +96,7 @@ where
monero_wallet,
rng,
swap_id,
config,
settings,
)
.await
}
@ -118,7 +118,7 @@ where
monero_wallet,
rng,
swap_id,
config,
settings,
)
.await
}
@ -171,7 +171,7 @@ where
monero_wallet,
rng,
swap_id,
config,
settings,
)
.await
}
@ -218,7 +218,7 @@ where
monero_wallet,
rng,
swap_id,
config,
settings,
)
.await
}
@ -261,7 +261,7 @@ where
monero_wallet,
rng,
swap_id,
config,
settings,
)
.await
}
@ -297,7 +297,7 @@ where
monero_wallet,
rng,
swap_id,
config,
settings,
)
.await
}
@ -319,7 +319,7 @@ where
monero_wallet,
rng,
swap_id,
config,
settings,
)
.await
}
@ -345,7 +345,7 @@ where
monero_wallet,
rng,
swap_id,
config,
settings,
)
.await
}
@ -356,7 +356,7 @@ 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(), settings).await?;
BobState::BtcRefunded(state)
}
ExpiredTimelocks::Punish => BobState::BtcPunished {
@ -375,7 +375,7 @@ where
monero_wallet,
rng,
swap_id,
config,
settings,
)
.await
}

108
swap/src/settings.rs Normal file
View File

@ -0,0 +1,108 @@
use crate::bitcoin::Timelock;
use conquer_once::Lazy;
use std::time::Duration;
#[derive(Debug, Copy, Clone)]
pub struct Protocol {
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,
}
impl Protocol {
pub fn mainnet() -> Self {
Self {
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,
}
}
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,
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,
}
}
pub fn regtest() -> Self {
Self {
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::*;
// 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 BITCOIN_FINALITY_CONFIRMATIONS: u32 = 3;
pub static BITCOIN_AVG_BLOCK_TIME: Lazy<Duration> = Lazy::new(|| Duration::from_secs(10 * 60));
pub static MONERO_FINALITY_CONFIRMATIONS: u32 = 15;
// Set to 12 hours, arbitrary value to be reviewed properly
pub static BITCOIN_CANCEL_TIMELOCK: Timelock = Timelock::new(72);
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(60 * 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;
// This does not reflect recommended values for mainnet!
pub static BITCOIN_CANCEL_TIMELOCK: Timelock = Timelock::new(12);
pub static BITCOIN_PUNISH_TIMELOCK: Timelock = Timelock::new(6);
}
mod regtest {
use super::*;
// 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 BITCOIN_FINALITY_CONFIRMATIONS: u32 = 1;
pub static BITCOIN_AVG_BLOCK_TIME: Lazy<Duration> = Lazy::new(|| Duration::from_secs(5));
pub static MONERO_FINALITY_CONFIRMATIONS: u32 = 1;
pub static BITCOIN_CANCEL_TIMELOCK: Timelock = Timelock::new(50);
pub static BITCOIN_PUNISH_TIMELOCK: Timelock = Timelock::new(50);
}

View File

@ -6,11 +6,10 @@ use libp2p::{core::Multiaddr, PeerId};
use monero_harness::{image, Monero};
use std::{path::PathBuf, sync::Arc};
use swap::{
bitcoin,
config::Config,
monero,
bitcoin, monero,
protocol::{alice, alice::AliceState, bob, bob::BobState, SwapAmounts},
seed::Seed,
settings,
};
use tempfile::tempdir;
use testcontainers::{clients::Cli, Container};
@ -26,7 +25,7 @@ pub struct StartingBalances {
struct AliceParams {
seed: Seed,
config: Config,
settings: settings::Protocol,
swap_id: Uuid,
bitcoin_wallet: Arc<bitcoin::Wallet>,
monero_wallet: Arc<monero::Wallet>,
@ -38,7 +37,7 @@ impl AliceParams {
pub async fn builder(&self) -> alice::Builder {
alice::Builder::new(
self.seed,
self.config,
self.settings,
self.swap_id,
self.bitcoin_wallet.clone(),
self.monero_wallet.clone(),
@ -61,7 +60,7 @@ struct BobParams {
monero_wallet: Arc<monero::Wallet>,
alice_address: Multiaddr,
alice_peer_id: PeerId,
config: Config,
settings: settings::Protocol,
}
impl BobParams {
@ -74,7 +73,7 @@ impl BobParams {
self.monero_wallet.clone(),
self.alice_address.clone(),
self.alice_peer_id.clone(),
self.config,
self.settings,
)
}
}
@ -304,7 +303,7 @@ where
xmr: monero::Amount::from_piconero(1_000_000_000_000),
};
let config = Config::regtest();
let settings = settings::Protocol::regtest();
let alice_starting_balances = StartingBalances {
xmr: swap_amounts.xmr * 10,
@ -322,13 +321,13 @@ where
&containers.bitcoind,
&monero,
alice_starting_balances.clone(),
config,
settings,
)
.await;
let alice_params = AliceParams {
seed: Seed::random().unwrap(),
config,
settings,
swap_id: Uuid::new_v4(),
bitcoin_wallet: alice_bitcoin_wallet.clone(),
monero_wallet: alice_monero_wallet.clone(),
@ -346,7 +345,7 @@ where
&containers.bitcoind,
&monero,
bob_starting_balances.clone(),
config,
settings,
)
.await;
@ -358,7 +357,7 @@ where
monero_wallet: bob_monero_wallet.clone(),
alice_address: alice_params.listen_address.clone(),
alice_peer_id: alice_params.peer_id().await,
config,
settings,
};
let test = TestContext {
@ -391,7 +390,7 @@ async fn init_wallets(
bitcoind: &Bitcoind<'_>,
monero: &Monero,
starting_balances: StartingBalances,
config: Config,
settings: settings::Protocol,
) -> (Arc<bitcoin::Wallet>, Arc<monero::Wallet>) {
monero
.init(vec![(name, starting_balances.xmr.as_piconero())])
@ -400,11 +399,11 @@ async fn init_wallets(
let xmr_wallet = Arc::new(swap::monero::Wallet {
inner: monero.wallet(name).unwrap().client(),
network: config.monero_network,
network: settings.monero_network,
});
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(), settings.bitcoin_network)
.await
.unwrap(),
);