diff --git a/CHANGELOG.md b/CHANGELOG.md index b789604d..8307cf2a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +- ASB: The `history` command can now be used while the asb is running. - CLI: `--change-address` can now be omitted. In that case, any change is refunded to the internal bitcoin wallet. - ASB: The `history´ command can now also be executed while the asb is running. The database will be opened in read-only mode. diff --git a/swap/src/api.rs b/swap/src/api.rs index df325600..36c6972f 100644 --- a/swap/src/api.rs +++ b/swap/src/api.rs @@ -1,6 +1,6 @@ pub mod request; use crate::cli::command::{Bitcoin, Monero, Tor}; -use crate::database::open_db; +use crate::database::{open_db, AccessMode}; use crate::env::{Config as EnvConfig, GetConfig, Mainnet, Testnet}; use crate::fs::system_data_dir; use crate::network::rendezvous::XmrBtcNamespace; @@ -224,7 +224,7 @@ impl Context { let tor_socks5_port = tor.map_or(9050, |tor| tor.tor_socks5_port); let context = Context { - db: open_db(data_dir.join("sqlite"), false).await?, + db: open_db(data_dir.join("sqlite"), AccessMode::ReadWrite).await?, bitcoin_wallet, monero_wallet, monero_rpc_process, @@ -259,7 +259,7 @@ impl Context { bitcoin_wallet: Some(bob_bitcoin_wallet), monero_wallet: Some(bob_monero_wallet), config, - db: open_db(db_path, false) + db: open_db(db_path, AccessMode::ReadWrite) .await .expect("Could not open sqlite database"), monero_rpc_process: None, diff --git a/swap/src/bin/asb.rs b/swap/src/bin/asb.rs index 1fc4b5f6..0f2f13b5 100644 --- a/swap/src/bin/asb.rs +++ b/swap/src/bin/asb.rs @@ -30,7 +30,7 @@ use swap::asb::config::{ }; use swap::asb::{cancel, punish, redeem, refund, safely_abort, EventLoop, Finality, KrakenRate}; use swap::common::check_latest_version; -use swap::database::open_db; +use swap::database::{open_db, AccessMode}; use swap::network::rendezvous::XmrBtcNamespace; use swap::network::swarm; use swap::protocol::alice::{run, AliceState}; @@ -100,7 +100,7 @@ async fn main() -> Result<()> { match cmd { Command::Start { resume_only } => { - let db = open_db(config.data.dir.join("sqlite"), false).await?; + let db = open_db(config.data.dir.join("sqlite"), AccessMode::ReadWrite).await?; // check and warn for duplicate rendezvous points let mut rendezvous_addrs = config.network.rendezvous_point.clone(); @@ -225,7 +225,7 @@ async fn main() -> Result<()> { event_loop.run().await; } Command::History => { - let db = open_db(config.data.dir.join("sqlite"), true).await?; + let db = open_db(config.data.dir.join("sqlite"), AccessMode::ReadOnly).await?; let mut table = Table::new(); @@ -272,7 +272,7 @@ async fn main() -> Result<()> { tracing::info!(%bitcoin_balance, %monero_balance, "Current balance"); } Command::Cancel { swap_id } => { - let db = open_db(config.data.dir.join("sqlite"), false).await?; + let db = open_db(config.data.dir.join("sqlite"), AccessMode::ReadWrite).await?; let bitcoin_wallet = init_bitcoin_wallet(&config, &seed, env_config).await?; @@ -281,7 +281,7 @@ async fn main() -> Result<()> { tracing::info!("Cancel transaction successfully published with id {}", txid); } Command::Refund { swap_id } => { - let db = open_db(config.data.dir.join("sqlite"), false).await?; + let db = open_db(config.data.dir.join("sqlite"), AccessMode::ReadWrite).await?; let bitcoin_wallet = init_bitcoin_wallet(&config, &seed, env_config).await?; let monero_wallet = init_monero_wallet(&config, env_config).await?; @@ -297,7 +297,7 @@ async fn main() -> Result<()> { tracing::info!("Monero successfully refunded"); } Command::Punish { swap_id } => { - let db = open_db(config.data.dir.join("sqlite"), false).await?; + let db = open_db(config.data.dir.join("sqlite"), AccessMode::ReadWrite).await?; let bitcoin_wallet = init_bitcoin_wallet(&config, &seed, env_config).await?; @@ -306,7 +306,7 @@ async fn main() -> Result<()> { tracing::info!("Punish transaction successfully published with id {}", txid); } Command::SafelyAbort { swap_id } => { - let db = open_db(config.data.dir.join("sqlite"), false).await?; + let db = open_db(config.data.dir.join("sqlite"), AccessMode::ReadWrite).await?; safely_abort(swap_id, db).await?; @@ -316,7 +316,7 @@ async fn main() -> Result<()> { swap_id, do_not_await_finality, } => { - let db = open_db(config.data.dir.join("sqlite"), false).await?; + let db = open_db(config.data.dir.join("sqlite"), AccessMode::ReadWrite).await?; let bitcoin_wallet = init_bitcoin_wallet(&config, &seed, env_config).await?; diff --git a/swap/src/database.rs b/swap/src/database.rs index 0e307321..7c6185f7 100644 --- a/swap/src/database.rs +++ b/swap/src/database.rs @@ -83,19 +83,25 @@ impl Swap { } } +#[derive(Debug, Clone, Copy, Serialize, Deserialize, Hash, PartialEq)] +pub enum AccessMode { + ReadWrite, + ReadOnly, +} + pub async fn open_db( sqlite_path: impl AsRef, - read_only: bool, + access_mode: AccessMode, ) -> Result> { if sqlite_path.as_ref().exists() { tracing::debug!("Using existing sqlite database."); - let sqlite = SqliteDatabase::open(sqlite_path, read_only).await?; + let sqlite = SqliteDatabase::open(sqlite_path, access_mode).await?; Ok(Arc::new(sqlite)) } else { tracing::debug!("Creating and using new sqlite database."); ensure_directory_exists(sqlite_path.as_ref())?; tokio::fs::File::create(&sqlite_path).await?; - let sqlite = SqliteDatabase::open(sqlite_path, read_only).await?; + let sqlite = SqliteDatabase::open(sqlite_path, access_mode).await?; Ok(Arc::new(sqlite)) } } diff --git a/swap/src/database/sqlite.rs b/swap/src/database/sqlite.rs index 672a1382..b7051596 100644 --- a/swap/src/database/sqlite.rs +++ b/swap/src/database/sqlite.rs @@ -12,15 +12,19 @@ use std::str::FromStr; use time::OffsetDateTime; use uuid::Uuid; +use super::AccessMode; + pub struct SqliteDatabase { pool: Pool, } impl SqliteDatabase { - pub async fn open(path: impl AsRef, read_only: bool) -> Result + pub async fn open(path: impl AsRef, access_mode: AccessMode) -> Result where Self: std::marker::Sized, { + let read_only = matches!(access_mode, AccessMode::ReadOnly); + let path_str = format!("sqlite:{}", path.as_ref().display()); let options = SqliteConnectOptions::from_str(&path_str)?.read_only(read_only); @@ -515,7 +519,7 @@ mod tests { // file has to exist in order to connect with sqlite File::create(temp_db.clone()).unwrap(); - let db = SqliteDatabase::open(temp_db, false).await?; + let db = SqliteDatabase::open(temp_db, AccessMode::ReadWrite).await?; Ok(db) } diff --git a/swap/tests/harness/mod.rs b/swap/tests/harness/mod.rs index 1e1b5e89..44440a8e 100644 --- a/swap/tests/harness/mod.rs +++ b/swap/tests/harness/mod.rs @@ -16,7 +16,7 @@ use std::sync::Arc; use std::time::Duration; use swap::asb::FixedRate; use swap::bitcoin::{CancelTimelock, PunishTimelock, TxCancel, TxPunish, TxRedeem, TxRefund}; -use swap::database::SqliteDatabase; +use swap::database::{AccessMode, SqliteDatabase}; use swap::env::{Config, GetConfig}; use swap::fs::ensure_directory_exists; use swap::network::rendezvous::XmrBtcNamespace; @@ -232,7 +232,7 @@ async fn start_alice( tokio::fs::File::create(&db_path).await.unwrap(); } let db = Arc::new( - SqliteDatabase::open(db_path.as_path(), false) + SqliteDatabase::open(db_path.as_path(), AccessMode::ReadWrite) .await .unwrap(), ); @@ -437,7 +437,7 @@ impl BobParams { if !self.db_path.exists() { tokio::fs::File::create(&self.db_path).await?; } - let db = Arc::new(SqliteDatabase::open(&self.db_path, false).await?); + let db = Arc::new(SqliteDatabase::open(&self.db_path, AccessMode::ReadWrite).await?); let (event_loop, handle) = self.new_eventloop(swap_id, db.clone()).await?; @@ -467,7 +467,7 @@ impl BobParams { if !self.db_path.exists() { tokio::fs::File::create(&self.db_path).await?; } - let db = Arc::new(SqliteDatabase::open(&self.db_path, false).await?); + let db = Arc::new(SqliteDatabase::open(&self.db_path, AccessMode::ReadWrite).await?); let (event_loop, handle) = self.new_eventloop(swap_id, db.clone()).await?;