mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2024-10-01 01:45:40 -04:00
Save Alice's peer-id in the db for Bob
This allows loading the seller-peer-id from the database upon resuming a swap. Thus, the parameters `--seller-peer-id` is removed for the `resume` command. Other than the peer-id the multi address of a seller can change and thus is still a parameter. This parameter might become optional once we add DHT support.
This commit is contained in:
parent
bc442bcad3
commit
d90496931b
@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Changed
|
||||
|
||||
- The `resume` command of the `swap` CLI no longer require the `--seller-peer-id` parameter.
|
||||
This information is now saved in the database.
|
||||
|
||||
### Added
|
||||
|
||||
- A changelog file.
|
||||
|
@ -21,7 +21,7 @@ use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use structopt::StructOpt;
|
||||
use swap::bitcoin::{Amount, TxLock};
|
||||
use swap::cli::command::{AliceConnectParams, Arguments, Command, Data, MoneroParams};
|
||||
use swap::cli::command::{AliceMultiaddress, Arguments, Command, Data, MoneroParams};
|
||||
use swap::database::Database;
|
||||
use swap::env::{Config, GetConfig};
|
||||
use swap::network::quote::BidQuote;
|
||||
@ -81,9 +81,9 @@ async fn main() -> Result<()> {
|
||||
|
||||
match args.cmd {
|
||||
Command::BuyXmr {
|
||||
connect_params:
|
||||
AliceConnectParams {
|
||||
peer_id: alice_peer_id,
|
||||
alice_peer_id,
|
||||
alice_multi_addr:
|
||||
AliceMultiaddress {
|
||||
multiaddr: alice_addr,
|
||||
},
|
||||
monero_params:
|
||||
@ -131,9 +131,12 @@ async fn main() -> Result<()> {
|
||||
)
|
||||
.await?;
|
||||
|
||||
let swap_id = Uuid::new_v4();
|
||||
db.insert_peer_id(swap_id, alice_peer_id).await?;
|
||||
|
||||
let swap = Builder::new(
|
||||
db,
|
||||
Uuid::new_v4(),
|
||||
swap_id,
|
||||
bitcoin_wallet.clone(),
|
||||
Arc::new(monero_wallet),
|
||||
env_config,
|
||||
@ -167,9 +170,8 @@ async fn main() -> Result<()> {
|
||||
}
|
||||
Command::Resume {
|
||||
swap_id,
|
||||
connect_params:
|
||||
AliceConnectParams {
|
||||
peer_id: alice_peer_id,
|
||||
alice_multi_addr:
|
||||
AliceMultiaddress {
|
||||
multiaddr: alice_addr,
|
||||
},
|
||||
monero_params:
|
||||
@ -189,6 +191,7 @@ async fn main() -> Result<()> {
|
||||
init_monero_wallet(data_dir, monero_daemon_host, env_config).await?;
|
||||
let bitcoin_wallet = Arc::new(bitcoin_wallet);
|
||||
|
||||
let alice_peer_id = db.get_peer_id(swap_id)?;
|
||||
let mut swarm = swarm::new::<Behaviour>(&seed)?;
|
||||
swarm.add_address(alice_peer_id, alice_addr);
|
||||
|
||||
|
@ -37,8 +37,15 @@ pub struct Arguments {
|
||||
pub enum Command {
|
||||
/// Start a XMR for BTC swap
|
||||
BuyXmr {
|
||||
#[structopt(
|
||||
long = "seller-peer-id",
|
||||
default_value = DEFAULT_ALICE_PEER_ID,
|
||||
help = "The peer id of a specific swap partner can be optionally provided"
|
||||
)]
|
||||
alice_peer_id: PeerId,
|
||||
|
||||
#[structopt(flatten)]
|
||||
connect_params: AliceConnectParams,
|
||||
alice_multi_addr: AliceMultiaddress,
|
||||
|
||||
#[structopt(long = "electrum-rpc",
|
||||
help = "Provide the Bitcoin Electrum RPC URL",
|
||||
@ -60,7 +67,7 @@ pub enum Command {
|
||||
swap_id: Uuid,
|
||||
|
||||
#[structopt(flatten)]
|
||||
connect_params: AliceConnectParams,
|
||||
alice_multi_addr: AliceMultiaddress,
|
||||
|
||||
#[structopt(long = "electrum-rpc",
|
||||
help = "Provide the Bitcoin Electrum RPC URL",
|
||||
@ -108,14 +115,7 @@ pub enum Command {
|
||||
}
|
||||
|
||||
#[derive(structopt::StructOpt, Debug)]
|
||||
pub struct AliceConnectParams {
|
||||
#[structopt(
|
||||
long = "seller-peer-id",
|
||||
default_value = DEFAULT_ALICE_PEER_ID,
|
||||
help = "The peer id of a specific swap partner can be optionally provided"
|
||||
)]
|
||||
pub peer_id: PeerId,
|
||||
|
||||
pub struct AliceMultiaddress {
|
||||
#[structopt(
|
||||
long = "seller-addr",
|
||||
default_value = DEFAULT_ALICE_MULTIADDR,
|
||||
|
@ -3,10 +3,12 @@ pub use bob::Bob;
|
||||
|
||||
use anyhow::{anyhow, bail, Context, Result};
|
||||
use itertools::Itertools;
|
||||
use libp2p::PeerId;
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt::Display;
|
||||
use std::path::Path;
|
||||
use std::str::FromStr;
|
||||
use uuid::Uuid;
|
||||
|
||||
mod alice;
|
||||
@ -63,7 +65,10 @@ impl Swap {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Database(sled::Db);
|
||||
pub struct Database {
|
||||
swaps: sled::Tree,
|
||||
peers: sled::Tree,
|
||||
}
|
||||
|
||||
impl Database {
|
||||
pub fn open(path: &Path) -> Result<Self> {
|
||||
@ -72,22 +77,51 @@ impl Database {
|
||||
let db =
|
||||
sled::open(path).with_context(|| format!("Could not open the DB at {:?}", path))?;
|
||||
|
||||
Ok(Database(db))
|
||||
let swaps = db.open_tree("swaps")?;
|
||||
let peers = db.open_tree("peers")?;
|
||||
|
||||
Ok(Database { swaps, peers })
|
||||
}
|
||||
|
||||
pub async fn insert_peer_id(&self, swap_id: Uuid, peer_id: PeerId) -> Result<()> {
|
||||
let peer_id_str = peer_id.to_string();
|
||||
|
||||
let key = serialize(&swap_id)?;
|
||||
let value = serialize(&peer_id_str).context("Could not serialize peer-id")?;
|
||||
|
||||
self.peers.insert(key, value)?;
|
||||
|
||||
self.peers
|
||||
.flush_async()
|
||||
.await
|
||||
.map(|_| ())
|
||||
.context("Could not flush db")
|
||||
}
|
||||
|
||||
pub fn get_peer_id(&self, swap_id: Uuid) -> Result<PeerId> {
|
||||
let key = serialize(&swap_id)?;
|
||||
|
||||
let encoded = self
|
||||
.peers
|
||||
.get(&key)?
|
||||
.ok_or_else(|| anyhow!("No peer-id found for swap id {} in database", swap_id))?;
|
||||
|
||||
let peer_id: String = deserialize(&encoded).context("Could not deserialize peer-id")?;
|
||||
Ok(PeerId::from_str(peer_id.as_str())?)
|
||||
}
|
||||
|
||||
pub async fn insert_latest_state(&self, swap_id: Uuid, state: Swap) -> Result<()> {
|
||||
let key = serialize(&swap_id)?;
|
||||
let new_value = serialize(&state).context("Could not serialize new state value")?;
|
||||
|
||||
let old_value = self.0.get(&key)?;
|
||||
let old_value = self.swaps.get(&key)?;
|
||||
|
||||
self.0
|
||||
self.swaps
|
||||
.compare_and_swap(key, old_value, Some(new_value))
|
||||
.context("Could not write in the DB")?
|
||||
.context("Stored swap somehow changed, aborting saving")?;
|
||||
|
||||
// TODO: see if this can be done through sled config
|
||||
self.0
|
||||
self.swaps
|
||||
.flush_async()
|
||||
.await
|
||||
.map(|_| ())
|
||||
@ -98,7 +132,7 @@ impl Database {
|
||||
let key = serialize(&swap_id)?;
|
||||
|
||||
let encoded = self
|
||||
.0
|
||||
.swaps
|
||||
.get(&key)?
|
||||
.ok_or_else(|| anyhow!("Swap with id {} not found in database", swap_id))?;
|
||||
|
||||
@ -129,7 +163,7 @@ impl Database {
|
||||
}
|
||||
|
||||
fn all_swaps_iter(&self) -> impl Iterator<Item = Result<(Uuid, Swap)>> {
|
||||
self.0.iter().map(|item| {
|
||||
self.swaps.iter().map(|item| {
|
||||
let (key, value) = item.context("Failed to retrieve swap from DB")?;
|
||||
|
||||
let swap_id = deserialize::<Uuid>(&key)?;
|
||||
@ -277,4 +311,52 @@ mod tests {
|
||||
|
||||
assert_eq!(err.downcast_ref::<NotBob>().unwrap(), &NotBob);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn can_save_swap_state_and_peer_id_with_same_swap_id() -> Result<()> {
|
||||
let db_dir = tempfile::tempdir().unwrap();
|
||||
let db = Database::open(db_dir.path()).unwrap();
|
||||
|
||||
let alice_id = Uuid::new_v4();
|
||||
let alice_state = Alice::Done(AliceEndState::BtcPunished);
|
||||
let alice_swap = Swap::Alice(alice_state);
|
||||
let peer_id = PeerId::random();
|
||||
|
||||
db.insert_latest_state(alice_id, alice_swap.clone()).await?;
|
||||
db.insert_peer_id(alice_id, peer_id).await?;
|
||||
|
||||
let loaded_swap = db.get_state(alice_id)?;
|
||||
let loaded_peer_id = db.get_peer_id(alice_id)?;
|
||||
|
||||
assert_eq!(alice_swap, loaded_swap);
|
||||
assert_eq!(peer_id, loaded_peer_id);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_reopen_db() -> Result<()> {
|
||||
let db_dir = tempfile::tempdir().unwrap();
|
||||
let alice_id = Uuid::new_v4();
|
||||
let alice_state = Alice::Done(AliceEndState::BtcPunished);
|
||||
let alice_swap = Swap::Alice(alice_state);
|
||||
|
||||
let peer_id = PeerId::random();
|
||||
|
||||
{
|
||||
let db = Database::open(db_dir.path()).unwrap();
|
||||
db.insert_latest_state(alice_id, alice_swap.clone()).await?;
|
||||
db.insert_peer_id(alice_id, peer_id).await?;
|
||||
}
|
||||
|
||||
let db = Database::open(db_dir.path()).unwrap();
|
||||
|
||||
let loaded_swap = db.get_state(alice_id)?;
|
||||
let loaded_peer_id = db.get_peer_id(alice_id)?;
|
||||
|
||||
assert_eq!(alice_swap, loaded_swap);
|
||||
assert_eq!(peer_id, loaded_peer_id);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user