mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2025-01-11 07:29:39 -05:00
WIP
This commit is contained in:
parent
815a752c88
commit
8272e1c247
33
Cargo.lock
generated
33
Cargo.lock
generated
@ -3719,12 +3719,12 @@ checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2"
|
|||||||
name = "swap"
|
name = "swap"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-compression",
|
"async-compression",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"atty",
|
"atty",
|
||||||
"backoff",
|
"backoff",
|
||||||
"base64 0.13.0",
|
"base64 0.13.0",
|
||||||
"bdk",
|
"bdk",
|
||||||
"bdk-testutils",
|
"bdk-testutils",
|
||||||
"big-bytes",
|
"big-bytes",
|
||||||
@ -3739,6 +3739,7 @@ dependencies = [
|
|||||||
"ecdsa_fun",
|
"ecdsa_fun",
|
||||||
"futures",
|
"futures",
|
||||||
"get-port",
|
"get-port",
|
||||||
|
"hash_edwards_to_edwards",
|
||||||
"hyper 0.14.5",
|
"hyper 0.14.5",
|
||||||
"itertools 0.10.0",
|
"itertools 0.10.0",
|
||||||
"libp2p",
|
"libp2p",
|
||||||
@ -3766,16 +3767,16 @@ dependencies = [
|
|||||||
"strum",
|
"strum",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"testcontainers 0.12.0",
|
"testcontainers 0.12.0",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"time 0.2.26",
|
"time 0.2.26",
|
||||||
"tokio 1.4.0",
|
"tokio 1.4.0",
|
||||||
"tokio-tar",
|
"tokio-tar",
|
||||||
"tokio-tungstenite",
|
"tokio-tungstenite",
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
"toml",
|
"toml",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-appender",
|
"tracing-appender",
|
||||||
"tracing-futures",
|
"tracing-futures",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
"url 2.2.1",
|
"url 2.2.1",
|
||||||
"uuid",
|
"uuid",
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
[toolchain]
|
[toolchain]
|
||||||
channel = "nightly-2021-04-15"
|
channel = "nightly-2021-05-17"
|
||||||
components = ["rustfmt", "clippy"]
|
components = ["rustfmt", "clippy"]
|
||||||
targets = ["armv7-unknown-linux-gnueabihf"]
|
targets = ["armv7-unknown-linux-gnueabihf"]
|
||||||
|
@ -26,6 +26,7 @@ dialoguer = "0.8"
|
|||||||
directories-next = "2"
|
directories-next = "2"
|
||||||
ecdsa_fun = { git = "https://github.com/LLFourn/secp256kfun", features = ["libsecp_compat", "serde"] }
|
ecdsa_fun = { git = "https://github.com/LLFourn/secp256kfun", features = ["libsecp_compat", "serde"] }
|
||||||
futures = { version = "0.3", default-features = false }
|
futures = { version = "0.3", default-features = false }
|
||||||
|
hash_edwards_to_edwards = { git = "https://github.com/comit-network/hash_edwards_to_edwards" }
|
||||||
itertools = "0.10"
|
itertools = "0.10"
|
||||||
libp2p = { version = "0.36", default-features = false, features = ["tcp-tokio", "yamux", "mplex", "dns-tokio", "noise", "request-response"] }
|
libp2p = { version = "0.36", default-features = false, features = ["tcp-tokio", "yamux", "mplex", "dns-tokio", "noise", "request-response"] }
|
||||||
libp2p-async-await = { git = "https://github.com/comit-network/rust-libp2p-async-await" }
|
libp2p-async-await = { git = "https://github.com/comit-network/rust-libp2p-async-await" }
|
||||||
|
@ -49,7 +49,7 @@ pub const TX_FEE: u64 = 15_000;
|
|||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
|
||||||
pub struct SecretKey {
|
pub struct SecretKey {
|
||||||
inner: Scalar,
|
inner: Scalar,
|
||||||
public: Point,
|
pub(crate) public: Point,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SecretKey {
|
impl SecretKey {
|
||||||
@ -104,7 +104,7 @@ impl SecretKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq)]
|
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq)]
|
||||||
pub struct PublicKey(Point);
|
pub struct PublicKey(pub(crate) Point);
|
||||||
|
|
||||||
impl PublicKey {
|
impl PublicKey {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -30,7 +30,7 @@ pub fn private_key_from_secp256k1_scalar(scalar: bitcoin::Scalar) -> PrivateKey
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq)]
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq)]
|
||||||
pub struct PrivateViewKey(#[serde(with = "monero_private_key")] PrivateKey);
|
pub struct PrivateViewKey(#[serde(with = "monero_private_key")] pub PrivateKey);
|
||||||
|
|
||||||
impl PrivateViewKey {
|
impl PrivateViewKey {
|
||||||
pub fn new_random<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
|
pub fn new_random<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
|
||||||
|
@ -1,14 +1,116 @@
|
|||||||
use crate::bitcoin::Txid;
|
use crate::bitcoin::Txid;
|
||||||
|
use crate::protocol::CROSS_CURVE_PROOF_SYSTEM;
|
||||||
|
use curve25519_dalek::constants::ED25519_BASEPOINT_POINT;
|
||||||
|
use curve25519_dalek::edwards::EdwardsPoint;
|
||||||
|
use curve25519_dalek::scalar::Scalar;
|
||||||
|
use ecdsa_fun::fun::Point;
|
||||||
|
use hash_edwards_to_edwards::hash_point_to_point;
|
||||||
use monero_adaptor::AdaptorSignature;
|
use monero_adaptor::AdaptorSignature;
|
||||||
|
use rand::rngs::OsRng;
|
||||||
|
|
||||||
pub mod alice;
|
pub mod alice;
|
||||||
pub mod bob;
|
pub mod bob;
|
||||||
mod state_machine;
|
mod state_machine;
|
||||||
mod transactions;
|
pub mod transactions;
|
||||||
|
|
||||||
pub struct SeenBtcLock {
|
pub struct Alice {
|
||||||
s_0_b: crate::monero::Scalar,
|
pub a: crate::bitcoin::SecretKey,
|
||||||
pub adaptor_sig: AdaptorSignature,
|
pub s_a: crate::monero::Scalar,
|
||||||
tx_lock_id: Txid,
|
r_a: Scalar,
|
||||||
tx_lock: bitcoin::Transaction,
|
// private view keys
|
||||||
|
pub v_a: crate::monero::PrivateViewKey,
|
||||||
|
pub v_b: crate::monero::PrivateViewKey,
|
||||||
|
pub S_a: EdwardsPoint,
|
||||||
|
pub S_b: crate::monero::PublicKey,
|
||||||
|
pub R_a: EdwardsPoint,
|
||||||
|
pub S_prime_a: Point,
|
||||||
|
pub R_prime_a: EdwardsPoint,
|
||||||
|
pub pk_a: crate::bitcoin::PublicKey,
|
||||||
|
pub pk_b: crate::bitcoin::PublicKey,
|
||||||
|
pub K_a: crate::monero::PublicViewKey,
|
||||||
|
pub K_b: crate::monero::PublicViewKey,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Bob {
|
||||||
|
b: crate::bitcoin::SecretKey,
|
||||||
|
pub s_b: crate::monero::Scalar,
|
||||||
|
// private view keys
|
||||||
|
pub v_a: crate::monero::PrivateViewKey,
|
||||||
|
pub v_b: crate::monero::PrivateViewKey,
|
||||||
|
pub S_a: EdwardsPoint,
|
||||||
|
pub S_b: crate::monero::PublicKey,
|
||||||
|
pub R_a: EdwardsPoint,
|
||||||
|
pub S_prime_a: Point,
|
||||||
|
pub R_prime_a: EdwardsPoint,
|
||||||
|
pub pk_a: crate::bitcoin::PublicKey,
|
||||||
|
pub pk_b: crate::bitcoin::PublicKey,
|
||||||
|
pub K_a: crate::monero::PublicViewKey,
|
||||||
|
pub K_b: crate::monero::PublicViewKey,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setup() -> (Alice, Bob) {
|
||||||
|
let v_a = crate::monero::PrivateViewKey::new_random(&mut OsRng);
|
||||||
|
let v_b = crate::monero::PrivateViewKey::new_random(&mut OsRng);
|
||||||
|
|
||||||
|
let a = crate::bitcoin::SecretKey::new_random(&mut OsRng);
|
||||||
|
let b = crate::bitcoin::SecretKey::new_random(&mut OsRng);
|
||||||
|
|
||||||
|
let s_a = crate::monero::Scalar::random(&mut OsRng);
|
||||||
|
|
||||||
|
let s_b = crate::monero::Scalar::random(&mut OsRng);
|
||||||
|
let S_b = monero::PublicKey::from_private_key(&monero::PrivateKey { scalar: s_b });
|
||||||
|
|
||||||
|
let (_dleq_proof_s_a, (S_prime_a, S_a)) = CROSS_CURVE_PROOF_SYSTEM.prove(&s_a, &mut OsRng);
|
||||||
|
|
||||||
|
let (r_a, R_a, R_prime_a) = {
|
||||||
|
let r_a = Scalar::random(&mut OsRng);
|
||||||
|
let R_a = r_a * ED25519_BASEPOINT_POINT;
|
||||||
|
|
||||||
|
let pk_hashed_to_point = hash_point_to_point(S_a);
|
||||||
|
|
||||||
|
let R_prime_a = r_a * pk_hashed_to_point;
|
||||||
|
|
||||||
|
(r_a, R_a, R_prime_a)
|
||||||
|
};
|
||||||
|
|
||||||
|
let K_a = v_a.public();
|
||||||
|
let K_b = v_b.public();
|
||||||
|
|
||||||
|
let pk_a = a.public();
|
||||||
|
let pk_b = b.public();
|
||||||
|
|
||||||
|
let alice = Alice {
|
||||||
|
a,
|
||||||
|
v_a,
|
||||||
|
v_b,
|
||||||
|
s_a,
|
||||||
|
S_a,
|
||||||
|
S_b,
|
||||||
|
r_a,
|
||||||
|
R_a,
|
||||||
|
S_prime_a,
|
||||||
|
R_prime_a,
|
||||||
|
pk_a,
|
||||||
|
pk_b,
|
||||||
|
K_a,
|
||||||
|
K_b,
|
||||||
|
};
|
||||||
|
|
||||||
|
let bob = Bob {
|
||||||
|
b,
|
||||||
|
v_a,
|
||||||
|
v_b,
|
||||||
|
s_b,
|
||||||
|
S_a,
|
||||||
|
S_b,
|
||||||
|
R_a,
|
||||||
|
S_prime_a,
|
||||||
|
R_prime_a,
|
||||||
|
pk_a,
|
||||||
|
pk_b,
|
||||||
|
K_a,
|
||||||
|
K_b,
|
||||||
|
};
|
||||||
|
|
||||||
|
(alice, bob)
|
||||||
}
|
}
|
||||||
|
@ -1,53 +1,68 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use monero::PublicKey;
|
|
||||||
use rand::rngs::OsRng;
|
use rand::rngs::OsRng;
|
||||||
|
|
||||||
use monero_adaptor::alice::Alice2;
|
use crate::bitcoin::EncryptedSignature;
|
||||||
use monero_adaptor::AdaptorSignature;
|
use crate::monero::{Scalar, TransferProof, TransferRequest};
|
||||||
|
use crate::monero_ext::ScalarExt;
|
||||||
use crate::bitcoin::TxLock;
|
use crate::xmr_first_protocol::transactions::btc_lock::BtcLock;
|
||||||
use crate::monero::{Scalar, TransferRequest};
|
use crate::xmr_first_protocol::transactions::btc_redeem::BtcRedeem;
|
||||||
use curve25519_dalek::edwards::EdwardsPoint;
|
use crate::xmr_first_protocol::transactions::xmr_refund::XmrRefund;
|
||||||
|
|
||||||
// start
|
// start
|
||||||
pub struct Alice3 {
|
pub struct Alice3 {
|
||||||
pub xmr_swap_amount: crate::monero::Amount,
|
pub xmr_swap_amount: crate::monero::Amount,
|
||||||
pub btc_swap_amount: crate::bitcoin::Amount,
|
pub btc_swap_amount: crate::bitcoin::Amount,
|
||||||
// pub adaptor_sig: AdaptorSignature,
|
// pub adaptor_sig: AdaptorSignature,
|
||||||
|
// adaptor
|
||||||
|
// pub r_a: Scalar,
|
||||||
pub a: crate::bitcoin::SecretKey,
|
pub a: crate::bitcoin::SecretKey,
|
||||||
pub B: crate::bitcoin::PublicKey,
|
pub B: crate::bitcoin::PublicKey,
|
||||||
pub s_a: Scalar,
|
pub s_a: Scalar,
|
||||||
pub S_b_monero: EdwardsPoint,
|
pub S_b_monero: crate::monero::PublicKey,
|
||||||
pub v_a: crate::monero::PrivateViewKey,
|
pub v_a: crate::monero::PrivateViewKey,
|
||||||
|
pub redeem_address: bitcoin::Address,
|
||||||
}
|
}
|
||||||
|
|
||||||
// published xmr_lock, watching for btc_lock
|
// published xmr_lock, watching for btc_lock
|
||||||
pub struct Alice4 {
|
pub struct Alice4 {
|
||||||
a: crate::bitcoin::SecretKey,
|
pub a: crate::bitcoin::SecretKey,
|
||||||
B: crate::bitcoin::PublicKey,
|
pub B: crate::bitcoin::PublicKey,
|
||||||
|
// pub r_a: Scalar,
|
||||||
|
pub s_a: Scalar,
|
||||||
btc_swap_amount: crate::bitcoin::Amount,
|
btc_swap_amount: crate::bitcoin::Amount,
|
||||||
|
pub transfer_proof: TransferProof,
|
||||||
|
pub redeem_address: bitcoin::Address,
|
||||||
// pub adaptor_sig: AdaptorSignature,
|
// pub adaptor_sig: AdaptorSignature,
|
||||||
}
|
}
|
||||||
|
|
||||||
// published seen btc_lock, published btc_redeem
|
// published seen btc_lock, published btc_redeem
|
||||||
pub struct Alice5;
|
pub struct Alice5 {
|
||||||
|
pub a: crate::bitcoin::SecretKey,
|
||||||
|
pub B: crate::bitcoin::PublicKey,
|
||||||
|
// pub r_a: Scalar,
|
||||||
|
pub s_a: Scalar,
|
||||||
|
pub redeem_address: bitcoin::Address,
|
||||||
|
btc_swap_amount: crate::bitcoin::Amount,
|
||||||
|
}
|
||||||
|
|
||||||
impl Alice3 {
|
impl Alice3 {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
S_b_monero: EdwardsPoint,
|
S_b_monero: crate::monero::PublicKey,
|
||||||
B: crate::bitcoin::PublicKey,
|
B: crate::bitcoin::PublicKey,
|
||||||
xmr_swap_amount: crate::monero::Amount,
|
xmr_swap_amount: crate::monero::Amount,
|
||||||
btc_swap_amount: crate::bitcoin::Amount,
|
btc_swap_amount: crate::bitcoin::Amount,
|
||||||
|
redeem_address: bitcoin::Address,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
xmr_swap_amount,
|
xmr_swap_amount,
|
||||||
btc_swap_amount,
|
btc_swap_amount,
|
||||||
// adaptor_sig: alice2.adaptor_sig,
|
// r_a: Default::default(),
|
||||||
a: crate::bitcoin::SecretKey::new_random(&mut OsRng),
|
a: crate::bitcoin::SecretKey::new_random(&mut OsRng),
|
||||||
B,
|
B,
|
||||||
s_a: Scalar::random(&mut OsRng),
|
s_a: Scalar::random(&mut OsRng),
|
||||||
S_b_monero,
|
S_b_monero,
|
||||||
v_a: crate::monero::PrivateViewKey::new_random(&mut OsRng),
|
v_a: crate::monero::PrivateViewKey::new_random(&mut OsRng),
|
||||||
|
redeem_address,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub async fn publish_xmr_lock(&self, wallet: &crate::monero::Wallet) -> Result<Alice4> {
|
pub async fn publish_xmr_lock(&self, wallet: &crate::monero::Wallet) -> Result<Alice4> {
|
||||||
@ -63,21 +78,61 @@ impl Alice3 {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// we may have to send this to Bob
|
// we may have to send this to Bob
|
||||||
let _ = wallet.transfer(req).await?;
|
let transfer_proof = wallet.transfer(req).await?;
|
||||||
|
|
||||||
Ok(Alice4 {
|
Ok(Alice4 {
|
||||||
a: self.a.clone(),
|
a: self.a.clone(),
|
||||||
B: self.B,
|
B: self.B,
|
||||||
btc_swap_amount: Default::default(),
|
// r_a: Default::default(),
|
||||||
|
s_a: self.s_a,
|
||||||
|
btc_swap_amount: self.btc_swap_amount,
|
||||||
|
transfer_proof,
|
||||||
// adaptor_sig: self.adaptor_sig.clone(),
|
// adaptor_sig: self.adaptor_sig.clone(),
|
||||||
|
redeem_address: self.redeem_address.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pub async fn publish_xmr_refund(&self, refund_xmr: XmrRefund) -> Result<()> {
|
||||||
|
// let sig = refund_xmr.adaptor.adapt(self.r_a);
|
||||||
|
// todo!("sig");
|
||||||
|
// Ok(())
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Alice4 {
|
impl Alice4 {
|
||||||
pub async fn watch_for_btc_lock(&self, wallet: &crate::bitcoin::Wallet) -> Result<Alice5> {
|
pub async fn watch_for_btc_lock(&self, wallet: &crate::bitcoin::Wallet) -> Result<Alice5> {
|
||||||
let btc_lock = TxLock::new(wallet, self.btc_swap_amount, self.a.public(), self.B).await?;
|
let btc_lock = BtcLock::new(wallet, self.btc_swap_amount, self.a.public(), self.B).await?;
|
||||||
wallet.subscribe_to(btc_lock);
|
let btc_lock_watcher = wallet.subscribe_to(btc_lock).await;
|
||||||
Ok(Alice5)
|
|
||||||
|
btc_lock_watcher.wait_until_confirmed_with(1).await?;
|
||||||
|
|
||||||
|
Ok(Alice5 {
|
||||||
|
a: self.a.clone(),
|
||||||
|
B: self.B,
|
||||||
|
// r_a: Default::default(),
|
||||||
|
s_a: self.s_a,
|
||||||
|
redeem_address: self.redeem_address.clone(),
|
||||||
|
btc_swap_amount: self.btc_swap_amount,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Alice5 {
|
||||||
|
pub async fn publish_btc_redeem(
|
||||||
|
&self,
|
||||||
|
wallet: &crate::bitcoin::Wallet,
|
||||||
|
encsig: EncryptedSignature,
|
||||||
|
) -> Result<()> {
|
||||||
|
let tx_lock = BtcLock::new(wallet, self.btc_swap_amount, self.a.public(), self.B).await?;
|
||||||
|
let tx_redeem = BtcRedeem::new(&tx_lock, &self.redeem_address);
|
||||||
|
|
||||||
|
let signed_tx_redeem =
|
||||||
|
tx_redeem.complete(self.a.clone(), self.s_a.to_secpfun_scalar(), self.B, encsig)?;
|
||||||
|
|
||||||
|
let (txid, sub) = wallet.broadcast(signed_tx_redeem, "lock").await?;
|
||||||
|
|
||||||
|
let _ = sub.wait_until_confirmed_with(1).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,35 +1,147 @@
|
|||||||
|
use crate::monero::wallet::{TransferRequest, WatchRequest};
|
||||||
|
use crate::monero::TransferProof;
|
||||||
|
use crate::xmr_first_protocol::transactions::btc_lock::BtcLock;
|
||||||
|
use crate::xmr_first_protocol::transactions::btc_redeem::BtcRedeem;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use monero::PublicKey;
|
use monero_rpc::wallet::BlockHeight;
|
||||||
use rand::rngs::OsRng;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use monero_adaptor::alice::Alice2;
|
|
||||||
use monero_adaptor::AdaptorSignature;
|
|
||||||
|
|
||||||
use crate::bitcoin::Txid;
|
|
||||||
use crate::monero::wallet::WatchRequest;
|
|
||||||
use crate::monero::{Scalar, TransferRequest};
|
|
||||||
use crate::xmr_first_protocol::transactions::xmr_lock::XmrLock;
|
|
||||||
|
|
||||||
// watching for xmr_lock
|
// watching for xmr_lock
|
||||||
pub struct Bob3 {
|
pub struct Bob3 {
|
||||||
|
pub b: crate::bitcoin::SecretKey,
|
||||||
|
pub A: crate::bitcoin::PublicKey,
|
||||||
|
pub s_b: crate::monero::Scalar,
|
||||||
pub xmr_swap_amount: crate::monero::Amount,
|
pub xmr_swap_amount: crate::monero::Amount,
|
||||||
pub btc_swap_amount: crate::bitcoin::Amount,
|
pub btc_swap_amount: crate::bitcoin::Amount,
|
||||||
pub xmr_lock: XmrLock,
|
pub tx_lock: BtcLock,
|
||||||
v_b: crate::monero::PrivateViewKey,
|
// public spend key
|
||||||
|
pub S: crate::monero::PublicKey,
|
||||||
|
pub S_a_bitcoin: crate::bitcoin::PublicKey,
|
||||||
|
pub v: crate::monero::PrivateViewKey,
|
||||||
|
pub alice_redeem_address: bitcoin::Address,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bob3 {
|
impl Bob3 {
|
||||||
pub fn watch_for_lock_xmr(&self, wallet: &crate::monero::Wallet) {
|
pub async fn watch_for_lock_xmr(
|
||||||
|
&self,
|
||||||
|
xmr_wallet: &crate::monero::Wallet,
|
||||||
|
btc_wallet: &crate::bitcoin::Wallet,
|
||||||
|
transfer_proof: TransferProof,
|
||||||
|
alice_redeem_address: bitcoin::Address,
|
||||||
|
) -> Result<Bob4> {
|
||||||
let req = WatchRequest {
|
let req = WatchRequest {
|
||||||
public_spend_key: self.xmr_lock.public_spend_key,
|
public_spend_key: self.S,
|
||||||
public_view_key: self.v_b.public(),
|
public_view_key: self.v.public(),
|
||||||
transfer_proof: self.xmr_lock.transfer_proof.clone(),
|
transfer_proof,
|
||||||
conf_target: 1,
|
conf_target: 1,
|
||||||
expected: self.xmr_swap_amount,
|
expected: self.xmr_swap_amount,
|
||||||
};
|
};
|
||||||
wallet.watch_for_transfer(req);
|
let _ = xmr_wallet.watch_for_transfer(req).await?;
|
||||||
|
|
||||||
|
let signed_tx_lock = btc_wallet
|
||||||
|
.sign_and_finalize(self.tx_lock.clone().into())
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let (_txid, sub) = btc_wallet.broadcast(signed_tx_lock, "lock").await?;
|
||||||
|
|
||||||
|
let _ = sub.wait_until_confirmed_with(1).await?;
|
||||||
|
|
||||||
|
Ok(Bob4 {
|
||||||
|
b: self.b.clone(),
|
||||||
|
A: self.A,
|
||||||
|
s_b: self.s_b,
|
||||||
|
S_a_bitcoin: self.S_a_bitcoin,
|
||||||
|
tx_lock: self.tx_lock.clone(),
|
||||||
|
alice_redeem_address,
|
||||||
|
v: self.v,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn emergency_refund_if_refund_xmr_seen(
|
||||||
|
&self,
|
||||||
|
xmr_wallet: &crate::monero::Wallet,
|
||||||
|
btc_wallet: &crate::bitcoin::Wallet,
|
||||||
|
transfer_proof: TransferProof,
|
||||||
|
) -> Result<Bob4> {
|
||||||
|
let req = WatchRequest {
|
||||||
|
public_spend_key: todo!(),
|
||||||
|
public_view_key: todo!(),
|
||||||
|
transfer_proof,
|
||||||
|
conf_target: 1,
|
||||||
|
expected: self.xmr_swap_amount,
|
||||||
|
};
|
||||||
|
let _ = xmr_wallet.watch_for_transfer(req).await?;
|
||||||
|
|
||||||
|
let emergency_refund = btc_wallet
|
||||||
|
.sign_and_finalize(self.tx_lock.clone().into())
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let (_txid, sub) = btc_wallet.broadcast(emergency_refund, "lock").await?;
|
||||||
|
|
||||||
|
let _ = sub.wait_until_confirmed_with(1).await?;
|
||||||
|
|
||||||
|
Ok(Bob4 {
|
||||||
|
b: self.b.clone(),
|
||||||
|
A: self.A,
|
||||||
|
s_b: self.s_b,
|
||||||
|
S_a_bitcoin: self.S_a_bitcoin,
|
||||||
|
tx_lock: self.tx_lock.clone(),
|
||||||
|
alice_redeem_address: self.alice_redeem_address.clone(),
|
||||||
|
v: self.v,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// published btc_lock, watching for xmr_redeem
|
// published btc_lock, watching for btc_redeem
|
||||||
pub struct Bob4;
|
pub struct Bob4 {
|
||||||
|
pub b: crate::bitcoin::SecretKey,
|
||||||
|
pub A: crate::bitcoin::PublicKey,
|
||||||
|
pub s_b: crate::monero::Scalar,
|
||||||
|
pub S_a_bitcoin: crate::bitcoin::PublicKey,
|
||||||
|
pub tx_lock: BtcLock,
|
||||||
|
pub alice_redeem_address: crate::bitcoin::Address,
|
||||||
|
pub v: crate::monero::PrivateViewKey,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Bob4 {
|
||||||
|
pub async fn redeem_xmr_when_btc_redeem_seen(
|
||||||
|
&self,
|
||||||
|
bitcoin_wallet: &crate::bitcoin::Wallet,
|
||||||
|
monero_wallet: &crate::monero::Wallet,
|
||||||
|
swap_id: Uuid,
|
||||||
|
) -> Result<()> {
|
||||||
|
let btc_redeem = BtcRedeem::new(&self.tx_lock, &self.alice_redeem_address);
|
||||||
|
let btc_redeem_encsig = self.b.encsign(self.S_a_bitcoin, btc_redeem.digest());
|
||||||
|
|
||||||
|
let btc_redeem_watcher = bitcoin_wallet.subscribe_to(btc_redeem.clone()).await;
|
||||||
|
|
||||||
|
btc_redeem_watcher.wait_until_confirmed_with(1).await?;
|
||||||
|
|
||||||
|
let btc_redeem_candidate = bitcoin_wallet
|
||||||
|
.get_raw_transaction(btc_redeem.txid())
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let btc_redeem_sig =
|
||||||
|
btc_redeem.extract_signature_by_key(btc_redeem_candidate, self.b.public())?;
|
||||||
|
let s_a = crate::bitcoin::recover(self.S_a_bitcoin, btc_redeem_sig, btc_redeem_encsig)?;
|
||||||
|
let s_a = crate::monero::private_key_from_secp256k1_scalar(s_a.into());
|
||||||
|
|
||||||
|
let (spend_key, view_key) = {
|
||||||
|
let s_b = monero::PrivateKey { scalar: self.s_b };
|
||||||
|
let s = s_a + s_b;
|
||||||
|
|
||||||
|
(s, self.v)
|
||||||
|
};
|
||||||
|
|
||||||
|
monero_wallet
|
||||||
|
.create_from_and_load(
|
||||||
|
&swap_id.to_string(),
|
||||||
|
spend_key,
|
||||||
|
view_key,
|
||||||
|
monero_rpc::wallet::BlockHeight { height: 0 },
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -7,7 +7,7 @@ pub struct StateMachine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl StateMachine {
|
impl StateMachine {
|
||||||
fn next(&mut self, event: Event) {
|
fn inject_event(&mut self, event: Event) {
|
||||||
match self.state {
|
match self.state {
|
||||||
State::WatchingForXmrLock => match event {
|
State::WatchingForXmrLock => match event {
|
||||||
Event::XmrConfirmed => {
|
Event::XmrConfirmed => {
|
||||||
@ -41,9 +41,11 @@ impl StateMachine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&mut self) {
|
fn poll(&mut self) -> Poll<Action> {
|
||||||
while let Some(event) = self.events.pop_front() {
|
if let Some(action) = self.actions.pop_front() {
|
||||||
self.next(event);
|
Poll::Ready(action)
|
||||||
|
} else {
|
||||||
|
Poll::Pending
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
pub mod btc_lock;
|
|
||||||
// pub mod btc_redeem;
|
|
||||||
pub mod xmr_lock;
|
|
||||||
pub mod xmr_refund;
|
|
||||||
|
|
||||||
use crate::bitcoin::wallet::Watchable;
|
|
||||||
use crate::bitcoin::{
|
|
||||||
build_shared_output_descriptor, Address, Amount, PartiallySignedTransaction, PublicKey,
|
|
||||||
Transaction, Txid, Wallet, TX_FEE,
|
|
||||||
};
|
|
||||||
use anyhow::{bail, Result};
|
|
||||||
use bdk::bitcoin::{OutPoint, Script, TxIn, TxOut};
|
|
||||||
use bdk::database::BatchDatabase;
|
|
||||||
use bdk::descriptor::Descriptor;
|
|
||||||
use ecdsa_fun::fun::Point;
|
|
||||||
use miniscript::DescriptorTrait;
|
|
||||||
use rand::thread_rng;
|
|
@ -4,6 +4,7 @@ use crate::bitcoin::{
|
|||||||
NotThreeWitnesses, PublicKey, SecretKey, TooManyInputs, Transaction,
|
NotThreeWitnesses, PublicKey, SecretKey, TooManyInputs, Transaction,
|
||||||
};
|
};
|
||||||
use crate::xmr_first_protocol::transactions::btc_lock::BtcLock;
|
use crate::xmr_first_protocol::transactions::btc_lock::BtcLock;
|
||||||
|
use crate::xmr_first_protocol::transactions::btc_redeem::BtcRedeem;
|
||||||
use ::bitcoin::util::bip143::SigHashCache;
|
use ::bitcoin::util::bip143::SigHashCache;
|
||||||
use ::bitcoin::{SigHash, SigHashType, Txid};
|
use ::bitcoin::{SigHash, SigHashType, Txid};
|
||||||
use anyhow::{bail, Context, Result};
|
use anyhow::{bail, Context, Result};
|
||||||
@ -17,30 +18,28 @@ use sha2::Sha256;
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct EmergencyRefund {
|
pub struct BtcEmergencyRefund {
|
||||||
inner: Transaction,
|
inner: Transaction,
|
||||||
digest: SigHash,
|
digest: SigHash,
|
||||||
lock_output_descriptor: Descriptor<::bitcoin::PublicKey>,
|
lock_output_descriptor: Descriptor<::bitcoin::PublicKey>,
|
||||||
watch_script: Script,
|
watch_script: Script,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EmergencyRefund {
|
impl BtcEmergencyRefund {
|
||||||
pub fn new(tx_lock: &BtcLock, redeem_address: &Address) -> Self {
|
pub fn new(tx_redeem: &BtcRedeem, redeem_address: &Address) -> Self {
|
||||||
// lock_input is the shared output that is now being used as an input for the
|
let tx_refund = tx_redeem.build_take_transaction(redeem_address, None);
|
||||||
// redeem transaction
|
|
||||||
let tx_redeem = tx_lock.build_spend_transaction(redeem_address, None);
|
|
||||||
|
|
||||||
let digest = SigHashCache::new(&tx_redeem).signature_hash(
|
let digest = SigHashCache::new(&tx_refund).signature_hash(
|
||||||
0, // Only one input: lock_input (lock transaction)
|
0, // Only one input: lock_input (lock transaction)
|
||||||
&tx_lock.output_descriptor.script_code(),
|
&tx_refund.output_descriptor.script_code(),
|
||||||
tx_lock.lock_amount().as_sat(),
|
tx_refund.lock_amount().as_sat(),
|
||||||
SigHashType::All,
|
SigHashType::All,
|
||||||
);
|
);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
inner: tx_redeem,
|
inner: tx_refund,
|
||||||
digest,
|
digest,
|
||||||
lock_output_descriptor: tx_lock.output_descriptor.clone(),
|
lock_output_descriptor: tx_refund.output_descriptor.clone(),
|
||||||
watch_script: redeem_address.script_pubkey(),
|
watch_script: redeem_address.script_pubkey(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -53,14 +52,6 @@ impl EmergencyRefund {
|
|||||||
self.digest
|
self.digest
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn encsig(
|
|
||||||
&self,
|
|
||||||
b: SecretKey,
|
|
||||||
S_a_bitcoin: PublicKey,
|
|
||||||
) -> crate::bitcoin::EncryptedSignature {
|
|
||||||
b.encsign(S_a_bitcoin, self.digest())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn complete(
|
pub fn complete(
|
||||||
mut self,
|
mut self,
|
||||||
a: SecretKey,
|
a: SecretKey,
|
||||||
@ -105,46 +96,9 @@ impl EmergencyRefund {
|
|||||||
|
|
||||||
Ok(self.inner)
|
Ok(self.inner)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_signature_by_key(
|
|
||||||
&self,
|
|
||||||
candidate_transaction: Transaction,
|
|
||||||
B: PublicKey,
|
|
||||||
) -> Result<Signature> {
|
|
||||||
let input = match candidate_transaction.input.as_slice() {
|
|
||||||
[input] => input,
|
|
||||||
[] => bail!("no inputs"),
|
|
||||||
[inputs @ ..] => bail!("too many inputs"),
|
|
||||||
};
|
|
||||||
|
|
||||||
let sigs = match input
|
|
||||||
.witness
|
|
||||||
.iter()
|
|
||||||
.map(|vec| vec.as_slice())
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.as_slice()
|
|
||||||
{
|
|
||||||
[sig_1, sig_2, _script] => [sig_1, sig_2]
|
|
||||||
.iter()
|
|
||||||
.map(|sig| {
|
|
||||||
bitcoin::secp256k1::Signature::from_der(&sig[..sig.len() - 1])
|
|
||||||
.map(Signature::from)
|
|
||||||
})
|
|
||||||
.collect::<std::result::Result<Vec<_>, _>>(),
|
|
||||||
[] => bail!("empty witness stack"),
|
|
||||||
[witnesses @ ..] => bail!("not three witnesses"),
|
|
||||||
}?;
|
|
||||||
|
|
||||||
let sig = sigs
|
|
||||||
.into_iter()
|
|
||||||
.find(|sig| verify_sig(&B, &self.digest(), &sig).is_ok())
|
|
||||||
.context("Neither signature on witness stack verifies against B")?;
|
|
||||||
|
|
||||||
Ok(sig)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Watchable for EmergencyRefund {
|
impl Watchable for BtcEmergencyRefund {
|
||||||
fn id(&self) -> Txid {
|
fn id(&self) -> Txid {
|
||||||
self.txid()
|
self.txid()
|
||||||
}
|
}
|
@ -1,12 +1,14 @@
|
|||||||
use crate::bitcoin::wallet::Watchable;
|
use crate::bitcoin::wallet::Watchable;
|
||||||
use crate::bitcoin::{
|
use crate::bitcoin::{
|
||||||
verify_encsig, verify_sig, Address, EmptyWitnessStack, EncryptedSignature, NoInputs,
|
verify_encsig, verify_sig, Address, EmptyWitnessStack, EncryptedSignature, NoInputs,
|
||||||
NotThreeWitnesses, PublicKey, SecretKey, TooManyInputs, Transaction, TxLock,
|
NotThreeWitnesses, PublicKey, SecretKey, TooManyInputs, Transaction, TX_FEE,
|
||||||
};
|
};
|
||||||
|
use crate::xmr_first_protocol::transactions::btc_lock::BtcLock;
|
||||||
use ::bitcoin::util::bip143::SigHashCache;
|
use ::bitcoin::util::bip143::SigHashCache;
|
||||||
use ::bitcoin::{SigHash, SigHashType, Txid};
|
use ::bitcoin::{SigHash, SigHashType, Txid};
|
||||||
use anyhow::{bail, Context, Result};
|
use anyhow::{bail, Context, Result};
|
||||||
use bitcoin::Script;
|
use bdk::bitcoin::Script;
|
||||||
|
use bitcoin::{PrivateKey, TxIn, TxOut};
|
||||||
use ecdsa_fun::adaptor::{Adaptor, HashTranscript};
|
use ecdsa_fun::adaptor::{Adaptor, HashTranscript};
|
||||||
use ecdsa_fun::fun::Scalar;
|
use ecdsa_fun::fun::Scalar;
|
||||||
use ecdsa_fun::nonce::Deterministic;
|
use ecdsa_fun::nonce::Deterministic;
|
||||||
@ -16,15 +18,15 @@ use sha2::Sha256;
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct TxRedeem {
|
pub struct BtcRedeem {
|
||||||
inner: Transaction,
|
inner: Transaction,
|
||||||
digest: SigHash,
|
digest: SigHash,
|
||||||
lock_output_descriptor: Descriptor<::bitcoin::PublicKey>,
|
lock_output_descriptor: Descriptor<::bitcoin::PublicKey>,
|
||||||
watch_script: Script,
|
watch_script: Script,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TxRedeem {
|
impl BtcRedeem {
|
||||||
pub fn new(tx_lock: &TxLock, redeem_address: &Address) -> Self {
|
pub fn new(tx_lock: &BtcLock, redeem_address: &Address) -> Self {
|
||||||
// lock_input is the shared output that is now being used as an input for the
|
// lock_input is the shared output that is now being used as an input for the
|
||||||
// redeem transaction
|
// redeem transaction
|
||||||
let tx_redeem = tx_lock.build_spend_transaction(redeem_address, None);
|
let tx_redeem = tx_lock.build_spend_transaction(redeem_address, None);
|
||||||
@ -52,12 +54,20 @@ impl TxRedeem {
|
|||||||
self.digest
|
self.digest
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn encsig(
|
||||||
|
&self,
|
||||||
|
b: SecretKey,
|
||||||
|
S_a_bitcoin: PublicKey,
|
||||||
|
) -> crate::bitcoin::EncryptedSignature {
|
||||||
|
b.encsign(S_a_bitcoin, self.digest())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn complete(
|
pub fn complete(
|
||||||
mut self,
|
mut self,
|
||||||
encrypted_signature: EncryptedSignature,
|
|
||||||
a: SecretKey,
|
a: SecretKey,
|
||||||
s_a: Scalar,
|
s_a: Scalar,
|
||||||
B: PublicKey,
|
B: PublicKey,
|
||||||
|
encrypted_signature: EncryptedSignature,
|
||||||
) -> Result<Transaction> {
|
) -> Result<Transaction> {
|
||||||
verify_encsig(
|
verify_encsig(
|
||||||
B,
|
B,
|
||||||
@ -76,11 +86,11 @@ impl TxRedeem {
|
|||||||
|
|
||||||
let A = ::bitcoin::PublicKey {
|
let A = ::bitcoin::PublicKey {
|
||||||
compressed: true,
|
compressed: true,
|
||||||
key: a.public().into(),
|
key: a.public.into(),
|
||||||
};
|
};
|
||||||
let B = ::bitcoin::PublicKey {
|
let B = ::bitcoin::PublicKey {
|
||||||
compressed: true,
|
compressed: true,
|
||||||
key: B.into(),
|
key: B.0.into(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// The order in which these are inserted doesn't matter
|
// The order in which these are inserted doesn't matter
|
||||||
@ -104,7 +114,7 @@ impl TxRedeem {
|
|||||||
) -> Result<Signature> {
|
) -> Result<Signature> {
|
||||||
let input = match candidate_transaction.input.as_slice() {
|
let input = match candidate_transaction.input.as_slice() {
|
||||||
[input] => input,
|
[input] => input,
|
||||||
[] => bail!(NoInputs),
|
[] => bail!("no inputs"),
|
||||||
[inputs @ ..] => bail!("too many inputs"),
|
[inputs @ ..] => bail!("too many inputs"),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -122,7 +132,7 @@ impl TxRedeem {
|
|||||||
.map(Signature::from)
|
.map(Signature::from)
|
||||||
})
|
})
|
||||||
.collect::<std::result::Result<Vec<_>, _>>(),
|
.collect::<std::result::Result<Vec<_>, _>>(),
|
||||||
[] => bail!(EmptyWitnessStack),
|
[] => bail!("empty witness stack"),
|
||||||
[witnesses @ ..] => bail!("not three witnesses"),
|
[witnesses @ ..] => bail!("not three witnesses"),
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
@ -133,9 +143,47 @@ impl TxRedeem {
|
|||||||
|
|
||||||
Ok(sig)
|
Ok(sig)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn build_transaction(
|
||||||
|
&self,
|
||||||
|
a: SecretKey,
|
||||||
|
s_a: Scalar,
|
||||||
|
B: PublicKey,
|
||||||
|
encsig: EncryptedSignature,
|
||||||
|
) -> Transaction {
|
||||||
|
let signed_tx_redeem = self.complete(a, s_a, B, encsig)?;
|
||||||
|
signed_tx_redeem
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build_take_transaction(
|
||||||
|
&self,
|
||||||
|
spend_address: &Address,
|
||||||
|
sequence: Option<u32>,
|
||||||
|
) -> Transaction {
|
||||||
|
let previous_output = self.as_outpoint();
|
||||||
|
|
||||||
|
let tx_in = TxIn {
|
||||||
|
previous_output,
|
||||||
|
script_sig: Default::default(),
|
||||||
|
sequence: sequence.unwrap_or(0xFFFF_FFFF),
|
||||||
|
witness: Vec::new(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let tx_out = TxOut {
|
||||||
|
value: self.inner.clone().extract_tx().output[self.lock_output_vout()].value - TX_FEE,
|
||||||
|
script_pubkey: spend_address.script_pubkey(),
|
||||||
|
};
|
||||||
|
|
||||||
|
Transaction {
|
||||||
|
version: 2,
|
||||||
|
lock_time: 0,
|
||||||
|
input: vec![tx_in],
|
||||||
|
output: vec![tx_out],
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Watchable for TxRedeem {
|
impl Watchable for BtcRedeem {
|
||||||
fn id(&self) -> Txid {
|
fn id(&self) -> Txid {
|
||||||
self.txid()
|
self.txid()
|
||||||
}
|
}
|
||||||
|
6
swap/src/xmr_first_protocol/transactions/mod.rs
Normal file
6
swap/src/xmr_first_protocol/transactions/mod.rs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
pub mod btc_emergency_refund;
|
||||||
|
pub mod btc_lock;
|
||||||
|
pub mod btc_redeem;
|
||||||
|
pub mod xmr_lock;
|
||||||
|
pub mod xmr_redeem;
|
||||||
|
pub mod xmr_refund;
|
@ -1,7 +1,59 @@
|
|||||||
use crate::monero::{PrivateViewKey, PublicKey, TransferProof};
|
use crate::monero::wallet::{TransferRequest, WatchRequest};
|
||||||
|
use crate::monero::{Amount, PrivateViewKey, Scalar, TransferProof};
|
||||||
|
use curve25519_dalek::edwards::EdwardsPoint;
|
||||||
|
use monero::PublicKey;
|
||||||
|
|
||||||
pub struct XmrLock {
|
pub struct XmrLock {
|
||||||
pub public_spend_key: PublicKey,
|
S_a: monero::PublicKey,
|
||||||
pub public_view_key: PrivateViewKey,
|
S_b: monero::PublicKey,
|
||||||
pub transfer_proof: TransferProof,
|
v_a: PrivateViewKey,
|
||||||
|
v_b: PrivateViewKey,
|
||||||
|
D: EdwardsPoint,
|
||||||
|
amount: Amount,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl XmrLock {
|
||||||
|
pub fn new(
|
||||||
|
S_a: monero::PublicKey,
|
||||||
|
S_b: monero::PublicKey,
|
||||||
|
v_a: PrivateViewKey,
|
||||||
|
v_b: PrivateViewKey,
|
||||||
|
D: EdwardsPoint,
|
||||||
|
amount: Amount,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
S_a,
|
||||||
|
S_b,
|
||||||
|
v_a,
|
||||||
|
v_b,
|
||||||
|
D,
|
||||||
|
amount,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn transfer_request(&self) -> TransferRequest {
|
||||||
|
let vk = self.S_a + self.S_b;
|
||||||
|
let v = self.v_a + self.v_b;
|
||||||
|
|
||||||
|
// use from KeyGenerator from monero.rs to do the H(vD) bit for the on time
|
||||||
|
// address
|
||||||
|
let one_time_address = todo!("KeyGenerator.random().one_time_key(self.D)");
|
||||||
|
|
||||||
|
TransferRequest {
|
||||||
|
public_spend_key: one_time_address,
|
||||||
|
public_view_key: v.public(),
|
||||||
|
amount: self.amount,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn watch_request(&self, transfer_proof: TransferProof) -> WatchRequest {
|
||||||
|
let public_spend_key = self.S_a + self.S_b;
|
||||||
|
let private_view_key = self.v_a + self.v_b;
|
||||||
|
|
||||||
|
WatchRequest {
|
||||||
|
public_spend_key,
|
||||||
|
public_view_key: private_view_key.public(),
|
||||||
|
transfer_proof,
|
||||||
|
conf_target: 1,
|
||||||
|
expected: self.amount,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
58
swap/src/xmr_first_protocol/transactions/xmr_redeem.rs
Normal file
58
swap/src/xmr_first_protocol/transactions/xmr_redeem.rs
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
use crate::monero::wallet::{TransferRequest, WatchRequest};
|
||||||
|
use crate::monero::{Amount, PrivateKey, PrivateViewKey, Scalar, TransferProof};
|
||||||
|
use curve25519_dalek::edwards::EdwardsPoint;
|
||||||
|
use monero::PublicKey;
|
||||||
|
|
||||||
|
pub struct XmrRedeem {
|
||||||
|
// recover s_a from btc_redeem
|
||||||
|
s_a: monero::PrivateKey,
|
||||||
|
s_b: monero::PrivateKey,
|
||||||
|
v_a: PrivateViewKey,
|
||||||
|
v_b: PrivateViewKey,
|
||||||
|
// D: EdwardsPoint,
|
||||||
|
amount: Amount,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl XmrRedeem {
|
||||||
|
pub fn new(
|
||||||
|
s_a: monero::PrivateKey,
|
||||||
|
s_b: monero::PrivateKey,
|
||||||
|
v_a: PrivateViewKey,
|
||||||
|
v_b: PrivateViewKey,
|
||||||
|
// D: EdwardsPoint,
|
||||||
|
amount: Amount,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
s_a,
|
||||||
|
s_b,
|
||||||
|
v_a,
|
||||||
|
v_b,
|
||||||
|
// D,
|
||||||
|
amount,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn transfer_request(&self) -> TransferRequest {
|
||||||
|
let v = self.v_a + self.v_b;
|
||||||
|
// let h = self.D * v_view;
|
||||||
|
// let private_spend_key = self.s_a + self.s_b + h;
|
||||||
|
let vk = self.s_a + self.s_b;
|
||||||
|
|
||||||
|
TransferRequest {
|
||||||
|
public_spend_key: PublicKey::from_private_key(&vk),
|
||||||
|
public_view_key: v.public(),
|
||||||
|
amount: self.amount,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn watch_request(&self, transfer_proof: TransferProof) -> WatchRequest {
|
||||||
|
let private_spend_key = self.s_a + self.s_b;
|
||||||
|
let private_view_key = self.v_a + self.v_b;
|
||||||
|
|
||||||
|
WatchRequest {
|
||||||
|
public_spend_key: PublicKey::from_private_key(&private_spend_key),
|
||||||
|
public_view_key: private_view_key.public(),
|
||||||
|
transfer_proof,
|
||||||
|
conf_target: 1,
|
||||||
|
expected: self.amount,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,26 +1,43 @@
|
|||||||
use crate::monero::TransferRequest;
|
use crate::monero::wallet::WatchRequest;
|
||||||
|
use crate::monero::{Amount, PrivateViewKey, Scalar};
|
||||||
use crate::xmr_first_protocol::alice::Alice4;
|
use crate::xmr_first_protocol::alice::Alice4;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use monero_adaptor::AdaptorSignature;
|
use monero_adaptor::Signature;
|
||||||
|
|
||||||
pub struct XmrRefund {
|
pub struct XmrRefund {
|
||||||
adaptor: AdaptorSignature,
|
signature: Signature,
|
||||||
|
amount: Amount,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct TransferRequest;
|
||||||
|
|
||||||
impl XmrRefund {
|
impl XmrRefund {
|
||||||
pub async fn publish_xmr_refund(&self, wallet: &crate::monero::Wallet) -> Result<()> {
|
pub fn new(signature: Signature, amount: Amount) -> Self {
|
||||||
let S_a = monero::PublicKey::from_private_key(&monero::PrivateKey { scalar: self.s_a });
|
XmrRefund {
|
||||||
|
signature,
|
||||||
let public_spend_key = S_a + self.S_b_monero;
|
amount: xmr_swap_amount,
|
||||||
let public_view_key = self.v_a.public();
|
}
|
||||||
|
}
|
||||||
let req = TransferRequest {
|
pub fn transfer_request(&self) -> TransferRequest {
|
||||||
public_spend_key,
|
todo!();
|
||||||
public_view_key,
|
TransferRequest
|
||||||
amount: self.xmr_swap_amount,
|
}
|
||||||
};
|
// pub fn watch_request(&self) -> WatchRequest {
|
||||||
|
// let S_a = monero::PublicKey::from_private_key(&monero::PrivateKey {
|
||||||
let _ = wallet.transfer(req).await?;
|
// scalar: self.s_a });
|
||||||
Ok(())
|
//
|
||||||
|
// let public_spend_key = S_a + self.S_b_monero;
|
||||||
|
// let public_view_key = self.v_a.public();
|
||||||
|
//
|
||||||
|
// WatchRequest {
|
||||||
|
// public_spend_key,
|
||||||
|
// public_view_key,
|
||||||
|
// transfer_proof: todo!("xfer without broadcasting to get xfer proof"),
|
||||||
|
// conf_target: 1,
|
||||||
|
// expected: self.amount,
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
pub fn extract_r_a(&self) -> Scalar {
|
||||||
|
self.signature.extract()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -834,7 +834,7 @@ pub async fn init_test_wallets(
|
|||||||
|
|
||||||
// This is just to keep the containers alive
|
// This is just to keep the containers alive
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
struct Containers<'a> {
|
pub struct Containers<'a> {
|
||||||
pub bitcoind_url: Url,
|
pub bitcoind_url: Url,
|
||||||
bitcoind: Container<'a, Cli, bitcoind::Bitcoind>,
|
bitcoind: Container<'a, Cli, bitcoind::Bitcoind>,
|
||||||
monerods: Vec<Container<'a, Cli, image::Monero>>,
|
monerods: Vec<Container<'a, Cli, image::Monero>>,
|
||||||
|
@ -1,16 +1,24 @@
|
|||||||
pub mod harness;
|
pub mod harness;
|
||||||
|
|
||||||
use rand::rngs::OsRng;
|
use rand::rngs::OsRng;
|
||||||
use swap::bitcoin::TxLock;
|
use swap::bitcoin::BtcLock;
|
||||||
use swap::env::GetConfig;
|
use swap::env::GetConfig;
|
||||||
use swap::monero;
|
use swap::monero;
|
||||||
|
use swap::monero::TransferRequest;
|
||||||
use swap::protocol::alice::event_loop::FixedRate;
|
use swap::protocol::alice::event_loop::FixedRate;
|
||||||
use swap::protocol::CROSS_CURVE_PROOF_SYSTEM;
|
use swap::protocol::CROSS_CURVE_PROOF_SYSTEM;
|
||||||
use swap::seed::Seed;
|
use swap::seed::Seed;
|
||||||
use swap::xmr_first_protocol::alice::{publish_xmr_refund, Alice3};
|
use swap::xmr_first_protocol::alice::{publish_xmr_refund, Alice3};
|
||||||
use swap::xmr_first_protocol::bob::Bob3;
|
use swap::xmr_first_protocol::bob::Bob3;
|
||||||
|
use swap::xmr_first_protocol::transactions::btc_lock::BtcLock;
|
||||||
|
use swap::xmr_first_protocol::transactions::xmr_lock::XmrLock;
|
||||||
|
use swap::xmr_first_protocol::transactions::xmr_refund::XmrRefund;
|
||||||
use tempfile::tempdir;
|
use tempfile::tempdir;
|
||||||
use testcontainers::clients::Cli;
|
use testcontainers::clients::Cli;
|
||||||
|
use swap::xmr_first_protocol::transactions::btc_redeem::BtcRedeem;
|
||||||
|
use monero::{PublicKey, PrivateKey};
|
||||||
|
use swap::xmr_first_protocol::setup;
|
||||||
|
use swap::xmr_first_protocol::transactions::xmr_redeem::XmrRedeem;
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn refund() {
|
async fn refund() {
|
||||||
@ -63,48 +71,60 @@ async fn refund() {
|
|||||||
&bob_seed,
|
&bob_seed,
|
||||||
env_config,
|
env_config,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let a = swap::bitcoin::SecretKey::new_random(&mut OsRng);
|
let (alice, bob) = setup();
|
||||||
let b = swap::bitcoin::SecretKey::new_random(&mut OsRng);
|
|
||||||
|
|
||||||
let s_a = monero::Scalar::random(&mut OsRng);
|
let btc_redeem_address = alice_bitcoin_wallet.new_address().await.unwrap();
|
||||||
let S_a = monero::PublicKey::from_private_key(&monero::PrivateKey { scalar: s_a });
|
|
||||||
|
|
||||||
let s_b = monero::Scalar::random(&mut OsRng);
|
// transactions
|
||||||
let S_b = monero::PublicKey::from_private_key(&monero::PrivateKey { scalar: s_b });
|
let btc_lock =
|
||||||
|
BtcLock::new(&bob_bitcoin_wallet, btc_swap_amount, a.public(), b.public()).await?;
|
||||||
|
let btc_redeem = BtcRedeem::new(&btc_lock, &btc_redeem_address);
|
||||||
|
let xmr_lock = XmrLock::new(alice.S_a.into(), alice.S_b, alice.v_a, alice.v_b, xmr_swap_amount);
|
||||||
|
//let xmr_redeem = XmrRedeem::new(s_a, PrivateKey::from_scalar(bob.s_b), alice.v_a, alice.v_b, xmr_swap_amount);
|
||||||
|
let xmr_refund = XmrRefund::new(sig, xmr_swap_amount);
|
||||||
|
|
||||||
let (dleq_proof_s_b, (S_b_bitcoin, S_b_monero)) =
|
// Alice publishes xmr_lock
|
||||||
CROSS_CURVE_PROOF_SYSTEM.prove(&s_b, &mut OsRng);
|
let xmr_lock_transfer_proof = alice_monero_wallet
|
||||||
|
.transfer(xmr_lock.transfer_request())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let v_a = monero::PrivateViewKey::new_random(&mut OsRng);
|
// Bob waits until xmr_lock is seen
|
||||||
let v_b = monero::PrivateViewKey::new_random(&mut OsRng);
|
let _ = bob_monero_wallet
|
||||||
|
.watch_for_transfer(xmr_lock.watch_request(xmr_lock_transfer_proof))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let tx_lock = TxLock::new(&bob_bitcoin_wallet, btc_swap_amount, a.public(), b.public()).await?;
|
// Bob publishes btc_lock
|
||||||
|
let signed_tx_lock = bob_bitcoin_wallet
|
||||||
|
.sign_and_finalize(btc_lock.clone().into())
|
||||||
|
.await?;
|
||||||
|
let (_txid, sub) = bob_bitcoin_wallet.broadcast(signed_tx_lock, "lock").await.unwrap();
|
||||||
|
let _ = sub.wait_until_confirmed_with(1).await?;
|
||||||
|
|
||||||
let alice = Alice3 {
|
// alice publishes xmr_refund
|
||||||
xmr_swap_amount,
|
// let xmr_refund_transfer_proof = alice_monero_wallet
|
||||||
btc_swap_amount,
|
// .transfer(xmr_refund.transfer_request())
|
||||||
a,
|
// .await
|
||||||
B: b.public(),
|
// .unwrap();
|
||||||
s_a,
|
|
||||||
S_b_monero: monero::PublicKey {
|
|
||||||
point: S_b_monero.compress(),
|
|
||||||
},
|
|
||||||
v_a,
|
|
||||||
redeem_address: alice_bitcoin_wallet.new_address().await?,
|
|
||||||
};
|
|
||||||
|
|
||||||
let bob = Bob3 {
|
// alice publishes btc_redeem
|
||||||
xmr_swap_amount,
|
btc_redeem.encsig((), ());
|
||||||
btc_swap_amount,
|
let (_, btc_redeem_sub) = alice_bitcoin_wallet.broadcast(btc_redeem.build_transaction(alice.a, alice.s_a, alice.pk_b, btc_lock.), "redeem")
|
||||||
tx_lock,
|
.await
|
||||||
S: S_b,
|
.unwrap();
|
||||||
v_b,
|
|
||||||
alice_redeem_address: bob_bitcoin_wallet.new_address().await?,
|
|
||||||
};
|
|
||||||
|
|
||||||
let alice = alice.publish_xmr_lock(&alice_monero_wallet).await.unwrap();
|
// bob sees xmr_refund and btc_redeem
|
||||||
|
let _ = bob_monero_wallet
|
||||||
|
.watch_for_transfer(xmr_lock.watch_request(xmr_refund_transfer_proof))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let _ = btc_redeem_sub.wait_until_seen()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
publish_xmr_refund(&alice_bitcoin_wallet).await.unwrap();
|
// extract r_a from xmr_refund
|
||||||
|
let _ = bob_bitcoin_wallet.broadcast("redeem")
|
||||||
}
|
}
|
||||||
|
@ -1,109 +1,155 @@
|
|||||||
pub mod harness;
|
// pub mod harness;
|
||||||
|
//
|
||||||
use curve25519_dalek::constants::ED25519_BASEPOINT_POINT;
|
// use rand::rngs::OsRng;
|
||||||
use curve25519_dalek::edwards::EdwardsPoint;
|
// use swap::env::GetConfig;
|
||||||
use monero_adaptor::alice::Alice0;
|
// use swap::monero;
|
||||||
use monero_adaptor::bob::Bob0;
|
// use swap::protocol::alice::event_loop::FixedRate;
|
||||||
use rand::rngs::OsRng;
|
// use swap::protocol::CROSS_CURVE_PROOF_SYSTEM;
|
||||||
use swap::env::GetConfig;
|
// use swap::seed::Seed;
|
||||||
use swap::monero;
|
// use swap::xmr_first_protocol::alice::Alice3;
|
||||||
use swap::monero::{PublicKey, Scalar};
|
// use swap::xmr_first_protocol::bob::Bob3;
|
||||||
use swap::protocol::alice::event_loop::FixedRate;
|
// use swap::xmr_first_protocol::transactions::btc_lock::BtcLock;
|
||||||
use swap::protocol::CROSS_CURVE_PROOF_SYSTEM;
|
// use swap::xmr_first_protocol::transactions::btc_redeem::BtcRedeem;
|
||||||
use swap::seed::Seed;
|
// use tempfile::tempdir;
|
||||||
use swap::xmr_first_protocol::alice::Alice3;
|
// use testcontainers::clients::Cli;
|
||||||
use swap::xmr_first_protocol::bob::Bob3;
|
// use uuid::Uuid;
|
||||||
use swap::xmr_first_protocol::{alice, bob};
|
//
|
||||||
use tempfile::tempdir;
|
// #[tokio::test]
|
||||||
use testcontainers::clients::Cli;
|
// async fn happy_path() {
|
||||||
|
// let cli = Cli::default();
|
||||||
#[tokio::test]
|
//
|
||||||
async fn happy_path() {
|
// let env_config = harness::SlowCancelConfig::get_config();
|
||||||
let cli = Cli::default();
|
//
|
||||||
|
// let (monero, containers) = harness::init_containers(&cli).await;
|
||||||
let env_config = harness::SlowCancelConfig::get_config();
|
//
|
||||||
|
// let btc_swap_amount = bitcoin::Amount::from_sat(1_000_000);
|
||||||
let (monero, containers) = harness::init_containers(&cli).await;
|
// let xmr_swap_amount =
|
||||||
|
// monero::Amount::from_monero(btc_swap_amount.as_btc() /
|
||||||
let btc_amount = bitcoin::Amount::from_sat(1_000_000);
|
// FixedRate::RATE).unwrap();
|
||||||
let xmr_amount = monero::Amount::from_monero(btc_amount.as_btc() / FixedRate::RATE).unwrap();
|
//
|
||||||
|
// let alice_starting_balances = harness::StartingBalances {
|
||||||
let alice_starting_balances = harness::StartingBalances {
|
// xmr: xmr_swap_amount * 10,
|
||||||
xmr: xmr_amount * 10,
|
// btc: bitcoin::Amount::ZERO,
|
||||||
btc: bitcoin::Amount::ZERO,
|
// };
|
||||||
};
|
//
|
||||||
|
// let electrs_rpc_port = containers
|
||||||
let electrs_rpc_port = containers
|
// .electrs
|
||||||
.electrs
|
// .get_host_port(harness::electrs::RPC_PORT)
|
||||||
.get_host_port(harness::electrs::RPC_PORT)
|
// .expect("Could not map electrs rpc port");
|
||||||
.expect("Could not map electrs rpc port");
|
//
|
||||||
|
// let alice_seed = Seed::random().unwrap();
|
||||||
let alice_seed = Seed::random().unwrap();
|
// let (alice_bitcoin_wallet, alice_monero_wallet) =
|
||||||
let (alice_bitcoin_wallet, alice_monero_wallet) = harness::init_test_wallets(
|
// harness::init_test_wallets( "Alice",
|
||||||
"Alice",
|
// containers.bitcoind_url.clone(),
|
||||||
containers.bitcoind_url.clone(),
|
// &monero,
|
||||||
&monero,
|
// alice_starting_balances.clone(),
|
||||||
alice_starting_balances.clone(),
|
// tempdir().unwrap().path(),
|
||||||
tempdir().unwrap().path(),
|
// electrs_rpc_port,
|
||||||
electrs_rpc_port,
|
// &alice_seed,
|
||||||
&alice_seed,
|
// env_config.clone(),
|
||||||
env_config.clone(),
|
// )
|
||||||
)
|
// .await;
|
||||||
.await;
|
//
|
||||||
|
// let bob_seed = Seed::random().unwrap();
|
||||||
let bob_seed = Seed::random().unwrap();
|
// let bob_starting_balances = harness::StartingBalances {
|
||||||
let bob_starting_balances = harness::StartingBalances {
|
// xmr: monero::Amount::ZERO,
|
||||||
xmr: monero::Amount::ZERO,
|
// btc: btc_swap_amount * 10,
|
||||||
btc: btc_amount * 10,
|
// };
|
||||||
};
|
//
|
||||||
|
// let (bob_bitcoin_wallet, bob_monero_wallet) = harness::init_test_wallets(
|
||||||
let (bob_bitcoin_wallet, bob_monero_wallet) = harness::init_test_wallets(
|
// "Bob",
|
||||||
"Bob",
|
// containers.bitcoind_url,
|
||||||
containers.bitcoind_url,
|
// &monero,
|
||||||
&monero,
|
// bob_starting_balances.clone(),
|
||||||
bob_starting_balances.clone(),
|
// tempdir().unwrap().path(),
|
||||||
tempdir().unwrap().path(),
|
// electrs_rpc_port,
|
||||||
electrs_rpc_port,
|
// &bob_seed,
|
||||||
&bob_seed,
|
// env_config,
|
||||||
env_config,
|
// )
|
||||||
)
|
// .await;
|
||||||
.await;
|
//
|
||||||
|
// let a = swap::bitcoin::SecretKey::new_random(&mut OsRng);
|
||||||
let a = crate::bitcoin::SecretKey::new_random(rng);
|
// let b = swap::bitcoin::SecretKey::new_random(&mut OsRng);
|
||||||
let b = crate::bitcoin::SecretKey::new_random(rng);
|
//
|
||||||
|
// let s_a = monero::Scalar::random(&mut OsRng);
|
||||||
let s_a = monero::Scalar::random(rng);
|
// let S_a = monero::PublicKey::from_private_key(&monero::PrivateKey {
|
||||||
let s_b = monero::Scalar::random(rng);
|
// scalar: s_a });
|
||||||
|
//
|
||||||
let (dleq_proof_s_b, (S_b_bitcoin, S_b_monero)) = CROSS_CURVE_PROOF_SYSTEM.prove(&s_b, rng);
|
// let s_b = monero::Scalar::random(&mut OsRng);
|
||||||
|
// let S_b = monero::PublicKey::from_private_key(&monero::PrivateKey {
|
||||||
let v_a = monero::PrivateViewKey::new_random(rng);
|
// scalar: s_b });
|
||||||
let v_b = monero::PrivateViewKey::new_random(rng);
|
//
|
||||||
|
// let (dleq_proof_s_b, (S_b_bitcoin, S_b_monero)) =
|
||||||
let alice = Alice3 {
|
// CROSS_CURVE_PROOF_SYSTEM.prove(&s_b, &mut OsRng);
|
||||||
xmr_swap_amount: xmr_amount,
|
//
|
||||||
btc_swap_amount: btc_amount,
|
// let (dleq_proof_s_b, (S_a_bitcoin, S_a_monero)) =
|
||||||
a,
|
// CROSS_CURVE_PROOF_SYSTEM.prove(&s_a, &mut OsRng);
|
||||||
B: b.public(),
|
//
|
||||||
s_a,
|
// let v_a = monero::PrivateViewKey::new_random(&mut OsRng);
|
||||||
S_b_monero,
|
// let v_b = monero::PrivateViewKey::new_random(&mut OsRng);
|
||||||
v_a,
|
//
|
||||||
};
|
// let btc_redeem_address = bob_bitcoin_wallet.new_address().await.unwrap();
|
||||||
|
//
|
||||||
let bob = Bob3 {
|
// let tx_lock = BtcLock::new(&bob_bitcoin_wallet, btc_swap_amount,
|
||||||
xmr_swap_amount,
|
// a.public(), b.public()) .await
|
||||||
btc_swap_amount,
|
// .unwrap();
|
||||||
xmr_lock,
|
//
|
||||||
v_b,
|
// let tx_redeem = BtcRedeem::new(&tx_lock, &btc_redeem_address);
|
||||||
};
|
//
|
||||||
|
// let encsig = tx_redeem.encsig(b.clone(),
|
||||||
alice.publish_xmr_lock(&alice_monero_wallet).await.unwrap();
|
// swap::bitcoin::PublicKey::from(S_a_bitcoin));
|
||||||
|
//
|
||||||
bob.watch_for_lock_xmr(&bob_monero_wallet_wallet)
|
// let alice = Alice3 {
|
||||||
.await
|
// xmr_swap_amount,
|
||||||
.unwrap();
|
// btc_swap_amount,
|
||||||
|
// a: a.clone(),
|
||||||
alice.publish_btc_redeem(&alice_btc_wallet).await.unwrap();
|
// B: b.public(),
|
||||||
|
// s_a,
|
||||||
bob.publish_xmr_redeem(&alice_monero_wallet).await.unwrap();
|
// S_b_monero: monero::PublicKey {
|
||||||
}
|
// point: S_b_monero.compress(),
|
||||||
|
// },
|
||||||
|
// v_a,
|
||||||
|
// redeem_address: alice_bitcoin_wallet.new_address().await.unwrap(),
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// let bob = Bob3 {
|
||||||
|
// b,
|
||||||
|
// A: a.public(),
|
||||||
|
// s_b,
|
||||||
|
// xmr_swap_amount,
|
||||||
|
// btc_swap_amount,
|
||||||
|
// tx_lock,
|
||||||
|
// S: S_b,
|
||||||
|
// S_a_bitcoin: swap::bitcoin::PublicKey::from(S_b_bitcoin),
|
||||||
|
// alice_redeem_address:
|
||||||
|
// bob_bitcoin_wallet.new_address().await.unwrap(), v: v_b,
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// let alice = alice.publish_xmr_lock(&alice_monero_wallet).await.unwrap();
|
||||||
|
//
|
||||||
|
// // also publishes lock btc
|
||||||
|
// let bob = bob
|
||||||
|
// .watch_for_lock_xmr(
|
||||||
|
// &bob_monero_wallet,
|
||||||
|
// &bob_bitcoin_wallet,
|
||||||
|
// alice.transfer_proof.clone(),
|
||||||
|
// btc_redeem_address,
|
||||||
|
// )
|
||||||
|
// .await
|
||||||
|
// .unwrap();
|
||||||
|
//
|
||||||
|
// let alice = alice
|
||||||
|
// .watch_for_btc_lock(&alice_bitcoin_wallet)
|
||||||
|
// .await
|
||||||
|
// .unwrap();
|
||||||
|
//
|
||||||
|
// let _ = alice
|
||||||
|
// .publish_btc_redeem(&alice_bitcoin_wallet, encsig)
|
||||||
|
// .await
|
||||||
|
// .unwrap();
|
||||||
|
//
|
||||||
|
// let swap_id = Uuid::new_v4();
|
||||||
|
// bob.redeem_xmr_when_btc_redeem_seen(&bob_bitcoin_wallet,
|
||||||
|
// &bob_monero_wallet, swap_id) .await
|
||||||
|
// .unwrap();
|
||||||
|
// }
|
||||||
|
Loading…
Reference in New Issue
Block a user