mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2024-10-01 01:45:40 -04:00
Merge pull request #14 from comit-network/db
Save and recover protocol state from disk
This commit is contained in:
commit
f7bcfa5e14
@ -3,7 +3,7 @@ use crate::{
|
|||||||
bitcoin::{BroadcastSignedTransaction, WatchForRawTransaction},
|
bitcoin::{BroadcastSignedTransaction, WatchForRawTransaction},
|
||||||
bob, monero,
|
bob, monero,
|
||||||
monero::{CreateWalletForOutput, Transfer},
|
monero::{CreateWalletForOutput, Transfer},
|
||||||
serde::{bitcoin_amount, cross_curve_dleq_scalar, ecdsa_fun_signature},
|
serde::bitcoin_amount,
|
||||||
transport::{ReceiveMessage, SendMessage},
|
transport::{ReceiveMessage, SendMessage},
|
||||||
};
|
};
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
@ -82,7 +82,7 @@ pub async fn next_state<
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::large_enum_variant)]
|
#[allow(clippy::large_enum_variant)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
pub enum State {
|
pub enum State {
|
||||||
State0(State0),
|
State0(State0),
|
||||||
State1(State1),
|
State1(State1),
|
||||||
@ -134,7 +134,7 @@ impl State {
|
|||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
pub struct State0 {
|
pub struct State0 {
|
||||||
a: bitcoin::SecretKey,
|
a: bitcoin::SecretKey,
|
||||||
#[serde(with = "cross_curve_dleq_scalar")]
|
//#[serde(with = "cross_curve_dleq_scalar")]
|
||||||
s_a: cross_curve_dleq::Scalar,
|
s_a: cross_curve_dleq::Scalar,
|
||||||
v_a: monero::PrivateViewKey,
|
v_a: monero::PrivateViewKey,
|
||||||
#[serde(with = "bitcoin_amount")]
|
#[serde(with = "bitcoin_amount")]
|
||||||
@ -223,7 +223,6 @@ impl State0 {
|
|||||||
pub struct State1 {
|
pub struct State1 {
|
||||||
a: bitcoin::SecretKey,
|
a: bitcoin::SecretKey,
|
||||||
B: bitcoin::PublicKey,
|
B: bitcoin::PublicKey,
|
||||||
#[serde(with = "cross_curve_dleq_scalar")]
|
|
||||||
s_a: cross_curve_dleq::Scalar,
|
s_a: cross_curve_dleq::Scalar,
|
||||||
S_b_monero: monero::PublicKey,
|
S_b_monero: monero::PublicKey,
|
||||||
S_b_bitcoin: bitcoin::PublicKey,
|
S_b_bitcoin: bitcoin::PublicKey,
|
||||||
@ -263,7 +262,6 @@ impl State1 {
|
|||||||
pub struct State2 {
|
pub struct State2 {
|
||||||
a: bitcoin::SecretKey,
|
a: bitcoin::SecretKey,
|
||||||
B: bitcoin::PublicKey,
|
B: bitcoin::PublicKey,
|
||||||
#[serde(with = "cross_curve_dleq_scalar")]
|
|
||||||
s_a: cross_curve_dleq::Scalar,
|
s_a: cross_curve_dleq::Scalar,
|
||||||
S_b_monero: monero::PublicKey,
|
S_b_monero: monero::PublicKey,
|
||||||
S_b_bitcoin: bitcoin::PublicKey,
|
S_b_bitcoin: bitcoin::PublicKey,
|
||||||
@ -340,13 +338,12 @@ impl State2 {
|
|||||||
pub struct State3 {
|
pub struct State3 {
|
||||||
pub a: bitcoin::SecretKey,
|
pub a: bitcoin::SecretKey,
|
||||||
pub B: bitcoin::PublicKey,
|
pub B: bitcoin::PublicKey,
|
||||||
#[serde(with = "cross_curve_dleq_scalar")]
|
|
||||||
pub s_a: cross_curve_dleq::Scalar,
|
pub s_a: cross_curve_dleq::Scalar,
|
||||||
pub S_b_monero: monero::PublicKey,
|
pub S_b_monero: monero::PublicKey,
|
||||||
pub S_b_bitcoin: bitcoin::PublicKey,
|
pub S_b_bitcoin: bitcoin::PublicKey,
|
||||||
pub v: monero::PrivateViewKey,
|
pub v: monero::PrivateViewKey,
|
||||||
#[serde(with = "bitcoin_amount")]
|
#[serde(with = "bitcoin_amount")]
|
||||||
btc: bitcoin::Amount,
|
pub btc: bitcoin::Amount,
|
||||||
pub xmr: monero::Amount,
|
pub xmr: monero::Amount,
|
||||||
pub refund_timelock: u32,
|
pub refund_timelock: u32,
|
||||||
pub punish_timelock: u32,
|
pub punish_timelock: u32,
|
||||||
@ -354,9 +351,7 @@ pub struct State3 {
|
|||||||
pub redeem_address: bitcoin::Address,
|
pub redeem_address: bitcoin::Address,
|
||||||
pub punish_address: bitcoin::Address,
|
pub punish_address: bitcoin::Address,
|
||||||
pub tx_lock: bitcoin::TxLock,
|
pub tx_lock: bitcoin::TxLock,
|
||||||
#[serde(with = "ecdsa_fun_signature")]
|
|
||||||
pub tx_punish_sig_bob: bitcoin::Signature,
|
pub tx_punish_sig_bob: bitcoin::Signature,
|
||||||
#[serde(with = "ecdsa_fun_signature")]
|
|
||||||
pub tx_cancel_sig_bob: bitcoin::Signature,
|
pub tx_cancel_sig_bob: bitcoin::Signature,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -397,7 +392,6 @@ impl State3 {
|
|||||||
pub struct State4 {
|
pub struct State4 {
|
||||||
a: bitcoin::SecretKey,
|
a: bitcoin::SecretKey,
|
||||||
B: bitcoin::PublicKey,
|
B: bitcoin::PublicKey,
|
||||||
#[serde(with = "cross_curve_dleq_scalar")]
|
|
||||||
s_a: cross_curve_dleq::Scalar,
|
s_a: cross_curve_dleq::Scalar,
|
||||||
S_b_monero: monero::PublicKey,
|
S_b_monero: monero::PublicKey,
|
||||||
S_b_bitcoin: bitcoin::PublicKey,
|
S_b_bitcoin: bitcoin::PublicKey,
|
||||||
@ -411,9 +405,7 @@ pub struct State4 {
|
|||||||
redeem_address: bitcoin::Address,
|
redeem_address: bitcoin::Address,
|
||||||
punish_address: bitcoin::Address,
|
punish_address: bitcoin::Address,
|
||||||
tx_lock: bitcoin::TxLock,
|
tx_lock: bitcoin::TxLock,
|
||||||
#[serde(with = "ecdsa_fun_signature")]
|
|
||||||
tx_punish_sig_bob: bitcoin::Signature,
|
tx_punish_sig_bob: bitcoin::Signature,
|
||||||
#[serde(with = "ecdsa_fun_signature")]
|
|
||||||
tx_cancel_sig_bob: bitcoin::Signature,
|
tx_cancel_sig_bob: bitcoin::Signature,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -504,7 +496,6 @@ impl State4 {
|
|||||||
pub struct State5 {
|
pub struct State5 {
|
||||||
a: bitcoin::SecretKey,
|
a: bitcoin::SecretKey,
|
||||||
B: bitcoin::PublicKey,
|
B: bitcoin::PublicKey,
|
||||||
#[serde(with = "cross_curve_dleq_scalar")]
|
|
||||||
s_a: cross_curve_dleq::Scalar,
|
s_a: cross_curve_dleq::Scalar,
|
||||||
S_b_monero: monero::PublicKey,
|
S_b_monero: monero::PublicKey,
|
||||||
S_b_bitcoin: bitcoin::PublicKey,
|
S_b_bitcoin: bitcoin::PublicKey,
|
||||||
@ -519,9 +510,9 @@ pub struct State5 {
|
|||||||
punish_address: bitcoin::Address,
|
punish_address: bitcoin::Address,
|
||||||
tx_lock: bitcoin::TxLock,
|
tx_lock: bitcoin::TxLock,
|
||||||
tx_lock_proof: monero::TransferProof,
|
tx_lock_proof: monero::TransferProof,
|
||||||
#[serde(with = "ecdsa_fun_signature")]
|
|
||||||
tx_punish_sig_bob: bitcoin::Signature,
|
tx_punish_sig_bob: bitcoin::Signature,
|
||||||
#[serde(with = "ecdsa_fun_signature")]
|
|
||||||
tx_cancel_sig_bob: bitcoin::Signature,
|
tx_cancel_sig_bob: bitcoin::Signature,
|
||||||
lock_xmr_fee: monero::Amount,
|
lock_xmr_fee: monero::Amount,
|
||||||
}
|
}
|
||||||
@ -599,7 +590,6 @@ impl State5 {
|
|||||||
pub struct State6 {
|
pub struct State6 {
|
||||||
a: bitcoin::SecretKey,
|
a: bitcoin::SecretKey,
|
||||||
B: bitcoin::PublicKey,
|
B: bitcoin::PublicKey,
|
||||||
#[serde(with = "cross_curve_dleq_scalar")]
|
|
||||||
s_a: cross_curve_dleq::Scalar,
|
s_a: cross_curve_dleq::Scalar,
|
||||||
S_b_monero: monero::PublicKey,
|
S_b_monero: monero::PublicKey,
|
||||||
S_b_bitcoin: bitcoin::PublicKey,
|
S_b_bitcoin: bitcoin::PublicKey,
|
||||||
@ -613,7 +603,7 @@ pub struct State6 {
|
|||||||
redeem_address: bitcoin::Address,
|
redeem_address: bitcoin::Address,
|
||||||
punish_address: bitcoin::Address,
|
punish_address: bitcoin::Address,
|
||||||
tx_lock: bitcoin::TxLock,
|
tx_lock: bitcoin::TxLock,
|
||||||
#[serde(with = "ecdsa_fun_signature")]
|
|
||||||
tx_punish_sig_bob: bitcoin::Signature,
|
tx_punish_sig_bob: bitcoin::Signature,
|
||||||
tx_redeem_encsig: EncryptedSignature,
|
tx_redeem_encsig: EncryptedSignature,
|
||||||
lock_xmr_fee: monero::Amount,
|
lock_xmr_fee: monero::Amount,
|
||||||
|
@ -6,7 +6,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
monero,
|
monero,
|
||||||
monero::{CreateWalletForOutput, WatchForTransfer},
|
monero::{CreateWalletForOutput, WatchForTransfer},
|
||||||
serde::{bitcoin_amount, cross_curve_dleq_scalar, monero_private_key},
|
serde::{bitcoin_amount, monero_private_key},
|
||||||
transport::{ReceiveMessage, SendMessage},
|
transport::{ReceiveMessage, SendMessage},
|
||||||
};
|
};
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
@ -82,7 +82,7 @@ pub async fn next_state<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
pub enum State {
|
pub enum State {
|
||||||
State0(State0),
|
State0(State0),
|
||||||
State1(State1),
|
State1(State1),
|
||||||
@ -109,7 +109,6 @@ impl_from_child_enum!(State5, State);
|
|||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
pub struct State0 {
|
pub struct State0 {
|
||||||
b: bitcoin::SecretKey,
|
b: bitcoin::SecretKey,
|
||||||
#[serde(with = "cross_curve_dleq_scalar")]
|
|
||||||
s_b: cross_curve_dleq::Scalar,
|
s_b: cross_curve_dleq::Scalar,
|
||||||
v_b: monero::PrivateViewKey,
|
v_b: monero::PrivateViewKey,
|
||||||
#[serde(with = "bitcoin_amount")]
|
#[serde(with = "bitcoin_amount")]
|
||||||
@ -200,7 +199,6 @@ impl State0 {
|
|||||||
pub struct State1 {
|
pub struct State1 {
|
||||||
A: bitcoin::PublicKey,
|
A: bitcoin::PublicKey,
|
||||||
b: bitcoin::SecretKey,
|
b: bitcoin::SecretKey,
|
||||||
#[serde(with = "cross_curve_dleq_scalar")]
|
|
||||||
s_b: cross_curve_dleq::Scalar,
|
s_b: cross_curve_dleq::Scalar,
|
||||||
S_a_monero: monero::PublicKey,
|
S_a_monero: monero::PublicKey,
|
||||||
S_a_bitcoin: bitcoin::PublicKey,
|
S_a_bitcoin: bitcoin::PublicKey,
|
||||||
@ -265,7 +263,6 @@ impl State1 {
|
|||||||
pub struct State2 {
|
pub struct State2 {
|
||||||
pub A: bitcoin::PublicKey,
|
pub A: bitcoin::PublicKey,
|
||||||
pub b: bitcoin::SecretKey,
|
pub b: bitcoin::SecretKey,
|
||||||
#[serde(with = "cross_curve_dleq_scalar")]
|
|
||||||
pub s_b: cross_curve_dleq::Scalar,
|
pub s_b: cross_curve_dleq::Scalar,
|
||||||
pub S_a_monero: monero::PublicKey,
|
pub S_a_monero: monero::PublicKey,
|
||||||
pub S_a_bitcoin: bitcoin::PublicKey,
|
pub S_a_bitcoin: bitcoin::PublicKey,
|
||||||
@ -338,7 +335,6 @@ impl State2 {
|
|||||||
pub struct State3 {
|
pub struct State3 {
|
||||||
A: bitcoin::PublicKey,
|
A: bitcoin::PublicKey,
|
||||||
b: bitcoin::SecretKey,
|
b: bitcoin::SecretKey,
|
||||||
#[serde(with = "cross_curve_dleq_scalar")]
|
|
||||||
s_b: cross_curve_dleq::Scalar,
|
s_b: cross_curve_dleq::Scalar,
|
||||||
S_a_monero: monero::PublicKey,
|
S_a_monero: monero::PublicKey,
|
||||||
S_a_bitcoin: bitcoin::PublicKey,
|
S_a_bitcoin: bitcoin::PublicKey,
|
||||||
@ -451,7 +447,6 @@ impl State3 {
|
|||||||
pub struct State4 {
|
pub struct State4 {
|
||||||
A: bitcoin::PublicKey,
|
A: bitcoin::PublicKey,
|
||||||
b: bitcoin::SecretKey,
|
b: bitcoin::SecretKey,
|
||||||
#[serde(with = "cross_curve_dleq_scalar")]
|
|
||||||
s_b: cross_curve_dleq::Scalar,
|
s_b: cross_curve_dleq::Scalar,
|
||||||
S_a_monero: monero::PublicKey,
|
S_a_monero: monero::PublicKey,
|
||||||
S_a_bitcoin: bitcoin::PublicKey,
|
S_a_bitcoin: bitcoin::PublicKey,
|
||||||
@ -522,7 +517,6 @@ pub struct State5 {
|
|||||||
b: bitcoin::SecretKey,
|
b: bitcoin::SecretKey,
|
||||||
#[serde(with = "monero_private_key")]
|
#[serde(with = "monero_private_key")]
|
||||||
s_a: monero::PrivateKey,
|
s_a: monero::PrivateKey,
|
||||||
#[serde(with = "cross_curve_dleq_scalar")]
|
|
||||||
s_b: cross_curve_dleq::Scalar,
|
s_b: cross_curve_dleq::Scalar,
|
||||||
S_a_monero: monero::PublicKey,
|
S_a_monero: monero::PublicKey,
|
||||||
S_a_bitcoin: bitcoin::PublicKey,
|
S_a_bitcoin: bitcoin::PublicKey,
|
||||||
|
@ -1,93 +1,3 @@
|
|||||||
pub mod ecdsa_fun_signature {
|
|
||||||
use serde::{de, de::Visitor, Deserializer, Serializer};
|
|
||||||
use std::{convert::TryFrom, fmt};
|
|
||||||
|
|
||||||
struct Bytes64Visitor;
|
|
||||||
|
|
||||||
impl<'de> Visitor<'de> for Bytes64Visitor {
|
|
||||||
type Value = ecdsa_fun::Signature;
|
|
||||||
|
|
||||||
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
write!(formatter, "a string containing 64 bytes")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_bytes<E>(self, s: &[u8]) -> Result<Self::Value, E>
|
|
||||||
where
|
|
||||||
E: de::Error,
|
|
||||||
{
|
|
||||||
if let Ok(value) = <[u8; 64]>::try_from(s) {
|
|
||||||
let sig = ecdsa_fun::Signature::from_bytes(value)
|
|
||||||
.expect("bytes represent an integer greater than or equal to the curve order");
|
|
||||||
Ok(sig)
|
|
||||||
} else {
|
|
||||||
Err(de::Error::invalid_length(s.len(), &self))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn serialize<S>(x: &ecdsa_fun::Signature, s: S) -> Result<S::Ok, S::Error>
|
|
||||||
where
|
|
||||||
S: Serializer,
|
|
||||||
{
|
|
||||||
s.serialize_bytes(&x.to_bytes())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deserialize<'de, D>(
|
|
||||||
deserializer: D,
|
|
||||||
) -> Result<ecdsa_fun::Signature, <D as Deserializer<'de>>::Error>
|
|
||||||
where
|
|
||||||
D: Deserializer<'de>,
|
|
||||||
{
|
|
||||||
let sig = deserializer.deserialize_bytes(Bytes64Visitor)?;
|
|
||||||
Ok(sig)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod cross_curve_dleq_scalar {
|
|
||||||
use serde::{de, de::Visitor, Deserializer, Serializer};
|
|
||||||
use std::{convert::TryFrom, fmt};
|
|
||||||
|
|
||||||
struct Bytes32Visitor;
|
|
||||||
|
|
||||||
impl<'de> Visitor<'de> for Bytes32Visitor {
|
|
||||||
type Value = cross_curve_dleq::Scalar;
|
|
||||||
|
|
||||||
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
write!(formatter, "a string containing 32 bytes")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_bytes<E>(self, s: &[u8]) -> Result<Self::Value, E>
|
|
||||||
where
|
|
||||||
E: de::Error,
|
|
||||||
{
|
|
||||||
if let Ok(value) = <[u8; 32]>::try_from(s) {
|
|
||||||
Ok(cross_curve_dleq::Scalar::from(value))
|
|
||||||
} else {
|
|
||||||
Err(de::Error::invalid_length(s.len(), &self))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn serialize<S>(x: &cross_curve_dleq::Scalar, s: S) -> Result<S::Ok, S::Error>
|
|
||||||
where
|
|
||||||
S: Serializer,
|
|
||||||
{
|
|
||||||
// Serialise as ed25519 because the inner bytes are private
|
|
||||||
// TODO: Open PR in cross_curve_dleq to allow accessing the inner bytes
|
|
||||||
s.serialize_bytes(&x.into_ed25519().to_bytes())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deserialize<'de, D>(
|
|
||||||
deserializer: D,
|
|
||||||
) -> Result<cross_curve_dleq::Scalar, <D as Deserializer<'de>>::Error>
|
|
||||||
where
|
|
||||||
D: Deserializer<'de>,
|
|
||||||
{
|
|
||||||
let dleq = deserializer.deserialize_bytes(Bytes32Visitor)?;
|
|
||||||
Ok(dleq)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod monero_private_key {
|
pub mod monero_private_key {
|
||||||
use serde::{de, de::Visitor, Deserializer, Serializer};
|
use serde::{de, de::Visitor, Deserializer, Serializer};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
@ -178,42 +88,16 @@ pub mod monero_amount {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use ::bitcoin::SigHash;
|
|
||||||
use curve25519_dalek::scalar::Scalar;
|
use curve25519_dalek::scalar::Scalar;
|
||||||
use rand::rngs::OsRng;
|
use rand::rngs::OsRng;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, PartialEq)]
|
|
||||||
pub struct CrossCurveDleqScalar(
|
|
||||||
#[serde(with = "cross_curve_dleq_scalar")] cross_curve_dleq::Scalar,
|
|
||||||
);
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, PartialEq)]
|
|
||||||
pub struct ECDSAFunSignature(#[serde(with = "ecdsa_fun_signature")] ecdsa_fun::Signature);
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, PartialEq)]
|
#[derive(Debug, Serialize, Deserialize, PartialEq)]
|
||||||
pub struct MoneroPrivateKey(#[serde(with = "monero_private_key")] crate::monero::PrivateKey);
|
pub struct MoneroPrivateKey(#[serde(with = "monero_private_key")] crate::monero::PrivateKey);
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, PartialEq)]
|
#[derive(Debug, Serialize, Deserialize, PartialEq)]
|
||||||
pub struct BitcoinAmount(#[serde(with = "bitcoin_amount")] ::bitcoin::Amount);
|
pub struct BitcoinAmount(#[serde(with = "bitcoin_amount")] ::bitcoin::Amount);
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn serde_cross_curv_dleq_scalar() {
|
|
||||||
let scalar = CrossCurveDleqScalar(cross_curve_dleq::Scalar::random(&mut OsRng));
|
|
||||||
let encoded = serde_cbor::to_vec(&scalar).unwrap();
|
|
||||||
let decoded: CrossCurveDleqScalar = serde_cbor::from_slice(&encoded).unwrap();
|
|
||||||
assert_eq!(scalar, decoded);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn serde_ecdsa_fun_sig() {
|
|
||||||
let secret_key = crate::bitcoin::SecretKey::new_random(&mut OsRng);
|
|
||||||
let sig = ECDSAFunSignature(secret_key.sign(SigHash::default()));
|
|
||||||
let encoded = serde_cbor::to_vec(&sig).unwrap();
|
|
||||||
let decoded: ECDSAFunSignature = serde_cbor::from_slice(&encoded).unwrap();
|
|
||||||
assert_eq!(sig, decoded);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn serde_monero_private_key() {
|
fn serde_monero_private_key() {
|
||||||
let key = MoneroPrivateKey(monero::PrivateKey::from_scalar(Scalar::random(&mut OsRng)));
|
let key = MoneroPrivateKey(monero::PrivateKey::from_scalar(Scalar::random(&mut OsRng)));
|
||||||
|
@ -11,14 +11,14 @@ mod tests {
|
|||||||
harness::{
|
harness::{
|
||||||
init_bitcoind, init_test,
|
init_bitcoind, init_test,
|
||||||
node::{run_alice_until, run_bob_until},
|
node::{run_alice_until, run_bob_until},
|
||||||
ALICE_TEST_DB_FOLDER, BOB_TEST_DB_FOLDER,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use futures::future;
|
use futures::future;
|
||||||
use monero_harness::Monero;
|
use monero_harness::Monero;
|
||||||
use rand::rngs::OsRng;
|
use rand::rngs::OsRng;
|
||||||
|
|
||||||
use std::{convert::TryInto, path::Path};
|
use crate::harness::storage::Database;
|
||||||
|
use std::convert::TryInto;
|
||||||
use testcontainers::clients::Cli;
|
use testcontainers::clients::Cli;
|
||||||
use tracing_subscriber::util::SubscriberInitExt;
|
use tracing_subscriber::util::SubscriberInitExt;
|
||||||
use xmr_btc::{
|
use xmr_btc::{
|
||||||
@ -251,8 +251,13 @@ mod tests {
|
|||||||
let cli = Cli::default();
|
let cli = Cli::default();
|
||||||
let (monero, _container) = Monero::new(&cli);
|
let (monero, _container) = Monero::new(&cli);
|
||||||
let bitcoind = init_bitcoind(&cli).await;
|
let bitcoind = init_bitcoind(&cli).await;
|
||||||
let alice_db = harness::storage::Database::open(Path::new(ALICE_TEST_DB_FOLDER)).unwrap();
|
|
||||||
let bob_db = harness::storage::Database::open(Path::new(BOB_TEST_DB_FOLDER)).unwrap();
|
let alice_db_dir = tempfile::tempdir().unwrap();
|
||||||
|
let alice_db: Database<alice::State> =
|
||||||
|
harness::storage::Database::open(alice_db_dir.path()).unwrap();
|
||||||
|
let bob_db_dir = tempfile::tempdir().unwrap();
|
||||||
|
let bob_db: Database<bob::State> =
|
||||||
|
harness::storage::Database::open(bob_db_dir.path()).unwrap();
|
||||||
|
|
||||||
let (
|
let (
|
||||||
alice_state0,
|
alice_state0,
|
||||||
@ -281,29 +286,26 @@ mod tests {
|
|||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let alice_state5: alice::State5 = alice_state.try_into().unwrap();
|
|
||||||
let bob_state3: bob::State3 = bob_state.try_into().unwrap();
|
|
||||||
|
|
||||||
// save state to db
|
// save state to db
|
||||||
alice_db.insert_latest_state(&alice_state5).await.unwrap();
|
alice_db.insert_latest_state(&alice_state).await.unwrap();
|
||||||
bob_db.insert_latest_state(&bob_state3).await.unwrap();
|
bob_db.insert_latest_state(&bob_state).await.unwrap();
|
||||||
};
|
};
|
||||||
|
|
||||||
let (alice_state6, bob_state5) = {
|
let (alice_state6, bob_state5) = {
|
||||||
// recover state from db
|
// recover state from db
|
||||||
let alice_state5: alice::State5 = alice_db.get_latest_state().unwrap();
|
let alice_state = alice_db.get_latest_state().unwrap();
|
||||||
let bob_state3: bob::State3 = bob_db.get_latest_state().unwrap();
|
let bob_state = bob_db.get_latest_state().unwrap();
|
||||||
|
|
||||||
let (alice_state, bob_state) = future::try_join(
|
let (alice_state, bob_state) = future::try_join(
|
||||||
run_alice_until(
|
run_alice_until(
|
||||||
&mut alice_node,
|
&mut alice_node,
|
||||||
alice_state5.into(),
|
alice_state,
|
||||||
harness::alice::is_state6,
|
harness::alice::is_state6,
|
||||||
&mut OsRng,
|
&mut OsRng,
|
||||||
),
|
),
|
||||||
run_bob_until(
|
run_bob_until(
|
||||||
&mut bob_node,
|
&mut bob_node,
|
||||||
bob_state3.into(),
|
bob_state,
|
||||||
harness::bob::is_state5,
|
harness::bob::is_state5,
|
||||||
&mut OsRng,
|
&mut OsRng,
|
||||||
),
|
),
|
||||||
|
@ -2,26 +2,32 @@ use anyhow::{anyhow, Context, Result};
|
|||||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
pub struct Database {
|
pub struct Database<T>
|
||||||
|
where
|
||||||
|
T: Serialize + DeserializeOwned,
|
||||||
|
{
|
||||||
db: sled::Db,
|
db: sled::Db,
|
||||||
|
_marker: std::marker::PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Database {
|
impl<T> Database<T>
|
||||||
|
where
|
||||||
|
T: Serialize + DeserializeOwned,
|
||||||
|
{
|
||||||
|
// TODO: serialize using lazy/one-time initlisation
|
||||||
const LAST_STATE_KEY: &'static str = "latest_state";
|
const LAST_STATE_KEY: &'static str = "latest_state";
|
||||||
|
|
||||||
pub fn open(path: &Path) -> Result<Self> {
|
pub fn open(path: &Path) -> Result<Self> {
|
||||||
let path = path
|
let db =
|
||||||
.to_str()
|
sled::open(path).with_context(|| format!("Could not open the DB at {:?}", path))?;
|
||||||
.ok_or_else(|| anyhow!("The path is not utf-8 valid: {:?}", path))?;
|
|
||||||
let db = sled::open(path).with_context(|| format!("Could not open the DB at {}", path))?;
|
|
||||||
|
|
||||||
Ok(Database { db })
|
Ok(Database {
|
||||||
|
db,
|
||||||
|
_marker: Default::default(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn insert_latest_state<T>(&self, state: &T) -> Result<()>
|
pub async fn insert_latest_state(&self, state: &T) -> Result<()> {
|
||||||
where
|
|
||||||
T: Serialize + DeserializeOwned,
|
|
||||||
{
|
|
||||||
let key = serialize(&Self::LAST_STATE_KEY)?;
|
let key = serialize(&Self::LAST_STATE_KEY)?;
|
||||||
let new_value = serialize(&state).context("Could not serialize new state value")?;
|
let new_value = serialize(&state).context("Could not serialize new state value")?;
|
||||||
|
|
||||||
@ -30,8 +36,9 @@ impl Database {
|
|||||||
self.db
|
self.db
|
||||||
.compare_and_swap(key, old_value, Some(new_value))
|
.compare_and_swap(key, old_value, Some(new_value))
|
||||||
.context("Could not write in the DB")?
|
.context("Could not write in the DB")?
|
||||||
.context("Stored swap somehow changed, aborting saving")?; // let _ =
|
.context("Stored swap somehow changed, aborting saving")?;
|
||||||
|
|
||||||
|
// TODO: see if this can be done through sled config
|
||||||
self.db
|
self.db
|
||||||
.flush_async()
|
.flush_async()
|
||||||
.await
|
.await
|
||||||
@ -39,10 +46,7 @@ impl Database {
|
|||||||
.context("Could not flush db")
|
.context("Could not flush db")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_latest_state<T>(&self) -> anyhow::Result<T>
|
pub fn get_latest_state(&self) -> anyhow::Result<T> {
|
||||||
where
|
|
||||||
T: DeserializeOwned,
|
|
||||||
{
|
|
||||||
let key = serialize(&Self::LAST_STATE_KEY)?;
|
let key = serialize(&Self::LAST_STATE_KEY)?;
|
||||||
|
|
||||||
let encoded = self
|
let encoded = self
|
||||||
@ -77,15 +81,12 @@ mod tests {
|
|||||||
use curve25519_dalek::scalar::Scalar;
|
use curve25519_dalek::scalar::Scalar;
|
||||||
use ecdsa_fun::fun::rand_core::OsRng;
|
use ecdsa_fun::fun::rand_core::OsRng;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use xmr_btc::serde::{
|
use xmr_btc::serde::{bitcoin_amount, monero_private_key};
|
||||||
bitcoin_amount, cross_curve_dleq_scalar, ecdsa_fun_signature, monero_private_key,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, PartialEq)]
|
#[derive(Debug, Serialize, Deserialize, PartialEq)]
|
||||||
pub struct TestState {
|
pub struct TestState {
|
||||||
A: xmr_btc::bitcoin::PublicKey,
|
A: xmr_btc::bitcoin::PublicKey,
|
||||||
a: xmr_btc::bitcoin::SecretKey,
|
a: xmr_btc::bitcoin::SecretKey,
|
||||||
#[serde(with = "cross_curve_dleq_scalar")]
|
|
||||||
s_a: ::cross_curve_dleq::Scalar,
|
s_a: ::cross_curve_dleq::Scalar,
|
||||||
#[serde(with = "monero_private_key")]
|
#[serde(with = "monero_private_key")]
|
||||||
s_b: monero::PrivateKey,
|
s_b: monero::PrivateKey,
|
||||||
@ -98,13 +99,13 @@ mod tests {
|
|||||||
refund_timelock: u32,
|
refund_timelock: u32,
|
||||||
refund_address: ::bitcoin::Address,
|
refund_address: ::bitcoin::Address,
|
||||||
transaction: ::bitcoin::Transaction,
|
transaction: ::bitcoin::Transaction,
|
||||||
#[serde(with = "ecdsa_fun_signature")]
|
|
||||||
tx_punish_sig: xmr_btc::bitcoin::Signature,
|
tx_punish_sig: xmr_btc::bitcoin::Signature,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn recover_state_from_db() {
|
async fn recover_state_from_db() {
|
||||||
let db = Database::open(Path::new("../target/test_recover.db")).unwrap();
|
let db_dir = tempfile::tempdir().unwrap();
|
||||||
|
let db = Database::open(db_dir.path()).unwrap();
|
||||||
|
|
||||||
let a = xmr_btc::bitcoin::SecretKey::new_random(&mut OsRng);
|
let a = xmr_btc::bitcoin::SecretKey::new_random(&mut OsRng);
|
||||||
let s_a = cross_curve_dleq::Scalar::random(&mut OsRng);
|
let s_a = cross_curve_dleq::Scalar::random(&mut OsRng);
|
||||||
|
Loading…
Reference in New Issue
Block a user