From acfd2dd6bb66b721b26fd03e4c250c705a274bb8 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Tue, 6 Jul 2021 19:34:02 +1000 Subject: [PATCH] Store Monero receive address in database and load it on resume --- CHANGELOG.md | 2 + swap/src/bin/swap.rs | 10 ++--- swap/src/cli/command.rs | 82 +++++++++-------------------------------- swap/src/database.rs | 49 ++++++++++++++++++++++++ 4 files changed, 72 insertions(+), 71 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1fd5197c..e6e1aab5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 The CLI can use regular TCP connections and having both - TCP and websockets - causes problems and unnecessary overhead. - The `--seller-addr` parameter from the CLI's `resume` command. This information is now loaded from the database. +- The `--receive-address` parameter from the CLI's `resume` command. + This information is now loaded from the database. ## [0.7.0] - 2021-05-28 diff --git a/swap/src/bin/swap.rs b/swap/src/bin/swap.rs index 4392bc60..7018d43a 100644 --- a/swap/src/bin/swap.rs +++ b/swap/src/bin/swap.rs @@ -12,7 +12,7 @@ #![forbid(unsafe_code)] #![allow(non_snake_case)] -use anyhow::{bail, Context, Result}; +use anyhow::{Context, Result}; use comfy_table::Table; use qrcode::render::unicode; use qrcode::QrCode; @@ -114,6 +114,8 @@ async fn main() -> Result<()> { info!(%amount, %fees, %swap_id, "Swapping"); db.insert_peer_id(swap_id, seller_peer_id).await?; + db.insert_monero_address(swap_id, monero_receive_address) + .await?; let swap = Swap::new( db, @@ -155,7 +157,6 @@ async fn main() -> Result<()> { swap_id, bitcoin_electrum_rpc_url, bitcoin_target_block, - monero_receive_address, monero_daemon_address, tor_socks5_port, } => { @@ -165,10 +166,6 @@ async fn main() -> Result<()> { let seed = Seed::from_file_or_generate(data_dir.as_path()) .context("Failed to read in seed file")?; - if monero_receive_address.network != env_config.monero_network { - bail!("The given monero address is on network {:?}, expected address of network {:?}.", monero_receive_address.network, env_config.monero_network) - } - let bitcoin_wallet = init_bitcoin_wallet( bitcoin_electrum_rpc_url, &seed, @@ -200,6 +197,7 @@ async fn main() -> Result<()> { EventLoop::new(swap_id, swarm, seller_peer_id, env_config)?; let handle = tokio::spawn(event_loop.run()); + let monero_receive_address = db.get_monero_address(swap_id)?; let swap = Swap::from_db( db, swap_id, diff --git a/swap/src/cli/command.rs b/swap/src/cli/command.rs index 54ec2c26..87b77523 100644 --- a/swap/src/cli/command.rs +++ b/swap/src/cli/command.rs @@ -75,11 +75,10 @@ where bitcoin_target_block, }, bitcoin_change_address, - monero: - Monero { - monero_receive_address, - monero_daemon_address, - }, + monero: Monero { + monero_daemon_address, + }, + monero_receive_address, tor: Tor { tor_socks5_port }, } => Arguments { env_config: env_config_from(is_testnet), @@ -119,11 +118,9 @@ where bitcoin_electrum_rpc_url, bitcoin_target_block, }, - monero: - Monero { - monero_receive_address, - monero_daemon_address, - }, + monero: Monero { + monero_daemon_address, + }, tor: Tor { tor_socks5_port }, } => Arguments { env_config: env_config_from(is_testnet), @@ -137,7 +134,6 @@ where is_testnet, )?, bitcoin_target_block: bitcoin_target_block_from(bitcoin_target_block, is_testnet), - monero_receive_address, monero_daemon_address: monero_daemon_address_from( monero_daemon_address, is_testnet, @@ -226,7 +222,6 @@ pub enum Command { swap_id: Uuid, bitcoin_electrum_rpc_url: Url, bitcoin_target_block: usize, - monero_receive_address: monero::Address, monero_daemon_address: String, tor_socks5_port: u16, }, @@ -299,6 +294,12 @@ pub enum RawCommand { #[structopt(flatten)] monero: Monero, + #[structopt(long = "receive-address", + help = "The monero address where you would like to receive monero", + parse(try_from_str = parse_monero_address) + )] + monero_receive_address: monero::Address, + #[structopt(flatten)] tor: Tor, }, @@ -355,12 +356,6 @@ pub enum RawCommand { #[derive(structopt::StructOpt, Debug)] pub struct Monero { - #[structopt(long = "receive-address", - help = "The monero address where you would like to receive monero", - parse(try_from_str = parse_monero_address) - )] - pub monero_receive_address: monero::Address, - #[structopt( long = "monero-daemon-address", help = "Specify to connect to a monero daemon of your choice: :" @@ -628,14 +623,7 @@ mod tests { #[test] fn given_resume_on_mainnet_then_defaults_to_mainnet() { - let raw_ars = vec![ - BINARY_NAME, - "resume", - "--swap-id", - SWAP_ID, - "--receive-address", - MONERO_MAINNET_ADDRESS, - ]; + let raw_ars = vec![BINARY_NAME, "resume", "--swap-id", SWAP_ID]; let args = parse_args_and_apply_defaults(raw_ars).unwrap(); @@ -647,15 +635,7 @@ mod tests { #[test] fn given_resume_on_testnet_then_defaults_to_testnet() { - let raw_ars = vec![ - BINARY_NAME, - "--testnet", - "resume", - "--swap-id", - SWAP_ID, - "--receive-address", - MONERO_STAGENET_ADDRESS, - ]; + let raw_ars = vec![BINARY_NAME, "--testnet", "resume", "--swap-id", SWAP_ID]; let args = parse_args_and_apply_defaults(raw_ars).unwrap(); @@ -771,8 +751,6 @@ mod tests { "resume", "--swap-id", SWAP_ID, - "--receive-address", - MONERO_MAINNET_ADDRESS, ]; let args = parse_args_and_apply_defaults(raw_ars).unwrap(); @@ -793,8 +771,6 @@ mod tests { "resume", "--swap-id", SWAP_ID, - "--receive-address", - MONERO_STAGENET_ADDRESS, ]; let args = parse_args_and_apply_defaults(raw_ars).unwrap(); @@ -847,15 +823,7 @@ mod tests { ParseResult::Arguments(Arguments::buy_xmr_testnet_defaults().with_debug()) ); - let raw_ars = vec![ - BINARY_NAME, - "--debug", - "resume", - "--swap-id", - SWAP_ID, - "--receive-address", - MONERO_MAINNET_ADDRESS, - ]; + let raw_ars = vec![BINARY_NAME, "--debug", "resume", "--swap-id", SWAP_ID]; let args = parse_args_and_apply_defaults(raw_ars).unwrap(); assert_eq!( @@ -870,8 +838,6 @@ mod tests { "resume", "--swap-id", SWAP_ID, - "--receive-address", - MONERO_STAGENET_ADDRESS, ]; let args = parse_args_and_apply_defaults(raw_ars).unwrap(); @@ -920,15 +886,7 @@ mod tests { ParseResult::Arguments(Arguments::buy_xmr_testnet_defaults().with_json()) ); - let raw_ars = vec![ - BINARY_NAME, - "--json", - "resume", - "--swap-id", - SWAP_ID, - "--receive-address", - MONERO_MAINNET_ADDRESS, - ]; + let raw_ars = vec![BINARY_NAME, "--json", "resume", "--swap-id", SWAP_ID]; let args = parse_args_and_apply_defaults(raw_ars).unwrap(); assert_eq!( @@ -943,8 +901,6 @@ mod tests { "resume", "--swap-id", SWAP_ID, - "--receive-address", - MONERO_STAGENET_ADDRESS, ]; let args = parse_args_and_apply_defaults(raw_ars).unwrap(); @@ -1005,8 +961,6 @@ mod tests { bitcoin_electrum_rpc_url: Url::from_str(DEFAULT_ELECTRUM_RPC_URL_TESTNET) .unwrap(), bitcoin_target_block: DEFAULT_BITCOIN_CONFIRMATION_TARGET_TESTNET, - monero_receive_address: monero::Address::from_str(MONERO_STAGENET_ADDRESS) - .unwrap(), monero_daemon_address: DEFAULT_MONERO_DAEMON_ADDRESS_STAGENET.to_string(), tor_socks5_port: DEFAULT_SOCKS5_PORT, }, @@ -1023,8 +977,6 @@ mod tests { swap_id: Uuid::from_str(SWAP_ID).unwrap(), bitcoin_electrum_rpc_url: Url::from_str(DEFAULT_ELECTRUM_RPC_URL).unwrap(), bitcoin_target_block: DEFAULT_BITCOIN_CONFIRMATION_TARGET, - monero_receive_address: monero::Address::from_str(MONERO_MAINNET_ADDRESS) - .unwrap(), monero_daemon_address: DEFAULT_MONERO_DAEMON_ADDRESS.to_string(), tor_socks5_port: DEFAULT_SOCKS5_PORT, }, diff --git a/swap/src/database.rs b/swap/src/database.rs index 34225c2f..339a1e35 100644 --- a/swap/src/database.rs +++ b/swap/src/database.rs @@ -69,6 +69,7 @@ pub struct Database { swaps: sled::Tree, peers: sled::Tree, addresses: sled::Tree, + monero_addresses: sled::Tree, } impl Database { @@ -81,11 +82,13 @@ impl Database { let swaps = db.open_tree("swaps")?; let peers = db.open_tree("peers")?; let addresses = db.open_tree("addresses")?; + let monero_addresses = db.open_tree("monero_addresses")?; Ok(Database { swaps, peers, addresses, + monero_addresses, }) } @@ -116,6 +119,39 @@ impl Database { Ok(PeerId::from_str(peer_id.as_str())?) } + pub async fn insert_monero_address( + &self, + swap_id: Uuid, + address: monero::Address, + ) -> Result<()> { + let key = swap_id.as_bytes(); + let value = serialize(&address)?; + + self.monero_addresses.insert(key, value)?; + + self.monero_addresses + .flush_async() + .await + .map(|_| ()) + .context("Could not flush db") + } + + pub fn get_monero_address(&self, swap_id: Uuid) -> Result { + let encoded = self + .monero_addresses + .get(swap_id.as_bytes())? + .ok_or_else(|| { + anyhow!( + "No Monero address found for swap id {} in database", + swap_id + ) + })?; + + let monero_address = deserialize(&encoded)?; + + Ok(monero_address) + } + pub async fn insert_address(&self, peer_id: PeerId, address: Multiaddr) -> Result<()> { let key = peer_id.to_bytes(); @@ -425,4 +461,17 @@ mod tests { Ok(()) } + + #[tokio::test] + async fn save_and_load_monero_address() -> Result<()> { + let db_dir = tempfile::tempdir()?; + let swap_id = Uuid::new_v4(); + + Database::open(db_dir.path())?.insert_monero_address(swap_id, "53gEuGZUhP9JMEBZoGaFNzhwEgiG7hwQdMCqFxiyiTeFPmkbt1mAoNybEUvYBKHcnrSgxnVWgZsTvRBaHBNXPa8tHiCU51a".parse()?).await?; + let loaded_monero_address = Database::open(db_dir.path())?.get_monero_address(swap_id)?; + + assert_eq!(loaded_monero_address.to_string(), "53gEuGZUhP9JMEBZoGaFNzhwEgiG7hwQdMCqFxiyiTeFPmkbt1mAoNybEUvYBKHcnrSgxnVWgZsTvRBaHBNXPa8tHiCU51a"); + + Ok(()) + } }