mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2024-10-01 01:45:40 -04:00
Merge #119
119: Remember the block-height before XMR lock for generated monero wallet r=da-kami a=da-kami The first approach https://github.com/comit-network/xmr-btc-swap/pull/121 was using `get_transfer_by_txid` that allows extrancting the exact tx-lock 1st confirmation block height. But that introduced an additional error scenario, and I actually ran into that error scenario (`transaction not found`) once I ran it on `stagenet`. Might be that `get_transfer_by_txid` requires running the node in a specific way (like `txindex` on bitcoin). I am not sure at this stage and don't want to invest more time. Long story short: I opted for just recording the height before watching for XMR locked. This means that we record a height right after sending the Bitcoin lock tx. (Because we start watching for XMR lock right after that.) Bob's new wallet unnecessarily scans an additional 7+ blocks (assuming inclusion in the next Bitcoin block and one confirmation for Monero lock) every time which is a matter of milliseconds. Not worth optimising this further at this stage. This solution is more resilient as well, because it does not add another error scenario. Co-authored-by: Daniel Karzel <daniel@comit.network>
This commit is contained in:
commit
2790dec6dc
@ -186,7 +186,7 @@ impl Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get wallet block height, this might be behind monerod height.
|
/// Get wallet block height, this might be behind monerod height.
|
||||||
pub(crate) async fn block_height(&self) -> Result<BlockHeight> {
|
pub async fn block_height(&self) -> Result<BlockHeight> {
|
||||||
let request = Request::new("get_height", "");
|
let request = Request::new("get_height", "");
|
||||||
|
|
||||||
let response = self
|
let response = self
|
||||||
@ -238,9 +238,16 @@ impl Client {
|
|||||||
address: &str,
|
address: &str,
|
||||||
spend_key: &str,
|
spend_key: &str,
|
||||||
view_key: &str,
|
view_key: &str,
|
||||||
|
restore_height: Option<u32>,
|
||||||
) -> Result<GenerateFromKeys> {
|
) -> Result<GenerateFromKeys> {
|
||||||
|
let restore_height = if let Some(restore_height) = restore_height {
|
||||||
|
restore_height
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
let params = GenerateFromKeysParams {
|
let params = GenerateFromKeysParams {
|
||||||
restore_height: 0,
|
restore_height,
|
||||||
filename: view_key.into(),
|
filename: view_key.into(),
|
||||||
address: address.into(),
|
address: address.into(),
|
||||||
spendkey: spend_key.into(),
|
spendkey: spend_key.into(),
|
||||||
|
@ -210,6 +210,7 @@ pub trait CreateWalletForOutput {
|
|||||||
&self,
|
&self,
|
||||||
private_spend_key: PrivateKey,
|
private_spend_key: PrivateKey,
|
||||||
private_view_key: PrivateViewKey,
|
private_view_key: PrivateViewKey,
|
||||||
|
restore_height: Option<u32>,
|
||||||
) -> anyhow::Result<()>;
|
) -> anyhow::Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,6 +68,7 @@ impl CreateWalletForOutput for Wallet {
|
|||||||
&self,
|
&self,
|
||||||
private_spend_key: PrivateKey,
|
private_spend_key: PrivateKey,
|
||||||
private_view_key: PrivateViewKey,
|
private_view_key: PrivateViewKey,
|
||||||
|
restore_height: Option<u32>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let public_spend_key = PublicKey::from_private_key(&private_spend_key);
|
let public_spend_key = PublicKey::from_private_key(&private_spend_key);
|
||||||
let public_view_key = PublicKey::from_private_key(&private_view_key.into());
|
let public_view_key = PublicKey::from_private_key(&private_view_key.into());
|
||||||
@ -80,6 +81,7 @@ impl CreateWalletForOutput for Wallet {
|
|||||||
&address.to_string(),
|
&address.to_string(),
|
||||||
&private_spend_key.to_string(),
|
&private_spend_key.to_string(),
|
||||||
&PrivateKey::from(private_view_key).to_string(),
|
&PrivateKey::from(private_view_key).to_string(),
|
||||||
|
restore_height,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
@ -538,10 +538,11 @@ impl State5 {
|
|||||||
|
|
||||||
let s = s_b.scalar + self.s_a.into_ed25519();
|
let s = s_b.scalar + self.s_a.into_ed25519();
|
||||||
|
|
||||||
|
// TODO: Optimized rescan height should be passed for refund as well.
|
||||||
// NOTE: This actually generates and opens a new wallet, closing the currently
|
// NOTE: This actually generates and opens a new wallet, closing the currently
|
||||||
// open one.
|
// open one.
|
||||||
monero_wallet
|
monero_wallet
|
||||||
.create_and_load_wallet_for_output(monero::PrivateKey::from_scalar(s), self.v)
|
.create_and_load_wallet_for_output(monero::PrivateKey::from_scalar(s), self.v, None)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -405,7 +405,7 @@ pub async fn run_until(
|
|||||||
let view_key = state3.v;
|
let view_key = state3.v;
|
||||||
|
|
||||||
monero_wallet
|
monero_wallet
|
||||||
.create_and_load_wallet_for_output(spend_key, view_key)
|
.create_and_load_wallet_for_output(spend_key, view_key, None)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let state = AliceState::XmrRefunded;
|
let state = AliceState::XmrRefunded;
|
||||||
|
@ -304,7 +304,12 @@ pub struct State3 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl State3 {
|
impl State3 {
|
||||||
pub async fn watch_for_lock_xmr<W>(self, xmr_wallet: &W, msg: alice::Message2) -> Result<State4>
|
pub async fn watch_for_lock_xmr<W>(
|
||||||
|
self,
|
||||||
|
xmr_wallet: &W,
|
||||||
|
msg: alice::Message2,
|
||||||
|
monero_wallet_restore_blockheight: u32,
|
||||||
|
) -> Result<State4>
|
||||||
where
|
where
|
||||||
W: monero::WatchForTransfer,
|
W: monero::WatchForTransfer,
|
||||||
{
|
{
|
||||||
@ -340,6 +345,7 @@ impl State3 {
|
|||||||
tx_lock: self.tx_lock,
|
tx_lock: self.tx_lock,
|
||||||
tx_cancel_sig_a: self.tx_cancel_sig_a,
|
tx_cancel_sig_a: self.tx_cancel_sig_a,
|
||||||
tx_refund_encsig: self.tx_refund_encsig,
|
tx_refund_encsig: self.tx_refund_encsig,
|
||||||
|
monero_wallet_restore_blockheight,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -373,6 +379,7 @@ impl State3 {
|
|||||||
tx_lock: self.tx_lock.clone(),
|
tx_lock: self.tx_lock.clone(),
|
||||||
tx_cancel_sig_a: self.tx_cancel_sig_a.clone(),
|
tx_cancel_sig_a: self.tx_cancel_sig_a.clone(),
|
||||||
tx_refund_encsig: self.tx_refund_encsig.clone(),
|
tx_refund_encsig: self.tx_refund_encsig.clone(),
|
||||||
|
monero_wallet_restore_blockheight: 0u32,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -413,6 +420,7 @@ pub struct State4 {
|
|||||||
pub tx_lock: bitcoin::TxLock,
|
pub tx_lock: bitcoin::TxLock,
|
||||||
pub tx_cancel_sig_a: Signature,
|
pub tx_cancel_sig_a: Signature,
|
||||||
pub tx_refund_encsig: EncryptedSignature,
|
pub tx_refund_encsig: EncryptedSignature,
|
||||||
|
pub monero_wallet_restore_blockheight: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl State4 {
|
impl State4 {
|
||||||
@ -509,6 +517,7 @@ impl State4 {
|
|||||||
tx_lock: self.tx_lock.clone(),
|
tx_lock: self.tx_lock.clone(),
|
||||||
tx_refund_encsig: self.tx_refund_encsig.clone(),
|
tx_refund_encsig: self.tx_refund_encsig.clone(),
|
||||||
tx_cancel_sig: self.tx_cancel_sig_a.clone(),
|
tx_cancel_sig: self.tx_cancel_sig_a.clone(),
|
||||||
|
monero_wallet_restore_blockheight: self.monero_wallet_restore_blockheight,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -606,6 +615,7 @@ pub struct State5 {
|
|||||||
pub tx_lock: bitcoin::TxLock,
|
pub tx_lock: bitcoin::TxLock,
|
||||||
tx_refund_encsig: EncryptedSignature,
|
tx_refund_encsig: EncryptedSignature,
|
||||||
tx_cancel_sig: Signature,
|
tx_cancel_sig: Signature,
|
||||||
|
pub monero_wallet_restore_blockheight: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl State5 {
|
impl State5 {
|
||||||
@ -622,7 +632,11 @@ impl State5 {
|
|||||||
// NOTE: This actually generates and opens a new wallet, closing the currently
|
// NOTE: This actually generates and opens a new wallet, closing the currently
|
||||||
// open one.
|
// open one.
|
||||||
monero_wallet
|
monero_wallet
|
||||||
.create_and_load_wallet_for_output(s, self.v)
|
.create_and_load_wallet_for_output(
|
||||||
|
s,
|
||||||
|
self.v,
|
||||||
|
Some(self.monero_wallet_restore_blockheight),
|
||||||
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -142,11 +142,19 @@ where
|
|||||||
let cancel_timelock_expires =
|
let cancel_timelock_expires =
|
||||||
state3.wait_for_cancel_timelock_to_expire(bitcoin_wallet.as_ref());
|
state3.wait_for_cancel_timelock_to_expire(bitcoin_wallet.as_ref());
|
||||||
|
|
||||||
|
// Record the current monero wallet block height so we don't have to scan from
|
||||||
|
// block 0 once we create the redeem wallet.
|
||||||
|
// TODO: This can be optimized further by extracting the block height when
|
||||||
|
// tx-lock was included. However, scanning a few more blocks won't do any harm
|
||||||
|
// and is simpler.
|
||||||
|
let monero_wallet_restore_blockheight =
|
||||||
|
monero_wallet.inner.block_height().await?;
|
||||||
|
|
||||||
select! {
|
select! {
|
||||||
msg2 = msg2_watcher => {
|
msg2 = msg2_watcher => {
|
||||||
|
|
||||||
let xmr_lock_watcher = state3.clone()
|
let xmr_lock_watcher = state3.clone()
|
||||||
.watch_for_lock_xmr(monero_wallet.as_ref(), msg2?);
|
.watch_for_lock_xmr(monero_wallet.as_ref(), msg2?, monero_wallet_restore_blockheight.height);
|
||||||
let cancel_timelock_expires = state3.wait_for_cancel_timelock_to_expire(bitcoin_wallet.as_ref());
|
let cancel_timelock_expires = state3.wait_for_cancel_timelock_to_expire(bitcoin_wallet.as_ref());
|
||||||
|
|
||||||
select! {
|
select! {
|
||||||
|
Loading…
Reference in New Issue
Block a user