This commit is contained in:
rishflab 2021-05-21 15:58:41 +10:00
parent 815a752c88
commit 8272e1c247
20 changed files with 775 additions and 318 deletions

33
Cargo.lock generated
View File

@ -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",

View File

@ -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"]

View File

@ -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" }

View File

@ -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)]

View File

@ -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 {

View File

@ -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)
} }

View File

@ -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(())
} }
} }

View File

@ -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(())
}
}

View File

@ -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
} }
} }
} }

View File

@ -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;

View File

@ -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()
} }

View File

@ -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()
} }

View 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;

View File

@ -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,
}
}
} }

View 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,
}
}
}

View File

@ -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()
} }
} }

View File

@ -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>>,

View File

@ -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")
} }

View File

@ -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();
// }