mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2025-12-19 18:42:26 -05:00
Greatly reduce load onto the Electrum backend
We achieve our optimizations in three ways: 1. Batching calls instead of making them individually. To get access to the batch calls, we replace all our calls to the HTTP interface with RPC calls. 2. Never directly make network calls based on function calls on the wallet. Instead, inquiring about the status of a script always just returns information based on local data. With every call, we check when we last refreshed the local data and do so if the data is considered to be too old. This interval is configurable. 3. Use electrum's notification feature to get updated with the latest blockheight. Co-authored-by: Thomas Eizinger <thomas@eizinger.io> Co-authored-by: Rishab Sharma <rishflab@hotmail.com>
This commit is contained in:
parent
e17cbadccb
commit
e5c0158597
16 changed files with 628 additions and 378 deletions
|
|
@ -1,6 +1,6 @@
|
|||
use crate::bitcoin::{
|
||||
self, current_epoch, wait_for_cancel_timelock_to_expire, CancelTimelock, ExpiredTimelocks,
|
||||
PunishTimelock, Transaction, TxCancel, Txid,
|
||||
self, current_epoch, CancelTimelock, ExpiredTimelocks, PunishTimelock, Transaction, TxCancel,
|
||||
TxLock, Txid,
|
||||
};
|
||||
use crate::execution_params::ExecutionParams;
|
||||
use crate::monero;
|
||||
|
|
@ -9,7 +9,7 @@ use crate::monero_ext::ScalarExt;
|
|||
use crate::protocol::alice::{Message1, Message3};
|
||||
use crate::protocol::bob::{EncryptedSignature, Message0, Message2, Message4};
|
||||
use crate::protocol::CROSS_CURVE_PROOF_SYSTEM;
|
||||
use anyhow::{anyhow, bail, Context, Result};
|
||||
use anyhow::{anyhow, bail, Result};
|
||||
use ecdsa_fun::adaptor::{Adaptor, HashTranscript};
|
||||
use ecdsa_fun::nonce::Deterministic;
|
||||
use ecdsa_fun::Signature;
|
||||
|
|
@ -262,31 +262,27 @@ impl State2 {
|
|||
}
|
||||
}
|
||||
|
||||
pub async fn lock_btc(self, bitcoin_wallet: &bitcoin::Wallet) -> Result<State3> {
|
||||
let signed_tx = bitcoin_wallet
|
||||
.sign_and_finalize(self.tx_lock.clone().into())
|
||||
.await
|
||||
.context("Failed to sign Bitcoin lock transaction")?;
|
||||
|
||||
let _ = bitcoin_wallet.broadcast(signed_tx, "lock").await?;
|
||||
|
||||
Ok(State3 {
|
||||
A: self.A,
|
||||
b: self.b,
|
||||
s_b: self.s_b,
|
||||
S_a_monero: self.S_a_monero,
|
||||
S_a_bitcoin: self.S_a_bitcoin,
|
||||
v: self.v,
|
||||
xmr: self.xmr,
|
||||
cancel_timelock: self.cancel_timelock,
|
||||
punish_timelock: self.punish_timelock,
|
||||
refund_address: self.refund_address,
|
||||
redeem_address: self.redeem_address,
|
||||
tx_lock: self.tx_lock,
|
||||
tx_cancel_sig_a: self.tx_cancel_sig_a,
|
||||
tx_refund_encsig: self.tx_refund_encsig,
|
||||
min_monero_confirmations: self.min_monero_confirmations,
|
||||
})
|
||||
pub async fn lock_btc(self) -> Result<(State3, TxLock)> {
|
||||
Ok((
|
||||
State3 {
|
||||
A: self.A,
|
||||
b: self.b,
|
||||
s_b: self.s_b,
|
||||
S_a_monero: self.S_a_monero,
|
||||
S_a_bitcoin: self.S_a_bitcoin,
|
||||
v: self.v,
|
||||
xmr: self.xmr,
|
||||
cancel_timelock: self.cancel_timelock,
|
||||
punish_timelock: self.punish_timelock,
|
||||
refund_address: self.refund_address,
|
||||
redeem_address: self.redeem_address,
|
||||
tx_lock: self.tx_lock.clone(),
|
||||
tx_cancel_sig_a: self.tx_cancel_sig_a,
|
||||
tx_refund_encsig: self.tx_refund_encsig,
|
||||
min_monero_confirmations: self.min_monero_confirmations,
|
||||
},
|
||||
self.tx_lock,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -354,12 +350,14 @@ impl State3 {
|
|||
&self,
|
||||
bitcoin_wallet: &bitcoin::Wallet,
|
||||
) -> Result<()> {
|
||||
wait_for_cancel_timelock_to_expire(
|
||||
bitcoin_wallet,
|
||||
self.cancel_timelock,
|
||||
self.tx_lock.txid(),
|
||||
)
|
||||
.await
|
||||
bitcoin_wallet
|
||||
.watch_until_status(
|
||||
self.tx_lock.txid(),
|
||||
self.tx_lock.script_pubkey(),
|
||||
|status| status.is_confirmed_with(self.cancel_timelock),
|
||||
)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn cancel(&self) -> State4 {
|
||||
|
|
@ -390,13 +388,21 @@ impl State3 {
|
|||
&self,
|
||||
bitcoin_wallet: &bitcoin::Wallet,
|
||||
) -> Result<ExpiredTimelocks> {
|
||||
current_epoch(
|
||||
bitcoin_wallet,
|
||||
let tx_cancel = TxCancel::new(&self.tx_lock, self.cancel_timelock, self.A, self.b.public());
|
||||
|
||||
let tx_lock_status = bitcoin_wallet
|
||||
.status_of_script(&self.tx_lock.script_pubkey(), &self.tx_lock.txid())
|
||||
.await?;
|
||||
let tx_cancel_status = bitcoin_wallet
|
||||
.status_of_script(&tx_cancel.script_pubkey(), &tx_cancel.txid())
|
||||
.await?;
|
||||
|
||||
Ok(current_epoch(
|
||||
self.cancel_timelock,
|
||||
self.punish_timelock,
|
||||
self.tx_lock.txid(),
|
||||
)
|
||||
.await
|
||||
tx_lock_status,
|
||||
tx_cancel_status,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -419,10 +425,9 @@ pub struct State4 {
|
|||
|
||||
impl State4 {
|
||||
pub fn next_message(&self) -> EncryptedSignature {
|
||||
let tx_redeem = bitcoin::TxRedeem::new(&self.tx_lock, &self.redeem_address);
|
||||
let tx_redeem_encsig = self.b.encsign(self.S_a_bitcoin, tx_redeem.digest());
|
||||
|
||||
EncryptedSignature { tx_redeem_encsig }
|
||||
EncryptedSignature {
|
||||
tx_redeem_encsig: self.tx_redeem_encsig(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tx_redeem_encsig(&self) -> bitcoin::EncryptedSignature {
|
||||
|
|
@ -466,10 +471,16 @@ impl State4 {
|
|||
let tx_redeem = bitcoin::TxRedeem::new(&self.tx_lock, &self.redeem_address);
|
||||
let tx_redeem_encsig = self.b.encsign(self.S_a_bitcoin, tx_redeem.digest());
|
||||
|
||||
let tx_redeem_candidate = bitcoin_wallet
|
||||
.watch_for_raw_transaction(tx_redeem.txid())
|
||||
bitcoin_wallet
|
||||
.watch_until_status(
|
||||
tx_redeem.txid(),
|
||||
self.redeem_address.script_pubkey(),
|
||||
|status| status.has_been_seen(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
let tx_redeem_candidate = bitcoin_wallet.get_raw_transaction(tx_redeem.txid()).await?;
|
||||
|
||||
let tx_redeem_sig =
|
||||
tx_redeem.extract_signature_by_key(tx_redeem_candidate, self.b.public())?;
|
||||
let s_a = bitcoin::recover(self.S_a_bitcoin, tx_redeem_sig, tx_redeem_encsig)?;
|
||||
|
|
@ -488,25 +499,36 @@ impl State4 {
|
|||
&self,
|
||||
bitcoin_wallet: &bitcoin::Wallet,
|
||||
) -> Result<()> {
|
||||
wait_for_cancel_timelock_to_expire(
|
||||
bitcoin_wallet,
|
||||
self.cancel_timelock,
|
||||
self.tx_lock.txid(),
|
||||
)
|
||||
.await
|
||||
bitcoin_wallet
|
||||
.watch_until_status(
|
||||
self.tx_lock.txid(),
|
||||
self.tx_lock.script_pubkey(),
|
||||
|status| status.is_confirmed_with(self.cancel_timelock),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn expired_timelock(
|
||||
&self,
|
||||
bitcoin_wallet: &bitcoin::Wallet,
|
||||
) -> Result<ExpiredTimelocks> {
|
||||
current_epoch(
|
||||
bitcoin_wallet,
|
||||
let tx_cancel = TxCancel::new(&self.tx_lock, self.cancel_timelock, self.A, self.b.public());
|
||||
|
||||
let tx_lock_status = bitcoin_wallet
|
||||
.status_of_script(&self.tx_lock.script_pubkey(), &self.tx_lock.txid())
|
||||
.await?;
|
||||
let tx_cancel_status = bitcoin_wallet
|
||||
.status_of_script(&tx_cancel.script_pubkey(), &tx_cancel.txid())
|
||||
.await?;
|
||||
|
||||
Ok(current_epoch(
|
||||
self.cancel_timelock,
|
||||
self.punish_timelock,
|
||||
self.tx_lock.txid(),
|
||||
)
|
||||
.await
|
||||
tx_lock_status,
|
||||
tx_cancel_status,
|
||||
))
|
||||
}
|
||||
|
||||
pub async fn refund_btc(
|
||||
|
|
@ -530,7 +552,11 @@ impl State4 {
|
|||
let txid = bitcoin_wallet.broadcast(signed_tx_refund, "refund").await?;
|
||||
|
||||
bitcoin_wallet
|
||||
.wait_for_transaction_finality(txid, execution_params)
|
||||
.wait_for_transaction_finality(
|
||||
txid,
|
||||
self.refund_address.script_pubkey(),
|
||||
execution_params,
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue