mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2024-10-01 01:45:40 -04:00
Remove Refund timelock and T0/T1/T2
There are no refund timelock, only a cancellation timelock and punish timelock. Refund can be done as soon as the cancellation transaction is published.
This commit is contained in:
parent
405e377f79
commit
f0736d0906
@ -207,20 +207,20 @@ pub async fn publish_cancel_transaction<W>(
|
||||
tx_lock: TxLock,
|
||||
a: bitcoin::SecretKey,
|
||||
B: bitcoin::PublicKey,
|
||||
refund_timelock: u32,
|
||||
cancel_timelock: u32,
|
||||
tx_cancel_sig_bob: bitcoin::Signature,
|
||||
bitcoin_wallet: Arc<W>,
|
||||
) -> Result<bitcoin::TxCancel>
|
||||
where
|
||||
W: GetRawTransaction + TransactionBlockHeight + BlockHeight + BroadcastSignedTransaction,
|
||||
{
|
||||
// First wait for t1 to expire
|
||||
// First wait for cancel timelock to expire
|
||||
let tx_lock_height = bitcoin_wallet
|
||||
.transaction_block_height(tx_lock.txid())
|
||||
.await;
|
||||
poll_until_block_height_is_gte(bitcoin_wallet.as_ref(), tx_lock_height + refund_timelock).await;
|
||||
poll_until_block_height_is_gte(bitcoin_wallet.as_ref(), tx_lock_height + cancel_timelock).await;
|
||||
|
||||
let tx_cancel = bitcoin::TxCancel::new(&tx_lock, refund_timelock, a.public(), B);
|
||||
let tx_cancel = bitcoin::TxCancel::new(&tx_lock, cancel_timelock, a.public(), B);
|
||||
|
||||
// If Bob hasn't yet broadcasted the tx cancel, we do it
|
||||
if bitcoin_wallet
|
||||
@ -306,14 +306,14 @@ pub fn extract_monero_private_key(
|
||||
|
||||
pub fn build_bitcoin_punish_transaction(
|
||||
tx_lock: &TxLock,
|
||||
refund_timelock: u32,
|
||||
cancel_timelock: u32,
|
||||
punish_address: &bitcoin::Address,
|
||||
punish_timelock: u32,
|
||||
tx_punish_sig_bob: bitcoin::Signature,
|
||||
a: bitcoin::SecretKey,
|
||||
B: bitcoin::PublicKey,
|
||||
) -> Result<bitcoin::Transaction> {
|
||||
let tx_cancel = bitcoin::TxCancel::new(&tx_lock, refund_timelock, a.public(), B);
|
||||
let tx_cancel = bitcoin::TxCancel::new(&tx_lock, cancel_timelock, a.public(), B);
|
||||
let tx_punish = bitcoin::TxPunish::new(&tx_cancel, &punish_address, punish_timelock);
|
||||
|
||||
let sig_a = a.sign(tx_punish.digest());
|
||||
|
@ -34,7 +34,7 @@ use xmr_btc::{
|
||||
bitcoin::{TransactionBlockHeight, TxCancel, TxRefund, WatchForRawTransaction},
|
||||
config::Config,
|
||||
monero::CreateWalletForOutput,
|
||||
Epoch,
|
||||
ExpiredTimelocks,
|
||||
};
|
||||
|
||||
trait Rng: RngCore + CryptoRng + Send {}
|
||||
@ -78,7 +78,7 @@ pub enum AliceState {
|
||||
state3: State3,
|
||||
},
|
||||
XmrRefunded,
|
||||
T1Expired {
|
||||
CancelTimelockExpired {
|
||||
state3: State3,
|
||||
},
|
||||
Punished,
|
||||
@ -100,7 +100,7 @@ impl fmt::Display for AliceState {
|
||||
AliceState::SafelyAborted => write!(f, "safely_aborted"),
|
||||
AliceState::BtcPunishable { .. } => write!(f, "btc_punishable"),
|
||||
AliceState::XmrRefunded => write!(f, "xmr_refunded"),
|
||||
AliceState::T1Expired { .. } => write!(f, "t1 is expired"),
|
||||
AliceState::CancelTimelockExpired { .. } => write!(f, "cancel timelock is expired"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -113,7 +113,7 @@ impl From<&AliceState> for state::Alice {
|
||||
AliceState::XmrLocked { state3 } => Alice::XmrLocked(state3.clone()),
|
||||
AliceState::EncSigLearned {
|
||||
state3,
|
||||
encrypted_signature,,
|
||||
encrypted_signature,
|
||||
} => Alice::EncSigLearned {
|
||||
state: state3.clone(),
|
||||
encrypted_signature: encrypted_signature.clone(),
|
||||
@ -123,7 +123,9 @@ impl From<&AliceState> for state::Alice {
|
||||
AliceState::BtcRefunded { .. } => Alice::SwapComplete,
|
||||
AliceState::BtcPunishable { state3, .. } => Alice::BtcPunishable(state3.clone()),
|
||||
AliceState::XmrRefunded => Alice::SwapComplete,
|
||||
AliceState::T1Expired { state3 } => Alice::T1Expired(state3.clone()),
|
||||
AliceState::CancelTimelockExpired { state3 } => {
|
||||
Alice::CancelTimelockExpired(state3.clone())
|
||||
}
|
||||
AliceState::Punished => Alice::SwapComplete,
|
||||
AliceState::SafelyAborted => Alice::SwapComplete,
|
||||
// TODO: Potentially add support to resume swaps that are not Negotiated
|
||||
@ -166,11 +168,13 @@ impl TryFrom<state::Swap> for AliceState {
|
||||
state3: state,
|
||||
encrypted_signature,
|
||||
},
|
||||
Alice::T1Expired(state3) => AliceState::T1Expired { state3 },
|
||||
Alice::CancelTimelockExpired(state3) => {
|
||||
AliceState::CancelTimelockExpired { state3 }
|
||||
}
|
||||
Alice::BtcCancelled(state) => {
|
||||
let tx_cancel = bitcoin::TxCancel::new(
|
||||
&state.tx_lock,
|
||||
state.refund_timelock,
|
||||
state.cancel_timelock,
|
||||
state.a.public(),
|
||||
state.B,
|
||||
);
|
||||
@ -183,7 +187,7 @@ impl TryFrom<state::Swap> for AliceState {
|
||||
Alice::BtcPunishable(state) => {
|
||||
let tx_cancel = bitcoin::TxCancel::new(
|
||||
&state.tx_lock,
|
||||
state.refund_timelock,
|
||||
state.cancel_timelock,
|
||||
state.a.public(),
|
||||
state.B,
|
||||
);
|
||||
@ -386,28 +390,30 @@ pub async fn run_until(
|
||||
.await
|
||||
}
|
||||
AliceState::XmrLocked { state3 } => {
|
||||
// todo: match statement and wait for t1 can probably be expressed more cleanly
|
||||
let state = match state3.current_epoch(bitcoin_wallet.as_ref()).await? {
|
||||
Epoch::T0 => {
|
||||
// todo: match statement and wait for cancel timelock to expire can probably be
|
||||
// expressed more cleanly
|
||||
let state = match state3.expired_timelocks(bitcoin_wallet.as_ref()).await? {
|
||||
ExpiredTimelocks::None => {
|
||||
let wait_for_enc_sig = wait_for_bitcoin_encrypted_signature(
|
||||
&mut event_loop_handle,
|
||||
config.monero_max_finality_time,
|
||||
);
|
||||
let state3_clone = state3.clone();
|
||||
let t1_timeout = state3_clone.wait_for_t1(bitcoin_wallet.as_ref());
|
||||
let cancel_timelock_expires = state3_clone
|
||||
.wait_for_cancel_timelock_to_expire(bitcoin_wallet.as_ref());
|
||||
|
||||
pin_mut!(wait_for_enc_sig);
|
||||
pin_mut!(t1_timeout);
|
||||
pin_mut!(cancel_timelock_expires);
|
||||
|
||||
match select(t1_timeout, wait_for_enc_sig).await {
|
||||
Either::Left(_) => AliceState::T1Expired { state3 },
|
||||
match select(cancel_timelock_expires, wait_for_enc_sig).await {
|
||||
Either::Left(_) => AliceState::CancelTimelockExpired { state3 },
|
||||
Either::Right((enc_sig, _)) => AliceState::EncSigLearned {
|
||||
state3,
|
||||
encrypted_signature: enc_sig?,
|
||||
},
|
||||
}
|
||||
}
|
||||
_ => AliceState::T1Expired { state3 },
|
||||
_ => AliceState::CancelTimelockExpired { state3 },
|
||||
};
|
||||
|
||||
let db_state = (&state).into();
|
||||
@ -430,8 +436,8 @@ pub async fn run_until(
|
||||
encrypted_signature,
|
||||
} => {
|
||||
// TODO: Evaluate if it is correct for Alice to Redeem no matter what.
|
||||
// If T1 expired she should potentially not try redeem. (The implementation
|
||||
// gives her an advantage.)
|
||||
// If cancel timelock expired she should potentially not try redeem. (The
|
||||
// implementation gives her an advantage.)
|
||||
|
||||
let signed_tx_redeem = match build_bitcoin_redeem_transaction(
|
||||
encrypted_signature,
|
||||
@ -443,9 +449,11 @@ pub async fn run_until(
|
||||
) {
|
||||
Ok(tx) => tx,
|
||||
Err(_) => {
|
||||
state3.wait_for_t1(bitcoin_wallet.as_ref()).await?;
|
||||
state3
|
||||
.wait_for_cancel_timelock_to_expire(bitcoin_wallet.as_ref())
|
||||
.await?;
|
||||
|
||||
let state = AliceState::T1Expired { state3 };
|
||||
let state = AliceState::CancelTimelockExpired { state3 };
|
||||
let db_state = (&state).into();
|
||||
db.insert_latest_state(swap_id, Swap::Alice(db_state))
|
||||
.await?;
|
||||
@ -489,12 +497,12 @@ pub async fn run_until(
|
||||
)
|
||||
.await
|
||||
}
|
||||
AliceState::T1Expired { state3 } => {
|
||||
AliceState::CancelTimelockExpired { state3 } => {
|
||||
let tx_cancel = publish_cancel_transaction(
|
||||
state3.tx_lock.clone(),
|
||||
state3.a.clone(),
|
||||
state3.B,
|
||||
state3.refund_timelock,
|
||||
state3.cancel_timelock,
|
||||
state3.tx_cancel_sig_bob.clone(),
|
||||
bitcoin_wallet.clone(),
|
||||
)
|
||||
@ -591,7 +599,7 @@ pub async fn run_until(
|
||||
AliceState::BtcPunishable { tx_refund, state3 } => {
|
||||
let signed_tx_punish = build_bitcoin_punish_transaction(
|
||||
&state3.tx_lock,
|
||||
state3.refund_timelock,
|
||||
state3.cancel_timelock,
|
||||
&state3.punish_address,
|
||||
state3.punish_timelock,
|
||||
state3.tx_punish_sig_bob.clone(),
|
||||
|
@ -84,7 +84,7 @@ async fn main() -> Result<()> {
|
||||
v_a,
|
||||
amounts.btc,
|
||||
amounts.xmr,
|
||||
config.bitcoin_refund_timelock,
|
||||
config.bitcoin_cancel_timelock,
|
||||
config.bitcoin_punish_timelock,
|
||||
redeem_address,
|
||||
punish_address,
|
||||
@ -132,7 +132,7 @@ async fn main() -> Result<()> {
|
||||
&mut OsRng,
|
||||
send_bitcoin,
|
||||
receive_monero,
|
||||
config.bitcoin_refund_timelock,
|
||||
config.bitcoin_cancel_timelock,
|
||||
config.bitcoin_punish_timelock,
|
||||
refund_address,
|
||||
);
|
||||
|
@ -14,7 +14,7 @@ use tracing::info;
|
||||
use uuid::Uuid;
|
||||
use xmr_btc::{
|
||||
bob::{self, State2},
|
||||
Epoch,
|
||||
ExpiredTimelocks,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@ -28,7 +28,7 @@ pub enum BobState {
|
||||
XmrLocked(bob::State4),
|
||||
EncSigSent(bob::State4),
|
||||
BtcRedeemed(bob::State5),
|
||||
T1Expired(bob::State4),
|
||||
CancelTimelockExpired(bob::State4),
|
||||
Cancelled(bob::State4),
|
||||
BtcRefunded(bob::State4),
|
||||
XmrRedeemed,
|
||||
@ -45,7 +45,7 @@ impl fmt::Display for BobState {
|
||||
BobState::XmrLocked(..) => write!(f, "xmr_locked"),
|
||||
BobState::EncSigSent(..) => write!(f, "encsig_sent"),
|
||||
BobState::BtcRedeemed(..) => write!(f, "btc_redeemed"),
|
||||
BobState::T1Expired(..) => write!(f, "t1_expired"),
|
||||
BobState::CancelTimelockExpired(..) => write!(f, "cancel_timelock_expired"),
|
||||
BobState::Cancelled(..) => write!(f, "cancelled"),
|
||||
BobState::BtcRefunded(..) => write!(f, "btc_refunded"),
|
||||
BobState::XmrRedeemed => write!(f, "xmr_redeemed"),
|
||||
@ -67,7 +67,7 @@ impl From<BobState> for state::Bob {
|
||||
BobState::XmrLocked(state4) => Bob::XmrLocked { state4 },
|
||||
BobState::EncSigSent(state4) => Bob::EncSigSent { state4 },
|
||||
BobState::BtcRedeemed(state5) => Bob::BtcRedeemed(state5),
|
||||
BobState::T1Expired(state4) => Bob::T1Expired(state4),
|
||||
BobState::CancelTimelockExpired(state4) => Bob::CancelTimelockExpired(state4),
|
||||
BobState::Cancelled(state4) => Bob::BtcCancelled(state4),
|
||||
BobState::BtcRefunded(_)
|
||||
| BobState::XmrRedeemed
|
||||
@ -88,7 +88,7 @@ impl TryFrom<state::Swap> for BobState {
|
||||
Bob::XmrLocked { state4 } => BobState::XmrLocked(state4),
|
||||
Bob::EncSigSent { state4 } => BobState::EncSigSent(state4),
|
||||
Bob::BtcRedeemed(state5) => BobState::BtcRedeemed(state5),
|
||||
Bob::T1Expired(state4) => BobState::T1Expired(state4),
|
||||
Bob::CancelTimelockExpired(state4) => BobState::CancelTimelockExpired(state4),
|
||||
Bob::BtcCancelled(state4) => BobState::Cancelled(state4),
|
||||
Bob::SwapComplete => BobState::SafelyAborted,
|
||||
};
|
||||
@ -221,41 +221,43 @@ where
|
||||
.await
|
||||
}
|
||||
// Bob has locked Btc
|
||||
// Watch for Alice to Lock Xmr or for t1 to elapse
|
||||
// Watch for Alice to Lock Xmr or for cancel timelock to elapse
|
||||
BobState::BtcLocked(state3) => {
|
||||
let state = if let Epoch::T0 = state3.current_epoch(bitcoin_wallet.as_ref()).await?
|
||||
let state = if let ExpiredTimelocks::None =
|
||||
state3.current_epoch(bitcoin_wallet.as_ref()).await?
|
||||
{
|
||||
event_loop_handle.dial().await?;
|
||||
|
||||
let msg2_watcher = event_loop_handle.recv_message2();
|
||||
let t1_timeout = state3.wait_for_t1(bitcoin_wallet.as_ref());
|
||||
let cancel_timelock_expires =
|
||||
state3.wait_for_cancel_timelock_to_expire(bitcoin_wallet.as_ref());
|
||||
|
||||
select! {
|
||||
msg2 = msg2_watcher => {
|
||||
|
||||
let xmr_lock_watcher = state3.clone()
|
||||
.watch_for_lock_xmr(monero_wallet.as_ref(), msg2?);
|
||||
let t1_timeout = state3.wait_for_t1(bitcoin_wallet.as_ref());
|
||||
let cancel_timelock_expires = state3.wait_for_cancel_timelock_to_expire(bitcoin_wallet.as_ref());
|
||||
|
||||
select! {
|
||||
state4 = xmr_lock_watcher => {
|
||||
BobState::XmrLocked(state4?)
|
||||
},
|
||||
_ = t1_timeout => {
|
||||
let state4 = state3.t1_expired();
|
||||
BobState::T1Expired(state4)
|
||||
_ = cancel_timelock_expires => {
|
||||
let state4 = state3.state4();
|
||||
BobState::CancelTimelockExpired(state4)
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
_ = t1_timeout => {
|
||||
let state4 = state3.t1_expired();
|
||||
BobState::T1Expired(state4)
|
||||
_ = cancel_timelock_expires => {
|
||||
let state4 = state3.state4();
|
||||
BobState::CancelTimelockExpired(state4)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let state4 = state3.t1_expired();
|
||||
BobState::T1Expired(state4)
|
||||
let state4 = state3.state4();
|
||||
BobState::CancelTimelockExpired(state4)
|
||||
};
|
||||
let db_state = state.clone().into();
|
||||
db.insert_latest_state(swap_id, state::Swap::Bob(db_state))
|
||||
@ -273,7 +275,9 @@ where
|
||||
.await
|
||||
}
|
||||
BobState::XmrLocked(state) => {
|
||||
let state = if let Epoch::T0 = state.current_epoch(bitcoin_wallet.as_ref()).await? {
|
||||
let state = if let ExpiredTimelocks::None =
|
||||
state.expired_timelock(bitcoin_wallet.as_ref()).await?
|
||||
{
|
||||
event_loop_handle.dial().await?;
|
||||
// Alice has locked Xmr
|
||||
// Bob sends Alice his key
|
||||
@ -283,18 +287,19 @@ where
|
||||
// TODO(Franck): Refund if message cannot be sent.
|
||||
let enc_sig_sent_watcher = event_loop_handle.send_message3(tx_redeem_encsig);
|
||||
let bitcoin_wallet = bitcoin_wallet.clone();
|
||||
let t1_timeout = state4_clone.wait_for_t1(bitcoin_wallet.as_ref());
|
||||
let cancel_timelock_expires =
|
||||
state4_clone.wait_for_cancel_timelock_to_expire(bitcoin_wallet.as_ref());
|
||||
|
||||
select! {
|
||||
_ = enc_sig_sent_watcher => {
|
||||
BobState::EncSigSent(state)
|
||||
},
|
||||
_ = t1_timeout => {
|
||||
BobState::T1Expired(state)
|
||||
_ = cancel_timelock_expires => {
|
||||
BobState::CancelTimelockExpired(state)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
BobState::T1Expired(state)
|
||||
BobState::CancelTimelockExpired(state)
|
||||
};
|
||||
let db_state = state.clone().into();
|
||||
db.insert_latest_state(swap_id, state::Swap::Bob(db_state))
|
||||
@ -312,21 +317,24 @@ where
|
||||
.await
|
||||
}
|
||||
BobState::EncSigSent(state) => {
|
||||
let state = if let Epoch::T0 = state.current_epoch(bitcoin_wallet.as_ref()).await? {
|
||||
let state = if let ExpiredTimelocks::None =
|
||||
state.expired_timelock(bitcoin_wallet.as_ref()).await?
|
||||
{
|
||||
let state_clone = state.clone();
|
||||
let redeem_watcher = state_clone.watch_for_redeem_btc(bitcoin_wallet.as_ref());
|
||||
let t1_timeout = state_clone.wait_for_t1(bitcoin_wallet.as_ref());
|
||||
let cancel_timelock_expires =
|
||||
state_clone.wait_for_cancel_timelock_to_expire(bitcoin_wallet.as_ref());
|
||||
|
||||
select! {
|
||||
state5 = redeem_watcher => {
|
||||
BobState::BtcRedeemed(state5?)
|
||||
},
|
||||
_ = t1_timeout => {
|
||||
BobState::T1Expired(state)
|
||||
_ = cancel_timelock_expires => {
|
||||
BobState::CancelTimelockExpired(state)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
BobState::T1Expired(state)
|
||||
BobState::CancelTimelockExpired(state)
|
||||
};
|
||||
|
||||
let db_state = state.clone().into();
|
||||
@ -364,7 +372,7 @@ where
|
||||
)
|
||||
.await
|
||||
}
|
||||
BobState::T1Expired(state4) => {
|
||||
BobState::CancelTimelockExpired(state4) => {
|
||||
if state4
|
||||
.check_for_tx_cancel(bitcoin_wallet.as_ref())
|
||||
.await
|
||||
@ -390,15 +398,16 @@ where
|
||||
.await
|
||||
}
|
||||
BobState::Cancelled(state) => {
|
||||
// TODO
|
||||
// Bob has cancelled the swap
|
||||
let state = match state.current_epoch(bitcoin_wallet.as_ref()).await? {
|
||||
Epoch::T0 => panic!("Cancelled before t1??? Something is really wrong"),
|
||||
Epoch::T1 => {
|
||||
let state = match state.expired_timelock(bitcoin_wallet.as_ref()).await? {
|
||||
ExpiredTimelocks::None => {
|
||||
bail!("Internal error: canceled state reached before cancel timelock was expired");
|
||||
}
|
||||
ExpiredTimelocks::Cancel => {
|
||||
state.refund_btc(bitcoin_wallet.as_ref()).await?;
|
||||
BobState::BtcRefunded(state)
|
||||
}
|
||||
Epoch::T2 => BobState::Punished,
|
||||
ExpiredTimelocks::Punish => BobState::Punished,
|
||||
};
|
||||
|
||||
let db_state = state.clone().into();
|
||||
|
@ -24,7 +24,7 @@ pub enum Alice {
|
||||
state: alice::State3,
|
||||
encrypted_signature: EncryptedSignature,
|
||||
},
|
||||
T1Expired(alice::State3),
|
||||
CancelTimelockExpired(alice::State3),
|
||||
BtcCancelled(alice::State3),
|
||||
BtcPunishable(alice::State3),
|
||||
BtcRefunded {
|
||||
@ -43,7 +43,7 @@ pub enum Bob {
|
||||
XmrLocked { state4: bob::State4 },
|
||||
EncSigSent { state4: bob::State4 },
|
||||
BtcRedeemed(bob::State5),
|
||||
T1Expired(bob::State4),
|
||||
CancelTimelockExpired(bob::State4),
|
||||
BtcCancelled(bob::State4),
|
||||
SwapComplete,
|
||||
}
|
||||
@ -76,7 +76,7 @@ impl Display for Alice {
|
||||
Alice::BtcLocked(_) => f.write_str("Bitcoin locked"),
|
||||
Alice::XmrLocked(_) => f.write_str("Monero locked"),
|
||||
Alice::BtcRedeemable { .. } => f.write_str("Bitcoin redeemable"),
|
||||
Alice::T1Expired(_) => f.write_str("Timelock T1 expired"),
|
||||
Alice::CancelTimelockExpired(_) => f.write_str("Cancel timelock is expired"),
|
||||
Alice::BtcCancelled(_) => f.write_str("Bitcoin cancel transaction published"),
|
||||
Alice::BtcPunishable(_) => f.write_str("Bitcoin punishable"),
|
||||
Alice::BtcRefunded { .. } => f.write_str("Monero refundable"),
|
||||
@ -92,7 +92,7 @@ impl Display for Bob {
|
||||
Bob::Negotiated { .. } => f.write_str("Handshake complete"),
|
||||
Bob::BtcLocked { .. } => f.write_str("Bitcoin locked"),
|
||||
Bob::XmrLocked { .. } => f.write_str("Monero locked"),
|
||||
Bob::T1Expired(_) => f.write_str("Timelock T1 expired"),
|
||||
Bob::CancelTimelockExpired(_) => f.write_str("Cancel timelock is expired"),
|
||||
Bob::BtcCancelled(_) => f.write_str("Bitcoin refundable"),
|
||||
Bob::BtcRedeemed(_) => f.write_str("Monero redeemable"),
|
||||
Bob::SwapComplete => f.write_str("Swap complete"),
|
||||
|
@ -88,7 +88,7 @@ pub async fn init_alice_state(
|
||||
v_a,
|
||||
amounts.btc,
|
||||
amounts.xmr,
|
||||
config.bitcoin_refund_timelock,
|
||||
config.bitcoin_cancel_timelock,
|
||||
config.bitcoin_punish_timelock,
|
||||
redeem_address,
|
||||
punish_address,
|
||||
@ -170,7 +170,7 @@ pub async fn init_bob_state(
|
||||
&mut OsRng,
|
||||
btc_to_swap,
|
||||
xmr_to_swap,
|
||||
config.bitcoin_refund_timelock,
|
||||
config.bitcoin_cancel_timelock,
|
||||
config.bitcoin_punish_timelock,
|
||||
refund_address,
|
||||
);
|
||||
|
@ -4,7 +4,7 @@ use crate::{
|
||||
bob, monero,
|
||||
monero::{CreateWalletForOutput, Transfer},
|
||||
transport::{ReceiveMessage, SendMessage},
|
||||
Epoch,
|
||||
ExpiredTimelocks,
|
||||
};
|
||||
use anyhow::{anyhow, Result};
|
||||
use async_trait::async_trait;
|
||||
@ -28,7 +28,9 @@ use std::{
|
||||
use tokio::{sync::Mutex, time::timeout};
|
||||
use tracing::{error, info};
|
||||
pub mod message;
|
||||
use crate::bitcoin::{current_epoch, wait_for_t1, BlockHeight, TransactionBlockHeight};
|
||||
use crate::bitcoin::{
|
||||
current_epoch, wait_for_cancel_timelock_to_expire, BlockHeight, TransactionBlockHeight,
|
||||
};
|
||||
pub use message::{Message, Message0, Message1, Message2};
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -74,7 +76,7 @@ pub fn action_generator<N, B>(
|
||||
S_b_bitcoin,
|
||||
v,
|
||||
xmr,
|
||||
refund_timelock,
|
||||
cancel_timelock,
|
||||
punish_timelock,
|
||||
refund_address,
|
||||
redeem_address,
|
||||
@ -138,7 +140,7 @@ where
|
||||
.await;
|
||||
let poll_until_btc_has_expired = poll_until_block_height_is_gte(
|
||||
bitcoin_client.as_ref(),
|
||||
tx_lock_height + refund_timelock,
|
||||
tx_lock_height + cancel_timelock,
|
||||
)
|
||||
.shared();
|
||||
pin_mut!(poll_until_btc_has_expired);
|
||||
@ -221,7 +223,7 @@ where
|
||||
|
||||
if let Err(SwapFailed::AfterXmrLock(Reason::BtcExpired)) = swap_result {
|
||||
let refund_result: Result<(), RefundFailed> = async {
|
||||
let tx_cancel = bitcoin::TxCancel::new(&tx_lock, refund_timelock, a.public(), B);
|
||||
let tx_cancel = bitcoin::TxCancel::new(&tx_lock, cancel_timelock, a.public(), B);
|
||||
let signed_tx_cancel = {
|
||||
let sig_a = a.sign(tx_cancel.digest());
|
||||
let sig_b = tx_cancel_sig_bob.clone();
|
||||
@ -292,7 +294,7 @@ where
|
||||
// with the refund on Monero. Doing so may be too verbose with the current,
|
||||
// linear approach. A different design may be required
|
||||
if let Err(RefundFailed::BtcPunishable) = refund_result {
|
||||
let tx_cancel = bitcoin::TxCancel::new(&tx_lock, refund_timelock, a.public(), B);
|
||||
let tx_cancel = bitcoin::TxCancel::new(&tx_lock, cancel_timelock, a.public(), B);
|
||||
let tx_punish =
|
||||
bitcoin::TxPunish::new(&tx_cancel, &punish_address, punish_timelock);
|
||||
let tx_punish_txid = tx_punish.txid();
|
||||
@ -410,7 +412,7 @@ impl State {
|
||||
rng: &mut R,
|
||||
btc: bitcoin::Amount,
|
||||
xmr: monero::Amount,
|
||||
refund_timelock: u32,
|
||||
cancel_timelock: u32,
|
||||
punish_timelock: u32,
|
||||
redeem_address: bitcoin::Address,
|
||||
punish_address: bitcoin::Address,
|
||||
@ -425,7 +427,7 @@ impl State {
|
||||
v_a,
|
||||
btc,
|
||||
xmr,
|
||||
refund_timelock,
|
||||
cancel_timelock,
|
||||
punish_timelock,
|
||||
redeem_address,
|
||||
punish_address,
|
||||
@ -441,7 +443,7 @@ pub struct State0 {
|
||||
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
|
||||
pub btc: bitcoin::Amount,
|
||||
pub xmr: monero::Amount,
|
||||
pub refund_timelock: u32,
|
||||
pub cancel_timelock: u32,
|
||||
pub punish_timelock: u32,
|
||||
pub redeem_address: bitcoin::Address,
|
||||
pub punish_address: bitcoin::Address,
|
||||
@ -455,7 +457,7 @@ impl State0 {
|
||||
v_a: monero::PrivateViewKey,
|
||||
btc: bitcoin::Amount,
|
||||
xmr: monero::Amount,
|
||||
refund_timelock: u32,
|
||||
cancel_timelock: u32,
|
||||
punish_timelock: u32,
|
||||
redeem_address: bitcoin::Address,
|
||||
punish_address: bitcoin::Address,
|
||||
@ -468,7 +470,7 @@ impl State0 {
|
||||
punish_address,
|
||||
btc,
|
||||
xmr,
|
||||
refund_timelock,
|
||||
cancel_timelock,
|
||||
punish_timelock,
|
||||
}
|
||||
}
|
||||
@ -510,7 +512,7 @@ impl State0 {
|
||||
v,
|
||||
btc: self.btc,
|
||||
xmr: self.xmr,
|
||||
refund_timelock: self.refund_timelock,
|
||||
cancel_timelock: self.cancel_timelock,
|
||||
punish_timelock: self.punish_timelock,
|
||||
refund_address: msg.refund_address,
|
||||
redeem_address: self.redeem_address,
|
||||
@ -530,7 +532,7 @@ pub struct State1 {
|
||||
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
|
||||
btc: bitcoin::Amount,
|
||||
xmr: monero::Amount,
|
||||
refund_timelock: u32,
|
||||
cancel_timelock: u32,
|
||||
punish_timelock: u32,
|
||||
refund_address: bitcoin::Address,
|
||||
redeem_address: bitcoin::Address,
|
||||
@ -548,7 +550,7 @@ impl State1 {
|
||||
v: self.v,
|
||||
btc: self.btc,
|
||||
xmr: self.xmr,
|
||||
refund_timelock: self.refund_timelock,
|
||||
cancel_timelock: self.cancel_timelock,
|
||||
punish_timelock: self.punish_timelock,
|
||||
refund_address: self.refund_address,
|
||||
redeem_address: self.redeem_address,
|
||||
@ -569,7 +571,7 @@ pub struct State2 {
|
||||
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
|
||||
btc: bitcoin::Amount,
|
||||
xmr: monero::Amount,
|
||||
refund_timelock: u32,
|
||||
cancel_timelock: u32,
|
||||
punish_timelock: u32,
|
||||
refund_address: bitcoin::Address,
|
||||
redeem_address: bitcoin::Address,
|
||||
@ -580,7 +582,7 @@ pub struct State2 {
|
||||
impl State2 {
|
||||
pub fn next_message(&self) -> Message1 {
|
||||
let tx_cancel =
|
||||
bitcoin::TxCancel::new(&self.tx_lock, self.refund_timelock, self.a.public(), self.B);
|
||||
bitcoin::TxCancel::new(&self.tx_lock, self.cancel_timelock, self.a.public(), self.B);
|
||||
|
||||
let tx_refund = bitcoin::TxRefund::new(&tx_cancel, &self.refund_address);
|
||||
// Alice encsigns the refund transaction(bitcoin) digest with Bob's monero
|
||||
@ -599,7 +601,7 @@ impl State2 {
|
||||
|
||||
pub fn receive(self, msg: bob::Message2) -> Result<State3> {
|
||||
let tx_cancel =
|
||||
bitcoin::TxCancel::new(&self.tx_lock, self.refund_timelock, self.a.public(), self.B);
|
||||
bitcoin::TxCancel::new(&self.tx_lock, self.cancel_timelock, self.a.public(), self.B);
|
||||
bitcoin::verify_sig(&self.B, &tx_cancel.digest(), &msg.tx_cancel_sig)?;
|
||||
let tx_punish =
|
||||
bitcoin::TxPunish::new(&tx_cancel, &self.punish_address, self.punish_timelock);
|
||||
@ -615,7 +617,7 @@ impl State2 {
|
||||
// TODO(Franck): Review if these amounts are actually needed
|
||||
btc: self.btc,
|
||||
xmr: self.xmr,
|
||||
refund_timelock: self.refund_timelock,
|
||||
cancel_timelock: self.cancel_timelock,
|
||||
punish_timelock: self.punish_timelock,
|
||||
refund_address: self.refund_address,
|
||||
redeem_address: self.redeem_address,
|
||||
@ -638,7 +640,7 @@ pub struct State3 {
|
||||
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
|
||||
pub btc: bitcoin::Amount,
|
||||
pub xmr: monero::Amount,
|
||||
pub refund_timelock: u32,
|
||||
pub cancel_timelock: u32,
|
||||
pub punish_timelock: u32,
|
||||
pub refund_address: bitcoin::Address,
|
||||
pub redeem_address: bitcoin::Address,
|
||||
@ -669,7 +671,7 @@ impl State3 {
|
||||
v: self.v,
|
||||
btc: self.btc,
|
||||
xmr: self.xmr,
|
||||
refund_timelock: self.refund_timelock,
|
||||
cancel_timelock: self.cancel_timelock,
|
||||
punish_timelock: self.punish_timelock,
|
||||
refund_address: self.refund_address,
|
||||
redeem_address: self.redeem_address,
|
||||
@ -680,20 +682,25 @@ impl State3 {
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn wait_for_t1<W>(&self, bitcoin_wallet: &W) -> Result<()>
|
||||
pub async fn wait_for_cancel_timelock_to_expire<W>(&self, bitcoin_wallet: &W) -> Result<()>
|
||||
where
|
||||
W: WatchForRawTransaction + TransactionBlockHeight + BlockHeight,
|
||||
{
|
||||
wait_for_t1(bitcoin_wallet, self.refund_timelock, self.tx_lock.txid()).await
|
||||
wait_for_cancel_timelock_to_expire(
|
||||
bitcoin_wallet,
|
||||
self.cancel_timelock,
|
||||
self.tx_lock.txid(),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn current_epoch<W>(&self, bitcoin_wallet: &W) -> Result<Epoch>
|
||||
pub async fn expired_timelocks<W>(&self, bitcoin_wallet: &W) -> Result<ExpiredTimelocks>
|
||||
where
|
||||
W: WatchForRawTransaction + TransactionBlockHeight + BlockHeight,
|
||||
{
|
||||
current_epoch(
|
||||
bitcoin_wallet,
|
||||
self.refund_timelock,
|
||||
self.cancel_timelock,
|
||||
self.punish_timelock,
|
||||
self.tx_lock.txid(),
|
||||
)
|
||||
@ -712,7 +719,7 @@ pub struct State4 {
|
||||
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
|
||||
btc: bitcoin::Amount,
|
||||
xmr: monero::Amount,
|
||||
refund_timelock: u32,
|
||||
cancel_timelock: u32,
|
||||
punish_timelock: u32,
|
||||
refund_address: bitcoin::Address,
|
||||
redeem_address: bitcoin::Address,
|
||||
@ -745,7 +752,7 @@ impl State4 {
|
||||
v: self.v,
|
||||
btc: self.btc,
|
||||
xmr: self.xmr,
|
||||
refund_timelock: self.refund_timelock,
|
||||
cancel_timelock: self.cancel_timelock,
|
||||
punish_timelock: self.punish_timelock,
|
||||
refund_address: self.refund_address,
|
||||
redeem_address: self.redeem_address,
|
||||
@ -763,7 +770,7 @@ impl State4 {
|
||||
bitcoin_wallet: &W,
|
||||
) -> Result<()> {
|
||||
let tx_cancel =
|
||||
bitcoin::TxCancel::new(&self.tx_lock, self.refund_timelock, self.a.public(), self.B);
|
||||
bitcoin::TxCancel::new(&self.tx_lock, self.cancel_timelock, self.a.public(), self.B);
|
||||
let tx_punish =
|
||||
bitcoin::TxPunish::new(&tx_cancel, &self.punish_address, self.punish_timelock);
|
||||
|
||||
@ -809,7 +816,7 @@ pub struct State5 {
|
||||
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
|
||||
btc: bitcoin::Amount,
|
||||
xmr: monero::Amount,
|
||||
refund_timelock: u32,
|
||||
cancel_timelock: u32,
|
||||
punish_timelock: u32,
|
||||
refund_address: bitcoin::Address,
|
||||
redeem_address: bitcoin::Address,
|
||||
@ -840,7 +847,7 @@ impl State5 {
|
||||
v: self.v,
|
||||
btc: self.btc,
|
||||
xmr: self.xmr,
|
||||
refund_timelock: self.refund_timelock,
|
||||
cancel_timelock: self.cancel_timelock,
|
||||
punish_timelock: self.punish_timelock,
|
||||
refund_address: self.refund_address,
|
||||
redeem_address: self.redeem_address,
|
||||
@ -859,7 +866,7 @@ impl State5 {
|
||||
M: CreateWalletForOutput,
|
||||
{
|
||||
let tx_cancel =
|
||||
bitcoin::TxCancel::new(&self.tx_lock, self.refund_timelock, self.a.public(), self.B);
|
||||
bitcoin::TxCancel::new(&self.tx_lock, self.cancel_timelock, self.a.public(), self.B);
|
||||
|
||||
let tx_refund = bitcoin::TxRefund::new(&tx_cancel, &self.refund_address);
|
||||
|
||||
@ -898,7 +905,7 @@ pub struct State6 {
|
||||
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
|
||||
btc: bitcoin::Amount,
|
||||
xmr: monero::Amount,
|
||||
refund_timelock: u32,
|
||||
cancel_timelock: u32,
|
||||
punish_timelock: u32,
|
||||
refund_address: bitcoin::Address,
|
||||
redeem_address: bitcoin::Address,
|
||||
|
@ -11,7 +11,7 @@ use serde::{Deserialize, Serialize};
|
||||
use sha2::Sha256;
|
||||
use std::str::FromStr;
|
||||
|
||||
use crate::Epoch;
|
||||
use crate::ExpiredTimelocks;
|
||||
pub use bitcoin::{util::psbt::PartiallySignedTransaction, *};
|
||||
pub use ecdsa_fun::{adaptor::EncryptedSignature, fun::Scalar, Signature};
|
||||
pub use transactions::{TxCancel, TxLock, TxPunish, TxRedeem, TxRefund};
|
||||
@ -247,28 +247,31 @@ where
|
||||
|
||||
pub async fn current_epoch<W>(
|
||||
bitcoin_wallet: &W,
|
||||
refund_timelock: u32,
|
||||
cancel_timelock: u32,
|
||||
punish_timelock: u32,
|
||||
lock_tx_id: ::bitcoin::Txid,
|
||||
) -> anyhow::Result<Epoch>
|
||||
) -> anyhow::Result<ExpiredTimelocks>
|
||||
where
|
||||
W: WatchForRawTransaction + TransactionBlockHeight + BlockHeight,
|
||||
{
|
||||
let current_block_height = bitcoin_wallet.block_height().await;
|
||||
let t0 = bitcoin_wallet.transaction_block_height(lock_tx_id).await;
|
||||
let t1 = t0 + refund_timelock;
|
||||
let t2 = t1 + punish_timelock;
|
||||
let lock_tx_height = bitcoin_wallet.transaction_block_height(lock_tx_id).await;
|
||||
let cancel_timelock_height = lock_tx_height + cancel_timelock;
|
||||
let punish_timelock_height = cancel_timelock_height + punish_timelock;
|
||||
|
||||
match (current_block_height < t1, current_block_height < t2) {
|
||||
(true, _) => Ok(Epoch::T0),
|
||||
(false, true) => Ok(Epoch::T1),
|
||||
(false, false) => Ok(Epoch::T2),
|
||||
match (
|
||||
current_block_height < cancel_timelock_height,
|
||||
current_block_height < punish_timelock_height,
|
||||
) {
|
||||
(true, _) => Ok(ExpiredTimelocks::None),
|
||||
(false, true) => Ok(ExpiredTimelocks::Cancel),
|
||||
(false, false) => Ok(ExpiredTimelocks::Punish),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn wait_for_t1<W>(
|
||||
pub async fn wait_for_cancel_timelock_to_expire<W>(
|
||||
bitcoin_wallet: &W,
|
||||
refund_timelock: u32,
|
||||
cancel_timelock: u32,
|
||||
lock_tx_id: ::bitcoin::Txid,
|
||||
) -> Result<()>
|
||||
where
|
||||
@ -276,8 +279,6 @@ where
|
||||
{
|
||||
let tx_lock_height = bitcoin_wallet.transaction_block_height(lock_tx_id).await;
|
||||
|
||||
let t1_timeout =
|
||||
poll_until_block_height_is_gte(bitcoin_wallet, tx_lock_height + refund_timelock);
|
||||
t1_timeout.await;
|
||||
poll_until_block_height_is_gte(bitcoin_wallet, tx_lock_height + cancel_timelock).await;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ use crate::{
|
||||
monero,
|
||||
serde::monero_private_key,
|
||||
transport::{ReceiveMessage, SendMessage},
|
||||
Epoch,
|
||||
ExpiredTimelocks,
|
||||
};
|
||||
use anyhow::{anyhow, Result};
|
||||
use async_trait::async_trait;
|
||||
@ -35,7 +35,8 @@ use tracing::error;
|
||||
pub mod message;
|
||||
use crate::{
|
||||
bitcoin::{
|
||||
current_epoch, wait_for_t1, BlockHeight, GetRawTransaction, Network, TransactionBlockHeight,
|
||||
current_epoch, wait_for_cancel_timelock_to_expire, BlockHeight, GetRawTransaction, Network,
|
||||
TransactionBlockHeight,
|
||||
},
|
||||
monero::{CreateWalletForOutput, WatchForTransfer},
|
||||
};
|
||||
@ -81,7 +82,7 @@ pub fn action_generator<N, M, B>(
|
||||
S_a_bitcoin,
|
||||
v,
|
||||
xmr,
|
||||
refund_timelock,
|
||||
cancel_timelock,
|
||||
redeem_address,
|
||||
refund_address,
|
||||
tx_lock,
|
||||
@ -142,7 +143,7 @@ where
|
||||
.await;
|
||||
let poll_until_btc_has_expired = poll_until_block_height_is_gte(
|
||||
bitcoin_client.as_ref(),
|
||||
tx_lock_height + refund_timelock,
|
||||
tx_lock_height + cancel_timelock,
|
||||
)
|
||||
.shared();
|
||||
pin_mut!(poll_until_btc_has_expired);
|
||||
@ -224,7 +225,7 @@ where
|
||||
}
|
||||
|
||||
if let Err(SwapFailed::AfterBtcLock(_)) = swap_result {
|
||||
let tx_cancel = bitcoin::TxCancel::new(&tx_lock, refund_timelock, A, b.public());
|
||||
let tx_cancel = bitcoin::TxCancel::new(&tx_lock, cancel_timelock, A, b.public());
|
||||
let tx_cancel_txid = tx_cancel.txid();
|
||||
let signed_tx_cancel = {
|
||||
let sig_a = tx_cancel_sig_a.clone();
|
||||
@ -356,7 +357,7 @@ pub struct State0 {
|
||||
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
|
||||
btc: bitcoin::Amount,
|
||||
xmr: monero::Amount,
|
||||
refund_timelock: u32,
|
||||
cancel_timelock: u32,
|
||||
punish_timelock: u32,
|
||||
refund_address: bitcoin::Address,
|
||||
}
|
||||
@ -366,7 +367,7 @@ impl State0 {
|
||||
rng: &mut R,
|
||||
btc: bitcoin::Amount,
|
||||
xmr: monero::Amount,
|
||||
refund_timelock: u32,
|
||||
cancel_timelock: u32,
|
||||
punish_timelock: u32,
|
||||
refund_address: bitcoin::Address,
|
||||
) -> Self {
|
||||
@ -381,7 +382,7 @@ impl State0 {
|
||||
v_b,
|
||||
btc,
|
||||
xmr,
|
||||
refund_timelock,
|
||||
cancel_timelock,
|
||||
punish_timelock,
|
||||
refund_address,
|
||||
}
|
||||
@ -426,7 +427,7 @@ impl State0 {
|
||||
v,
|
||||
btc: self.btc,
|
||||
xmr: self.xmr,
|
||||
refund_timelock: self.refund_timelock,
|
||||
cancel_timelock: self.cancel_timelock,
|
||||
punish_timelock: self.punish_timelock,
|
||||
refund_address: self.refund_address,
|
||||
redeem_address: msg.redeem_address,
|
||||
@ -447,7 +448,7 @@ pub struct State1 {
|
||||
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
|
||||
btc: bitcoin::Amount,
|
||||
xmr: monero::Amount,
|
||||
refund_timelock: u32,
|
||||
cancel_timelock: u32,
|
||||
punish_timelock: u32,
|
||||
refund_address: bitcoin::Address,
|
||||
redeem_address: bitcoin::Address,
|
||||
@ -463,7 +464,7 @@ impl State1 {
|
||||
}
|
||||
|
||||
pub fn receive(self, msg: alice::Message1) -> Result<State2> {
|
||||
let tx_cancel = TxCancel::new(&self.tx_lock, self.refund_timelock, self.A, self.b.public());
|
||||
let tx_cancel = TxCancel::new(&self.tx_lock, self.cancel_timelock, self.A, self.b.public());
|
||||
let tx_refund = bitcoin::TxRefund::new(&tx_cancel, &self.refund_address);
|
||||
|
||||
bitcoin::verify_sig(&self.A, &tx_cancel.digest(), &msg.tx_cancel_sig)?;
|
||||
@ -483,7 +484,7 @@ impl State1 {
|
||||
v: self.v,
|
||||
btc: self.btc,
|
||||
xmr: self.xmr,
|
||||
refund_timelock: self.refund_timelock,
|
||||
cancel_timelock: self.cancel_timelock,
|
||||
punish_timelock: self.punish_timelock,
|
||||
refund_address: self.refund_address,
|
||||
redeem_address: self.redeem_address,
|
||||
@ -506,7 +507,7 @@ pub struct State2 {
|
||||
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
|
||||
btc: bitcoin::Amount,
|
||||
pub xmr: monero::Amount,
|
||||
pub refund_timelock: u32,
|
||||
pub cancel_timelock: u32,
|
||||
pub punish_timelock: u32,
|
||||
pub refund_address: bitcoin::Address,
|
||||
pub redeem_address: bitcoin::Address,
|
||||
@ -518,7 +519,7 @@ pub struct State2 {
|
||||
|
||||
impl State2 {
|
||||
pub fn next_message(&self) -> Message2 {
|
||||
let tx_cancel = TxCancel::new(&self.tx_lock, self.refund_timelock, self.A, self.b.public());
|
||||
let tx_cancel = TxCancel::new(&self.tx_lock, self.cancel_timelock, self.A, self.b.public());
|
||||
let tx_cancel_sig = self.b.sign(tx_cancel.digest());
|
||||
let tx_punish =
|
||||
bitcoin::TxPunish::new(&tx_cancel, &self.punish_address, self.punish_timelock);
|
||||
@ -550,7 +551,7 @@ impl State2 {
|
||||
v: self.v,
|
||||
btc: self.btc,
|
||||
xmr: self.xmr,
|
||||
refund_timelock: self.refund_timelock,
|
||||
cancel_timelock: self.cancel_timelock,
|
||||
punish_timelock: self.punish_timelock,
|
||||
refund_address: self.refund_address,
|
||||
redeem_address: self.redeem_address,
|
||||
@ -573,7 +574,7 @@ pub struct State3 {
|
||||
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
|
||||
btc: bitcoin::Amount,
|
||||
xmr: monero::Amount,
|
||||
pub refund_timelock: u32,
|
||||
pub cancel_timelock: u32,
|
||||
punish_timelock: u32,
|
||||
pub refund_address: bitcoin::Address,
|
||||
redeem_address: bitcoin::Address,
|
||||
@ -612,7 +613,7 @@ impl State3 {
|
||||
v: self.v,
|
||||
btc: self.btc,
|
||||
xmr: self.xmr,
|
||||
refund_timelock: self.refund_timelock,
|
||||
cancel_timelock: self.cancel_timelock,
|
||||
punish_timelock: self.punish_timelock,
|
||||
refund_address: self.refund_address,
|
||||
redeem_address: self.redeem_address,
|
||||
@ -623,14 +624,19 @@ impl State3 {
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn wait_for_t1<W>(&self, bitcoin_wallet: &W) -> Result<()>
|
||||
pub async fn wait_for_cancel_timelock_to_expire<W>(&self, bitcoin_wallet: &W) -> Result<()>
|
||||
where
|
||||
W: WatchForRawTransaction + TransactionBlockHeight + BlockHeight,
|
||||
{
|
||||
wait_for_t1(bitcoin_wallet, self.refund_timelock, self.tx_lock.txid()).await
|
||||
wait_for_cancel_timelock_to_expire(
|
||||
bitcoin_wallet,
|
||||
self.cancel_timelock,
|
||||
self.tx_lock.txid(),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub fn t1_expired(&self) -> State4 {
|
||||
pub fn state4(&self) -> State4 {
|
||||
State4 {
|
||||
A: self.A,
|
||||
b: self.b.clone(),
|
||||
@ -640,7 +646,7 @@ impl State3 {
|
||||
v: self.v,
|
||||
btc: self.btc,
|
||||
xmr: self.xmr,
|
||||
refund_timelock: self.refund_timelock,
|
||||
cancel_timelock: self.cancel_timelock,
|
||||
punish_timelock: self.punish_timelock,
|
||||
refund_address: self.refund_address.clone(),
|
||||
redeem_address: self.redeem_address.clone(),
|
||||
@ -655,13 +661,13 @@ impl State3 {
|
||||
self.tx_lock.txid()
|
||||
}
|
||||
|
||||
pub async fn current_epoch<W>(&self, bitcoin_wallet: &W) -> Result<Epoch>
|
||||
pub async fn current_epoch<W>(&self, bitcoin_wallet: &W) -> Result<ExpiredTimelocks>
|
||||
where
|
||||
W: WatchForRawTransaction + TransactionBlockHeight + BlockHeight,
|
||||
{
|
||||
current_epoch(
|
||||
bitcoin_wallet,
|
||||
self.refund_timelock,
|
||||
self.cancel_timelock,
|
||||
self.punish_timelock,
|
||||
self.tx_lock.txid(),
|
||||
)
|
||||
@ -680,7 +686,7 @@ pub struct State4 {
|
||||
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
|
||||
btc: bitcoin::Amount,
|
||||
xmr: monero::Amount,
|
||||
pub refund_timelock: u32,
|
||||
pub cancel_timelock: u32,
|
||||
punish_timelock: u32,
|
||||
pub refund_address: bitcoin::Address,
|
||||
pub redeem_address: bitcoin::Address,
|
||||
@ -708,7 +714,7 @@ impl State4 {
|
||||
W: GetRawTransaction,
|
||||
{
|
||||
let tx_cancel =
|
||||
bitcoin::TxCancel::new(&self.tx_lock, self.refund_timelock, self.A, self.b.public());
|
||||
bitcoin::TxCancel::new(&self.tx_lock, self.cancel_timelock, self.A, self.b.public());
|
||||
|
||||
let sig_a = self.tx_cancel_sig_a.clone();
|
||||
let sig_b = self.b.sign(tx_cancel.digest());
|
||||
@ -731,7 +737,7 @@ impl State4 {
|
||||
W: BroadcastSignedTransaction,
|
||||
{
|
||||
let tx_cancel =
|
||||
bitcoin::TxCancel::new(&self.tx_lock, self.refund_timelock, self.A, self.b.public());
|
||||
bitcoin::TxCancel::new(&self.tx_lock, self.cancel_timelock, self.A, self.b.public());
|
||||
|
||||
let sig_a = self.tx_cancel_sig_a.clone();
|
||||
let sig_b = self.b.sign(tx_cancel.digest());
|
||||
@ -776,7 +782,7 @@ impl State4 {
|
||||
v: self.v,
|
||||
btc: self.btc,
|
||||
xmr: self.xmr,
|
||||
refund_timelock: self.refund_timelock,
|
||||
cancel_timelock: self.cancel_timelock,
|
||||
punish_timelock: self.punish_timelock,
|
||||
refund_address: self.refund_address.clone(),
|
||||
redeem_address: self.redeem_address.clone(),
|
||||
@ -787,20 +793,25 @@ impl State4 {
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn wait_for_t1<W>(&self, bitcoin_wallet: &W) -> Result<()>
|
||||
pub async fn wait_for_cancel_timelock_to_expire<W>(&self, bitcoin_wallet: &W) -> Result<()>
|
||||
where
|
||||
W: WatchForRawTransaction + TransactionBlockHeight + BlockHeight,
|
||||
{
|
||||
wait_for_t1(bitcoin_wallet, self.refund_timelock, self.tx_lock.txid()).await
|
||||
wait_for_cancel_timelock_to_expire(
|
||||
bitcoin_wallet,
|
||||
self.cancel_timelock,
|
||||
self.tx_lock.txid(),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn current_epoch<W>(&self, bitcoin_wallet: &W) -> Result<Epoch>
|
||||
pub async fn expired_timelock<W>(&self, bitcoin_wallet: &W) -> Result<ExpiredTimelocks>
|
||||
where
|
||||
W: WatchForRawTransaction + TransactionBlockHeight + BlockHeight,
|
||||
{
|
||||
current_epoch(
|
||||
bitcoin_wallet,
|
||||
self.refund_timelock,
|
||||
self.cancel_timelock,
|
||||
self.punish_timelock,
|
||||
self.tx_lock.txid(),
|
||||
)
|
||||
@ -812,7 +823,7 @@ impl State4 {
|
||||
bitcoin_wallet: &W,
|
||||
) -> Result<()> {
|
||||
let tx_cancel =
|
||||
bitcoin::TxCancel::new(&self.tx_lock, self.refund_timelock, self.A, self.b.public());
|
||||
bitcoin::TxCancel::new(&self.tx_lock, self.cancel_timelock, self.A, self.b.public());
|
||||
let tx_refund = bitcoin::TxRefund::new(&tx_cancel, &self.refund_address);
|
||||
|
||||
{
|
||||
@ -868,7 +879,7 @@ pub struct State5 {
|
||||
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
|
||||
btc: bitcoin::Amount,
|
||||
xmr: monero::Amount,
|
||||
refund_timelock: u32,
|
||||
cancel_timelock: u32,
|
||||
punish_timelock: u32,
|
||||
refund_address: bitcoin::Address,
|
||||
pub redeem_address: bitcoin::Address,
|
||||
|
@ -7,7 +7,7 @@ pub struct Config {
|
||||
pub bitcoin_finality_confirmations: u32,
|
||||
pub bitcoin_avg_block_time: Duration,
|
||||
pub monero_max_finality_time: Duration,
|
||||
pub bitcoin_refund_timelock: u32,
|
||||
pub bitcoin_cancel_timelock: u32,
|
||||
pub bitcoin_punish_timelock: u32,
|
||||
pub bitcoin_network: ::bitcoin::Network,
|
||||
}
|
||||
@ -22,7 +22,7 @@ impl Config {
|
||||
// blockchain is slow
|
||||
monero_max_finality_time: (*mainnet::MONERO_AVG_BLOCK_TIME).mul_f64(1.5)
|
||||
* mainnet::MONERO_FINALITY_CONFIRMATIONS,
|
||||
bitcoin_refund_timelock: mainnet::BITCOIN_REFUND_TIMELOCK,
|
||||
bitcoin_cancel_timelock: mainnet::BITCOIN_CANCEL_TIMELOCK,
|
||||
bitcoin_punish_timelock: mainnet::BITCOIN_PUNISH_TIMELOCK,
|
||||
bitcoin_network: ::bitcoin::Network::Bitcoin,
|
||||
}
|
||||
@ -37,7 +37,7 @@ impl Config {
|
||||
// blockchain is slow
|
||||
monero_max_finality_time: (*regtest::MONERO_AVG_BLOCK_TIME).mul_f64(1.5)
|
||||
* regtest::MONERO_FINALITY_CONFIRMATIONS,
|
||||
bitcoin_refund_timelock: regtest::BITCOIN_REFUND_TIMELOCK,
|
||||
bitcoin_cancel_timelock: regtest::BITCOIN_CANCEL_TIMELOCK,
|
||||
bitcoin_punish_timelock: regtest::BITCOIN_PUNISH_TIMELOCK,
|
||||
bitcoin_network: ::bitcoin::Network::Regtest,
|
||||
}
|
||||
@ -59,7 +59,7 @@ mod mainnet {
|
||||
pub static MONERO_AVG_BLOCK_TIME: Lazy<Duration> = Lazy::new(|| Duration::from_secs(2 * 60));
|
||||
|
||||
// Set to 12 hours, arbitrary value to be reviewed properly
|
||||
pub static BITCOIN_REFUND_TIMELOCK: u32 = 72;
|
||||
pub static BITCOIN_CANCEL_TIMELOCK: u32 = 72;
|
||||
pub static BITCOIN_PUNISH_TIMELOCK: u32 = 72;
|
||||
}
|
||||
|
||||
@ -77,7 +77,7 @@ mod regtest {
|
||||
|
||||
pub static MONERO_AVG_BLOCK_TIME: Lazy<Duration> = Lazy::new(|| Duration::from_secs(60));
|
||||
|
||||
pub static BITCOIN_REFUND_TIMELOCK: u32 = 50;
|
||||
pub static BITCOIN_CANCEL_TIMELOCK: u32 = 50;
|
||||
|
||||
pub static BITCOIN_PUNISH_TIMELOCK: u32 = 50;
|
||||
}
|
||||
|
@ -15,10 +15,10 @@
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum Epoch {
|
||||
T0,
|
||||
T1,
|
||||
T2,
|
||||
pub enum ExpiredTimelocks {
|
||||
None,
|
||||
Cancel,
|
||||
Punish,
|
||||
}
|
||||
|
||||
#[macro_use]
|
||||
|
Loading…
Reference in New Issue
Block a user