diff --git a/swap/src/api.rs b/swap/src/api.rs index fb071cd47..df3256002 100644 --- a/swap/src/api.rs +++ b/swap/src/api.rs @@ -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")).await?, + db: open_db(data_dir.join("sqlite"), false).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) + db: open_db(db_path, false) .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 ff3b0e4c2..1fc4b5f6f 100644 --- a/swap/src/bin/asb.rs +++ b/swap/src/bin/asb.rs @@ -95,13 +95,13 @@ async fn main() -> Result<()> { )); } - let db = open_db(config.data.dir.join("sqlite")).await?; - let seed = Seed::from_file_or_generate(&config.data.dir).expect("Could not retrieve/initialize seed"); match cmd { Command::Start { resume_only } => { + let db = open_db(config.data.dir.join("sqlite"), false).await?; + // check and warn for duplicate rendezvous points let mut rendezvous_addrs = config.network.rendezvous_point.clone(); let prev_len = rendezvous_addrs.len(); @@ -225,6 +225,8 @@ async fn main() -> Result<()> { event_loop.run().await; } Command::History => { + let db = open_db(config.data.dir.join("sqlite"), true).await?; + let mut table = Table::new(); table.set_header(vec!["SWAP ID", "STATE"]); @@ -270,6 +272,8 @@ 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 bitcoin_wallet = init_bitcoin_wallet(&config, &seed, env_config).await?; let (txid, _) = cancel(swap_id, Arc::new(bitcoin_wallet), db).await?; @@ -277,6 +281,8 @@ 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 bitcoin_wallet = init_bitcoin_wallet(&config, &seed, env_config).await?; let monero_wallet = init_monero_wallet(&config, env_config).await?; @@ -291,6 +297,8 @@ 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 bitcoin_wallet = init_bitcoin_wallet(&config, &seed, env_config).await?; let (txid, _) = punish(swap_id, Arc::new(bitcoin_wallet), db).await?; @@ -298,6 +306,8 @@ 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?; + safely_abort(swap_id, db).await?; tracing::info!("Swap safely aborted"); @@ -306,6 +316,8 @@ async fn main() -> Result<()> { swap_id, do_not_await_finality, } => { + let db = open_db(config.data.dir.join("sqlite"), false).await?; + let bitcoin_wallet = init_bitcoin_wallet(&config, &seed, env_config).await?; let (txid, _) = redeem( diff --git a/swap/src/database.rs b/swap/src/database.rs index 7af161961..0e307321f 100644 --- a/swap/src/database.rs +++ b/swap/src/database.rs @@ -83,16 +83,19 @@ impl Swap { } } -pub async fn open_db(sqlite_path: impl AsRef) -> Result> { +pub async fn open_db( + sqlite_path: impl AsRef, + read_only: bool, +) -> Result> { if sqlite_path.as_ref().exists() { tracing::debug!("Using existing sqlite database."); - let sqlite = SqliteDatabase::open(sqlite_path).await?; + let sqlite = SqliteDatabase::open(sqlite_path, read_only).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).await?; + let sqlite = SqliteDatabase::open(sqlite_path, read_only).await?; Ok(Arc::new(sqlite)) } } diff --git a/swap/src/database/sqlite.rs b/swap/src/database/sqlite.rs index 6cddd50ed..672a13828 100644 --- a/swap/src/database/sqlite.rs +++ b/swap/src/database/sqlite.rs @@ -4,7 +4,7 @@ use crate::protocol::{Database, State}; use anyhow::{anyhow, Context, Result}; use async_trait::async_trait; use libp2p::{Multiaddr, PeerId}; -use sqlx::sqlite::Sqlite; +use sqlx::sqlite::{Sqlite, SqliteConnectOptions}; use sqlx::{Pool, SqlitePool}; use std::collections::HashMap; use std::path::Path; @@ -17,14 +17,20 @@ pub struct SqliteDatabase { } impl SqliteDatabase { - pub async fn open(path: impl AsRef) -> Result + pub async fn open(path: impl AsRef, read_only: bool) -> Result where Self: std::marker::Sized, { let path_str = format!("sqlite:{}", path.as_ref().display()); - let pool = SqlitePool::connect(&path_str).await?; + let options = SqliteConnectOptions::from_str(&path_str)?.read_only(read_only); + + let pool = SqlitePool::connect_with(options).await?; let mut sqlite = Self { pool }; - sqlite.run_migrations().await?; + + if !read_only { + sqlite.run_migrations().await?; + } + Ok(sqlite) } @@ -509,7 +515,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).await?; + let db = SqliteDatabase::open(temp_db, false).await?; Ok(db) } diff --git a/swap/tests/harness/mod.rs b/swap/tests/harness/mod.rs index 028b09352..1e1b5e896 100644 --- a/swap/tests/harness/mod.rs +++ b/swap/tests/harness/mod.rs @@ -231,7 +231,11 @@ async fn start_alice( if !&db_path.exists() { tokio::fs::File::create(&db_path).await.unwrap(); } - let db = Arc::new(SqliteDatabase::open(db_path.as_path()).await.unwrap()); + let db = Arc::new( + SqliteDatabase::open(db_path.as_path(), false) + .await + .unwrap(), + ); let min_buy = bitcoin::Amount::from_sat(u64::MIN); let max_buy = bitcoin::Amount::from_sat(u64::MAX); @@ -433,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).await?); + let db = Arc::new(SqliteDatabase::open(&self.db_path, false).await?); let (event_loop, handle) = self.new_eventloop(swap_id, db.clone()).await?; @@ -463,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).await?); + let db = Arc::new(SqliteDatabase::open(&self.db_path, false).await?); let (event_loop, handle) = self.new_eventloop(swap_id, db.clone()).await?;