Cancel command

pull/170/head
Daniel Karzel 3 years ago
parent ec661178f4
commit 0600a7048e

428
Cargo.lock generated

File diff suppressed because it is too large Load Diff

@ -50,6 +50,7 @@ pub enum Command {
},
History,
Resume(Resume),
Cancel(Cancel),
}
#[derive(structopt::StructOpt, Debug)]
@ -79,6 +80,24 @@ pub enum Resume {
},
}
#[derive(structopt::StructOpt, Debug)]
pub enum Cancel {
BuyXmr {
#[structopt(long = "swap-id")]
swap_id: Uuid,
// TODO: Remove Alice peer-id/address, it should be saved in the database when running swap
// and loaded from the database when running resume/cancel/refund
#[structopt(long = "counterpart-peer-id")]
alice_peer_id: PeerId,
#[structopt(long = "counterpart-addr")]
alice_addr: Multiaddr,
#[structopt(flatten)]
config: Config,
},
}
#[derive(structopt::StructOpt, Debug)]
pub struct Config {
#[structopt(

@ -13,11 +13,12 @@
#![allow(non_snake_case)]
use crate::{
cli::{Command, Options, Resume},
cli::{Cancel, Command, Options, Resume},
config::{
initial_setup, query_user_for_initial_testnet_config, read_config, ConfigNotInitialized,
},
execution_params::GetExecutionParams,
protocol::bob::cancel::CancelError,
};
use anyhow::{Context, Result};
use database::Database;
@ -209,6 +210,36 @@ async fn main() -> Result<()> {
tokio::spawn(async move { event_loop.run().await });
bob::run(swap).await?;
}
Command::Cancel(Cancel::BuyXmr {
swap_id,
alice_peer_id,
alice_addr,
config,
}) => {
// TODO: Optimization: Only init the Bitcoin wallet, Monero wallet unnecessary
let (bitcoin_wallet, monero_wallet) =
init_wallets(config.path, bitcoin_network, monero_network).await?;
let bob_factory = Builder::new(
seed,
db_path,
swap_id,
Arc::new(bitcoin_wallet),
Arc::new(monero_wallet),
alice_addr,
alice_peer_id,
execution_params,
);
let (swap, event_loop) = bob_factory.build().await?;
tokio::spawn(async move { event_loop.run().await });
match bob::cancel(swap.swap_id, swap.state, swap.bitcoin_wallet, swap.db).await? {
Ok((txid, _)) => { info!("Cancel transaction successfully published with id {}", txid)},
Err(CancelError::CancelTimelockNotExpiredYet) => {info!("The Cancel Transaction cannot be published yet, because the timelock has not expired. Please try again later.")},
Err(CancelError::CancelTxAlreadyPublished) => {info!("The Cancel Transaction has already been published.")}
}
}
};
Ok(())

@ -20,6 +20,7 @@ use tracing::{debug, info};
use uuid::Uuid;
pub use self::{
cancel::cancel,
encrypted_signature::EncryptedSignature,
event_loop::{EventLoop, EventLoopHandle},
state::*,
@ -29,6 +30,7 @@ pub use self::{
pub use execution_setup::{Message0, Message2, Message4};
use libp2p::request_response::ResponseChannel;
pub mod cancel;
mod encrypted_signature;
pub mod event_loop;
mod execution_setup;

@ -0,0 +1,60 @@
use crate::{
bitcoin::{timelocks::ExpiredTimelocks, Txid, Wallet},
database::{Database, Swap},
protocol::bob::BobState,
};
use anyhow::{bail, Result};
use std::sync::Arc;
use uuid::Uuid;
#[derive(Debug, thiserror::Error, Clone, Copy)]
pub enum CancelError {
#[error("The cancel timelock has not expired yet.")]
CancelTimelockNotExpiredYet,
#[error("The cancel transaction has already been published.")]
CancelTxAlreadyPublished,
}
pub async fn cancel(
swap_id: Uuid,
state: BobState,
bitcoin_wallet: Arc<Wallet>,
db: Database,
) -> Result<Result<(Txid, BobState), CancelError>> {
let state4 = match state {
BobState::BtcLocked(state3) => state3.state4(),
BobState::XmrLockProofReceived { state, .. } => state.state4(),
BobState::XmrLocked(state4) => state4,
BobState::EncSigSent(state4) => state4,
BobState::CancelTimelockExpired(state4) => state4,
_ => bail!(
"Cannot cancel swap {} because it is in state {} which is not refundable.",
swap_id,
state
),
};
if let ExpiredTimelocks::None = state4.expired_timelock(bitcoin_wallet.as_ref()).await? {
return Ok(Err(CancelError::CancelTimelockNotExpiredYet));
}
if state4
.check_for_tx_cancel(bitcoin_wallet.as_ref())
.await
.is_ok()
{
let state = BobState::BtcCancelled(state4);
let db_state = state.into();
db.insert_latest_state(swap_id, Swap::Bob(db_state)).await?;
return Ok(Err(CancelError::CancelTxAlreadyPublished));
}
let txid = state4.submit_tx_cancel(bitcoin_wallet.as_ref()).await?;
let state = BobState::BtcCancelled(state4);
let db_state = state.clone().into();
db.insert_latest_state(swap_id, Swap::Bob(db_state)).await?;
Ok(Ok((txid, state)))
}
Loading…
Cancel
Save