mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2025-01-25 14:56:23 -05:00
Alice's spot_price Behaviour reports back Error
Instead of handling all errors on the inside spot_price errors are bubbled up (as `SwapRequestDeclined`). This allows us to test both Alice's and Bob's behaviour for all scenarios.
This commit is contained in:
parent
5aac76598d
commit
03a0dc73cd
@ -6,11 +6,14 @@ use crate::protocol::alice::{execution_setup, spot_price, State3};
|
|||||||
use anyhow::{anyhow, Error};
|
use anyhow::{anyhow, Error};
|
||||||
use libp2p::request_response::{RequestId, ResponseChannel};
|
use libp2p::request_response::{RequestId, ResponseChannel};
|
||||||
use libp2p::{NetworkBehaviour, PeerId};
|
use libp2p::{NetworkBehaviour, PeerId};
|
||||||
use std::fmt::Debug;
|
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum OutEvent {
|
pub enum OutEvent {
|
||||||
|
SwapRequestDeclined {
|
||||||
|
peer: PeerId,
|
||||||
|
error: spot_price::Error,
|
||||||
|
},
|
||||||
ExecutionSetupStart {
|
ExecutionSetupStart {
|
||||||
peer: PeerId,
|
peer: PeerId,
|
||||||
btc: bitcoin::Amount,
|
btc: bitcoin::Amount,
|
||||||
@ -65,7 +68,7 @@ impl OutEvent {
|
|||||||
#[allow(missing_debug_implementations)]
|
#[allow(missing_debug_implementations)]
|
||||||
pub struct Behaviour<LR>
|
pub struct Behaviour<LR>
|
||||||
where
|
where
|
||||||
LR: LatestRate + Send + 'static + Debug,
|
LR: LatestRate + Send + 'static,
|
||||||
{
|
{
|
||||||
pub quote: quote::Behaviour,
|
pub quote: quote::Behaviour,
|
||||||
pub spot_price: spot_price::Behaviour<LR>,
|
pub spot_price: spot_price::Behaviour<LR>,
|
||||||
@ -76,7 +79,7 @@ where
|
|||||||
|
|
||||||
impl<LR> Behaviour<LR>
|
impl<LR> Behaviour<LR>
|
||||||
where
|
where
|
||||||
LR: LatestRate + Send + 'static + Debug,
|
LR: LatestRate + Send + 'static,
|
||||||
{
|
{
|
||||||
pub fn new(
|
pub fn new(
|
||||||
balance: monero::Amount,
|
balance: monero::Amount,
|
||||||
|
@ -3,6 +3,7 @@ use crate::database::Database;
|
|||||||
use crate::env::Config;
|
use crate::env::Config;
|
||||||
use crate::network::quote::BidQuote;
|
use crate::network::quote::BidQuote;
|
||||||
use crate::network::transfer_proof;
|
use crate::network::transfer_proof;
|
||||||
|
use crate::protocol::alice::spot_price::Error;
|
||||||
use crate::protocol::alice::{AliceState, Behaviour, OutEvent, State0, State3, Swap};
|
use crate::protocol::alice::{AliceState, Behaviour, OutEvent, State0, State3, Swap};
|
||||||
use crate::{bitcoin, kraken, monero};
|
use crate::{bitcoin, kraken, monero};
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
@ -203,6 +204,18 @@ where
|
|||||||
|
|
||||||
self.swarm.behaviour_mut().execution_setup.run(peer, state0);
|
self.swarm.behaviour_mut().execution_setup.run(peer, state0);
|
||||||
}
|
}
|
||||||
|
SwarmEvent::Behaviour(OutEvent::SwapRequestDeclined { peer, error }) => {
|
||||||
|
match error {
|
||||||
|
Error::ResumeOnlyMode | Error::MaxBuyAmountExceeded { .. } => {
|
||||||
|
tracing::warn!(%peer, "Ignoring spot price request because: {}", error);
|
||||||
|
}
|
||||||
|
Error::BalanceTooLow { .. }
|
||||||
|
| Error::LatestRateFetchFailed(_)
|
||||||
|
| Error::SellQuoteCalculationFailed(_) => {
|
||||||
|
tracing::error!(%peer, "Ignoring spot price request because: {}", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
SwarmEvent::Behaviour(OutEvent::QuoteRequested { channel, peer }) => {
|
SwarmEvent::Behaviour(OutEvent::QuoteRequested { channel, peer }) => {
|
||||||
// TODO: Move the spot-price update into dedicated update stream to decouple it from quote requests
|
// TODO: Move the spot-price update into dedicated update stream to decouple it from quote requests
|
||||||
let current_balance = self.monero_wallet.get_balance().await;
|
let current_balance = self.monero_wallet.get_balance().await;
|
||||||
|
@ -14,10 +14,16 @@ use std::collections::VecDeque;
|
|||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::task::{Context, Poll};
|
use std::task::{Context, Poll};
|
||||||
|
|
||||||
pub struct OutEvent {
|
pub enum OutEvent {
|
||||||
peer: PeerId,
|
ExecutionSetupParams {
|
||||||
btc: bitcoin::Amount,
|
peer: PeerId,
|
||||||
xmr: monero::Amount,
|
btc: bitcoin::Amount,
|
||||||
|
xmr: monero::Amount,
|
||||||
|
},
|
||||||
|
Error {
|
||||||
|
peer: PeerId,
|
||||||
|
error: Error,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(NetworkBehaviour)]
|
#[derive(NetworkBehaviour)]
|
||||||
@ -25,7 +31,7 @@ pub struct OutEvent {
|
|||||||
#[allow(missing_debug_implementations)]
|
#[allow(missing_debug_implementations)]
|
||||||
pub struct Behaviour<LR>
|
pub struct Behaviour<LR>
|
||||||
where
|
where
|
||||||
LR: LatestRate + Send + 'static + Debug,
|
LR: LatestRate + Send + 'static,
|
||||||
{
|
{
|
||||||
behaviour: spot_price::Behaviour,
|
behaviour: spot_price::Behaviour,
|
||||||
|
|
||||||
@ -50,7 +56,7 @@ where
|
|||||||
/// bubbled up to the parent behaviour.
|
/// bubbled up to the parent behaviour.
|
||||||
impl<LR> Behaviour<LR>
|
impl<LR> Behaviour<LR>
|
||||||
where
|
where
|
||||||
LR: LatestRate + Send + 'static + Debug,
|
LR: LatestRate + Send + 'static,
|
||||||
{
|
{
|
||||||
pub fn new(
|
pub fn new(
|
||||||
balance: monero::Amount,
|
balance: monero::Amount,
|
||||||
@ -78,30 +84,24 @@ where
|
|||||||
self.balance = balance;
|
self.balance = balance;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send_error_response(
|
fn decline(
|
||||||
&mut self,
|
&mut self,
|
||||||
peer: PeerId,
|
peer: PeerId,
|
||||||
channel: ResponseChannel<spot_price::Response>,
|
channel: ResponseChannel<spot_price::Response>,
|
||||||
error: Error<LR>,
|
error: Error,
|
||||||
) {
|
) {
|
||||||
match error {
|
|
||||||
Error::ResumeOnlyMode | Error::MaxBuyAmountExceeded { .. } => {
|
|
||||||
tracing::warn!(%peer, "Ignoring spot price request because: {}", error);
|
|
||||||
}
|
|
||||||
Error::BalanceTooLow { .. }
|
|
||||||
| Error::LatestRateFetchFailed(_)
|
|
||||||
| Error::SellQuoteCalculationFailed(_) => {
|
|
||||||
tracing::error!(%peer, "Ignoring spot price request because: {}", error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if self
|
if self
|
||||||
.behaviour
|
.behaviour
|
||||||
.send_response(channel, spot_price::Response::Error(error.into()))
|
.send_response(
|
||||||
|
channel,
|
||||||
|
spot_price::Response::Error(error.to_error_response()),
|
||||||
|
)
|
||||||
.is_err()
|
.is_err()
|
||||||
{
|
{
|
||||||
tracing::debug!(%peer, "Unable to send error response for spot price request");
|
tracing::debug!(%peer, "Unable to send error response for spot price request");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.events.push_back(OutEvent::Error { peer, error });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn poll<BIE>(
|
fn poll<BIE>(
|
||||||
@ -120,7 +120,7 @@ where
|
|||||||
|
|
||||||
impl<LR> NetworkBehaviourEventProcess<spot_price::OutEvent> for Behaviour<LR>
|
impl<LR> NetworkBehaviourEventProcess<spot_price::OutEvent> for Behaviour<LR>
|
||||||
where
|
where
|
||||||
LR: LatestRate + Send + 'static + Debug,
|
LR: LatestRate + Send + 'static,
|
||||||
{
|
{
|
||||||
fn inject_event(&mut self, event: spot_price::OutEvent) {
|
fn inject_event(&mut self, event: spot_price::OutEvent) {
|
||||||
let (peer, message) = match event {
|
let (peer, message) = match event {
|
||||||
@ -150,13 +150,13 @@ where
|
|||||||
};
|
};
|
||||||
|
|
||||||
if self.resume_only {
|
if self.resume_only {
|
||||||
self.send_error_response(peer, channel, Error::ResumeOnlyMode);
|
self.decline(peer, channel, Error::ResumeOnlyMode);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let btc = request.btc;
|
let btc = request.btc;
|
||||||
if btc > self.max_buy {
|
if btc > self.max_buy {
|
||||||
self.send_error_response(peer, channel, Error::MaxBuyAmountExceeded {
|
self.decline(peer, channel, Error::MaxBuyAmountExceeded {
|
||||||
max: self.max_buy,
|
max: self.max_buy,
|
||||||
buy: btc,
|
buy: btc,
|
||||||
});
|
});
|
||||||
@ -166,14 +166,14 @@ where
|
|||||||
let rate = match self.latest_rate.latest_rate() {
|
let rate = match self.latest_rate.latest_rate() {
|
||||||
Ok(rate) => rate,
|
Ok(rate) => rate,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
self.send_error_response(peer, channel, Error::LatestRateFetchFailed(e));
|
self.decline(peer, channel, Error::LatestRateFetchFailed(Box::new(e)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let xmr = match rate.sell_quote(btc) {
|
let xmr = match rate.sell_quote(btc) {
|
||||||
Ok(xmr) => xmr,
|
Ok(xmr) => xmr,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
self.send_error_response(peer, channel, Error::SellQuoteCalculationFailed(e));
|
self.decline(peer, channel, Error::SellQuoteCalculationFailed(e));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -182,7 +182,7 @@ where
|
|||||||
let xmr_lock_fees = self.lock_fee;
|
let xmr_lock_fees = self.lock_fee;
|
||||||
|
|
||||||
if xmr_balance < xmr + xmr_lock_fees {
|
if xmr_balance < xmr + xmr_lock_fees {
|
||||||
self.send_error_response(peer, channel, Error::BalanceTooLow { buy: btc });
|
self.decline(peer, channel, Error::BalanceTooLow { buy: btc });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,43 +194,24 @@ where
|
|||||||
tracing::error!(%peer, "Failed to send spot price response of {} for {}", xmr, btc)
|
tracing::error!(%peer, "Failed to send spot price response of {} for {}", xmr, btc)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.events.push_back(OutEvent { peer, btc, xmr });
|
self.events
|
||||||
|
.push_back(OutEvent::ExecutionSetupParams { peer, btc, xmr });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<OutEvent> for alice::OutEvent {
|
impl From<OutEvent> for alice::OutEvent {
|
||||||
fn from(event: OutEvent) -> Self {
|
fn from(event: OutEvent) -> Self {
|
||||||
Self::ExecutionSetupStart {
|
match event {
|
||||||
peer: event.peer,
|
OutEvent::ExecutionSetupParams { peer, btc, xmr } => {
|
||||||
btc: event.btc,
|
Self::ExecutionSetupStart { peer, btc, xmr }
|
||||||
xmr: event.xmr,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<LR> From<Error<LR>> for spot_price::Error
|
|
||||||
where
|
|
||||||
LR: LatestRate + Debug,
|
|
||||||
{
|
|
||||||
fn from(error: Error<LR>) -> Self {
|
|
||||||
match error {
|
|
||||||
Error::ResumeOnlyMode => spot_price::Error::NoSwapsAccepted,
|
|
||||||
Error::MaxBuyAmountExceeded { max, buy } => {
|
|
||||||
spot_price::Error::MaxBuyAmountExceeded { max, buy }
|
|
||||||
}
|
|
||||||
Error::BalanceTooLow { buy } => spot_price::Error::BalanceTooLow { buy },
|
|
||||||
Error::LatestRateFetchFailed(_) | Error::SellQuoteCalculationFailed(_) => {
|
|
||||||
spot_price::Error::Other
|
|
||||||
}
|
}
|
||||||
|
OutEvent::Error { peer, error } => Self::SwapRequestDeclined { peer, error },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
pub enum Error<LR>
|
pub enum Error {
|
||||||
where
|
|
||||||
LR: LatestRate + Debug,
|
|
||||||
{
|
|
||||||
#[error("ASB is running in resume-only mode")]
|
#[error("ASB is running in resume-only mode")]
|
||||||
ResumeOnlyMode,
|
ResumeOnlyMode,
|
||||||
#[error("Maximum buy {max} exceeded {buy}")]
|
#[error("Maximum buy {max} exceeded {buy}")]
|
||||||
@ -242,8 +223,24 @@ where
|
|||||||
BalanceTooLow { buy: bitcoin::Amount },
|
BalanceTooLow { buy: bitcoin::Amount },
|
||||||
|
|
||||||
#[error("Failed to fetch latest rate")]
|
#[error("Failed to fetch latest rate")]
|
||||||
LatestRateFetchFailed(LR::Error),
|
LatestRateFetchFailed(#[source] Box<dyn std::error::Error + Send + 'static>),
|
||||||
|
|
||||||
#[error("Failed to calculate quote: {0}")]
|
#[error("Failed to calculate quote: {0}")]
|
||||||
SellQuoteCalculationFailed(anyhow::Error),
|
SellQuoteCalculationFailed(#[source] anyhow::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error {
|
||||||
|
pub fn to_error_response(&self) -> spot_price::Error {
|
||||||
|
match self {
|
||||||
|
Error::ResumeOnlyMode => spot_price::Error::NoSwapsAccepted,
|
||||||
|
Error::MaxBuyAmountExceeded { max, buy } => spot_price::Error::MaxBuyAmountExceeded {
|
||||||
|
max: *max,
|
||||||
|
buy: *buy,
|
||||||
|
},
|
||||||
|
Error::BalanceTooLow { buy } => spot_price::Error::BalanceTooLow { buy: *buy },
|
||||||
|
Error::LatestRateFetchFailed(_) | Error::SellQuoteCalculationFailed(_) => {
|
||||||
|
spot_price::Error::Other
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user