mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2024-10-01 01:45:40 -04:00
feat(asb + cli): Redact logs + unify tracing infrastructure (#1733)
This commit is contained in:
parent
55bfd95694
commit
7871cf256b
@ -1,2 +1,6 @@
|
|||||||
[target.armv7-unknown-linux-gnueabihf]
|
[target.armv7-unknown-linux-gnueabihf]
|
||||||
linker = "arm-linux-gnueabihf-gcc"
|
linker = "arm-linux-gnueabihf-gcc"
|
||||||
|
|
||||||
|
# windows defaults to smaller stack sizes which isn't enough
|
||||||
|
[target.'cfg(windows)']
|
||||||
|
rustflags = ["-C", "link-args=/STACK:8388608"]
|
||||||
|
@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
- ASB + CLI: You can now use the `logs` command to retrieve logs stored in the past, redacting addresses and id's using `logs --redact`.
|
||||||
|
- ASB: The `--disable-timestamp` flag has been removed
|
||||||
|
|
||||||
## [0.13.4] - 2024-07-25
|
## [0.13.4] - 2024-07-25
|
||||||
|
|
||||||
- ASB: The `history` command can now be used while the asb is running.
|
- ASB: The `history` command can now be used while the asb is running.
|
||||||
|
39
Cargo.lock
generated
39
Cargo.lock
generated
@ -78,6 +78,15 @@ dependencies = [
|
|||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aho-corasick"
|
||||||
|
version = "1.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ansi_term"
|
name = "ansi_term"
|
||||||
version = "0.11.0"
|
version = "0.11.0"
|
||||||
@ -1500,7 +1509,7 @@ version = "0.4.10"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc"
|
checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick 0.7.18",
|
||||||
"bstr",
|
"bstr",
|
||||||
"fnv",
|
"fnv",
|
||||||
"log",
|
"log",
|
||||||
@ -2508,7 +2517,7 @@ version = "0.0.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1"
|
checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"regex-automata",
|
"regex-automata 0.1.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -2517,7 +2526,7 @@ version = "0.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
|
checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"regex-automata",
|
"regex-automata 0.1.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -2653,7 +2662,7 @@ dependencies = [
|
|||||||
"testcontainers",
|
"testcontainers",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-subscriber 0.2.25",
|
"tracing-subscriber 0.3.18",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -3449,13 +3458,14 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.7.3"
|
version = "1.10.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d"
|
checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick 1.1.3",
|
||||||
"memchr",
|
"memchr",
|
||||||
"regex-syntax 0.6.29",
|
"regex-automata 0.4.7",
|
||||||
|
"regex-syntax 0.8.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -3468,6 +3478,17 @@ dependencies = [
|
|||||||
"regex-syntax 0.6.29",
|
"regex-syntax 0.6.29",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-automata"
|
||||||
|
version = "0.4.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick 1.1.3",
|
||||||
|
"memchr",
|
||||||
|
"regex-syntax 0.8.2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-syntax"
|
name = "regex-syntax"
|
||||||
version = "0.6.29"
|
version = "0.6.29"
|
||||||
@ -4557,12 +4578,14 @@ dependencies = [
|
|||||||
"monero",
|
"monero",
|
||||||
"monero-harness",
|
"monero-harness",
|
||||||
"monero-rpc",
|
"monero-rpc",
|
||||||
|
"once_cell",
|
||||||
"pem",
|
"pem",
|
||||||
"port_check",
|
"port_check",
|
||||||
"proptest",
|
"proptest",
|
||||||
"qrcode",
|
"qrcode",
|
||||||
"rand 0.8.3",
|
"rand 0.8.3",
|
||||||
"rand_chacha 0.3.1",
|
"rand_chacha 0.3.1",
|
||||||
|
"regex",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"rust_decimal",
|
"rust_decimal",
|
||||||
"rust_decimal_macros",
|
"rust_decimal_macros",
|
||||||
|
@ -13,4 +13,4 @@ rand = "0.7"
|
|||||||
testcontainers = "0.15"
|
testcontainers = "0.15"
|
||||||
tokio = { version = "1", default-features = false, features = [ "rt-multi-thread", "time", "macros" ] }
|
tokio = { version = "1", default-features = false, features = [ "rt-multi-thread", "time", "macros" ] }
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
tracing-subscriber = { version = "0.2", default-features = false, features = [ "fmt", "ansi", "env-filter", "tracing-log" ] }
|
tracing-subscriber = { version = "0.3", default-features = false, features = [ "fmt", "ansi", "env-filter", "tracing-log" ] }
|
||||||
|
@ -37,11 +37,13 @@ jsonrpsee-core = "0.16.2"
|
|||||||
libp2p = { version = "0.42.2", default-features = false, features = [ "tcp-tokio", "yamux", "mplex", "dns-tokio", "noise", "request-response", "websocket", "ping", "rendezvous", "identify" ] }
|
libp2p = { version = "0.42.2", default-features = false, features = [ "tcp-tokio", "yamux", "mplex", "dns-tokio", "noise", "request-response", "websocket", "ping", "rendezvous", "identify" ] }
|
||||||
monero = { version = "0.12", features = [ "serde_support" ] }
|
monero = { version = "0.12", features = [ "serde_support" ] }
|
||||||
monero-rpc = { path = "../monero-rpc" }
|
monero-rpc = { path = "../monero-rpc" }
|
||||||
|
once_cell = "1.19"
|
||||||
pem = "3.0"
|
pem = "3.0"
|
||||||
proptest = "1"
|
proptest = "1"
|
||||||
qrcode = "0.14"
|
qrcode = "0.14"
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
rand_chacha = "0.3"
|
rand_chacha = "0.3"
|
||||||
|
regex = "1.10"
|
||||||
reqwest = { version = "0.12", features = [ "http2", "rustls-tls", "stream", "socks" ], default-features = false }
|
reqwest = { version = "0.12", features = [ "http2", "rustls-tls", "stream", "socks" ], default-features = false }
|
||||||
rust_decimal = { version = "1", features = [ "serde-float" ] }
|
rust_decimal = { version = "1", features = [ "serde-float" ] }
|
||||||
rust_decimal_macros = "1"
|
rust_decimal_macros = "1"
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
pub mod request;
|
pub mod request;
|
||||||
use crate::cli::command::{Bitcoin, Monero, Tor};
|
use crate::cli::command::{Bitcoin, Monero, Tor};
|
||||||
|
use crate::common::tracing_util::Format;
|
||||||
use crate::database::{open_db, AccessMode};
|
use crate::database::{open_db, AccessMode};
|
||||||
use crate::env::{Config as EnvConfig, GetConfig, Mainnet, Testnet};
|
use crate::env::{Config as EnvConfig, GetConfig, Mainnet, Testnet};
|
||||||
use crate::fs::system_data_dir;
|
use crate::fs::system_data_dir;
|
||||||
use crate::network::rendezvous::XmrBtcNamespace;
|
use crate::network::rendezvous::XmrBtcNamespace;
|
||||||
use crate::protocol::Database;
|
use crate::protocol::Database;
|
||||||
use crate::seed::Seed;
|
use crate::seed::Seed;
|
||||||
use crate::{bitcoin, cli, monero};
|
use crate::{bitcoin, common, monero};
|
||||||
use anyhow::{bail, Context as AnyContext, Error, Result};
|
use anyhow::{bail, Context as AnyContext, Error, Result};
|
||||||
use futures::future::try_join_all;
|
use futures::future::try_join_all;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
@ -16,6 +17,8 @@ use std::path::PathBuf;
|
|||||||
use std::sync::{Arc, Once};
|
use std::sync::{Arc, Once};
|
||||||
use tokio::sync::{broadcast, broadcast::Sender, Mutex, RwLock};
|
use tokio::sync::{broadcast, broadcast::Sender, Mutex, RwLock};
|
||||||
use tokio::task::JoinHandle;
|
use tokio::task::JoinHandle;
|
||||||
|
use tracing::level_filters::LevelFilter;
|
||||||
|
use tracing::Level;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
static START: Once = Once::new();
|
static START: Once = Once::new();
|
||||||
@ -186,8 +189,15 @@ impl Context {
|
|||||||
let data_dir = data::data_dir_from(data, is_testnet)?;
|
let data_dir = data::data_dir_from(data, is_testnet)?;
|
||||||
let env_config = env_config_from(is_testnet);
|
let env_config = env_config_from(is_testnet);
|
||||||
|
|
||||||
|
let format = if json { Format::Json } else { Format::Raw };
|
||||||
|
let level_filter = if debug {
|
||||||
|
LevelFilter::from_level(Level::DEBUG)
|
||||||
|
} else {
|
||||||
|
LevelFilter::from_level(Level::INFO)
|
||||||
|
};
|
||||||
|
|
||||||
START.call_once(|| {
|
START.call_once(|| {
|
||||||
let _ = cli::tracing::init(debug, json, data_dir.join("logs"));
|
let _ = common::tracing_util::init(level_filter, format, data_dir.join("logs"));
|
||||||
});
|
});
|
||||||
|
|
||||||
let seed = Seed::from_file_or_generate(data_dir.as_path())
|
let seed = Seed::from_file_or_generate(data_dir.as_path())
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use crate::api::Context;
|
use crate::api::Context;
|
||||||
use crate::bitcoin::{Amount, ExpiredTimelocks, TxLock};
|
use crate::bitcoin::{Amount, ExpiredTimelocks, TxLock};
|
||||||
use crate::cli::{list_sellers, EventLoop, SellerStatus};
|
use crate::cli::{list_sellers, EventLoop, SellerStatus};
|
||||||
|
use crate::common::get_logs;
|
||||||
use crate::libp2p_ext::MultiAddrExt;
|
use crate::libp2p_ext::MultiAddrExt;
|
||||||
use crate::network::quote::{BidQuote, ZeroQuoteReceived};
|
use crate::network::quote::{BidQuote, ZeroQuoteReceived};
|
||||||
use crate::network::swarm;
|
use crate::network::swarm;
|
||||||
@ -19,6 +20,7 @@ use std::cmp::min;
|
|||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tracing::{debug_span, field, Instrument, Span};
|
use tracing::{debug_span, field, Instrument, Span};
|
||||||
@ -48,6 +50,11 @@ pub enum Method {
|
|||||||
swap_id: Uuid,
|
swap_id: Uuid,
|
||||||
},
|
},
|
||||||
History,
|
History,
|
||||||
|
Logs {
|
||||||
|
logs_dir: Option<PathBuf>,
|
||||||
|
redact: bool,
|
||||||
|
swap_id: Option<Uuid>,
|
||||||
|
},
|
||||||
Config,
|
Config,
|
||||||
WithdrawBtc {
|
WithdrawBtc {
|
||||||
amount: Option<Amount>,
|
amount: Option<Amount>,
|
||||||
@ -125,6 +132,13 @@ impl Method {
|
|||||||
log_reference_id = field::Empty
|
log_reference_id = field::Empty
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Method::Logs { .. } => {
|
||||||
|
debug_span!(
|
||||||
|
"method",
|
||||||
|
method_name = "Logs",
|
||||||
|
log_reference_id = field::Empty
|
||||||
|
)
|
||||||
|
}
|
||||||
Method::ListSellers { .. } => {
|
Method::ListSellers { .. } => {
|
||||||
debug_span!(
|
debug_span!(
|
||||||
"method",
|
"method",
|
||||||
@ -733,6 +747,20 @@ impl Request {
|
|||||||
|
|
||||||
Ok(json!({"swaps": json_results}))
|
Ok(json!({"swaps": json_results}))
|
||||||
}
|
}
|
||||||
|
Method::Logs {
|
||||||
|
logs_dir,
|
||||||
|
redact,
|
||||||
|
swap_id,
|
||||||
|
} => {
|
||||||
|
let dir = logs_dir.unwrap_or(context.config.data_dir.join("logs"));
|
||||||
|
let logs = get_logs(dir, swap_id, redact).await?;
|
||||||
|
|
||||||
|
for msg in &logs {
|
||||||
|
println!("{msg}");
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(json!({ "logs": logs }))
|
||||||
|
}
|
||||||
Method::GetRawStates => {
|
Method::GetRawStates => {
|
||||||
let raw_history = context.db.raw_all().await?;
|
let raw_history = context.db.raw_all().await?;
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@ mod event_loop;
|
|||||||
mod network;
|
mod network;
|
||||||
mod rate;
|
mod rate;
|
||||||
mod recovery;
|
mod recovery;
|
||||||
pub mod tracing;
|
|
||||||
|
|
||||||
pub use event_loop::{EventLoop, EventLoopHandle, FixedRate, KrakenRate, LatestRate};
|
pub use event_loop::{EventLoop, EventLoopHandle, FixedRate, KrakenRate, LatestRate};
|
||||||
pub use network::behaviour::{Behaviour, OutEvent};
|
pub use network::behaviour::{Behaviour, OutEvent};
|
||||||
|
@ -19,7 +19,6 @@ where
|
|||||||
let args = RawArguments::from_clap(&matches);
|
let args = RawArguments::from_clap(&matches);
|
||||||
|
|
||||||
let json = args.json;
|
let json = args.json;
|
||||||
let disable_timestamp = args.disable_timestamp;
|
|
||||||
let testnet = args.testnet;
|
let testnet = args.testnet;
|
||||||
let config = args.config;
|
let config = args.config;
|
||||||
let command: RawCommand = args.cmd;
|
let command: RawCommand = args.cmd;
|
||||||
@ -28,7 +27,6 @@ where
|
|||||||
RawCommand::Start { resume_only } => Arguments {
|
RawCommand::Start { resume_only } => Arguments {
|
||||||
testnet,
|
testnet,
|
||||||
json,
|
json,
|
||||||
disable_timestamp,
|
|
||||||
config_path: config_path(config, testnet)?,
|
config_path: config_path(config, testnet)?,
|
||||||
env_config: env_config(testnet),
|
env_config: env_config(testnet),
|
||||||
cmd: Command::Start { resume_only },
|
cmd: Command::Start { resume_only },
|
||||||
@ -36,15 +34,28 @@ where
|
|||||||
RawCommand::History { only_unfinished } => Arguments {
|
RawCommand::History { only_unfinished } => Arguments {
|
||||||
testnet,
|
testnet,
|
||||||
json,
|
json,
|
||||||
disable_timestamp,
|
|
||||||
config_path: config_path(config, testnet)?,
|
config_path: config_path(config, testnet)?,
|
||||||
env_config: env_config(testnet),
|
env_config: env_config(testnet),
|
||||||
cmd: Command::History { only_unfinished },
|
cmd: Command::History { only_unfinished },
|
||||||
},
|
},
|
||||||
|
RawCommand::Logs {
|
||||||
|
logs_dir: dir_path,
|
||||||
|
swap_id,
|
||||||
|
redact,
|
||||||
|
} => Arguments {
|
||||||
|
testnet,
|
||||||
|
json,
|
||||||
|
config_path: config_path(config, testnet)?,
|
||||||
|
env_config: env_config(testnet),
|
||||||
|
cmd: Command::Logs {
|
||||||
|
logs_dir: dir_path,
|
||||||
|
swap_id,
|
||||||
|
redact,
|
||||||
|
},
|
||||||
|
},
|
||||||
RawCommand::WithdrawBtc { amount, address } => Arguments {
|
RawCommand::WithdrawBtc { amount, address } => Arguments {
|
||||||
testnet,
|
testnet,
|
||||||
json,
|
json,
|
||||||
disable_timestamp,
|
|
||||||
config_path: config_path(config, testnet)?,
|
config_path: config_path(config, testnet)?,
|
||||||
env_config: env_config(testnet),
|
env_config: env_config(testnet),
|
||||||
cmd: Command::WithdrawBtc {
|
cmd: Command::WithdrawBtc {
|
||||||
@ -55,7 +66,6 @@ where
|
|||||||
RawCommand::Balance => Arguments {
|
RawCommand::Balance => Arguments {
|
||||||
testnet,
|
testnet,
|
||||||
json,
|
json,
|
||||||
disable_timestamp,
|
|
||||||
config_path: config_path(config, testnet)?,
|
config_path: config_path(config, testnet)?,
|
||||||
env_config: env_config(testnet),
|
env_config: env_config(testnet),
|
||||||
cmd: Command::Balance,
|
cmd: Command::Balance,
|
||||||
@ -63,7 +73,6 @@ where
|
|||||||
RawCommand::Config => Arguments {
|
RawCommand::Config => Arguments {
|
||||||
testnet,
|
testnet,
|
||||||
json,
|
json,
|
||||||
disable_timestamp,
|
|
||||||
config_path: config_path(config, testnet)?,
|
config_path: config_path(config, testnet)?,
|
||||||
env_config: env_config(testnet),
|
env_config: env_config(testnet),
|
||||||
cmd: Command::Config,
|
cmd: Command::Config,
|
||||||
@ -71,7 +80,6 @@ where
|
|||||||
RawCommand::ExportBitcoinWallet => Arguments {
|
RawCommand::ExportBitcoinWallet => Arguments {
|
||||||
testnet,
|
testnet,
|
||||||
json,
|
json,
|
||||||
disable_timestamp,
|
|
||||||
config_path: config_path(config, testnet)?,
|
config_path: config_path(config, testnet)?,
|
||||||
env_config: env_config(testnet),
|
env_config: env_config(testnet),
|
||||||
cmd: Command::ExportBitcoinWallet,
|
cmd: Command::ExportBitcoinWallet,
|
||||||
@ -82,7 +90,6 @@ where
|
|||||||
}) => Arguments {
|
}) => Arguments {
|
||||||
testnet,
|
testnet,
|
||||||
json,
|
json,
|
||||||
disable_timestamp,
|
|
||||||
config_path: config_path(config, testnet)?,
|
config_path: config_path(config, testnet)?,
|
||||||
env_config: env_config(testnet),
|
env_config: env_config(testnet),
|
||||||
cmd: Command::Redeem {
|
cmd: Command::Redeem {
|
||||||
@ -96,7 +103,6 @@ where
|
|||||||
}) => Arguments {
|
}) => Arguments {
|
||||||
testnet,
|
testnet,
|
||||||
json,
|
json,
|
||||||
disable_timestamp,
|
|
||||||
config_path: config_path(config, testnet)?,
|
config_path: config_path(config, testnet)?,
|
||||||
env_config: env_config(testnet),
|
env_config: env_config(testnet),
|
||||||
cmd: Command::Cancel { swap_id },
|
cmd: Command::Cancel { swap_id },
|
||||||
@ -106,7 +112,6 @@ where
|
|||||||
}) => Arguments {
|
}) => Arguments {
|
||||||
testnet,
|
testnet,
|
||||||
json,
|
json,
|
||||||
disable_timestamp,
|
|
||||||
config_path: config_path(config, testnet)?,
|
config_path: config_path(config, testnet)?,
|
||||||
env_config: env_config(testnet),
|
env_config: env_config(testnet),
|
||||||
cmd: Command::Refund { swap_id },
|
cmd: Command::Refund { swap_id },
|
||||||
@ -116,7 +121,6 @@ where
|
|||||||
}) => Arguments {
|
}) => Arguments {
|
||||||
testnet,
|
testnet,
|
||||||
json,
|
json,
|
||||||
disable_timestamp,
|
|
||||||
config_path: config_path(config, testnet)?,
|
config_path: config_path(config, testnet)?,
|
||||||
env_config: env_config(testnet),
|
env_config: env_config(testnet),
|
||||||
cmd: Command::Punish { swap_id },
|
cmd: Command::Punish { swap_id },
|
||||||
@ -124,7 +128,6 @@ where
|
|||||||
RawCommand::ManualRecovery(ManualRecovery::SafelyAbort { swap_id }) => Arguments {
|
RawCommand::ManualRecovery(ManualRecovery::SafelyAbort { swap_id }) => Arguments {
|
||||||
testnet,
|
testnet,
|
||||||
json,
|
json,
|
||||||
disable_timestamp,
|
|
||||||
config_path: config_path(config, testnet)?,
|
config_path: config_path(config, testnet)?,
|
||||||
env_config: env_config(testnet),
|
env_config: env_config(testnet),
|
||||||
cmd: Command::SafelyAbort { swap_id },
|
cmd: Command::SafelyAbort { swap_id },
|
||||||
@ -184,7 +187,6 @@ pub struct BitcoinAddressNetworkMismatch {
|
|||||||
pub struct Arguments {
|
pub struct Arguments {
|
||||||
pub testnet: bool,
|
pub testnet: bool,
|
||||||
pub json: bool,
|
pub json: bool,
|
||||||
pub disable_timestamp: bool,
|
|
||||||
pub config_path: PathBuf,
|
pub config_path: PathBuf,
|
||||||
pub env_config: env::Config,
|
pub env_config: env::Config,
|
||||||
pub cmd: Command,
|
pub cmd: Command,
|
||||||
@ -199,6 +201,11 @@ pub enum Command {
|
|||||||
only_unfinished: bool,
|
only_unfinished: bool,
|
||||||
},
|
},
|
||||||
Config,
|
Config,
|
||||||
|
Logs {
|
||||||
|
logs_dir: Option<PathBuf>,
|
||||||
|
swap_id: Option<Uuid>,
|
||||||
|
redact: bool,
|
||||||
|
},
|
||||||
WithdrawBtc {
|
WithdrawBtc {
|
||||||
amount: Option<Amount>,
|
amount: Option<Amount>,
|
||||||
address: Address,
|
address: Address,
|
||||||
@ -270,6 +277,25 @@ pub enum RawCommand {
|
|||||||
)]
|
)]
|
||||||
resume_only: bool,
|
resume_only: bool,
|
||||||
},
|
},
|
||||||
|
#[structopt(about = "Prints all logging messages issued in the past.")]
|
||||||
|
Logs {
|
||||||
|
#[structopt(
|
||||||
|
short = "d",
|
||||||
|
help = "Print the logs from this directory instead of the default one."
|
||||||
|
)]
|
||||||
|
logs_dir: Option<PathBuf>,
|
||||||
|
#[structopt(
|
||||||
|
help = "Redact swap-ids, Bitcoin and Monero addresses.",
|
||||||
|
long = "redact"
|
||||||
|
)]
|
||||||
|
redact: bool,
|
||||||
|
#[structopt(
|
||||||
|
long = "swap-id",
|
||||||
|
help = "Filter for logs concerning this swap.",
|
||||||
|
long_help = "This checks whether each logging message contains the swap id. Some messages might be skipped when they don't contain the swap id even though they're relevant."
|
||||||
|
)]
|
||||||
|
swap_id: Option<Uuid>,
|
||||||
|
},
|
||||||
#[structopt(about = "Prints swap-id and the state of each swap ever made.")]
|
#[structopt(about = "Prints swap-id and the state of each swap ever made.")]
|
||||||
History {
|
History {
|
||||||
#[structopt(
|
#[structopt(
|
||||||
@ -374,7 +400,6 @@ mod tests {
|
|||||||
let expected_args = Arguments {
|
let expected_args = Arguments {
|
||||||
testnet: false,
|
testnet: false,
|
||||||
json: false,
|
json: false,
|
||||||
disable_timestamp: false,
|
|
||||||
config_path: default_mainnet_conf_path,
|
config_path: default_mainnet_conf_path,
|
||||||
env_config: mainnet_env_config,
|
env_config: mainnet_env_config,
|
||||||
cmd: Command::Start { resume_only: false },
|
cmd: Command::Start { resume_only: false },
|
||||||
@ -392,7 +417,6 @@ mod tests {
|
|||||||
let expected_args = Arguments {
|
let expected_args = Arguments {
|
||||||
testnet: false,
|
testnet: false,
|
||||||
json: false,
|
json: false,
|
||||||
disable_timestamp: false,
|
|
||||||
config_path: default_mainnet_conf_path,
|
config_path: default_mainnet_conf_path,
|
||||||
env_config: mainnet_env_config,
|
env_config: mainnet_env_config,
|
||||||
cmd: Command::History {
|
cmd: Command::History {
|
||||||
@ -412,7 +436,6 @@ mod tests {
|
|||||||
let expected_args = Arguments {
|
let expected_args = Arguments {
|
||||||
testnet: false,
|
testnet: false,
|
||||||
json: false,
|
json: false,
|
||||||
disable_timestamp: false,
|
|
||||||
config_path: default_mainnet_conf_path,
|
config_path: default_mainnet_conf_path,
|
||||||
env_config: mainnet_env_config,
|
env_config: mainnet_env_config,
|
||||||
cmd: Command::Balance,
|
cmd: Command::Balance,
|
||||||
@ -434,7 +457,6 @@ mod tests {
|
|||||||
let expected_args = Arguments {
|
let expected_args = Arguments {
|
||||||
testnet: false,
|
testnet: false,
|
||||||
json: false,
|
json: false,
|
||||||
disable_timestamp: false,
|
|
||||||
config_path: default_mainnet_conf_path,
|
config_path: default_mainnet_conf_path,
|
||||||
env_config: mainnet_env_config,
|
env_config: mainnet_env_config,
|
||||||
cmd: Command::WithdrawBtc {
|
cmd: Command::WithdrawBtc {
|
||||||
@ -461,7 +483,6 @@ mod tests {
|
|||||||
let expected_args = Arguments {
|
let expected_args = Arguments {
|
||||||
testnet: false,
|
testnet: false,
|
||||||
json: false,
|
json: false,
|
||||||
disable_timestamp: false,
|
|
||||||
config_path: default_mainnet_conf_path,
|
config_path: default_mainnet_conf_path,
|
||||||
env_config: mainnet_env_config,
|
env_config: mainnet_env_config,
|
||||||
cmd: Command::Cancel {
|
cmd: Command::Cancel {
|
||||||
@ -487,7 +508,6 @@ mod tests {
|
|||||||
let expected_args = Arguments {
|
let expected_args = Arguments {
|
||||||
testnet: false,
|
testnet: false,
|
||||||
json: false,
|
json: false,
|
||||||
disable_timestamp: false,
|
|
||||||
config_path: default_mainnet_conf_path,
|
config_path: default_mainnet_conf_path,
|
||||||
env_config: mainnet_env_config,
|
env_config: mainnet_env_config,
|
||||||
cmd: Command::Refund {
|
cmd: Command::Refund {
|
||||||
@ -513,7 +533,6 @@ mod tests {
|
|||||||
let expected_args = Arguments {
|
let expected_args = Arguments {
|
||||||
testnet: false,
|
testnet: false,
|
||||||
json: false,
|
json: false,
|
||||||
disable_timestamp: false,
|
|
||||||
config_path: default_mainnet_conf_path,
|
config_path: default_mainnet_conf_path,
|
||||||
env_config: mainnet_env_config,
|
env_config: mainnet_env_config,
|
||||||
cmd: Command::Punish {
|
cmd: Command::Punish {
|
||||||
@ -539,7 +558,6 @@ mod tests {
|
|||||||
let expected_args = Arguments {
|
let expected_args = Arguments {
|
||||||
testnet: false,
|
testnet: false,
|
||||||
json: false,
|
json: false,
|
||||||
disable_timestamp: false,
|
|
||||||
config_path: default_mainnet_conf_path,
|
config_path: default_mainnet_conf_path,
|
||||||
env_config: mainnet_env_config,
|
env_config: mainnet_env_config,
|
||||||
cmd: Command::SafelyAbort {
|
cmd: Command::SafelyAbort {
|
||||||
@ -559,7 +577,6 @@ mod tests {
|
|||||||
let expected_args = Arguments {
|
let expected_args = Arguments {
|
||||||
testnet: true,
|
testnet: true,
|
||||||
json: false,
|
json: false,
|
||||||
disable_timestamp: false,
|
|
||||||
config_path: default_testnet_conf_path,
|
config_path: default_testnet_conf_path,
|
||||||
env_config: testnet_env_config,
|
env_config: testnet_env_config,
|
||||||
cmd: Command::Start { resume_only: false },
|
cmd: Command::Start { resume_only: false },
|
||||||
@ -577,7 +594,6 @@ mod tests {
|
|||||||
let expected_args = Arguments {
|
let expected_args = Arguments {
|
||||||
testnet: true,
|
testnet: true,
|
||||||
json: false,
|
json: false,
|
||||||
disable_timestamp: false,
|
|
||||||
config_path: default_testnet_conf_path,
|
config_path: default_testnet_conf_path,
|
||||||
env_config: testnet_env_config,
|
env_config: testnet_env_config,
|
||||||
cmd: Command::History {
|
cmd: Command::History {
|
||||||
@ -597,7 +613,6 @@ mod tests {
|
|||||||
let expected_args = Arguments {
|
let expected_args = Arguments {
|
||||||
testnet: true,
|
testnet: true,
|
||||||
json: false,
|
json: false,
|
||||||
disable_timestamp: false,
|
|
||||||
config_path: default_testnet_conf_path,
|
config_path: default_testnet_conf_path,
|
||||||
env_config: testnet_env_config,
|
env_config: testnet_env_config,
|
||||||
cmd: Command::Balance,
|
cmd: Command::Balance,
|
||||||
@ -621,7 +636,6 @@ mod tests {
|
|||||||
let expected_args = Arguments {
|
let expected_args = Arguments {
|
||||||
testnet: true,
|
testnet: true,
|
||||||
json: false,
|
json: false,
|
||||||
disable_timestamp: false,
|
|
||||||
config_path: default_testnet_conf_path,
|
config_path: default_testnet_conf_path,
|
||||||
env_config: testnet_env_config,
|
env_config: testnet_env_config,
|
||||||
cmd: Command::WithdrawBtc {
|
cmd: Command::WithdrawBtc {
|
||||||
@ -648,7 +662,6 @@ mod tests {
|
|||||||
let expected_args = Arguments {
|
let expected_args = Arguments {
|
||||||
testnet: true,
|
testnet: true,
|
||||||
json: false,
|
json: false,
|
||||||
disable_timestamp: false,
|
|
||||||
config_path: default_testnet_conf_path,
|
config_path: default_testnet_conf_path,
|
||||||
env_config: testnet_env_config,
|
env_config: testnet_env_config,
|
||||||
cmd: Command::Cancel {
|
cmd: Command::Cancel {
|
||||||
@ -675,7 +688,6 @@ mod tests {
|
|||||||
let expected_args = Arguments {
|
let expected_args = Arguments {
|
||||||
testnet: true,
|
testnet: true,
|
||||||
json: false,
|
json: false,
|
||||||
disable_timestamp: false,
|
|
||||||
config_path: default_testnet_conf_path,
|
config_path: default_testnet_conf_path,
|
||||||
env_config: testnet_env_config,
|
env_config: testnet_env_config,
|
||||||
cmd: Command::Refund {
|
cmd: Command::Refund {
|
||||||
@ -702,7 +714,6 @@ mod tests {
|
|||||||
let expected_args = Arguments {
|
let expected_args = Arguments {
|
||||||
testnet: true,
|
testnet: true,
|
||||||
json: false,
|
json: false,
|
||||||
disable_timestamp: false,
|
|
||||||
config_path: default_testnet_conf_path,
|
config_path: default_testnet_conf_path,
|
||||||
env_config: testnet_env_config,
|
env_config: testnet_env_config,
|
||||||
cmd: Command::Punish {
|
cmd: Command::Punish {
|
||||||
@ -729,7 +740,6 @@ mod tests {
|
|||||||
let expected_args = Arguments {
|
let expected_args = Arguments {
|
||||||
testnet: true,
|
testnet: true,
|
||||||
json: false,
|
json: false,
|
||||||
disable_timestamp: false,
|
|
||||||
config_path: default_testnet_conf_path,
|
config_path: default_testnet_conf_path,
|
||||||
env_config: testnet_env_config,
|
env_config: testnet_env_config,
|
||||||
cmd: Command::SafelyAbort {
|
cmd: Command::SafelyAbort {
|
||||||
@ -749,7 +759,6 @@ mod tests {
|
|||||||
let expected_args = Arguments {
|
let expected_args = Arguments {
|
||||||
testnet: false,
|
testnet: false,
|
||||||
json: false,
|
json: false,
|
||||||
disable_timestamp: true,
|
|
||||||
config_path: default_mainnet_conf_path,
|
config_path: default_mainnet_conf_path,
|
||||||
env_config: mainnet_env_config,
|
env_config: mainnet_env_config,
|
||||||
cmd: Command::Start { resume_only: false },
|
cmd: Command::Start { resume_only: false },
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
use anyhow::Result;
|
|
||||||
use tracing_subscriber::filter::LevelFilter;
|
|
||||||
use tracing_subscriber::fmt::time::UtcTime;
|
|
||||||
use tracing_subscriber::FmtSubscriber;
|
|
||||||
|
|
||||||
pub fn init(level: LevelFilter, json_format: bool, timestamp: bool) -> Result<()> {
|
|
||||||
if level == LevelFilter::OFF {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
let is_terminal = atty::is(atty::Stream::Stderr);
|
|
||||||
|
|
||||||
let builder = FmtSubscriber::builder()
|
|
||||||
.with_env_filter(format!("asb={},swap={}", level, level))
|
|
||||||
.with_writer(std::io::stderr)
|
|
||||||
.with_ansi(is_terminal)
|
|
||||||
.with_timer(UtcTime::rfc_3339())
|
|
||||||
.with_target(false);
|
|
||||||
|
|
||||||
match (json_format, timestamp) {
|
|
||||||
(true, true) => builder.json().init(),
|
|
||||||
(true, false) => builder.json().without_time().init(),
|
|
||||||
(false, true) => builder.init(),
|
|
||||||
(false, false) => builder.without_time().init(),
|
|
||||||
}
|
|
||||||
|
|
||||||
tracing::info!(%level, "Initialized tracing");
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
@ -31,7 +31,8 @@ use swap::asb::config::{
|
|||||||
initial_setup, query_user_for_initial_config, read_config, Config, ConfigNotInitialized,
|
initial_setup, query_user_for_initial_config, read_config, Config, ConfigNotInitialized,
|
||||||
};
|
};
|
||||||
use swap::asb::{cancel, punish, redeem, refund, safely_abort, EventLoop, Finality, KrakenRate};
|
use swap::asb::{cancel, punish, redeem, refund, safely_abort, EventLoop, Finality, KrakenRate};
|
||||||
use swap::common::check_latest_version;
|
use swap::common::tracing_util::Format;
|
||||||
|
use swap::common::{self, check_latest_version, get_logs};
|
||||||
use swap::database::{open_db, AccessMode};
|
use swap::database::{open_db, AccessMode};
|
||||||
use swap::network::rendezvous::XmrBtcNamespace;
|
use swap::network::rendezvous::XmrBtcNamespace;
|
||||||
use swap::network::swarm;
|
use swap::network::swarm;
|
||||||
@ -40,44 +41,40 @@ use swap::protocol::alice::{run, AliceState};
|
|||||||
use swap::protocol::State;
|
use swap::protocol::State;
|
||||||
use swap::seed::Seed;
|
use swap::seed::Seed;
|
||||||
use swap::tor::AuthenticatedClient;
|
use swap::tor::AuthenticatedClient;
|
||||||
use swap::{asb, bitcoin, kraken, monero, tor};
|
use swap::{bitcoin, kraken, monero, tor};
|
||||||
use tracing_subscriber::filter::LevelFilter;
|
use tracing_subscriber::filter::LevelFilter;
|
||||||
|
|
||||||
const DEFAULT_WALLET_NAME: &str = "asb-wallet";
|
const DEFAULT_WALLET_NAME: &str = "asb-wallet";
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<()> {
|
||||||
|
// parse cli arguments
|
||||||
let Arguments {
|
let Arguments {
|
||||||
testnet,
|
testnet,
|
||||||
json,
|
json,
|
||||||
disable_timestamp,
|
|
||||||
config_path,
|
config_path,
|
||||||
env_config,
|
env_config,
|
||||||
cmd,
|
cmd,
|
||||||
} = match parse_args(env::args_os()) {
|
} = match parse_args(env::args_os()) {
|
||||||
Ok(args) => args,
|
Ok(args) => args,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
// make sure to display the clap error message it exists
|
||||||
if let Some(clap_err) = e.downcast_ref::<clap::Error>() {
|
if let Some(clap_err) = e.downcast_ref::<clap::Error>() {
|
||||||
match clap_err.kind {
|
if let ErrorKind::HelpDisplayed | ErrorKind::VersionDisplayed = clap_err.kind {
|
||||||
ErrorKind::HelpDisplayed | ErrorKind::VersionDisplayed => {
|
|
||||||
println!("{}", clap_err.message);
|
println!("{}", clap_err.message);
|
||||||
std::process::exit(0);
|
std::process::exit(0);
|
||||||
}
|
}
|
||||||
_ => {
|
|
||||||
bail!(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
bail!(e);
|
bail!(e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// warn if we're not on the latest version
|
||||||
if let Err(e) = check_latest_version(env!("CARGO_PKG_VERSION")).await {
|
if let Err(e) = check_latest_version(env!("CARGO_PKG_VERSION")).await {
|
||||||
eprintln!("{}", e);
|
eprintln!("{}", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
asb::tracing::init(LevelFilter::DEBUG, json, !disable_timestamp).expect("initialize tracing");
|
// read config from the specified path
|
||||||
|
|
||||||
let config = match read_config(config_path.clone())? {
|
let config = match read_config(config_path.clone())? {
|
||||||
Ok(config) => config,
|
Ok(config) => config,
|
||||||
Err(ConfigNotInitialized {}) => {
|
Err(ConfigNotInitialized {}) => {
|
||||||
@ -86,6 +83,12 @@ async fn main() -> Result<()> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// initialize tracing
|
||||||
|
let format = if json { Format::Json } else { Format::Raw };
|
||||||
|
let log_dir = config.data.dir.join("logs");
|
||||||
|
common::tracing_util::init(LevelFilter::DEBUG, format, log_dir).expect("initialize tracing");
|
||||||
|
|
||||||
|
// check for conflicting env / config values
|
||||||
if config.monero.network != env_config.monero_network {
|
if config.monero.network != env_config.monero_network {
|
||||||
bail!(format!(
|
bail!(format!(
|
||||||
"Expected monero network in config file to be {:?} but was {:?}",
|
"Expected monero network in config file to be {:?} but was {:?}",
|
||||||
@ -112,6 +115,7 @@ async fn main() -> Result<()> {
|
|||||||
rendezvous_addrs.sort();
|
rendezvous_addrs.sort();
|
||||||
rendezvous_addrs.dedup();
|
rendezvous_addrs.dedup();
|
||||||
let new_len = rendezvous_addrs.len();
|
let new_len = rendezvous_addrs.len();
|
||||||
|
|
||||||
if new_len < prev_len {
|
if new_len < prev_len {
|
||||||
tracing::warn!(
|
tracing::warn!(
|
||||||
"`rendezvous_point` config has {} duplicate entries, they are being ignored.",
|
"`rendezvous_point` config has {} duplicate entries, they are being ignored.",
|
||||||
@ -119,9 +123,12 @@ async fn main() -> Result<()> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// initialize monero wallet
|
||||||
let monero_wallet = init_monero_wallet(&config, env_config).await?;
|
let monero_wallet = init_monero_wallet(&config, env_config).await?;
|
||||||
let monero_address = monero_wallet.get_main_address();
|
let monero_address = monero_wallet.get_main_address();
|
||||||
tracing::info!(%monero_address, "Monero wallet address");
|
tracing::info!(%monero_address, "Monero wallet address");
|
||||||
|
|
||||||
|
// check monero balance
|
||||||
let monero = monero_wallet.get_balance().await?;
|
let monero = monero_wallet.get_balance().await?;
|
||||||
match (monero.balance, monero.unlocked_balance) {
|
match (monero.balance, monero.unlocked_balance) {
|
||||||
(0, _) => {
|
(0, _) => {
|
||||||
@ -144,6 +151,7 @@ async fn main() -> Result<()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// init bitcoin wallet
|
||||||
let bitcoin_wallet = init_bitcoin_wallet(&config, &seed, env_config).await?;
|
let bitcoin_wallet = init_bitcoin_wallet(&config, &seed, env_config).await?;
|
||||||
let bitcoin_balance = bitcoin_wallet.balance().await?;
|
let bitcoin_balance = bitcoin_wallet.balance().await?;
|
||||||
tracing::info!(%bitcoin_balance, "Bitcoin wallet balance");
|
tracing::info!(%bitcoin_balance, "Bitcoin wallet balance");
|
||||||
@ -314,6 +322,19 @@ async fn main() -> Result<()> {
|
|||||||
let config_json = serde_json::to_string_pretty(&config)?;
|
let config_json = serde_json::to_string_pretty(&config)?;
|
||||||
println!("{}", config_json);
|
println!("{}", config_json);
|
||||||
}
|
}
|
||||||
|
Command::Logs {
|
||||||
|
logs_dir,
|
||||||
|
swap_id,
|
||||||
|
redact,
|
||||||
|
} => {
|
||||||
|
let dir = logs_dir.unwrap_or(config.data.dir.join("logs"));
|
||||||
|
|
||||||
|
let log_messages = get_logs(dir, swap_id, redact).await?;
|
||||||
|
|
||||||
|
for msg in log_messages {
|
||||||
|
println!("{msg}");
|
||||||
|
}
|
||||||
|
}
|
||||||
Command::WithdrawBtc { amount, address } => {
|
Command::WithdrawBtc { amount, address } => {
|
||||||
let bitcoin_wallet = init_bitcoin_wallet(&config, &seed, env_config).await?;
|
let bitcoin_wallet = init_bitcoin_wallet(&config, &seed, env_config).await?;
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@ pub mod cancel_and_refund;
|
|||||||
pub mod command;
|
pub mod command;
|
||||||
mod event_loop;
|
mod event_loop;
|
||||||
mod list_sellers;
|
mod list_sellers;
|
||||||
pub mod tracing;
|
|
||||||
pub mod transport;
|
pub mod transport;
|
||||||
|
|
||||||
pub use behaviour::{Behaviour, OutEvent};
|
pub use behaviour::{Behaviour, OutEvent};
|
||||||
|
@ -105,6 +105,22 @@ where
|
|||||||
.await?;
|
.await?;
|
||||||
(context, request)
|
(context, request)
|
||||||
}
|
}
|
||||||
|
CliCommand::Logs {
|
||||||
|
logs_dir,
|
||||||
|
redact,
|
||||||
|
swap_id,
|
||||||
|
} => {
|
||||||
|
let request = Request::new(Method::Logs {
|
||||||
|
logs_dir,
|
||||||
|
redact,
|
||||||
|
swap_id,
|
||||||
|
});
|
||||||
|
let context =
|
||||||
|
Context::build(None, None, None, data, is_testnet, debug, json, None, false)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
(context, request)
|
||||||
|
}
|
||||||
CliCommand::Config => {
|
CliCommand::Config => {
|
||||||
let request = Request::new(Method::Config);
|
let request = Request::new(Method::Config);
|
||||||
|
|
||||||
@ -341,6 +357,25 @@ enum CliCommand {
|
|||||||
},
|
},
|
||||||
/// Show a list of past, ongoing and completed swaps
|
/// Show a list of past, ongoing and completed swaps
|
||||||
History,
|
History,
|
||||||
|
/// Output all logging messages that have been issued.
|
||||||
|
Logs {
|
||||||
|
#[structopt(
|
||||||
|
short = "d",
|
||||||
|
help = "Print the logs from this directory instead of the default one."
|
||||||
|
)]
|
||||||
|
logs_dir: Option<PathBuf>,
|
||||||
|
#[structopt(
|
||||||
|
help = "Redact swap-ids, Bitcoin and Monero addresses.",
|
||||||
|
long = "redact"
|
||||||
|
)]
|
||||||
|
redact: bool,
|
||||||
|
#[structopt(
|
||||||
|
long = "swap-id",
|
||||||
|
help = "Filter for logs concerning this swap.",
|
||||||
|
long_help = "This checks whether each logging message contains the swap id. Some messages might be skipped when they don't contain the swap id even though they're relevant."
|
||||||
|
)]
|
||||||
|
swap_id: Option<Uuid>,
|
||||||
|
},
|
||||||
#[structopt(about = "Prints the current config")]
|
#[structopt(about = "Prints the current config")]
|
||||||
Config,
|
Config,
|
||||||
#[structopt(about = "Allows withdrawing BTC from the internal Bitcoin wallet.")]
|
#[structopt(about = "Allows withdrawing BTC from the internal Bitcoin wallet.")]
|
||||||
|
@ -1,112 +0,0 @@
|
|||||||
use anyhow::Result;
|
|
||||||
use std::path::Path;
|
|
||||||
use time::format_description::well_known::Rfc3339;
|
|
||||||
use tracing::subscriber::set_global_default;
|
|
||||||
use tracing::{Event, Level, Subscriber};
|
|
||||||
use tracing_subscriber::fmt::format::{DefaultFields, Format, JsonFields};
|
|
||||||
use tracing_subscriber::fmt::time::UtcTime;
|
|
||||||
use tracing_subscriber::layer::{Context, SubscriberExt};
|
|
||||||
use tracing_subscriber::{fmt, EnvFilter, Layer, Registry};
|
|
||||||
|
|
||||||
pub fn init(debug: bool, json: bool, dir: impl AsRef<Path>) -> Result<()> {
|
|
||||||
let level_filter = EnvFilter::try_new("swap=debug")?;
|
|
||||||
let registry = Registry::default().with(level_filter);
|
|
||||||
|
|
||||||
let appender = tracing_appender::rolling::never(dir.as_ref(), "swap-all.log");
|
|
||||||
|
|
||||||
let file_logger = registry.with(
|
|
||||||
fmt::layer()
|
|
||||||
.with_ansi(false)
|
|
||||||
.with_target(false)
|
|
||||||
.json()
|
|
||||||
.with_writer(appender),
|
|
||||||
);
|
|
||||||
|
|
||||||
if json && debug {
|
|
||||||
set_global_default(file_logger.with(debug_json_terminal_printer()))?;
|
|
||||||
} else if json && !debug {
|
|
||||||
set_global_default(file_logger.with(info_json_terminal_printer()))?;
|
|
||||||
} else if !json && debug {
|
|
||||||
set_global_default(file_logger.with(debug_terminal_printer()))?;
|
|
||||||
} else {
|
|
||||||
set_global_default(file_logger.with(info_terminal_printer()))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
tracing::info!("Logging initialized to {}", dir.as_ref().display());
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct StdErrPrinter<L> {
|
|
||||||
inner: L,
|
|
||||||
level: Level,
|
|
||||||
}
|
|
||||||
|
|
||||||
type StdErrLayer<S, T> =
|
|
||||||
fmt::Layer<S, DefaultFields, Format<fmt::format::Full, T>, fn() -> std::io::Stderr>;
|
|
||||||
|
|
||||||
type StdErrJsonLayer<S, T> =
|
|
||||||
fmt::Layer<S, JsonFields, Format<fmt::format::Json, T>, fn() -> std::io::Stderr>;
|
|
||||||
|
|
||||||
fn debug_terminal_printer<S>() -> StdErrPrinter<StdErrLayer<S, UtcTime<Rfc3339>>> {
|
|
||||||
let is_terminal = atty::is(atty::Stream::Stderr);
|
|
||||||
StdErrPrinter {
|
|
||||||
inner: fmt::layer()
|
|
||||||
.with_ansi(is_terminal)
|
|
||||||
.with_target(false)
|
|
||||||
.with_timer(UtcTime::rfc_3339())
|
|
||||||
.with_writer(std::io::stderr),
|
|
||||||
level: Level::DEBUG,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn debug_json_terminal_printer<S>() -> StdErrPrinter<StdErrJsonLayer<S, UtcTime<Rfc3339>>> {
|
|
||||||
let is_terminal = atty::is(atty::Stream::Stderr);
|
|
||||||
StdErrPrinter {
|
|
||||||
inner: fmt::layer()
|
|
||||||
.with_ansi(is_terminal)
|
|
||||||
.with_target(false)
|
|
||||||
.with_timer(UtcTime::rfc_3339())
|
|
||||||
.json()
|
|
||||||
.with_writer(std::io::stderr),
|
|
||||||
level: Level::DEBUG,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn info_terminal_printer<S>() -> StdErrPrinter<StdErrLayer<S, ()>> {
|
|
||||||
let is_terminal = atty::is(atty::Stream::Stderr);
|
|
||||||
StdErrPrinter {
|
|
||||||
inner: fmt::layer()
|
|
||||||
.with_ansi(is_terminal)
|
|
||||||
.with_target(false)
|
|
||||||
.with_level(false)
|
|
||||||
.without_time()
|
|
||||||
.with_writer(std::io::stderr),
|
|
||||||
level: Level::INFO,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn info_json_terminal_printer<S>() -> StdErrPrinter<StdErrJsonLayer<S, ()>> {
|
|
||||||
let is_terminal = atty::is(atty::Stream::Stderr);
|
|
||||||
StdErrPrinter {
|
|
||||||
inner: fmt::layer()
|
|
||||||
.with_ansi(is_terminal)
|
|
||||||
.with_target(false)
|
|
||||||
.with_level(false)
|
|
||||||
.without_time()
|
|
||||||
.json()
|
|
||||||
.with_writer(std::io::stderr),
|
|
||||||
level: Level::INFO,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<L, S> Layer<S> for StdErrPrinter<L>
|
|
||||||
where
|
|
||||||
L: 'static + Layer<S>,
|
|
||||||
S: Subscriber + for<'a> tracing_subscriber::registry::LookupSpan<'a>,
|
|
||||||
{
|
|
||||||
fn on_event(&self, event: &Event<'_>, ctx: Context<'_, S>) {
|
|
||||||
if self.level.ge(event.metadata().level()) {
|
|
||||||
self.inner.on_event(event, ctx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,56 +0,0 @@
|
|||||||
use anyhow::anyhow;
|
|
||||||
|
|
||||||
const LATEST_RELEASE_URL: &str = "https://github.com/comit-network/xmr-btc-swap/releases/latest";
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
||||||
pub enum Version {
|
|
||||||
Current,
|
|
||||||
Available,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check the latest release from GitHub API.
|
|
||||||
pub async fn check_latest_version(current_version: &str) -> anyhow::Result<Version> {
|
|
||||||
let response = reqwest::get(LATEST_RELEASE_URL).await?;
|
|
||||||
let e = "Failed to get latest release.";
|
|
||||||
let download_url = response.url();
|
|
||||||
let segments = download_url.path_segments().ok_or_else(|| anyhow!(e))?;
|
|
||||||
let latest_version = segments.last().ok_or_else(|| anyhow!(e))?;
|
|
||||||
|
|
||||||
let result = if is_latest_version(current_version, latest_version) {
|
|
||||||
Version::Current
|
|
||||||
} else {
|
|
||||||
tracing::warn!(%current_version, %latest_version, %download_url,
|
|
||||||
"You are not on the latest version",
|
|
||||||
);
|
|
||||||
Version::Available
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
// todo: naive implementation can be improved using semver
|
|
||||||
fn is_latest_version(current: &str, latest: &str) -> bool {
|
|
||||||
current == latest
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn it_compares_versions() {
|
|
||||||
assert!(is_latest_version("0.10.2", "0.10.2"));
|
|
||||||
assert!(!is_latest_version("0.10.2", "0.10.3"));
|
|
||||||
assert!(!is_latest_version("0.10.2", "0.11.0"));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
|
||||||
#[ignore = "For local testing, makes http requests to github."]
|
|
||||||
async fn it_compares_with_github() {
|
|
||||||
let result = check_latest_version("0.11.0").await.unwrap();
|
|
||||||
assert_eq!(result, Version::Available);
|
|
||||||
|
|
||||||
let result = check_latest_version("0.11.1").await.unwrap();
|
|
||||||
assert_eq!(result, Version::Current);
|
|
||||||
}
|
|
||||||
}
|
|
221
swap/src/common/mod.rs
Normal file
221
swap/src/common/mod.rs
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
pub mod tracing_util;
|
||||||
|
|
||||||
|
use std::{collections::HashMap, path::PathBuf};
|
||||||
|
|
||||||
|
use anyhow::anyhow;
|
||||||
|
use tokio::{
|
||||||
|
fs::{read_dir, File},
|
||||||
|
io::{AsyncBufReadExt, BufReader},
|
||||||
|
};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
const LATEST_RELEASE_URL: &str = "https://github.com/comit-network/xmr-btc-swap/releases/latest";
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub enum Version {
|
||||||
|
Current,
|
||||||
|
Available,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check the latest release from GitHub API.
|
||||||
|
pub async fn check_latest_version(current_version: &str) -> anyhow::Result<Version> {
|
||||||
|
let response = reqwest::get(LATEST_RELEASE_URL).await?;
|
||||||
|
let e = "Failed to get latest release.";
|
||||||
|
let download_url = response.url();
|
||||||
|
let segments = download_url.path_segments().ok_or_else(|| anyhow!(e))?;
|
||||||
|
let latest_version = segments.last().ok_or_else(|| anyhow!(e))?;
|
||||||
|
|
||||||
|
let result = if is_latest_version(current_version, latest_version) {
|
||||||
|
Version::Current
|
||||||
|
} else {
|
||||||
|
tracing::warn!(%current_version, %latest_version, %download_url,
|
||||||
|
"You are not on the latest version",
|
||||||
|
);
|
||||||
|
Version::Available
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo: naive implementation can be improved using semver
|
||||||
|
fn is_latest_version(current: &str, latest: &str) -> bool {
|
||||||
|
current == latest
|
||||||
|
}
|
||||||
|
|
||||||
|
/// helper macro for [`redact`]... eldrich sorcery
|
||||||
|
/// the macro does in essence the following:
|
||||||
|
/// 1. create a static regex automaton for the pattern
|
||||||
|
/// 2. find all matching patterns using regex
|
||||||
|
/// 3. create a placeholder for each distinct matching pattern
|
||||||
|
/// 4. add the placeholder to the hashmap
|
||||||
|
macro_rules! regex_find_placeholders {
|
||||||
|
($pattern:expr, $create_placeholder:expr, $replacements:expr, $input:expr) => {{
|
||||||
|
// compile the regex pattern
|
||||||
|
static REGEX: once_cell::sync::Lazy<regex::Regex> = once_cell::sync::Lazy::new(|| {
|
||||||
|
tracing::debug!("initializing regex");
|
||||||
|
regex::Regex::new($pattern).expect("invalid regex pattern")
|
||||||
|
});
|
||||||
|
|
||||||
|
// keep count of count patterns to generate distinct placeholders
|
||||||
|
let mut counter: usize = 0;
|
||||||
|
|
||||||
|
// for every matched address check whether we already found it
|
||||||
|
// and if we didn't, generate a placeholder for it
|
||||||
|
for address in REGEX.find_iter($input) {
|
||||||
|
if !$replacements.contains_key(address.as_str()) {
|
||||||
|
#[allow(clippy::redundant_closure_call)]
|
||||||
|
$replacements.insert(address.as_str().to_owned(), $create_placeholder(counter));
|
||||||
|
counter += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Print the logs from the specified logs or from the default location
|
||||||
|
/// to the specified path or the terminal.
|
||||||
|
///
|
||||||
|
/// If specified, filter by swap id or redact addresses.
|
||||||
|
pub async fn get_logs(
|
||||||
|
logs_dir: PathBuf,
|
||||||
|
swap_id: Option<Uuid>,
|
||||||
|
redact_addresses: bool,
|
||||||
|
) -> anyhow::Result<Vec<String>> {
|
||||||
|
tracing::debug!("reading logfiles from {}", logs_dir.display());
|
||||||
|
|
||||||
|
// get all files in the directory
|
||||||
|
let mut log_files = read_dir(&logs_dir).await?;
|
||||||
|
|
||||||
|
let mut log_messages = Vec::new();
|
||||||
|
// when we redact we need to store the placeholder
|
||||||
|
let mut placeholders = HashMap::new();
|
||||||
|
|
||||||
|
// print all lines from every log file. TODO: sort files by date?
|
||||||
|
while let Some(entry) = log_files.next_entry().await? {
|
||||||
|
// get the file path
|
||||||
|
let file_path = entry.path();
|
||||||
|
|
||||||
|
// filter for .log files
|
||||||
|
let file_name = file_path
|
||||||
|
.file_name()
|
||||||
|
.and_then(|name| name.to_str())
|
||||||
|
.unwrap_or("");
|
||||||
|
|
||||||
|
if !file_name.ends_with(".log") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// use BufReader to stay easy on memory and then read line by line
|
||||||
|
let buf_reader = BufReader::new(File::open(&file_path).await?);
|
||||||
|
let mut lines = buf_reader.lines();
|
||||||
|
|
||||||
|
// print each line, redacted if the flag is set
|
||||||
|
while let Some(line) = lines.next_line().await? {
|
||||||
|
// if we should filter by swap id, check if the line contains it
|
||||||
|
if let Some(swap_id) = swap_id {
|
||||||
|
// we only want lines which contain the swap id
|
||||||
|
if !line.contains(&swap_id.to_string()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// redact if necessary
|
||||||
|
let line = if redact_addresses {
|
||||||
|
redact_with(&line, &mut placeholders)
|
||||||
|
} else {
|
||||||
|
line
|
||||||
|
};
|
||||||
|
// save redacted message
|
||||||
|
log_messages.push(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(log_messages)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Redact logs, etc. by replacing Bitcoin and Monero addresses
|
||||||
|
/// with generic placeholders.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```rust
|
||||||
|
/// use swap::common::redact;
|
||||||
|
///
|
||||||
|
/// let redacted = redact("a9165a1e-d26d-4b56-bf6d-ca9658825c44");
|
||||||
|
/// assert_eq!(redacted, "<swap_id_0>");
|
||||||
|
/// ```
|
||||||
|
pub fn redact(input: &str) -> String {
|
||||||
|
let mut replacements = HashMap::new();
|
||||||
|
redact_with(input, &mut replacements)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Same as [`redact`] but retrieves palceholders from and stores them
|
||||||
|
/// in a specified hashmap.
|
||||||
|
pub fn redact_with(input: &str, replacements: &mut HashMap<String, String>) -> String {
|
||||||
|
// TODO: verify regex patterns
|
||||||
|
const MONERO_ADDR_REGEX: &str = r#"[48][1-9A-HJ-NP-Za-km-z]{94}"#;
|
||||||
|
const BITCOIN_ADDR_REGEX: &str = r#"\b[13][a-km-zA-HJ-NP-Z1-9]{25,34}\b"#;
|
||||||
|
// Both XMR and BTC transactions have
|
||||||
|
// a 64 bit hex id so they aren't distinguishible
|
||||||
|
const TX_ID_REGEX: &str = r#"\b[a-fA-F0-9]{64}\b"#;
|
||||||
|
const SWAP_ID_REGEX: &str =
|
||||||
|
r#"\b[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}\b"#;
|
||||||
|
|
||||||
|
// use the macro to find all addresses and generate placeholders
|
||||||
|
// has to be a macro in order to create the regex automata only once.
|
||||||
|
regex_find_placeholders!(
|
||||||
|
MONERO_ADDR_REGEX,
|
||||||
|
|count| format!("<monero_address_{count}>"),
|
||||||
|
replacements,
|
||||||
|
input
|
||||||
|
);
|
||||||
|
regex_find_placeholders!(
|
||||||
|
BITCOIN_ADDR_REGEX,
|
||||||
|
|count| format!("<bitcoin_address_{count}>"),
|
||||||
|
replacements,
|
||||||
|
input
|
||||||
|
);
|
||||||
|
regex_find_placeholders!(
|
||||||
|
TX_ID_REGEX,
|
||||||
|
|count| format!("<tx_id_{count}>"),
|
||||||
|
replacements,
|
||||||
|
input
|
||||||
|
);
|
||||||
|
regex_find_placeholders!(
|
||||||
|
SWAP_ID_REGEX,
|
||||||
|
|count| format!("<swap_id_{count}>"),
|
||||||
|
replacements,
|
||||||
|
input
|
||||||
|
);
|
||||||
|
|
||||||
|
// allocate string variable to operate on
|
||||||
|
let mut redacted = input.to_owned();
|
||||||
|
|
||||||
|
// Finally we go through the input string and replace each occurance of an
|
||||||
|
// address we want to redact with the corresponding placeholder
|
||||||
|
for (address, placeholder) in replacements.iter() {
|
||||||
|
redacted = redacted.replace(address, placeholder);
|
||||||
|
}
|
||||||
|
|
||||||
|
redacted
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_compares_versions() {
|
||||||
|
assert!(is_latest_version("0.10.2", "0.10.2"));
|
||||||
|
assert!(!is_latest_version("0.10.2", "0.10.3"));
|
||||||
|
assert!(!is_latest_version("0.10.2", "0.11.0"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
#[ignore = "For local testing, makes http requests to github."]
|
||||||
|
async fn it_compares_with_github() {
|
||||||
|
let result = check_latest_version("0.11.0").await.unwrap();
|
||||||
|
assert_eq!(result, Version::Available);
|
||||||
|
|
||||||
|
let result = check_latest_version("0.11.1").await.unwrap();
|
||||||
|
assert_eq!(result, Version::Current);
|
||||||
|
}
|
||||||
|
}
|
64
swap/src/common/tracing_util.rs
Normal file
64
swap/src/common/tracing_util.rs
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
use std::path::Path;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use tracing_subscriber::filter::{Directive, LevelFilter};
|
||||||
|
use tracing_subscriber::fmt::time::UtcTime;
|
||||||
|
use tracing_subscriber::layer::SubscriberExt;
|
||||||
|
use tracing_subscriber::util::SubscriberInitExt;
|
||||||
|
use tracing_subscriber::{fmt, EnvFilter, Layer};
|
||||||
|
|
||||||
|
/// Output formats for logging messages.
|
||||||
|
pub enum Format {
|
||||||
|
/// Standard, human readable format.
|
||||||
|
Raw,
|
||||||
|
/// JSON, machine readable format.
|
||||||
|
Json,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Initialize tracing and enable logging messages according to these options.
|
||||||
|
/// Besides printing to `stdout`, this will append to a log file.
|
||||||
|
/// Said file will contain JSON-formatted logs of all levels,
|
||||||
|
/// disregarding the arguments to this function.
|
||||||
|
pub fn init(level_filter: LevelFilter, format: Format, dir: impl AsRef<Path>) -> Result<()> {
|
||||||
|
let env_filter = EnvFilter::from_default_env()
|
||||||
|
.add_directive(Directive::from_str(&format!("asb={}", &level_filter))?)
|
||||||
|
.add_directive(Directive::from_str(&format!("swap={}", &level_filter))?);
|
||||||
|
|
||||||
|
// file logger will always write in JSON format and with timestamps
|
||||||
|
let file_appender = tracing_appender::rolling::never(&dir, "swap-all.log");
|
||||||
|
|
||||||
|
let file_layer = fmt::layer()
|
||||||
|
.with_writer(file_appender)
|
||||||
|
.with_ansi(false)
|
||||||
|
.with_timer(UtcTime::rfc_3339())
|
||||||
|
.with_target(false)
|
||||||
|
.json()
|
||||||
|
.with_filter(env_filter);
|
||||||
|
|
||||||
|
// terminal logger
|
||||||
|
let is_terminal = atty::is(atty::Stream::Stderr);
|
||||||
|
let terminal_layer = fmt::layer()
|
||||||
|
.with_writer(std::io::stdout)
|
||||||
|
.with_ansi(is_terminal)
|
||||||
|
.with_timer(UtcTime::rfc_3339())
|
||||||
|
.with_target(false);
|
||||||
|
|
||||||
|
// combine the layers and start logging, format with json if specified
|
||||||
|
if let Format::Json = format {
|
||||||
|
tracing_subscriber::registry()
|
||||||
|
.with(file_layer)
|
||||||
|
.with(terminal_layer.json().with_filter(level_filter))
|
||||||
|
.init();
|
||||||
|
} else {
|
||||||
|
tracing_subscriber::registry()
|
||||||
|
.with(file_layer)
|
||||||
|
.with(terminal_layer.with_filter(level_filter))
|
||||||
|
.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
// now we can use the tracing macros to log messages
|
||||||
|
tracing::info!(%level_filter, logs_dir=%dir.as_ref().display(), "Initialized tracing");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
@ -5,7 +5,7 @@ use anyhow::{anyhow, Context, Result};
|
|||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use libp2p::{Multiaddr, PeerId};
|
use libp2p::{Multiaddr, PeerId};
|
||||||
use sqlx::sqlite::{Sqlite, SqliteConnectOptions};
|
use sqlx::sqlite::{Sqlite, SqliteConnectOptions};
|
||||||
use sqlx::{Pool, SqlitePool};
|
use sqlx::{ConnectOptions, Pool, SqlitePool};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
@ -26,7 +26,8 @@ impl SqliteDatabase {
|
|||||||
let read_only = matches!(access_mode, AccessMode::ReadOnly);
|
let read_only = matches!(access_mode, AccessMode::ReadOnly);
|
||||||
|
|
||||||
let path_str = format!("sqlite:{}", path.as_ref().display());
|
let path_str = format!("sqlite:{}", path.as_ref().display());
|
||||||
let options = SqliteConnectOptions::from_str(&path_str)?.read_only(read_only);
|
let mut options = SqliteConnectOptions::from_str(&path_str)?.read_only(read_only);
|
||||||
|
options.disable_statement_logging();
|
||||||
|
|
||||||
let pool = SqlitePool::connect_with(options).await?;
|
let pool = SqlitePool::connect_with(options).await?;
|
||||||
let mut sqlite = Self { pool };
|
let mut sqlite = Self { pool };
|
||||||
|
@ -7,7 +7,9 @@ use anyhow::Result;
|
|||||||
use jsonrpsee::server::RpcModule;
|
use jsonrpsee::server::RpcModule;
|
||||||
use jsonrpsee::types::Params;
|
use jsonrpsee::types::Params;
|
||||||
use libp2p::core::Multiaddr;
|
use libp2p::core::Multiaddr;
|
||||||
|
use serde::Deserialize;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::path::PathBuf;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
@ -48,8 +50,30 @@ pub fn register_modules(context: Arc<Context>) -> Result<RpcModule<Arc<Context>>
|
|||||||
execute_request(params_raw, Method::Balance { force_refresh }, &context).await
|
execute_request(params_raw, Method::Balance { force_refresh }, &context).await
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
module.register_async_method("get_history", |params, context| async move {
|
module.register_async_method("get_history", |params_raw, context| async move {
|
||||||
execute_request(params, Method::History, &context).await
|
execute_request(params_raw, Method::History, &context).await
|
||||||
|
})?;
|
||||||
|
|
||||||
|
module.register_async_method("get_logs", |params_raw, context| async move {
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
struct Params {
|
||||||
|
swap_id: Option<Uuid>,
|
||||||
|
logs_dir: Option<PathBuf>,
|
||||||
|
redact: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
let params: Params = params_raw.parse()?;
|
||||||
|
|
||||||
|
execute_request(
|
||||||
|
params_raw,
|
||||||
|
Method::Logs {
|
||||||
|
swap_id: params.swap_id,
|
||||||
|
logs_dir: params.logs_dir,
|
||||||
|
redact: params.redact,
|
||||||
|
},
|
||||||
|
&context,
|
||||||
|
)
|
||||||
|
.await
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
module.register_async_method("get_raw_states", |params, context| async move {
|
module.register_async_method("get_raw_states", |params, context| async move {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use crate::fs::ensure_directory_exists;
|
use crate::fs::ensure_directory_exists;
|
||||||
use ::bitcoin::secp256k1::constants::SECRET_KEY_SIZE;
|
|
||||||
use ::bitcoin::secp256k1::{self, SecretKey};
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use bdk::bitcoin::util::bip32::ExtendedPrivKey;
|
use bdk::bitcoin::util::bip32::ExtendedPrivKey;
|
||||||
use bitcoin::hashes::{sha256, Hash, HashEngine};
|
use bitcoin::hashes::{sha256, Hash, HashEngine};
|
||||||
|
use bitcoin::secp256k1::constants::SECRET_KEY_SIZE;
|
||||||
|
use bitcoin::secp256k1::{self, SecretKey};
|
||||||
use libp2p::identity;
|
use libp2p::identity;
|
||||||
use pem::{encode, Pem};
|
use pem::{encode, Pem};
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
|
Loading…
Reference in New Issue
Block a user