|
|
|
@ -2,6 +2,7 @@ pub use alice::Alice;
|
|
|
|
|
pub use bob::Bob;
|
|
|
|
|
|
|
|
|
|
use anyhow::{anyhow, bail, Context, Result};
|
|
|
|
|
use itertools::Itertools;
|
|
|
|
|
use serde::de::DeserializeOwned;
|
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
|
use std::fmt::Display;
|
|
|
|
@ -38,11 +39,26 @@ impl Display for Swap {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(thiserror::Error, Debug, Clone, Copy, PartialEq)]
|
|
|
|
|
#[error("Not in the role of Alice")]
|
|
|
|
|
struct NotAlice;
|
|
|
|
|
|
|
|
|
|
#[derive(thiserror::Error, Debug, Clone, Copy, PartialEq)]
|
|
|
|
|
#[error("Not in the role of Bob")]
|
|
|
|
|
struct NotBob;
|
|
|
|
|
|
|
|
|
|
impl Swap {
|
|
|
|
|
pub fn try_into_alice(self) -> Result<Alice> {
|
|
|
|
|
match self {
|
|
|
|
|
Swap::Alice(alice) => Ok(alice),
|
|
|
|
|
Swap::Bob(_) => bail!(NotAlice),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn try_into_bob(self) -> Result<Bob> {
|
|
|
|
|
match self {
|
|
|
|
|
Swap::Bob(bob) => Ok(bob),
|
|
|
|
|
Swap::Alice(_) => bail!("Swap instance is not Bob"),
|
|
|
|
|
Swap::Alice(_) => bail!(NotBob),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -90,22 +106,42 @@ impl Database {
|
|
|
|
|
Ok(state)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn all(&self) -> Result<Vec<(Uuid, Swap)>> {
|
|
|
|
|
self.0
|
|
|
|
|
.iter()
|
|
|
|
|
.map(|item| match item {
|
|
|
|
|
Ok((key, value)) => {
|
|
|
|
|
let swap_id = deserialize::<Uuid>(&key);
|
|
|
|
|
let swap = deserialize::<Swap>(&value).context("Failed to deserialize swap");
|
|
|
|
|
|
|
|
|
|
match (swap_id, swap) {
|
|
|
|
|
(Ok(swap_id), Ok(swap)) => Ok((swap_id, swap)),
|
|
|
|
|
(Ok(_), Err(err)) => Err(err),
|
|
|
|
|
_ => bail!("Failed to deserialize swap"),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Err(err) => Err(err).context("Failed to retrieve swap from DB"),
|
|
|
|
|
})
|
|
|
|
|
pub fn all_alice(&self) -> Result<Vec<(Uuid, Alice)>> {
|
|
|
|
|
self.all_alice_iter().collect()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn all_alice_iter(&self) -> impl Iterator<Item = Result<(Uuid, Alice)>> {
|
|
|
|
|
self.all_swaps_iter().map(|item| {
|
|
|
|
|
let (swap_id, swap) = item?;
|
|
|
|
|
Ok((swap_id, swap.try_into_alice()?))
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn all_bob(&self) -> Result<Vec<(Uuid, Bob)>> {
|
|
|
|
|
self.all_bob_iter().collect()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn all_bob_iter(&self) -> impl Iterator<Item = Result<(Uuid, Bob)>> {
|
|
|
|
|
self.all_swaps_iter().map(|item| {
|
|
|
|
|
let (swap_id, swap) = item?;
|
|
|
|
|
Ok((swap_id, swap.try_into_bob()?))
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn all_swaps_iter(&self) -> impl Iterator<Item = Result<(Uuid, Swap)>> {
|
|
|
|
|
self.0.iter().map(|item| {
|
|
|
|
|
let (key, value) = item.context("Failed to retrieve swap from DB")?;
|
|
|
|
|
|
|
|
|
|
let swap_id = deserialize::<Uuid>(&key)?;
|
|
|
|
|
let swap = deserialize::<Swap>(&value).context("Failed to deserialize swap")?;
|
|
|
|
|
|
|
|
|
|
Ok((swap_id, swap))
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn unfinished_alice(&self) -> Result<Vec<(Uuid, Alice)>> {
|
|
|
|
|
self.all_alice_iter()
|
|
|
|
|
.filter_ok(|(_swap_id, alice)| !matches!(alice, Alice::Done(_)))
|
|
|
|
|
.collect()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -187,26 +223,58 @@ mod tests {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
|
async fn can_fetch_all_keys() {
|
|
|
|
|
async fn all_swaps_as_alice() {
|
|
|
|
|
let db_dir = tempfile::tempdir().unwrap();
|
|
|
|
|
let db = Database::open(db_dir.path()).unwrap();
|
|
|
|
|
|
|
|
|
|
let state_1 = Swap::Alice(Alice::Done(AliceEndState::BtcPunished));
|
|
|
|
|
let swap_id_1 = Uuid::new_v4();
|
|
|
|
|
db.insert_latest_state(swap_id_1, state_1.clone())
|
|
|
|
|
let alice_state = Alice::Done(AliceEndState::BtcPunished);
|
|
|
|
|
let alice_swap = Swap::Alice(alice_state.clone());
|
|
|
|
|
let alice_swap_id = Uuid::new_v4();
|
|
|
|
|
db.insert_latest_state(alice_swap_id, alice_swap)
|
|
|
|
|
.await
|
|
|
|
|
.expect("Failed to save second state");
|
|
|
|
|
.expect("Failed to save alice state 1");
|
|
|
|
|
|
|
|
|
|
let state_2 = Swap::Bob(Bob::Done(BobEndState::SafelyAborted));
|
|
|
|
|
let swap_id_2 = Uuid::new_v4();
|
|
|
|
|
db.insert_latest_state(swap_id_2, state_2.clone())
|
|
|
|
|
let alice_swaps = db.all_alice().unwrap();
|
|
|
|
|
assert_eq!(alice_swaps.len(), 1);
|
|
|
|
|
assert!(alice_swaps.contains(&(alice_swap_id, alice_state)));
|
|
|
|
|
|
|
|
|
|
let bob_state = Bob::Done(BobEndState::SafelyAborted);
|
|
|
|
|
let bob_swap = Swap::Bob(bob_state);
|
|
|
|
|
let bob_swap_id = Uuid::new_v4();
|
|
|
|
|
db.insert_latest_state(bob_swap_id, bob_swap)
|
|
|
|
|
.await
|
|
|
|
|
.expect("Failed to save first state");
|
|
|
|
|
.expect("Failed to save bob state 1");
|
|
|
|
|
|
|
|
|
|
let err = db.all_alice().unwrap_err();
|
|
|
|
|
|
|
|
|
|
assert_eq!(err.downcast_ref::<NotAlice>().unwrap(), &NotAlice);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
|
async fn all_swaps_as_bob() {
|
|
|
|
|
let db_dir = tempfile::tempdir().unwrap();
|
|
|
|
|
let db = Database::open(db_dir.path()).unwrap();
|
|
|
|
|
|
|
|
|
|
let bob_state = Bob::Done(BobEndState::SafelyAborted);
|
|
|
|
|
let bob_swap = Swap::Bob(bob_state.clone());
|
|
|
|
|
let bob_swap_id = Uuid::new_v4();
|
|
|
|
|
db.insert_latest_state(bob_swap_id, bob_swap)
|
|
|
|
|
.await
|
|
|
|
|
.expect("Failed to save bob state 1");
|
|
|
|
|
|
|
|
|
|
let bob_swaps = db.all_bob().unwrap();
|
|
|
|
|
assert_eq!(bob_swaps.len(), 1);
|
|
|
|
|
assert!(bob_swaps.contains(&(bob_swap_id, bob_state)));
|
|
|
|
|
|
|
|
|
|
let alice_state = Alice::Done(AliceEndState::BtcPunished);
|
|
|
|
|
let alice_swap = Swap::Alice(alice_state);
|
|
|
|
|
let alice_swap_id = Uuid::new_v4();
|
|
|
|
|
db.insert_latest_state(alice_swap_id, alice_swap)
|
|
|
|
|
.await
|
|
|
|
|
.expect("Failed to save alice state 1");
|
|
|
|
|
|
|
|
|
|
let swaps = db.all().unwrap();
|
|
|
|
|
let err = db.all_bob().unwrap_err();
|
|
|
|
|
|
|
|
|
|
assert_eq!(swaps.len(), 2);
|
|
|
|
|
assert!(swaps.contains(&(swap_id_1, state_1)));
|
|
|
|
|
assert!(swaps.contains(&(swap_id_2, state_2)));
|
|
|
|
|
assert_eq!(err.downcast_ref::<NotBob>().unwrap(), &NotBob);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|