mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2025-01-12 16:09:29 -05:00
Add steps from EncSignLearned
This commit is contained in:
parent
8976a03b3d
commit
8e31a3af6a
@ -3,7 +3,7 @@
|
|||||||
use self::{amounts::*, message0::*, message1::*, message2::*, message3::*};
|
use self::{amounts::*, message0::*, message1::*, message2::*, message3::*};
|
||||||
use crate::{
|
use crate::{
|
||||||
bitcoin,
|
bitcoin,
|
||||||
bitcoin::TX_LOCK_MINE_TIMEOUT,
|
bitcoin::{EncryptedSignature, TX_LOCK_MINE_TIMEOUT},
|
||||||
monero,
|
monero,
|
||||||
network::{
|
network::{
|
||||||
peer_tracker::{self, PeerTracker},
|
peer_tracker::{self, PeerTracker},
|
||||||
@ -19,6 +19,7 @@ use anyhow::{anyhow, bail, Context, Result};
|
|||||||
use async_recursion::async_recursion;
|
use async_recursion::async_recursion;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use backoff::{backoff::Constant as ConstantBackoff, future::FutureOperation as _};
|
use backoff::{backoff::Constant as ConstantBackoff, future::FutureOperation as _};
|
||||||
|
use ecdsa_fun::{adaptor::Adaptor, nonce::Deterministic};
|
||||||
use genawaiter::GeneratorState;
|
use genawaiter::GeneratorState;
|
||||||
use libp2p::{
|
use libp2p::{
|
||||||
core::{identity::Keypair, Multiaddr},
|
core::{identity::Keypair, Multiaddr},
|
||||||
@ -26,6 +27,7 @@ use libp2p::{
|
|||||||
NetworkBehaviour, PeerId,
|
NetworkBehaviour, PeerId,
|
||||||
};
|
};
|
||||||
use rand::{rngs::OsRng, CryptoRng, RngCore};
|
use rand::{rngs::OsRng, CryptoRng, RngCore};
|
||||||
|
use sha2::Sha256;
|
||||||
use std::{sync::Arc, time::Duration};
|
use std::{sync::Arc, time::Duration};
|
||||||
use tokio::{sync::Mutex, time::timeout};
|
use tokio::{sync::Mutex, time::timeout};
|
||||||
use tracing::{debug, info, warn};
|
use tracing::{debug, info, warn};
|
||||||
@ -61,10 +63,16 @@ pub enum AliceState {
|
|||||||
amounts: SwapAmounts,
|
amounts: SwapAmounts,
|
||||||
state3: State3,
|
state3: State3,
|
||||||
},
|
},
|
||||||
XmrLocked,
|
XmrLocked {
|
||||||
|
state3: State3,
|
||||||
|
},
|
||||||
|
EncSignLearned {
|
||||||
|
state3: State3,
|
||||||
|
encrypted_signature: EncryptedSignature,
|
||||||
|
},
|
||||||
BtcRedeemed,
|
BtcRedeemed,
|
||||||
XmrRefunded,
|
XmrRefunded,
|
||||||
Cancelled,
|
WaitingToCancel,
|
||||||
Punished,
|
Punished,
|
||||||
SafelyAborted,
|
SafelyAborted,
|
||||||
}
|
}
|
||||||
@ -239,11 +247,11 @@ where
|
|||||||
// primitive to execute the protocol 2. the more general/business
|
// primitive to execute the protocol 2. the more general/business
|
||||||
// state that contains the crypto + other business data such as network
|
// state that contains the crypto + other business data such as network
|
||||||
// communication, amounts to verify, swap id, etc.
|
// communication, amounts to verify, swap id, etc.
|
||||||
db.insert_latest_state(swap_id, state::Alice::XmrLocked(state3).into())
|
db.insert_latest_state(swap_id, state::Alice::XmrLocked(state3.clone()).into())
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
simple_swap(
|
simple_swap(
|
||||||
AliceState::XmrLocked,
|
AliceState::XmrLocked { state3 },
|
||||||
rng,
|
rng,
|
||||||
swarm,
|
swarm,
|
||||||
db,
|
db,
|
||||||
@ -252,35 +260,121 @@ where
|
|||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
AliceState::XmrLocked => {
|
AliceState::XmrLocked { state3 } => {
|
||||||
// Alice has locked Xmr
|
let encsig = timeout(
|
||||||
// Alice waits until Bob sends her key to redeem BTC
|
// TODO(Franck): This is now inefficient as time has been spent since btc was
|
||||||
// Todo: Poll the swarm here until msg from Bob arrives or t1
|
// locked
|
||||||
if unimplemented!("key_received") {
|
Duration::from_secs(TX_LOCK_MINE_TIMEOUT),
|
||||||
// Alice redeems BTC
|
async {
|
||||||
simple_swap(
|
match swarm.next().await {
|
||||||
AliceState::BtcRedeemed,
|
OutEvent::Message3(msg) => Ok(msg.tx_redeem_encsig),
|
||||||
rng,
|
other => Err(anyhow!(
|
||||||
swarm,
|
"Expected Bob's Bitcoin redeem encsig, got: {:?}",
|
||||||
db,
|
other
|
||||||
bitcoin_wallet,
|
)),
|
||||||
monero_wallet,
|
}
|
||||||
)
|
},
|
||||||
.await
|
)
|
||||||
} else {
|
.await
|
||||||
// submit TxCancel
|
.context("Timed out, Bob did not send redeem encsign in time");
|
||||||
simple_swap(
|
|
||||||
AliceState::Cancelled,
|
match encsig {
|
||||||
rng,
|
Err(_timeout_error) => {
|
||||||
swarm,
|
// TODO(Franck): Insert in DB
|
||||||
db,
|
|
||||||
bitcoin_wallet,
|
simple_swap(
|
||||||
monero_wallet,
|
AliceState::WaitingToCancel,
|
||||||
)
|
rng,
|
||||||
.await
|
swarm,
|
||||||
|
db,
|
||||||
|
bitcoin_wallet,
|
||||||
|
monero_wallet,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
Ok(Err(_unexpected_msg_error)) => {
|
||||||
|
// TODO(Franck): Insert in DB
|
||||||
|
|
||||||
|
simple_swap(
|
||||||
|
AliceState::WaitingToCancel,
|
||||||
|
rng,
|
||||||
|
swarm,
|
||||||
|
db,
|
||||||
|
bitcoin_wallet,
|
||||||
|
monero_wallet,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
Ok(Ok(encrypted_signature)) => {
|
||||||
|
// TODO(Franck): Insert in DB
|
||||||
|
|
||||||
|
simple_swap(
|
||||||
|
AliceState::EncSignLearned {
|
||||||
|
state3,
|
||||||
|
encrypted_signature,
|
||||||
|
},
|
||||||
|
rng,
|
||||||
|
swarm,
|
||||||
|
db,
|
||||||
|
bitcoin_wallet,
|
||||||
|
monero_wallet,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AliceState::Cancelled => {
|
AliceState::EncSignLearned {
|
||||||
|
state3,
|
||||||
|
encrypted_signature,
|
||||||
|
} => {
|
||||||
|
let (signed_tx_redeem, tx_redeem_txid) = {
|
||||||
|
let adaptor = Adaptor::<Sha256, Deterministic<Sha256>>::default();
|
||||||
|
|
||||||
|
let tx_redeem = bitcoin::TxRedeem::new(&state3.tx_lock, &state3.redeem_address);
|
||||||
|
|
||||||
|
bitcoin::verify_encsig(
|
||||||
|
state3.B.clone(),
|
||||||
|
state3.s_a.into_secp256k1().into(),
|
||||||
|
&tx_redeem.digest(),
|
||||||
|
&encrypted_signature,
|
||||||
|
)
|
||||||
|
.context("Invalid encrypted signature received")?;
|
||||||
|
|
||||||
|
let sig_a = state3.a.sign(tx_redeem.digest());
|
||||||
|
let sig_b = adaptor
|
||||||
|
.decrypt_signature(&state3.s_a.into_secp256k1(), encrypted_signature.clone());
|
||||||
|
|
||||||
|
let tx = tx_redeem
|
||||||
|
.add_signatures(
|
||||||
|
&state3.tx_lock,
|
||||||
|
(state3.a.public(), sig_a),
|
||||||
|
(state3.B.clone(), sig_b),
|
||||||
|
)
|
||||||
|
.expect("sig_{a,b} to be valid signatures for tx_redeem");
|
||||||
|
let txid = tx.txid();
|
||||||
|
|
||||||
|
(tx, txid)
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO(Franck): Insert in db
|
||||||
|
|
||||||
|
let _ = bitcoin_wallet
|
||||||
|
.broadcast_signed_transaction(signed_tx_redeem)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
// TODO(Franck) Wait for confirmations
|
||||||
|
|
||||||
|
simple_swap(
|
||||||
|
AliceState::BtcRedeemed,
|
||||||
|
rng,
|
||||||
|
swarm,
|
||||||
|
db,
|
||||||
|
bitcoin_wallet,
|
||||||
|
monero_wallet,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
AliceState::WaitingToCancel => {
|
||||||
// Wait until t2 or if TxRefund is seen
|
// Wait until t2 or if TxRefund is seen
|
||||||
// If Bob has refunded the Alice should extract Bob's monero secret key and move
|
// If Bob has refunded the Alice should extract Bob's monero secret key and move
|
||||||
// the TxLockXmr output to her wallet.
|
// the TxLockXmr output to her wallet.
|
||||||
@ -330,7 +424,7 @@ pub async fn abort(state: AliceState) -> Result<AliceState> {
|
|||||||
// Alice does not need to do anything to recover
|
// Alice does not need to do anything to recover
|
||||||
abort(AliceState::SafelyAborted).await
|
abort(AliceState::SafelyAborted).await
|
||||||
}
|
}
|
||||||
AliceState::XmrLocked => {
|
AliceState::XmrLocked { state3 } => {
|
||||||
// Alice has locked XMR
|
// Alice has locked XMR
|
||||||
// Alice watches for TxRedeem until t1
|
// Alice watches for TxRedeem until t1
|
||||||
if unimplemented!("TxRedeemSeen") {
|
if unimplemented!("TxRedeemSeen") {
|
||||||
@ -338,12 +432,13 @@ pub async fn abort(state: AliceState) -> Result<AliceState> {
|
|||||||
abort(AliceState::BtcRedeemed).await
|
abort(AliceState::BtcRedeemed).await
|
||||||
} else if unimplemented!("T1Elapsed") {
|
} else if unimplemented!("T1Elapsed") {
|
||||||
// publish TxCancel or see if it has been published
|
// publish TxCancel or see if it has been published
|
||||||
abort(AliceState::Cancelled).await
|
abort(AliceState::WaitingToCancel).await
|
||||||
} else {
|
} else {
|
||||||
Err(unimplemented!())
|
Err(unimplemented!())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AliceState::Cancelled => {
|
AliceState::EncSignLearned { .. } => todo!(),
|
||||||
|
AliceState::WaitingToCancel => {
|
||||||
// Alice has cancelled the swap
|
// Alice has cancelled the swap
|
||||||
// Alice waits watches for t2 or TxRefund
|
// Alice waits watches for t2 or TxRefund
|
||||||
if unimplemented!("TxRefundSeen") {
|
if unimplemented!("TxRefundSeen") {
|
||||||
|
Loading…
Reference in New Issue
Block a user