mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2024-10-01 01:45:40 -04:00
Add resume-only mode for the ASB
Resume-only is a maintenance mode where no swaps are accepted but unfinished swaps are resumed. This is achieve by ignoring incoming spot-price requests (that would lead to execution setup) in the event-loop.
This commit is contained in:
parent
08d7d587cf
commit
f6497778ed
@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
- Resume-only mode for the ASB.
|
||||
When started with `--resume-only` the ASB does not accept new, incoming swap requests but only finishes swaps that are resumed upon startup.
|
||||
|
||||
### Fixed
|
||||
|
||||
- An issue where both the ASB and the CLI point to the same default directory `xmr-btc-swap` for storing data.
|
||||
|
@ -34,6 +34,12 @@ pub enum Command {
|
||||
default_value = "0.02"
|
||||
)]
|
||||
ask_spread: Decimal,
|
||||
|
||||
#[structopt(
|
||||
long = "resume-only",
|
||||
help = "For maintenance only. When set, no new swap requests will be accepted, but existing unfinished swaps will be resumed."
|
||||
)]
|
||||
resume_only: bool,
|
||||
},
|
||||
History,
|
||||
WithdrawBtc {
|
||||
|
@ -81,6 +81,7 @@ async fn main() -> Result<()> {
|
||||
Command::Start {
|
||||
max_buy,
|
||||
ask_spread,
|
||||
resume_only,
|
||||
} => {
|
||||
let bitcoin_wallet = init_bitcoin_wallet(&config, &seed, env_config).await?;
|
||||
let monero_wallet = init_monero_wallet(&config, env_config).await?;
|
||||
@ -133,6 +134,7 @@ async fn main() -> Result<()> {
|
||||
Arc::new(db),
|
||||
KrakenRate::new(ask_spread, kraken_price_updates),
|
||||
max_buy,
|
||||
resume_only,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
@ -41,7 +41,16 @@ pub struct Request {
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct Response {
|
||||
pub xmr: monero::Amount,
|
||||
pub xmr: Option<monero::Amount>,
|
||||
pub error: Option<Error>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, thiserror::Error, Serialize, Deserialize)]
|
||||
pub enum Error {
|
||||
#[error(
|
||||
"This seller currently does not accept incoming swap requests, please try again later"
|
||||
)]
|
||||
MaintenanceMode,
|
||||
}
|
||||
|
||||
/// Constructs a new instance of the `spot-price` behaviour to be used by Alice.
|
||||
|
@ -42,6 +42,7 @@ pub struct EventLoop<RS> {
|
||||
max_buy: bitcoin::Amount,
|
||||
|
||||
swap_sender: mpsc::Sender<Swap>,
|
||||
resume_only: bool,
|
||||
|
||||
/// Stores incoming [`EncryptedSignature`]s per swap.
|
||||
recv_encrypted_signature: HashMap<Uuid, bmrng::RequestSender<bitcoin::EncryptedSignature, ()>>,
|
||||
@ -62,6 +63,7 @@ impl<LR> EventLoop<LR>
|
||||
where
|
||||
LR: LatestRate,
|
||||
{
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
swarm: Swarm<Behaviour>,
|
||||
env_config: Config,
|
||||
@ -70,6 +72,7 @@ where
|
||||
db: Arc<Database>,
|
||||
latest_rate: LR,
|
||||
max_buy: bitcoin::Amount,
|
||||
resume_only: bool,
|
||||
) -> Result<(Self, mpsc::Receiver<Swap>)> {
|
||||
let swap_channel = MpscChannels::default();
|
||||
|
||||
@ -81,6 +84,7 @@ where
|
||||
db,
|
||||
latest_rate,
|
||||
swap_sender: swap_channel.sender,
|
||||
resume_only,
|
||||
max_buy,
|
||||
recv_encrypted_signature: Default::default(),
|
||||
inflight_encrypted_signatures: Default::default(),
|
||||
@ -144,6 +148,20 @@ where
|
||||
swarm_event = self.swarm.next_event() => {
|
||||
match swarm_event {
|
||||
SwarmEvent::Behaviour(OutEvent::SpotPriceRequested { request, channel, peer }) => {
|
||||
if self.resume_only {
|
||||
tracing::warn!(%peer, "Ignoring spot price request from {} because ASB started in resume-only mode", peer);
|
||||
|
||||
match self.swarm.behaviour_mut().spot_price.send_response(channel, spot_price::Response { xmr: None, error: Some(spot_price::Error::MaintenanceMode) }) {
|
||||
Ok(_) => {},
|
||||
Err(_) => {
|
||||
tracing::debug!(%peer, "Failed to respond with error to spot price request");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
let btc = request.btc;
|
||||
let xmr = match self.handle_spot_price_request(btc, self.monero_wallet.clone()).await {
|
||||
Ok(xmr) => xmr,
|
||||
@ -153,7 +171,7 @@ where
|
||||
}
|
||||
};
|
||||
|
||||
match self.swarm.behaviour_mut().spot_price.send_response(channel, spot_price::Response { xmr }) {
|
||||
match self.swarm.behaviour_mut().spot_price.send_response(channel, spot_price::Response { xmr: Some(xmr), error: None }) {
|
||||
Ok(_) => {},
|
||||
Err(_) => {
|
||||
// if we can't respond, the peer probably just disconnected so it is not a huge deal, only log this on debug
|
||||
|
@ -3,7 +3,7 @@ use crate::network::quote::BidQuote;
|
||||
use crate::network::{encrypted_signature, spot_price};
|
||||
use crate::protocol::bob::{Behaviour, OutEvent, State0, State2};
|
||||
use crate::{bitcoin, monero};
|
||||
use anyhow::{Context, Result};
|
||||
use anyhow::{bail, Context, Result};
|
||||
use futures::future::{BoxFuture, OptionFuture};
|
||||
use futures::{FutureExt, StreamExt};
|
||||
use libp2p::request_response::{RequestId, ResponseChannel};
|
||||
@ -261,11 +261,22 @@ impl EventLoopHandle {
|
||||
}
|
||||
|
||||
pub async fn request_spot_price(&mut self, btc: bitcoin::Amount) -> Result<monero::Amount> {
|
||||
Ok(self
|
||||
let response = self
|
||||
.spot_price
|
||||
.send_receive(spot_price::Request { btc })
|
||||
.await?
|
||||
.xmr)
|
||||
.await?;
|
||||
|
||||
match (response.xmr, response.error) {
|
||||
(Some(xmr), None) => Ok(xmr),
|
||||
(_, Some(error)) => {
|
||||
bail!(error);
|
||||
}
|
||||
(None, None) => {
|
||||
bail!(
|
||||
"Unexpected response for spot-price request, neither price nor error received"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn request_quote(&mut self) -> Result<BidQuote> {
|
||||
|
@ -234,6 +234,7 @@ fn start_alice(
|
||||
db,
|
||||
FixedRate::default(),
|
||||
bitcoin::Amount::ONE_BTC,
|
||||
false,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user