mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2025-02-08 19:08:47 -05:00
Cancel command
This commit is contained in:
parent
ec661178f4
commit
0600a7048e
430
Cargo.lock
generated
430
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -50,6 +50,7 @@ pub enum Command {
|
|||||||
},
|
},
|
||||||
History,
|
History,
|
||||||
Resume(Resume),
|
Resume(Resume),
|
||||||
|
Cancel(Cancel),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(structopt::StructOpt, Debug)]
|
#[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)]
|
#[derive(structopt::StructOpt, Debug)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
#[structopt(
|
#[structopt(
|
||||||
|
@ -13,11 +13,12 @@
|
|||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
cli::{Command, Options, Resume},
|
cli::{Cancel, Command, Options, Resume},
|
||||||
config::{
|
config::{
|
||||||
initial_setup, query_user_for_initial_testnet_config, read_config, ConfigNotInitialized,
|
initial_setup, query_user_for_initial_testnet_config, read_config, ConfigNotInitialized,
|
||||||
},
|
},
|
||||||
execution_params::GetExecutionParams,
|
execution_params::GetExecutionParams,
|
||||||
|
protocol::bob::cancel::CancelError,
|
||||||
};
|
};
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use database::Database;
|
use database::Database;
|
||||||
@ -209,6 +210,36 @@ async fn main() -> Result<()> {
|
|||||||
tokio::spawn(async move { event_loop.run().await });
|
tokio::spawn(async move { event_loop.run().await });
|
||||||
bob::run(swap).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(())
|
Ok(())
|
||||||
|
@ -20,6 +20,7 @@ use tracing::{debug, info};
|
|||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
pub use self::{
|
pub use self::{
|
||||||
|
cancel::cancel,
|
||||||
encrypted_signature::EncryptedSignature,
|
encrypted_signature::EncryptedSignature,
|
||||||
event_loop::{EventLoop, EventLoopHandle},
|
event_loop::{EventLoop, EventLoopHandle},
|
||||||
state::*,
|
state::*,
|
||||||
@ -29,6 +30,7 @@ pub use self::{
|
|||||||
pub use execution_setup::{Message0, Message2, Message4};
|
pub use execution_setup::{Message0, Message2, Message4};
|
||||||
use libp2p::request_response::ResponseChannel;
|
use libp2p::request_response::ResponseChannel;
|
||||||
|
|
||||||
|
pub mod cancel;
|
||||||
mod encrypted_signature;
|
mod encrypted_signature;
|
||||||
pub mod event_loop;
|
pub mod event_loop;
|
||||||
mod execution_setup;
|
mod execution_setup;
|
||||||
|
60
swap/src/protocol/bob/cancel.rs
Normal file
60
swap/src/protocol/bob/cancel.rs
Normal file
@ -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…
x
Reference in New Issue
Block a user