mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2024-10-01 01:45:40 -04:00
Merge #618
618: Don't spam on transaction status change r=da-kami a=thomaseizinger Co-authored-by: Thomas Eizinger <thomas@eizinger.io>
This commit is contained in:
commit
238e52228e
@ -483,14 +483,13 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::determine_btc_to_swap;
|
use crate::determine_btc_to_swap;
|
||||||
use ::bitcoin::Amount;
|
use ::bitcoin::Amount;
|
||||||
use std::io;
|
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use tracing::subscriber;
|
use swap::tracing_ext::capture_logs;
|
||||||
use tracing_subscriber::fmt::MakeWriter;
|
use tracing::level_filters::LevelFilter;
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn given_no_balance_and_transfers_less_than_max_swaps_max_giveable() {
|
async fn given_no_balance_and_transfers_less_than_max_swaps_max_giveable() {
|
||||||
let writer = capture_logs();
|
let writer = capture_logs(LevelFilter::INFO);
|
||||||
let givable = Arc::new(Mutex::new(MaxGiveable::new(vec![
|
let givable = Arc::new(Mutex::new(MaxGiveable::new(vec![
|
||||||
Amount::ZERO,
|
Amount::ZERO,
|
||||||
Amount::from_btc(0.0009).unwrap(),
|
Amount::from_btc(0.0009).unwrap(),
|
||||||
@ -525,7 +524,7 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn given_no_balance_and_transfers_more_then_swaps_max_quantity_from_quote() {
|
async fn given_no_balance_and_transfers_more_then_swaps_max_quantity_from_quote() {
|
||||||
let writer = capture_logs();
|
let writer = capture_logs(LevelFilter::INFO);
|
||||||
let givable = Arc::new(Mutex::new(MaxGiveable::new(vec![
|
let givable = Arc::new(Mutex::new(MaxGiveable::new(vec![
|
||||||
Amount::ZERO,
|
Amount::ZERO,
|
||||||
Amount::from_btc(0.1).unwrap(),
|
Amount::from_btc(0.1).unwrap(),
|
||||||
@ -560,7 +559,7 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn given_initial_balance_below_max_quantity_swaps_max_givable() {
|
async fn given_initial_balance_below_max_quantity_swaps_max_givable() {
|
||||||
let writer = capture_logs();
|
let writer = capture_logs(LevelFilter::INFO);
|
||||||
let givable = Arc::new(Mutex::new(MaxGiveable::new(vec![
|
let givable = Arc::new(Mutex::new(MaxGiveable::new(vec![
|
||||||
Amount::from_btc(0.0049).unwrap(),
|
Amount::from_btc(0.0049).unwrap(),
|
||||||
Amount::from_btc(99.9).unwrap(),
|
Amount::from_btc(99.9).unwrap(),
|
||||||
@ -593,7 +592,7 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn given_initial_balance_above_max_quantity_swaps_max_quantity() {
|
async fn given_initial_balance_above_max_quantity_swaps_max_quantity() {
|
||||||
let writer = capture_logs();
|
let writer = capture_logs(LevelFilter::INFO);
|
||||||
let givable = Arc::new(Mutex::new(MaxGiveable::new(vec![
|
let givable = Arc::new(Mutex::new(MaxGiveable::new(vec![
|
||||||
Amount::from_btc(0.1).unwrap(),
|
Amount::from_btc(0.1).unwrap(),
|
||||||
Amount::from_btc(99.9).unwrap(),
|
Amount::from_btc(99.9).unwrap(),
|
||||||
@ -626,7 +625,7 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn given_no_initial_balance_then_min_wait_for_sufficient_deposit() {
|
async fn given_no_initial_balance_then_min_wait_for_sufficient_deposit() {
|
||||||
let writer = capture_logs();
|
let writer = capture_logs(LevelFilter::INFO);
|
||||||
let givable = Arc::new(Mutex::new(MaxGiveable::new(vec![
|
let givable = Arc::new(Mutex::new(MaxGiveable::new(vec![
|
||||||
Amount::ZERO,
|
Amount::ZERO,
|
||||||
Amount::from_btc(0.01).unwrap(),
|
Amount::from_btc(0.01).unwrap(),
|
||||||
@ -661,7 +660,7 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn given_balance_less_then_min_wait_for_sufficient_deposit() {
|
async fn given_balance_less_then_min_wait_for_sufficient_deposit() {
|
||||||
let writer = capture_logs();
|
let writer = capture_logs(LevelFilter::INFO);
|
||||||
let givable = Arc::new(Mutex::new(MaxGiveable::new(vec![
|
let givable = Arc::new(Mutex::new(MaxGiveable::new(vec![
|
||||||
Amount::from_btc(0.0001).unwrap(),
|
Amount::from_btc(0.0001).unwrap(),
|
||||||
Amount::from_btc(0.01).unwrap(),
|
Amount::from_btc(0.01).unwrap(),
|
||||||
@ -696,7 +695,7 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn given_no_initial_balance_and_transfers_less_than_min_keep_waiting() {
|
async fn given_no_initial_balance_and_transfers_less_than_min_keep_waiting() {
|
||||||
let writer = capture_logs();
|
let writer = capture_logs(LevelFilter::INFO);
|
||||||
let givable = Arc::new(Mutex::new(MaxGiveable::new(vec![
|
let givable = Arc::new(Mutex::new(MaxGiveable::new(vec![
|
||||||
Amount::ZERO,
|
Amount::ZERO,
|
||||||
Amount::from_btc(0.01).unwrap(),
|
Amount::from_btc(0.01).unwrap(),
|
||||||
@ -736,7 +735,7 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn given_longer_delay_until_deposit_should_not_spam_user() {
|
async fn given_longer_delay_until_deposit_should_not_spam_user() {
|
||||||
let writer = capture_logs();
|
let writer = capture_logs(LevelFilter::INFO);
|
||||||
let givable = Arc::new(Mutex::new(MaxGiveable::new(vec![
|
let givable = Arc::new(Mutex::new(MaxGiveable::new(vec![
|
||||||
Amount::ZERO,
|
Amount::ZERO,
|
||||||
Amount::ZERO,
|
Amount::ZERO,
|
||||||
@ -778,63 +777,6 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Setup tracing with a capturing writer, allowing assertions on the log
|
|
||||||
/// messages.
|
|
||||||
///
|
|
||||||
/// Time and ANSI are disabled to make the output more predictable and
|
|
||||||
/// readable.
|
|
||||||
fn capture_logs() -> MakeCapturingWriter {
|
|
||||||
let make_writer = MakeCapturingWriter::default();
|
|
||||||
|
|
||||||
let guard = subscriber::set_default(
|
|
||||||
tracing_subscriber::fmt()
|
|
||||||
.with_ansi(false)
|
|
||||||
.without_time()
|
|
||||||
.with_writer(make_writer.clone())
|
|
||||||
.finish(),
|
|
||||||
);
|
|
||||||
// don't clean up guard we stay initialized
|
|
||||||
std::mem::forget(guard);
|
|
||||||
|
|
||||||
make_writer
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, Clone)]
|
|
||||||
struct MakeCapturingWriter {
|
|
||||||
writer: CapturingWriter,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MakeCapturingWriter {
|
|
||||||
fn captured(&self) -> String {
|
|
||||||
let captured = &self.writer.captured;
|
|
||||||
let cursor = captured.lock().unwrap();
|
|
||||||
String::from_utf8(cursor.clone().into_inner()).unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MakeWriter for MakeCapturingWriter {
|
|
||||||
type Writer = CapturingWriter;
|
|
||||||
|
|
||||||
fn make_writer(&self) -> Self::Writer {
|
|
||||||
self.writer.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, Clone)]
|
|
||||||
struct CapturingWriter {
|
|
||||||
captured: Arc<Mutex<io::Cursor<Vec<u8>>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl io::Write for CapturingWriter {
|
|
||||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
|
||||||
self.captured.lock().unwrap().write(buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn flush(&mut self) -> io::Result<()> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct MaxGiveable {
|
struct MaxGiveable {
|
||||||
amounts: Vec<Amount>,
|
amounts: Vec<Amount>,
|
||||||
call_counter: usize,
|
call_counter: usize,
|
||||||
|
@ -149,16 +149,7 @@ impl Wallet {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
match (last_status, new_status) {
|
last_status = Some(print_status_change(txid, last_status, new_status));
|
||||||
(None, new_status) => {
|
|
||||||
tracing::debug!(%txid, status = %new_status, "Found relevant Bitcoin transaction");
|
|
||||||
},
|
|
||||||
(Some(old_status), new_status) => {
|
|
||||||
tracing::debug!(%txid, %new_status, %old_status, "Bitcoin transaction status changed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
last_status = Some(new_status);
|
|
||||||
|
|
||||||
let all_receivers_gone = sender.send(new_status).is_err();
|
let all_receivers_gone = sender.send(new_status).is_err();
|
||||||
|
|
||||||
@ -182,6 +173,20 @@ impl Wallet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn print_status_change(txid: Txid, old: Option<ScriptStatus>, new: ScriptStatus) -> ScriptStatus {
|
||||||
|
match (old, new) {
|
||||||
|
(None, new_status) => {
|
||||||
|
tracing::debug!(%txid, status = %new_status, "Found relevant Bitcoin transaction");
|
||||||
|
}
|
||||||
|
(Some(old_status), new_status) if old_status != new_status => {
|
||||||
|
tracing::debug!(%txid, %new_status, %old_status, "Bitcoin transaction status changed");
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
new
|
||||||
|
}
|
||||||
|
|
||||||
/// Represents a subscription to the status of a given transaction.
|
/// Represents a subscription to the status of a given transaction.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Subscription {
|
pub struct Subscription {
|
||||||
@ -850,7 +855,9 @@ impl fmt::Display for ScriptStatus {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::bitcoin::{PublicKey, TxLock};
|
use crate::bitcoin::{PublicKey, TxLock};
|
||||||
|
use crate::tracing_ext::capture_logs;
|
||||||
use proptest::prelude::*;
|
use proptest::prelude::*;
|
||||||
|
use tracing::level_filters::LevelFilter;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn given_depth_0_should_meet_confirmation_target_one() {
|
fn given_depth_0_should_meet_confirmation_target_one() {
|
||||||
@ -1124,4 +1131,38 @@ mod tests {
|
|||||||
_ => panic!("expected exactly two outputs"),
|
_ => panic!("expected exactly two outputs"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn printing_status_change_doesnt_spam_on_same_status() {
|
||||||
|
let writer = capture_logs(LevelFilter::DEBUG);
|
||||||
|
|
||||||
|
let tx = Txid::default();
|
||||||
|
let mut old = None;
|
||||||
|
old = Some(print_status_change(tx, old, ScriptStatus::Unseen));
|
||||||
|
old = Some(print_status_change(tx, old, ScriptStatus::InMempool));
|
||||||
|
old = Some(print_status_change(tx, old, ScriptStatus::InMempool));
|
||||||
|
old = Some(print_status_change(tx, old, ScriptStatus::InMempool));
|
||||||
|
old = Some(print_status_change(tx, old, ScriptStatus::InMempool));
|
||||||
|
old = Some(print_status_change(tx, old, ScriptStatus::InMempool));
|
||||||
|
old = Some(print_status_change(tx, old, ScriptStatus::InMempool));
|
||||||
|
old = Some(print_status_change(tx, old, confs(1)));
|
||||||
|
old = Some(print_status_change(tx, old, confs(2)));
|
||||||
|
old = Some(print_status_change(tx, old, confs(3)));
|
||||||
|
old = Some(print_status_change(tx, old, confs(3)));
|
||||||
|
print_status_change(tx, old, confs(3));
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
writer.captured(),
|
||||||
|
r"DEBUG swap::bitcoin::wallet: Found relevant Bitcoin transaction txid=0000000000000000000000000000000000000000000000000000000000000000 status=unseen
|
||||||
|
DEBUG swap::bitcoin::wallet: Bitcoin transaction status changed txid=0000000000000000000000000000000000000000000000000000000000000000 new_status=in mempool old_status=unseen
|
||||||
|
DEBUG swap::bitcoin::wallet: Bitcoin transaction status changed txid=0000000000000000000000000000000000000000000000000000000000000000 new_status=confirmed with 1 blocks old_status=in mempool
|
||||||
|
DEBUG swap::bitcoin::wallet: Bitcoin transaction status changed txid=0000000000000000000000000000000000000000000000000000000000000000 new_status=confirmed with 2 blocks old_status=confirmed with 1 blocks
|
||||||
|
DEBUG swap::bitcoin::wallet: Bitcoin transaction status changed txid=0000000000000000000000000000000000000000000000000000000000000000 new_status=confirmed with 3 blocks old_status=confirmed with 2 blocks
|
||||||
|
"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn confs(confirmations: u32) -> ScriptStatus {
|
||||||
|
ScriptStatus::from_confirmations(confirmations)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,5 +29,6 @@ pub mod network;
|
|||||||
pub mod protocol;
|
pub mod protocol;
|
||||||
pub mod seed;
|
pub mod seed;
|
||||||
pub mod tor;
|
pub mod tor;
|
||||||
|
pub mod tracing_ext;
|
||||||
|
|
||||||
mod monero_ext;
|
mod monero_ext;
|
||||||
|
65
swap/src/tracing_ext.rs
Normal file
65
swap/src/tracing_ext.rs
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
#![allow(clippy::unwrap_used)] // This is only meant to be used in tests.
|
||||||
|
|
||||||
|
use std::io;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
use tracing::subscriber;
|
||||||
|
use tracing_subscriber::filter::LevelFilter;
|
||||||
|
use tracing_subscriber::fmt::MakeWriter;
|
||||||
|
|
||||||
|
/// Setup tracing with a capturing writer, allowing assertions on the log
|
||||||
|
/// messages.
|
||||||
|
///
|
||||||
|
/// Time and ANSI are disabled to make the output more predictable and
|
||||||
|
/// readable.
|
||||||
|
pub fn capture_logs(min_level: LevelFilter) -> MakeCapturingWriter {
|
||||||
|
let make_writer = MakeCapturingWriter::default();
|
||||||
|
|
||||||
|
let guard = subscriber::set_default(
|
||||||
|
tracing_subscriber::fmt()
|
||||||
|
.with_ansi(false)
|
||||||
|
.without_time()
|
||||||
|
.with_writer(make_writer.clone())
|
||||||
|
.with_env_filter(format!("{}", min_level))
|
||||||
|
.finish(),
|
||||||
|
);
|
||||||
|
// don't clean up guard we stay initialized
|
||||||
|
std::mem::forget(guard);
|
||||||
|
|
||||||
|
make_writer
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Clone)]
|
||||||
|
pub struct MakeCapturingWriter {
|
||||||
|
writer: CapturingWriter,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MakeCapturingWriter {
|
||||||
|
pub fn captured(&self) -> String {
|
||||||
|
let captured = &self.writer.captured;
|
||||||
|
let cursor = captured.lock().unwrap();
|
||||||
|
String::from_utf8(cursor.clone().into_inner()).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MakeWriter for MakeCapturingWriter {
|
||||||
|
type Writer = CapturingWriter;
|
||||||
|
|
||||||
|
fn make_writer(&self) -> Self::Writer {
|
||||||
|
self.writer.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Clone)]
|
||||||
|
pub struct CapturingWriter {
|
||||||
|
captured: Arc<Mutex<io::Cursor<Vec<u8>>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl io::Write for CapturingWriter {
|
||||||
|
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||||
|
self.captured.lock().unwrap().write(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flush(&mut self) -> io::Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user