mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2025-01-11 07:29:39 -05:00
Implement wait_for_transaction_finality
This commit is contained in:
parent
65e910e1c1
commit
765482b0aa
55
Cargo.lock
generated
55
Cargo.lock
generated
@ -124,6 +124,17 @@ dependencies = [
|
|||||||
"syn 1.0.48",
|
"syn 1.0.48",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "async-recursion"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e5444eec77a9ec2bfe4524139e09195862e981400c4358d3b760cae634e4c4ee"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 1.0.24",
|
||||||
|
"quote 1.0.7",
|
||||||
|
"syn 1.0.48",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-trait"
|
name = "async-trait"
|
||||||
version = "0.1.41"
|
version = "0.1.41"
|
||||||
@ -261,6 +272,26 @@ dependencies = [
|
|||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitcoin-harness"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "git+https://github.com/d4nte/bitcoin-harness-rs?branch=access-wallet-client#2ceccaa89bd994c2bc49e23a11cd8af647afc31b"
|
||||||
|
dependencies = [
|
||||||
|
"base64 0.12.3",
|
||||||
|
"bitcoin",
|
||||||
|
"bitcoincore-rpc-json",
|
||||||
|
"futures",
|
||||||
|
"hex 0.4.2",
|
||||||
|
"reqwest",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"testcontainers",
|
||||||
|
"thiserror",
|
||||||
|
"tokio",
|
||||||
|
"tracing",
|
||||||
|
"url",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitcoin_hashes"
|
name = "bitcoin_hashes"
|
||||||
version = "0.7.6"
|
version = "0.7.6"
|
||||||
@ -534,6 +565,21 @@ dependencies = [
|
|||||||
"bitflags",
|
"bitflags",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "conquer-once"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5cb45322099323eefa1b48850ce6c148f5b510894c531e038539f6370c887214"
|
||||||
|
dependencies = [
|
||||||
|
"conquer-util",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "conquer-util"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e763eef8846b13b380f37dfecda401770b0ca4e56e95170237bd7c25c7db3582"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "const_fn"
|
name = "const_fn"
|
||||||
version = "0.4.3"
|
version = "0.4.3"
|
||||||
@ -1975,10 +2021,8 @@ name = "monero-harness"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"curve25519-dalek 2.1.0",
|
|
||||||
"digest_auth",
|
"digest_auth",
|
||||||
"futures",
|
"futures",
|
||||||
"monero",
|
|
||||||
"port_check",
|
"port_check",
|
||||||
"rand 0.7.3",
|
"rand 0.7.3",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
@ -3339,12 +3383,14 @@ name = "swap"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"async-recursion",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"atty",
|
"atty",
|
||||||
"backoff",
|
"backoff",
|
||||||
"base64 0.12.3",
|
"base64 0.12.3",
|
||||||
"bitcoin",
|
"bitcoin",
|
||||||
"bitcoin-harness",
|
"bitcoin-harness 0.1.0 (git+https://github.com/d4nte/bitcoin-harness-rs?branch=access-wallet-client)",
|
||||||
|
"conquer-once",
|
||||||
"derivative",
|
"derivative",
|
||||||
"ecdsa_fun",
|
"ecdsa_fun",
|
||||||
"futures",
|
"futures",
|
||||||
@ -4121,7 +4167,8 @@ dependencies = [
|
|||||||
"backoff",
|
"backoff",
|
||||||
"base64 0.12.3",
|
"base64 0.12.3",
|
||||||
"bitcoin",
|
"bitcoin",
|
||||||
"bitcoin-harness",
|
"bitcoin-harness 0.1.0 (git+https://github.com/coblox/bitcoin-harness-rs?rev=3be644cd9512c157d3337a189298b8257ed54d04)",
|
||||||
|
"conquer-once",
|
||||||
"cross-curve-dleq",
|
"cross-curve-dleq",
|
||||||
"curve25519-dalek 2.1.0",
|
"curve25519-dalek 2.1.0",
|
||||||
"ecdsa_fun",
|
"ecdsa_fun",
|
||||||
|
@ -13,7 +13,7 @@ atty = "0.2"
|
|||||||
backoff = { version = "0.2", features = ["tokio"] }
|
backoff = { version = "0.2", features = ["tokio"] }
|
||||||
base64 = "0.12"
|
base64 = "0.12"
|
||||||
bitcoin = { version = "0.23", features = ["rand", "use-serde"] } # TODO: Upgrade other crates in this repo to use this version.
|
bitcoin = { version = "0.23", features = ["rand", "use-serde"] } # TODO: Upgrade other crates in this repo to use this version.
|
||||||
bitcoin-harness = { git = "https://github.com/coblox/bitcoin-harness-rs", rev = "3be644cd9512c157d3337a189298b8257ed54d04" }
|
bitcoin-harness = { git = "https://github.com/d4nte/bitcoin-harness-rs", branch = "access-wallet-client" }
|
||||||
conquer-once = "0.3"
|
conquer-once = "0.3"
|
||||||
derivative = "2"
|
derivative = "2"
|
||||||
ecdsa_fun = { git = "https://github.com/LLFourn/secp256kfun", rev = "510d48ef6a2b19805f7f5c70c598e5b03f668e7a", features = ["libsecp_compat", "serde", "serialization"] }
|
ecdsa_fun = { git = "https://github.com/LLFourn/secp256kfun", rev = "510d48ef6a2b19805f7f5c70c598e5b03f668e7a", features = ["libsecp_compat", "serde", "serialization"] }
|
||||||
|
@ -15,6 +15,7 @@ use libp2p::request_response::ResponseChannel;
|
|||||||
use sha2::Sha256;
|
use sha2::Sha256;
|
||||||
use std::{sync::Arc, time::Duration};
|
use std::{sync::Arc, time::Duration};
|
||||||
use tokio::time::timeout;
|
use tokio::time::timeout;
|
||||||
|
use tracing::trace;
|
||||||
use xmr_btc::{
|
use xmr_btc::{
|
||||||
alice,
|
alice,
|
||||||
alice::{State0, State3},
|
alice::{State0, State3},
|
||||||
@ -23,13 +24,11 @@ use xmr_btc::{
|
|||||||
EncryptedSignature, GetRawTransaction, TransactionBlockHeight, TxCancel, TxLock, TxRefund,
|
EncryptedSignature, GetRawTransaction, TransactionBlockHeight, TxCancel, TxLock, TxRefund,
|
||||||
WaitForTransactionFinality, WatchForRawTransaction,
|
WaitForTransactionFinality, WatchForRawTransaction,
|
||||||
},
|
},
|
||||||
|
config::Config,
|
||||||
cross_curve_dleq,
|
cross_curve_dleq,
|
||||||
monero::Transfer,
|
monero::Transfer,
|
||||||
};
|
};
|
||||||
|
|
||||||
// For each step, we are giving Bob 10 minutes to act.
|
|
||||||
static BOB_TIME_TO_ACT: Lazy<Duration> = Lazy::new(|| Duration::from_secs(10 * 60));
|
|
||||||
|
|
||||||
// The maximum we assume we need to wait from the moment the monero transaction
|
// The maximum we assume we need to wait from the moment the monero transaction
|
||||||
// is mined to the moment it reaches finality. We set 15 confirmations for now
|
// is mined to the moment it reaches finality. We set 15 confirmations for now
|
||||||
// (based on Kraken). 1.5 multiplier in case the blockchain is slower than
|
// (based on Kraken). 1.5 multiplier in case the blockchain is slower than
|
||||||
@ -44,8 +43,10 @@ pub async fn negotiate(
|
|||||||
v_a: monero::PrivateViewKey,
|
v_a: monero::PrivateViewKey,
|
||||||
swarm: &mut Swarm,
|
swarm: &mut Swarm,
|
||||||
bitcoin_wallet: Arc<bitcoin::Wallet>,
|
bitcoin_wallet: Arc<bitcoin::Wallet>,
|
||||||
|
config: Config,
|
||||||
) -> Result<(ResponseChannel<AliceToBob>, State3)> {
|
) -> Result<(ResponseChannel<AliceToBob>, State3)> {
|
||||||
let event = timeout(*BOB_TIME_TO_ACT, swarm.next())
|
trace!("Starting negotiate");
|
||||||
|
let event = timeout(config.bob_time_to_act, swarm.next())
|
||||||
.await
|
.await
|
||||||
.context("Failed to receive dial connection from Bob")?;
|
.context("Failed to receive dial connection from Bob")?;
|
||||||
match event {
|
match event {
|
||||||
@ -53,7 +54,7 @@ pub async fn negotiate(
|
|||||||
other => bail!("Unexpected event received: {:?}", other),
|
other => bail!("Unexpected event received: {:?}", other),
|
||||||
}
|
}
|
||||||
|
|
||||||
let event = timeout(*BOB_TIME_TO_ACT, swarm.next())
|
let event = timeout(config.bob_time_to_act, swarm.next())
|
||||||
.await
|
.await
|
||||||
.context("Failed to receive amounts from Bob")?;
|
.context("Failed to receive amounts from Bob")?;
|
||||||
let (btc, channel) = match event {
|
let (btc, channel) = match event {
|
||||||
@ -89,7 +90,7 @@ pub async fn negotiate(
|
|||||||
// TODO(Franck): Understand why this is needed.
|
// TODO(Franck): Understand why this is needed.
|
||||||
swarm.set_state0(state0.clone());
|
swarm.set_state0(state0.clone());
|
||||||
|
|
||||||
let event = timeout(*BOB_TIME_TO_ACT, swarm.next())
|
let event = timeout(config.bob_time_to_act, swarm.next())
|
||||||
.await
|
.await
|
||||||
.context("Failed to receive message 0 from Bob")?;
|
.context("Failed to receive message 0 from Bob")?;
|
||||||
let message0 = match event {
|
let message0 = match event {
|
||||||
@ -99,7 +100,7 @@ pub async fn negotiate(
|
|||||||
|
|
||||||
let state1 = state0.receive(message0)?;
|
let state1 = state0.receive(message0)?;
|
||||||
|
|
||||||
let event = timeout(*BOB_TIME_TO_ACT, swarm.next())
|
let event = timeout(config.bob_time_to_act, swarm.next())
|
||||||
.await
|
.await
|
||||||
.context("Failed to receive message 1 from Bob")?;
|
.context("Failed to receive message 1 from Bob")?;
|
||||||
let (msg, channel) = match event {
|
let (msg, channel) = match event {
|
||||||
@ -112,7 +113,7 @@ pub async fn negotiate(
|
|||||||
let message1 = state2.next_message();
|
let message1 = state2.next_message();
|
||||||
swarm.send_message1(channel, message1);
|
swarm.send_message1(channel, message1);
|
||||||
|
|
||||||
let event = timeout(*BOB_TIME_TO_ACT, swarm.next())
|
let event = timeout(config.bob_time_to_act, swarm.next())
|
||||||
.await
|
.await
|
||||||
.context("Failed to receive message 2 from Bob")?;
|
.context("Failed to receive message 2 from Bob")?;
|
||||||
let (msg, channel) = match event {
|
let (msg, channel) = match event {
|
||||||
@ -128,13 +129,14 @@ pub async fn negotiate(
|
|||||||
pub async fn wait_for_locked_bitcoin<W>(
|
pub async fn wait_for_locked_bitcoin<W>(
|
||||||
lock_bitcoin_txid: bitcoin::Txid,
|
lock_bitcoin_txid: bitcoin::Txid,
|
||||||
bitcoin_wallet: Arc<W>,
|
bitcoin_wallet: Arc<W>,
|
||||||
|
config: Config,
|
||||||
) -> Result<()>
|
) -> Result<()>
|
||||||
where
|
where
|
||||||
W: WatchForRawTransaction + WaitForTransactionFinality,
|
W: WatchForRawTransaction + WaitForTransactionFinality,
|
||||||
{
|
{
|
||||||
// We assume we will see Bob's transaction in the mempool first.
|
// We assume we will see Bob's transaction in the mempool first.
|
||||||
timeout(
|
timeout(
|
||||||
*BOB_TIME_TO_ACT,
|
config.bob_time_to_act,
|
||||||
bitcoin_wallet.watch_for_raw_transaction(lock_bitcoin_txid),
|
bitcoin_wallet.watch_for_raw_transaction(lock_bitcoin_txid),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
@ -142,7 +144,7 @@ where
|
|||||||
|
|
||||||
// // We saw the transaction in the mempool, waiting for it to be confirmed.
|
// // We saw the transaction in the mempool, waiting for it to be confirmed.
|
||||||
// bitcoin_wallet
|
// bitcoin_wallet
|
||||||
// .wait_for_transaction_finality(lock_bitcoin_txid)
|
// .wait_for_transaction_finality(lock_bitcoin_txid, config)
|
||||||
// .await;
|
// .await;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -225,17 +227,18 @@ pub fn build_bitcoin_redeem_transaction(
|
|||||||
pub async fn publish_bitcoin_redeem_transaction<W>(
|
pub async fn publish_bitcoin_redeem_transaction<W>(
|
||||||
redeem_tx: bitcoin::Transaction,
|
redeem_tx: bitcoin::Transaction,
|
||||||
bitcoin_wallet: Arc<W>,
|
bitcoin_wallet: Arc<W>,
|
||||||
|
config: Config,
|
||||||
) -> Result<()>
|
) -> Result<()>
|
||||||
where
|
where
|
||||||
W: BroadcastSignedTransaction + WaitForTransactionFinality,
|
W: BroadcastSignedTransaction + WaitForTransactionFinality,
|
||||||
{
|
{
|
||||||
let _tx_id = bitcoin_wallet
|
let tx_id = bitcoin_wallet
|
||||||
.broadcast_signed_transaction(redeem_tx)
|
.broadcast_signed_transaction(redeem_tx)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// // TODO(Franck): Not sure if we wait for finality here or just mined
|
bitcoin_wallet
|
||||||
// bitcoin_wallet.wait_for_transaction_finality(tx_id).await;
|
.wait_for_transaction_finality(tx_id, config)
|
||||||
Ok(())
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn publish_cancel_transaction<W>(
|
pub async fn publish_cancel_transaction<W>(
|
||||||
@ -364,6 +367,7 @@ pub fn build_bitcoin_punish_transaction(
|
|||||||
pub async fn publish_bitcoin_punish_transaction<W>(
|
pub async fn publish_bitcoin_punish_transaction<W>(
|
||||||
punish_tx: bitcoin::Transaction,
|
punish_tx: bitcoin::Transaction,
|
||||||
bitcoin_wallet: Arc<W>,
|
bitcoin_wallet: Arc<W>,
|
||||||
|
config: Config,
|
||||||
) -> Result<bitcoin::Txid>
|
) -> Result<bitcoin::Txid>
|
||||||
where
|
where
|
||||||
W: BroadcastSignedTransaction + WaitForTransactionFinality,
|
W: BroadcastSignedTransaction + WaitForTransactionFinality,
|
||||||
@ -372,8 +376,9 @@ where
|
|||||||
.broadcast_signed_transaction(punish_tx)
|
.broadcast_signed_transaction(punish_tx)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// todo: enable this once trait is implemented
|
bitcoin_wallet
|
||||||
// bitcoin_wallet.wait_for_transaction_finality(txid).await;
|
.wait_for_transaction_finality(txid, config)
|
||||||
|
.await?;
|
||||||
|
|
||||||
Ok(txid)
|
Ok(txid)
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ use std::sync::Arc;
|
|||||||
use xmr_btc::{
|
use xmr_btc::{
|
||||||
alice::State3,
|
alice::State3,
|
||||||
bitcoin::{TransactionBlockHeight, TxCancel, TxRefund, WatchForRawTransaction},
|
bitcoin::{TransactionBlockHeight, TxCancel, TxRefund, WatchForRawTransaction},
|
||||||
|
config::Config,
|
||||||
cross_curve_dleq,
|
cross_curve_dleq,
|
||||||
monero::CreateWalletForOutput,
|
monero::CreateWalletForOutput,
|
||||||
};
|
};
|
||||||
@ -92,6 +93,7 @@ pub async fn swap(
|
|||||||
mut swarm: Swarm,
|
mut swarm: Swarm,
|
||||||
bitcoin_wallet: Arc<crate::bitcoin::Wallet>,
|
bitcoin_wallet: Arc<crate::bitcoin::Wallet>,
|
||||||
monero_wallet: Arc<crate::monero::Wallet>,
|
monero_wallet: Arc<crate::monero::Wallet>,
|
||||||
|
config: Config,
|
||||||
) -> Result<AliceState> {
|
) -> Result<AliceState> {
|
||||||
match state {
|
match state {
|
||||||
AliceState::Started {
|
AliceState::Started {
|
||||||
@ -100,8 +102,16 @@ pub async fn swap(
|
|||||||
s_a,
|
s_a,
|
||||||
v_a,
|
v_a,
|
||||||
} => {
|
} => {
|
||||||
let (channel, state3) =
|
let (channel, state3) = negotiate(
|
||||||
negotiate(amounts, a, s_a, v_a, &mut swarm, bitcoin_wallet.clone()).await?;
|
amounts,
|
||||||
|
a,
|
||||||
|
s_a,
|
||||||
|
v_a,
|
||||||
|
&mut swarm,
|
||||||
|
bitcoin_wallet.clone(),
|
||||||
|
config,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
swap(
|
swap(
|
||||||
AliceState::Negotiated {
|
AliceState::Negotiated {
|
||||||
@ -112,6 +122,7 @@ pub async fn swap(
|
|||||||
swarm,
|
swarm,
|
||||||
bitcoin_wallet,
|
bitcoin_wallet,
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
|
config,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -120,7 +131,8 @@ pub async fn swap(
|
|||||||
channel,
|
channel,
|
||||||
amounts,
|
amounts,
|
||||||
} => {
|
} => {
|
||||||
let _ = wait_for_locked_bitcoin(state3.tx_lock.txid(), bitcoin_wallet.clone()).await?;
|
let _ = wait_for_locked_bitcoin(state3.tx_lock.txid(), bitcoin_wallet.clone(), config)
|
||||||
|
.await?;
|
||||||
|
|
||||||
swap(
|
swap(
|
||||||
AliceState::BtcLocked {
|
AliceState::BtcLocked {
|
||||||
@ -131,6 +143,7 @@ pub async fn swap(
|
|||||||
swarm,
|
swarm,
|
||||||
bitcoin_wallet,
|
bitcoin_wallet,
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
|
config,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -153,6 +166,7 @@ pub async fn swap(
|
|||||||
swarm,
|
swarm,
|
||||||
bitcoin_wallet,
|
bitcoin_wallet,
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
|
config,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -169,6 +183,7 @@ pub async fn swap(
|
|||||||
swarm,
|
swarm,
|
||||||
bitcoin_wallet,
|
bitcoin_wallet,
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
|
config,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -178,6 +193,7 @@ pub async fn swap(
|
|||||||
swarm,
|
swarm,
|
||||||
bitcoin_wallet,
|
bitcoin_wallet,
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
|
config,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -202,6 +218,7 @@ pub async fn swap(
|
|||||||
swarm,
|
swarm,
|
||||||
bitcoin_wallet,
|
bitcoin_wallet,
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
|
config,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
@ -210,13 +227,15 @@ pub async fn swap(
|
|||||||
// TODO(Franck): Error handling is delicate here.
|
// TODO(Franck): Error handling is delicate here.
|
||||||
// If Bob sees this transaction he can redeem Monero
|
// If Bob sees this transaction he can redeem Monero
|
||||||
// e.g. If the Bitcoin node is down then the user needs to take action.
|
// e.g. If the Bitcoin node is down then the user needs to take action.
|
||||||
publish_bitcoin_redeem_transaction(signed_tx_redeem, bitcoin_wallet.clone()).await?;
|
publish_bitcoin_redeem_transaction(signed_tx_redeem, bitcoin_wallet.clone(), config)
|
||||||
|
.await?;
|
||||||
|
|
||||||
swap(
|
swap(
|
||||||
AliceState::BtcRedeemed,
|
AliceState::BtcRedeemed,
|
||||||
swarm,
|
swarm,
|
||||||
bitcoin_wallet,
|
bitcoin_wallet,
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
|
config,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -236,6 +255,7 @@ pub async fn swap(
|
|||||||
swarm,
|
swarm,
|
||||||
bitcoin_wallet,
|
bitcoin_wallet,
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
|
config,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -261,6 +281,7 @@ pub async fn swap(
|
|||||||
swarm,
|
swarm,
|
||||||
bitcoin_wallet.clone(),
|
bitcoin_wallet.clone(),
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
|
config,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -274,6 +295,7 @@ pub async fn swap(
|
|||||||
swarm,
|
swarm,
|
||||||
bitcoin_wallet.clone(),
|
bitcoin_wallet.clone(),
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
|
config,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -310,8 +332,11 @@ pub async fn swap(
|
|||||||
state3.B.clone(),
|
state3.B.clone(),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let punish_tx_finalised =
|
let punish_tx_finalised = publish_bitcoin_punish_transaction(
|
||||||
publish_bitcoin_punish_transaction(signed_tx_punish, bitcoin_wallet.clone());
|
signed_tx_punish,
|
||||||
|
bitcoin_wallet.clone(),
|
||||||
|
config,
|
||||||
|
);
|
||||||
|
|
||||||
let refund_tx_seen = bitcoin_wallet.watch_for_raw_transaction(tx_refund.txid());
|
let refund_tx_seen = bitcoin_wallet.watch_for_raw_transaction(tx_refund.txid());
|
||||||
|
|
||||||
@ -325,6 +350,7 @@ pub async fn swap(
|
|||||||
swarm,
|
swarm,
|
||||||
bitcoin_wallet.clone(),
|
bitcoin_wallet.clone(),
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
|
config,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -338,6 +364,7 @@ pub async fn swap(
|
|||||||
swarm,
|
swarm,
|
||||||
bitcoin_wallet.clone(),
|
bitcoin_wallet.clone(),
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
|
config,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -6,9 +6,13 @@ use backoff::{backoff::Constant as ConstantBackoff, future::FutureOperation as _
|
|||||||
use bitcoin::util::psbt::PartiallySignedTransaction;
|
use bitcoin::util::psbt::PartiallySignedTransaction;
|
||||||
use bitcoin_harness::bitcoind_rpc::PsbtBase64;
|
use bitcoin_harness::bitcoind_rpc::PsbtBase64;
|
||||||
use reqwest::Url;
|
use reqwest::Url;
|
||||||
use xmr_btc::bitcoin::{
|
use tokio::time::interval;
|
||||||
BlockHeight, BroadcastSignedTransaction, BuildTxLockPsbt, SignTxLock, TransactionBlockHeight,
|
use xmr_btc::{
|
||||||
WatchForRawTransaction,
|
bitcoin::{
|
||||||
|
BlockHeight, BroadcastSignedTransaction, BuildTxLockPsbt, SignTxLock,
|
||||||
|
TransactionBlockHeight, WatchForRawTransaction,
|
||||||
|
},
|
||||||
|
config::Config,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use ::bitcoin::{Address, Transaction};
|
pub use ::bitcoin::{Address, Transaction};
|
||||||
@ -148,7 +152,23 @@ impl TransactionBlockHeight for Wallet {
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl WaitForTransactionFinality for Wallet {
|
impl WaitForTransactionFinality for Wallet {
|
||||||
async fn wait_for_transaction_finality(&self, _txid: Txid) {
|
async fn wait_for_transaction_finality(&self, txid: Txid, config: Config) -> Result<()> {
|
||||||
todo!()
|
// TODO(Franck): This assumes that bitcoind runs with txindex=1
|
||||||
|
|
||||||
|
// Divide by 4 to not check too often yet still be aware of the new block early
|
||||||
|
// on.
|
||||||
|
let mut interval = interval(config.bitcoin_avg_block_time / 4);
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let tx = self.0.client.get_raw_transaction_verbose(txid).await?;
|
||||||
|
if let Some(confirmations) = tx.confirmations {
|
||||||
|
if confirmations >= config.bitcoin_finality_confirmations {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
interval.tick().await;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -202,11 +202,13 @@ async fn happy_path_recursive_executor() {
|
|||||||
};
|
};
|
||||||
let alice_swarm =
|
let alice_swarm =
|
||||||
alice::new_swarm(alice_multiaddr.clone(), alice_transport, alice_behaviour).unwrap();
|
alice::new_swarm(alice_multiaddr.clone(), alice_transport, alice_behaviour).unwrap();
|
||||||
|
let config = xmr_btc::config::Config::regtest();
|
||||||
let alice_swap = alice::swap::swap(
|
let alice_swap = alice::swap::swap(
|
||||||
alice_state,
|
alice_state,
|
||||||
alice_swarm,
|
alice_swarm,
|
||||||
alice_btc_wallet.clone(),
|
alice_btc_wallet.clone(),
|
||||||
alice_xmr_wallet.clone(),
|
alice_xmr_wallet.clone(),
|
||||||
|
config,
|
||||||
);
|
);
|
||||||
|
|
||||||
let bob_db_dir = tempdir().unwrap();
|
let bob_db_dir = tempdir().unwrap();
|
||||||
|
@ -10,6 +10,7 @@ edition = "2018"
|
|||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
async-trait = "0.1"
|
async-trait = "0.1"
|
||||||
bitcoin = { version = "0.23", features = ["rand", "serde"] }
|
bitcoin = { version = "0.23", features = ["rand", "serde"] }
|
||||||
|
conquer-once = "0.3"
|
||||||
cross-curve-dleq = { git = "https://github.com/comit-network/cross-curve-dleq", rev = "a19608734da1e8803cb4c806022483df4e7d5588", features = ["serde"] }
|
cross-curve-dleq = { git = "https://github.com/comit-network/cross-curve-dleq", rev = "a19608734da1e8803cb4c806022483df4e7d5588", features = ["serde"] }
|
||||||
curve25519-dalek = "2"
|
curve25519-dalek = "2"
|
||||||
ecdsa_fun = { git = "https://github.com/LLFourn/secp256kfun", rev = "510d48ef6a2b19805f7f5c70c598e5b03f668e7a", features = ["libsecp_compat", "serde", "serialization"] }
|
ecdsa_fun = { git = "https://github.com/LLFourn/secp256kfun", rev = "510d48ef6a2b19805f7f5c70c598e5b03f668e7a", features = ["libsecp_compat", "serde", "serialization"] }
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
pub mod transactions;
|
pub mod transactions;
|
||||||
|
|
||||||
|
use crate::config::Config;
|
||||||
use anyhow::{anyhow, bail, Result};
|
use anyhow::{anyhow, bail, Result};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use bitcoin::hashes::{hex::ToHex, Hash};
|
use bitcoin::hashes::{hex::ToHex, Hash};
|
||||||
@ -188,7 +189,7 @@ pub trait WatchForRawTransaction {
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait WaitForTransactionFinality {
|
pub trait WaitForTransactionFinality {
|
||||||
async fn wait_for_transaction_finality(&self, txid: Txid);
|
async fn wait_for_transaction_finality(&self, txid: Txid, config: Config) -> Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
|
49
xmr-btc/src/config.rs
Normal file
49
xmr-btc/src/config.rs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
use conquer_once::Lazy;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct Config {
|
||||||
|
pub bob_time_to_act: Duration,
|
||||||
|
pub bitcoin_finality_confirmations: u32,
|
||||||
|
pub bitcoin_avg_block_time: Duration,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Config {
|
||||||
|
pub fn mainnet() -> Self {
|
||||||
|
Self {
|
||||||
|
bob_time_to_act: *mainnet::BOB_TIME_TO_ACT,
|
||||||
|
bitcoin_finality_confirmations: mainnet::BITCOIN_FINALITY_CONFIRMATIONS,
|
||||||
|
bitcoin_avg_block_time: *mainnet::BITCOIN_AVG_BLOCK_TIME,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn regtest() -> Self {
|
||||||
|
Self {
|
||||||
|
bob_time_to_act: *regtest::BOB_TIME_TO_ACT,
|
||||||
|
bitcoin_finality_confirmations: regtest::BITCOIN_FINALITY_CONFIRMATIONS,
|
||||||
|
bitcoin_avg_block_time: *regtest::BITCOIN_AVG_BLOCK_TIME,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod mainnet {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
// For each step, we are giving Bob 10 minutes to act.
|
||||||
|
pub static BOB_TIME_TO_ACT: Lazy<Duration> = Lazy::new(|| Duration::from_secs(10 * 60));
|
||||||
|
|
||||||
|
pub static BITCOIN_FINALITY_CONFIRMATIONS: u32 = 3;
|
||||||
|
|
||||||
|
pub static BITCOIN_AVG_BLOCK_TIME: Lazy<Duration> = Lazy::new(|| Duration::from_secs(10 * 60));
|
||||||
|
}
|
||||||
|
|
||||||
|
mod regtest {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
// In test, set to 5 seconds to fail fast
|
||||||
|
pub static BOB_TIME_TO_ACT: Lazy<Duration> = Lazy::new(|| Duration::from_secs(5));
|
||||||
|
|
||||||
|
pub static BITCOIN_FINALITY_CONFIRMATIONS: u32 = 1;
|
||||||
|
|
||||||
|
pub static BITCOIN_AVG_BLOCK_TIME: Lazy<Duration> = Lazy::new(|| Duration::from_secs(1));
|
||||||
|
}
|
@ -48,6 +48,7 @@ mod utils {
|
|||||||
pub mod alice;
|
pub mod alice;
|
||||||
pub mod bitcoin;
|
pub mod bitcoin;
|
||||||
pub mod bob;
|
pub mod bob;
|
||||||
|
pub mod config;
|
||||||
pub mod monero;
|
pub mod monero;
|
||||||
pub mod serde;
|
pub mod serde;
|
||||||
pub mod transport;
|
pub mod transport;
|
||||||
|
Loading…
Reference in New Issue
Block a user