2021-09-27 20:15:31 -04:00
|
|
|
use crate::protocol::alice::swap::is_complete as alice_is_complete;
|
|
|
|
use crate::protocol::alice::AliceState;
|
|
|
|
use crate::protocol::bob::swap::is_complete as bob_is_complete;
|
|
|
|
use crate::protocol::bob::BobState;
|
2021-03-24 01:55:00 -04:00
|
|
|
use crate::{bitcoin, monero};
|
2021-09-27 20:15:31 -04:00
|
|
|
use anyhow::Result;
|
|
|
|
use async_trait::async_trait;
|
2021-02-18 20:22:55 -05:00
|
|
|
use conquer_once::Lazy;
|
2021-09-27 20:15:31 -04:00
|
|
|
use libp2p::{Multiaddr, PeerId};
|
2021-03-24 01:55:00 -04:00
|
|
|
use serde::{Deserialize, Serialize};
|
2021-02-18 20:22:55 -05:00
|
|
|
use sha2::Sha256;
|
2021-03-24 01:55:00 -04:00
|
|
|
use sigma_fun::ext::dl_secp256k1_ed25519_eq::{CrossCurveDLEQ, CrossCurveDLEQProof};
|
2021-03-03 19:28:58 -05:00
|
|
|
use sigma_fun::HashTranscript;
|
2021-09-27 20:15:31 -04:00
|
|
|
use std::convert::TryInto;
|
2021-04-08 04:56:26 -04:00
|
|
|
use uuid::Uuid;
|
2021-02-18 20:22:55 -05:00
|
|
|
|
2021-01-04 22:08:36 -05:00
|
|
|
pub mod alice;
|
|
|
|
pub mod bob;
|
2021-01-19 21:29:46 -05:00
|
|
|
|
2021-02-18 20:22:55 -05:00
|
|
|
pub static CROSS_CURVE_PROOF_SYSTEM: Lazy<
|
|
|
|
CrossCurveDLEQ<HashTranscript<Sha256, rand_chacha::ChaCha20Rng>>,
|
|
|
|
> = Lazy::new(|| {
|
|
|
|
CrossCurveDLEQ::<HashTranscript<Sha256, rand_chacha::ChaCha20Rng>>::new(
|
2022-09-13 08:19:58 -04:00
|
|
|
(*ecdsa_fun::fun::G).normalize(),
|
2021-02-18 20:22:55 -05:00
|
|
|
curve25519_dalek::constants::ED25519_BASEPOINT_POINT,
|
|
|
|
)
|
|
|
|
});
|
|
|
|
|
2021-03-24 01:55:00 -04:00
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
|
|
pub struct Message0 {
|
2021-04-08 04:56:26 -04:00
|
|
|
swap_id: Uuid,
|
2021-03-24 01:55:00 -04:00
|
|
|
B: bitcoin::PublicKey,
|
|
|
|
S_b_monero: monero::PublicKey,
|
|
|
|
S_b_bitcoin: bitcoin::PublicKey,
|
|
|
|
dleq_proof_s_b: CrossCurveDLEQProof,
|
|
|
|
v_b: monero::PrivateViewKey,
|
|
|
|
refund_address: bitcoin::Address,
|
2021-04-28 20:40:04 -04:00
|
|
|
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
|
|
|
|
tx_refund_fee: bitcoin::Amount,
|
2021-04-28 20:59:40 -04:00
|
|
|
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
|
|
|
|
tx_cancel_fee: bitcoin::Amount,
|
2021-03-24 01:55:00 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
|
|
pub struct Message1 {
|
|
|
|
A: bitcoin::PublicKey,
|
|
|
|
S_a_monero: monero::PublicKey,
|
|
|
|
S_a_bitcoin: bitcoin::PublicKey,
|
|
|
|
dleq_proof_s_a: CrossCurveDLEQProof,
|
|
|
|
v_a: monero::PrivateViewKey,
|
|
|
|
redeem_address: bitcoin::Address,
|
|
|
|
punish_address: bitcoin::Address,
|
2021-04-28 03:08:00 -04:00
|
|
|
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
|
|
|
|
tx_redeem_fee: bitcoin::Amount,
|
2021-04-28 20:40:04 -04:00
|
|
|
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
|
|
|
|
tx_punish_fee: bitcoin::Amount,
|
2021-03-24 01:55:00 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
|
|
pub struct Message2 {
|
2021-03-24 03:30:55 -04:00
|
|
|
psbt: bitcoin::PartiallySignedTransaction,
|
2021-03-24 01:55:00 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
|
|
pub struct Message3 {
|
|
|
|
tx_cancel_sig: bitcoin::Signature,
|
|
|
|
tx_refund_encsig: bitcoin::EncryptedSignature,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
|
|
pub struct Message4 {
|
|
|
|
tx_punish_sig: bitcoin::Signature,
|
|
|
|
tx_cancel_sig: bitcoin::Signature,
|
|
|
|
}
|
2021-09-27 20:15:31 -04:00
|
|
|
|
|
|
|
#[allow(clippy::large_enum_variant)]
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
|
|
pub enum State {
|
|
|
|
Alice(AliceState),
|
|
|
|
Bob(BobState),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl State {
|
|
|
|
pub fn swap_finished(&self) -> bool {
|
|
|
|
match self {
|
|
|
|
State::Alice(state) => alice_is_complete(state),
|
|
|
|
State::Bob(state) => bob_is_complete(state),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<AliceState> for State {
|
|
|
|
fn from(alice: AliceState) -> Self {
|
|
|
|
Self::Alice(alice)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<BobState> for State {
|
|
|
|
fn from(bob: BobState) -> Self {
|
|
|
|
Self::Bob(bob)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(thiserror::Error, Debug, Clone, Copy, PartialEq)]
|
|
|
|
#[error("Not in the role of Alice")]
|
|
|
|
pub struct NotAlice;
|
|
|
|
|
|
|
|
#[derive(thiserror::Error, Debug, Clone, Copy, PartialEq)]
|
|
|
|
#[error("Not in the role of Bob")]
|
|
|
|
pub struct NotBob;
|
|
|
|
|
|
|
|
impl TryInto<BobState> for State {
|
|
|
|
type Error = NotBob;
|
|
|
|
|
|
|
|
fn try_into(self) -> std::result::Result<BobState, Self::Error> {
|
|
|
|
match self {
|
|
|
|
State::Alice(_) => Err(NotBob),
|
|
|
|
State::Bob(state) => Ok(state),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TryInto<AliceState> for State {
|
|
|
|
type Error = NotAlice;
|
|
|
|
|
|
|
|
fn try_into(self) -> std::result::Result<AliceState, Self::Error> {
|
|
|
|
match self {
|
|
|
|
State::Alice(state) => Ok(state),
|
|
|
|
State::Bob(_) => Err(NotAlice),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[async_trait]
|
|
|
|
pub trait Database {
|
|
|
|
async fn insert_peer_id(&self, swap_id: Uuid, peer_id: PeerId) -> Result<()>;
|
|
|
|
async fn get_peer_id(&self, swap_id: Uuid) -> Result<PeerId>;
|
|
|
|
async fn insert_monero_address(&self, swap_id: Uuid, address: monero::Address) -> Result<()>;
|
|
|
|
async fn get_monero_address(&self, swap_id: Uuid) -> Result<monero::Address>;
|
|
|
|
async fn insert_address(&self, peer_id: PeerId, address: Multiaddr) -> Result<()>;
|
|
|
|
async fn get_addresses(&self, peer_id: PeerId) -> Result<Vec<Multiaddr>>;
|
|
|
|
async fn insert_latest_state(&self, swap_id: Uuid, state: State) -> Result<()>;
|
|
|
|
async fn get_state(&self, swap_id: Uuid) -> Result<State>;
|
|
|
|
async fn all(&self) -> Result<Vec<(Uuid, State)>>;
|
|
|
|
}
|