Merge pull request #60 from D4nte/rust-bitcoin-0.25

This commit is contained in:
Franck Royer 2020-12-04 13:43:13 +11:00 committed by GitHub
commit 0ce3c54f13
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 141 additions and 241 deletions

62
Cargo.lock generated
View File

@ -241,13 +241,12 @@ checksum = "5f0dc55f2d8a1a85650ac47858bb001b4c0dd73d79e3c455a842925e68d29cd3"
[[package]]
name = "bitcoin"
version = "0.23.0"
version = "0.25.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a32c9d2fa897cfbb0db45d71e3d2838666194abc4828c0f994e4b5c3bf85ba4"
checksum = "aefc9be9f17185f4ebccae6575d342063f775924d57df0000edb1880c0fb7095"
dependencies = [
"bech32",
"bitcoin_hashes",
"hex 0.3.2",
"secp256k1",
"serde",
]
@ -255,27 +254,7 @@ dependencies = [
[[package]]
name = "bitcoin-harness"
version = "0.1.0"
source = "git+https://github.com/d4nte/bitcoin-harness-rs?rev=2869620689f7e54bdb8ab3d1838560cb9bc8fd60#2869620689f7e54bdb8ab3d1838560cb9bc8fd60"
dependencies = [
"base64 0.12.3",
"bitcoin",
"bitcoincore-rpc-json",
"futures",
"hex 0.4.2",
"reqwest",
"serde",
"serde_json",
"testcontainers",
"thiserror",
"tokio",
"tracing",
"url",
]
[[package]]
name = "bitcoin-harness"
version = "0.1.0"
source = "git+https://github.com/coblox/bitcoin-harness-rs?rev=3be644cd9512c157d3337a189298b8257ed54d04#3be644cd9512c157d3337a189298b8257ed54d04"
source = "git+https://github.com/d4nte/bitcoin-harness-rs?branch=rust-bitcoin-0.25#e773e37a070fb38f982c5b80919071420e4ead21"
dependencies = [
"base64 0.12.3",
"bitcoin",
@ -294,18 +273,18 @@ dependencies = [
[[package]]
name = "bitcoin_hashes"
version = "0.7.6"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b375d62f341cef9cd9e77793ec8f1db3fc9ce2e4d57e982c8fe697a2c16af3b6"
checksum = "0aaf87b776808e26ae93289bc7d025092b6d909c193f0cdee0b3a86e7bd3c776"
dependencies = [
"serde",
]
[[package]]
name = "bitcoincore-rpc-json"
version = "0.11.0"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea6d55f23cd516d515ae10911164c603ea1040024670ec109715a20d7f6c9d0c"
checksum = "76d488ec31e9cb6726c361be5160f7d2aaace89a0681acf1f476b8fada770b6e"
dependencies = [
"bitcoin",
"hex 0.3.2",
@ -626,7 +605,7 @@ dependencies = [
[[package]]
name = "cross-curve-dleq"
version = "0.1.0"
source = "git+https://github.com/comit-network/cross-curve-dleq?rev=a19608734da1e8803cb4c806022483df4e7d5588#a19608734da1e8803cb4c806022483df4e7d5588"
source = "git+https://github.com/comit-network/cross-curve-dleq?rev=b43c73ac93a79fdce90cd11a458564c613048f0e#b43c73ac93a79fdce90cd11a458564c613048f0e"
dependencies = [
"bit-vec",
"curve25519-dalek 2.1.0",
@ -846,7 +825,7 @@ checksum = "134951f4028bdadb9b84baf4232681efbf277da25144b9b0ad65df75946c422b"
[[package]]
name = "ecdsa_fun"
version = "0.3.2-alpha.0"
source = "git+https://github.com/LLFourn/secp256kfun?rev=510d48ef6a2b19805f7f5c70c598e5b03f668e7a#510d48ef6a2b19805f7f5c70c598e5b03f668e7a"
source = "git+https://github.com/LLFourn/secp256kfun?rev=cdfbc766045ea678a41780919d6228dd5acee3be#cdfbc766045ea678a41780919d6228dd5acee3be"
dependencies = [
"secp256kfun",
"serde",
@ -1960,9 +1939,9 @@ dependencies = [
[[package]]
name = "miniscript"
version = "1.0.0"
version = "4.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58f196216a07ade53d91a263b3721057f1f0cfd6f95f3d324626f3f9cf7cdfce"
checksum = "cc7da049151be4bc7f8da628f5e862e6fae3fe5d7c8201a746cb8373735e789b"
dependencies = [
"bitcoin",
"serde",
@ -2947,9 +2926,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "secp256k1"
version = "0.17.2"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2932dc07acd2066ff2e3921a4419606b220ba6cd03a9935123856cc534877056"
checksum = "c6179428c22c73ac0fbb7b5579a56353ce78ba29759b3b8575183336ea74cdfb"
dependencies = [
"rand 0.6.5",
"secp256k1-sys",
@ -2958,9 +2937,9 @@ dependencies = [
[[package]]
name = "secp256k1-sys"
version = "0.1.2"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ab2c26f0d3552a0f12e639ae8a64afc2e3db9c52fe32f5fc6c289d38519f220"
checksum = "11553d210db090930f4432bea123b31f70bbf693ace14504ea2a35e796c28dd2"
dependencies = [
"cc",
]
@ -2968,7 +2947,7 @@ dependencies = [
[[package]]
name = "secp256kfun"
version = "0.3.2-alpha.0"
source = "git+https://github.com/LLFourn/secp256kfun?rev=510d48ef6a2b19805f7f5c70c598e5b03f668e7a#510d48ef6a2b19805f7f5c70c598e5b03f668e7a"
source = "git+https://github.com/LLFourn/secp256kfun?rev=cdfbc766045ea678a41780919d6228dd5acee3be#cdfbc766045ea678a41780919d6228dd5acee3be"
dependencies = [
"digest 0.9.0",
"rand_core 0.5.1",
@ -2980,9 +2959,8 @@ dependencies = [
[[package]]
name = "secp256kfun_parity_backend"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "959911ff66eae1b170a4eec00aa9b987647ad604dc57982014d85e635b7b4f99"
version = "0.1.3-alpha.0"
source = "git+https://github.com/LLFourn/secp256kfun?rev=cdfbc766045ea678a41780919d6228dd5acee3be#cdfbc766045ea678a41780919d6228dd5acee3be"
dependencies = [
"crunchy 0.2.2",
"subtle 2.3.0",
@ -3389,7 +3367,7 @@ dependencies = [
"backoff",
"base64 0.12.3",
"bitcoin",
"bitcoin-harness 0.1.0 (git+https://github.com/d4nte/bitcoin-harness-rs?rev=2869620689f7e54bdb8ab3d1838560cb9bc8fd60)",
"bitcoin-harness",
"conquer-once",
"derivative",
"ecdsa_fun",
@ -4167,7 +4145,7 @@ dependencies = [
"backoff",
"base64 0.12.3",
"bitcoin",
"bitcoin-harness 0.1.0 (git+https://github.com/coblox/bitcoin-harness-rs?rev=3be644cd9512c157d3337a189298b8257ed54d04)",
"bitcoin-harness",
"conquer-once",
"cross-curve-dleq",
"curve25519-dalek 2.1.0",

View File

@ -12,11 +12,11 @@ async-trait = "0.1"
atty = "0.2"
backoff = { version = "0.2", features = ["tokio"] }
base64 = "0.12"
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/d4nte/bitcoin-harness-rs", rev = "2869620689f7e54bdb8ab3d1838560cb9bc8fd60" }
bitcoin = { version = "0.25", features = ["rand", "use-serde"] }
bitcoin-harness = { git = "https://github.com/d4nte/bitcoin-harness-rs", branch = "rust-bitcoin-0.25" }
conquer-once = "0.3"
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 = "cdfbc766045ea678a41780919d6228dd5acee3be", features = ["libsecp_compat", "serde"] }
futures = { version = "0.3", default-features = false }
genawaiter = "0.99.1"
libp2p = { version = "0.29", default-features = false, features = ["tcp-tokio", "yamux", "mplex", "dns", "noise", "request-response"] }

View File

@ -207,7 +207,7 @@ pub fn build_bitcoin_redeem_transaction(
let tx_redeem = bitcoin::TxRedeem::new(tx_lock, redeem_address);
bitcoin::verify_encsig(
B.clone(),
B,
s_a.into_secp256k1().into(),
&tx_redeem.digest(),
&encrypted_signature,
@ -258,7 +258,7 @@ where
.await;
poll_until_block_height_is_gte(bitcoin_wallet.as_ref(), tx_lock_height + refund_timelock).await;
let tx_cancel = bitcoin::TxCancel::new(&tx_lock, refund_timelock, a.public(), B.clone());
let tx_cancel = bitcoin::TxCancel::new(&tx_lock, refund_timelock, a.public(), B);
// If Bob hasn't yet broadcasted the tx cancel, we do it
if bitcoin_wallet
@ -274,7 +274,7 @@ where
let tx_cancel = tx_cancel
.clone()
.add_signatures(&tx_lock, (a.public(), sig_a), (B.clone(), sig_b))
.add_signatures(&tx_lock, (a.public(), sig_a), (B, sig_b))
.expect("sig_{a,b} to be valid signatures for tx_cancel");
// TODO(Franck): Error handling is delicate, why can't we broadcast?
@ -331,7 +331,7 @@ pub fn extract_monero_private_key(
let tx_refund_sig = tx_refund
.extract_signature_by_key(published_refund_tx, a.public())
.context("Failed to extract signature from Bitcoin refund tx")?;
let tx_refund_encsig = a.encsign(S_b_bitcoin.clone(), tx_refund.digest());
let tx_refund_encsig = a.encsign(S_b_bitcoin, tx_refund.digest());
let s_b = bitcoin::recover(S_b_bitcoin, tx_refund_sig, tx_refund_encsig)
.context("Failed to recover Monero secret key from Bitcoin signature")?;
@ -351,7 +351,7 @@ pub fn build_bitcoin_punish_transaction(
a: bitcoin::SecretKey,
B: bitcoin::PublicKey,
) -> Result<bitcoin::Transaction> {
let tx_cancel = bitcoin::TxCancel::new(&tx_lock, refund_timelock, a.public(), B.clone());
let tx_cancel = bitcoin::TxCancel::new(&tx_lock, refund_timelock, a.public(), B);
let tx_punish = bitcoin::TxPunish::new(&tx_cancel, &punish_address, punish_timelock);
let sig_a = a.sign(tx_punish.digest());

View File

@ -208,7 +208,7 @@ pub async fn swap(
&state3.tx_lock,
state3.a.clone(),
state3.s_a,
state3.B.clone(),
state3.B,
&state3.redeem_address,
) {
Ok(tx) => tx,
@ -243,7 +243,7 @@ pub async fn swap(
let tx_cancel = publish_cancel_transaction(
state3.tx_lock.clone(),
state3.a.clone(),
state3.B.clone(),
state3.B,
state3.refund_timelock,
state3.tx_cancel_sig_bob.clone(),
bitcoin_wallet.clone(),
@ -329,7 +329,7 @@ pub async fn swap(
state3.punish_timelock,
state3.tx_punish_sig_bob.clone(),
state3.a.clone(),
state3.B.clone(),
state3.B,
)?;
let punish_tx_finalised = publish_bitcoin_punish_transaction(

View File

@ -55,7 +55,7 @@ pub async fn alice_recover(
&state.tx_lock,
state.refund_timelock,
state.a.public(),
state.B.clone(),
state.B,
);
info!("Checking if the Bitcoin cancel transaction has been published");
@ -81,11 +81,7 @@ pub async fn alice_recover(
let tx_cancel = tx_cancel
.clone()
.add_signatures(
&state.tx_lock,
(state.a.public(), sig_a),
(state.B.clone(), sig_b),
)
.add_signatures(&state.tx_lock, (state.a.public(), sig_a), (state.B, sig_b))
.expect("sig_{a,b} to be valid signatures for tx_cancel");
// TODO: We should not fail if the transaction is already on the blockchain
@ -123,9 +119,7 @@ pub async fn alice_recover(
let tx_refund_sig = tx_refund
.extract_signature_by_key(tx_refund_published, state.a.public())?;
let tx_refund_encsig = state
.a
.encsign(state.S_b_bitcoin.clone(), tx_refund.digest());
let tx_refund_encsig = state.a.encsign(state.S_b_bitcoin, tx_refund.digest());
let s_b = bitcoin::recover(state.S_b_bitcoin, tx_refund_sig, tx_refund_encsig)?;
let s_b = monero::PrivateKey::from_scalar(
@ -152,7 +146,7 @@ pub async fn alice_recover(
let sig_tx_punish = tx_punish.add_signatures(
&tx_cancel,
(state.a.public(), sig_a),
(state.B.clone(), sig_b),
(state.B, sig_b),
)?;
bitcoin_wallet
@ -187,7 +181,7 @@ pub async fn alice_recover(
&state.tx_lock,
state.refund_timelock,
state.a.public(),
state.B.clone(),
state.B,
);
info!("Checking if the Bitcoin cancel transaction has been published");
@ -202,11 +196,7 @@ pub async fn alice_recover(
let tx_cancel = tx_cancel
.clone()
.add_signatures(
&state.tx_lock,
(state.a.public(), sig_a),
(state.B.clone(), sig_b),
)
.add_signatures(&state.tx_lock, (state.a.public(), sig_a), (state.B, sig_b))
.expect("sig_{a,b} to be valid signatures for tx_cancel");
// TODO: We should not fail if the transaction is already on the blockchain
@ -244,9 +234,8 @@ pub async fn alice_recover(
let tx_refund_sig = tx_refund
.extract_signature_by_key(tx_refund_published, state.a.public())?;
let tx_refund_encsig = state
.a
.encsign(state.S_b_bitcoin.clone(), tx_refund.digest());
let tx_refund_encsig =
state.a.encsign(state.S_b_bitcoin, tx_refund.digest());
let s_b =
bitcoin::recover(state.S_b_bitcoin, tx_refund_sig, tx_refund_encsig)?;
@ -274,7 +263,7 @@ pub async fn alice_recover(
let sig_tx_punish = tx_punish.add_signatures(
&tx_cancel,
(state.a.public(), sig_a),
(state.B.clone(), sig_b),
(state.B, sig_b),
)?;
bitcoin_wallet
@ -292,7 +281,7 @@ pub async fn alice_recover(
&state.tx_lock,
state.refund_timelock,
state.a.public(),
state.B.clone(),
state.B,
);
let tx_refund = bitcoin::TxRefund::new(&tx_cancel, &state.refund_address);
@ -310,9 +299,7 @@ pub async fn alice_recover(
let tx_refund_sig = tx_refund
.extract_signature_by_key(tx_refund_published, state.a.public())?;
let tx_refund_encsig = state
.a
.encsign(state.S_b_bitcoin.clone(), tx_refund.digest());
let tx_refund_encsig = state.a.encsign(state.S_b_bitcoin, tx_refund.digest());
let s_b = bitcoin::recover(state.S_b_bitcoin, tx_refund_sig, tx_refund_encsig)?;
let s_b = monero::PrivateKey::from_scalar(
@ -339,7 +326,7 @@ pub async fn alice_recover(
let sig_tx_punish = tx_punish.add_signatures(
&tx_cancel,
(state.a.public(), sig_a),
(state.B.clone(), sig_b),
(state.B, sig_b),
)?;
bitcoin_wallet
@ -381,7 +368,7 @@ pub async fn bob_recover(
let tx_cancel = bitcoin::TxCancel::new(
&state.tx_lock,
state.refund_timelock,
state.A.clone(),
state.A,
state.b.public(),
);
@ -408,11 +395,7 @@ pub async fn bob_recover(
let tx_cancel = tx_cancel
.clone()
.add_signatures(
&state.tx_lock,
(state.A.clone(), sig_a),
(state.b.public(), sig_b),
)
.add_signatures(&state.tx_lock, (state.A, sig_a), (state.b.public(), sig_b))
.expect("sig_{a,b} to be valid signatures for tx_cancel");
// TODO: We should not fail if the transaction is already on the blockchain
@ -431,11 +414,7 @@ pub async fn bob_recover(
let sig_b = state.b.sign(tx_refund.digest());
tx_refund
.add_signatures(
&tx_cancel,
(state.A.clone(), sig_a),
(state.b.public(), sig_b),
)
.add_signatures(&tx_cancel, (state.A, sig_a), (state.b.public(), sig_b))
.expect("sig_{a,b} to be valid signatures for tx_refund")
};
@ -455,9 +434,7 @@ pub async fn bob_recover(
.get_raw_transaction(tx_redeem.txid())
.await?;
let tx_redeem_encsig = state
.b
.encsign(state.S_a_bitcoin.clone(), tx_redeem.digest());
let tx_redeem_encsig = state.b.encsign(state.S_a_bitcoin, tx_redeem.digest());
let tx_redeem_sig =
tx_redeem.extract_signature_by_key(tx_redeem_published, state.b.public())?;

View File

@ -9,15 +9,15 @@ edition = "2018"
[dependencies]
anyhow = "1"
async-trait = "0.1"
bitcoin = { version = "0.23", features = ["rand", "serde"] }
bitcoin = { version = "0.25", 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 = "b43c73ac93a79fdce90cd11a458564c613048f0e", features = ["serde"] }
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 = "cdfbc766045ea678a41780919d6228dd5acee3be", features = ["libsecp_compat", "serde"] }
ed25519-dalek = { version = "1.0.0-pre.4", features = ["serde"] }# Cannot be 1 because they depend on curve25519-dalek version 3
futures = "0.3"
genawaiter = "0.99.1"
miniscript = { version = "1", features = ["serde"] }
miniscript = { version = "4", features = ["serde"] }
monero = { version = "0.9", features = ["serde_support"] }
rand = "0.7"
serde = { version = "1", features = ["derive"] }
@ -29,7 +29,7 @@ tracing = "0.1"
[dev-dependencies]
backoff = { version = "0.2", features = ["tokio"] }
base64 = "0.12"
bitcoin-harness = { git = "https://github.com/coblox/bitcoin-harness-rs", rev = "3be644cd9512c157d3337a189298b8257ed54d04" }
bitcoin-harness = { git = "https://github.com/d4nte/bitcoin-harness-rs", branch = "rust-bitcoin-0.25" }
futures = "0.3"
monero-harness = { path = "../monero-harness" }
reqwest = { version = "0.10", default-features = false }

View File

@ -179,7 +179,7 @@ where
let tx_redeem = bitcoin::TxRedeem::new(&tx_lock, &redeem_address);
bitcoin::verify_encsig(
B.clone(),
B,
s_a.into_secp256k1().into(),
&tx_redeem.digest(),
&tx_redeem_encsig,
@ -191,7 +191,7 @@ where
adaptor.decrypt_signature(&s_a.into_secp256k1(), tx_redeem_encsig.clone());
let tx = tx_redeem
.add_signatures(&tx_lock, (a.public(), sig_a), (B.clone(), sig_b))
.add_signatures(&tx_lock, (a.public(), sig_a), (B, sig_b))
.expect("sig_{a,b} to be valid signatures for tx_redeem");
let txid = tx.txid();
@ -220,15 +220,14 @@ 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.clone());
let tx_cancel = bitcoin::TxCancel::new(&tx_lock, refund_timelock, a.public(), B);
let signed_tx_cancel = {
let sig_a = a.sign(tx_cancel.digest());
let sig_b = tx_cancel_sig_bob.clone();
tx_cancel
.clone()
.add_signatures(&tx_lock, (a.public(), sig_a), (B.clone(), sig_b))
.add_signatures(&tx_lock, (a.public(), sig_a), (B, sig_b))
.expect("sig_{a,b} to be valid signatures for tx_cancel")
};
@ -266,7 +265,7 @@ where
let tx_refund_sig = tx_refund
.extract_signature_by_key(tx_refund_published, a.public())
.map_err(|_| RefundFailed::BtcRefundSignature)?;
let tx_refund_encsig = a.encsign(S_b_bitcoin.clone(), tx_refund.digest());
let tx_refund_encsig = a.encsign(S_b_bitcoin, tx_refund.digest());
let s_b = bitcoin::recover(S_b_bitcoin, tx_refund_sig, tx_refund_encsig)
.map_err(|_| RefundFailed::SecretRecovery)?;
@ -292,8 +291,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.clone());
let tx_cancel = bitcoin::TxCancel::new(&tx_lock, refund_timelock, a.public(), B);
let tx_punish =
bitcoin::TxPunish::new(&tx_cancel, &punish_address, punish_timelock);
let tx_punish_txid = tx_punish.txid();
@ -580,12 +578,8 @@ 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.clone(),
);
let tx_cancel =
bitcoin::TxCancel::new(&self.tx_lock, self.refund_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
@ -593,7 +587,7 @@ impl State2 {
// tx_lock_bitcoin to Bob's refund address.
// recover(encsign(a, S_b, d), sign(a, d), S_b) = s_b where d is a digest, (a,
// A) is alice's keypair and (s_b, S_b) is bob's keypair.
let tx_refund_encsig = self.a.encsign(self.S_b_bitcoin.clone(), tx_refund.digest());
let tx_refund_encsig = self.a.encsign(self.S_b_bitcoin, tx_refund.digest());
let tx_cancel_sig = self.a.sign(tx_cancel.digest());
Message1 {
@ -603,12 +597,8 @@ 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.clone(),
);
let tx_cancel =
bitcoin::TxCancel::new(&self.tx_lock, self.refund_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);
@ -751,12 +741,8 @@ impl State4 {
&self,
bitcoin_wallet: &W,
) -> Result<()> {
let tx_cancel = bitcoin::TxCancel::new(
&self.tx_lock,
self.refund_timelock,
self.a.public(),
self.B.clone(),
);
let tx_cancel =
bitcoin::TxCancel::new(&self.tx_lock, self.refund_timelock, self.a.public(), self.B);
let tx_punish =
bitcoin::TxPunish::new(&tx_cancel, &self.punish_address, self.punish_timelock);
@ -767,7 +753,7 @@ impl State4 {
let signed_tx_cancel = tx_cancel.clone().add_signatures(
&self.tx_lock,
(self.a.public(), sig_a),
(self.B.clone(), sig_b),
(self.B, sig_b),
)?;
let _ = bitcoin_wallet
@ -779,11 +765,8 @@ impl State4 {
let sig_a = self.a.sign(tx_punish.digest());
let sig_b = self.tx_punish_sig_bob.clone();
let signed_tx_punish = tx_punish.add_signatures(
&tx_cancel,
(self.a.public(), sig_a),
(self.B.clone(), sig_b),
)?;
let signed_tx_punish =
tx_punish.add_signatures(&tx_cancel, (self.a.public(), sig_a), (self.B, sig_b))?;
let _ = bitcoin_wallet
.broadcast_signed_transaction(signed_tx_punish)
@ -854,16 +837,12 @@ impl State5 {
B: WatchForRawTransaction,
M: CreateWalletForOutput,
{
let tx_cancel = bitcoin::TxCancel::new(
&self.tx_lock,
self.refund_timelock,
self.a.public(),
self.B.clone(),
);
let tx_cancel =
bitcoin::TxCancel::new(&self.tx_lock, self.refund_timelock, self.a.public(), self.B);
let tx_refund = bitcoin::TxRefund::new(&tx_cancel, &self.refund_address);
let tx_refund_encsig = self.a.encsign(self.S_b_bitcoin.clone(), tx_refund.digest());
let tx_refund_encsig = self.a.encsign(self.S_b_bitcoin, tx_refund.digest());
let tx_refund_candidate = bitcoin_wallet
.watch_for_raw_transaction(tx_refund.txid())
@ -923,11 +902,8 @@ impl State6 {
let sig_b =
adaptor.decrypt_signature(&self.s_a.into_secp256k1(), self.tx_redeem_encsig.clone());
let sig_tx_redeem = tx_redeem.add_signatures(
&self.tx_lock,
(self.a.public(), sig_a),
(self.B.clone(), sig_b),
)?;
let sig_tx_redeem =
tx_redeem.add_signatures(&self.tx_lock, (self.a.public(), sig_a), (self.B, sig_b))?;
bitcoin_wallet
.broadcast_signed_transaction(sig_tx_redeem)
.await?;

View File

@ -37,7 +37,7 @@ impl SecretKey {
}
pub fn public(&self) -> PublicKey {
PublicKey(self.public.clone())
PublicKey(self.public)
}
pub fn to_bytes(&self) -> [u8; 32] {
@ -72,7 +72,7 @@ impl SecretKey {
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq)]
pub struct PublicKey(Point);
impl From<PublicKey> for Point {

View File

@ -3,11 +3,11 @@ use crate::bitcoin::{
};
use anyhow::{bail, Context, Result};
use bitcoin::{
util::{bip143::SighashComponents, psbt::PartiallySignedTransaction},
Address, Amount, Network, SigHash, Transaction, TxIn, TxOut,
util::{bip143::SigHashCache, psbt::PartiallySignedTransaction},
Address, Amount, Network, SigHash, SigHashType, Transaction, TxIn, TxOut,
};
use ecdsa_fun::Signature;
use miniscript::Descriptor;
use miniscript::{Descriptor, NullCtx};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
@ -24,7 +24,7 @@ impl TxLock {
{
let lock_output_descriptor = build_shared_output_descriptor(A.0, B.0);
let address = lock_output_descriptor
.address(Network::Regtest)
.address(Network::Regtest, NullCtx)
.expect("can derive address from descriptor");
// We construct a psbt for convenience
@ -59,7 +59,9 @@ impl TxLock {
self.inner
.output
.iter()
.position(|output| output.script_pubkey == self.output_descriptor.script_pubkey())
.position(|output| {
output.script_pubkey == self.output_descriptor.script_pubkey(NullCtx)
})
.expect("transaction contains lock output")
}
@ -67,7 +69,7 @@ impl TxLock {
&self,
spend_address: &Address,
sequence: Option<u32>,
) -> (Transaction, TxIn) {
) -> Transaction {
let previous_output = self.as_outpoint();
let tx_in = TxIn {
@ -82,14 +84,12 @@ impl TxLock {
script_pubkey: spend_address.script_pubkey(),
};
let transaction = Transaction {
Transaction {
version: 2,
lock_time: 0,
input: vec![tx_in.clone()],
input: vec![tx_in],
output: vec![tx_out],
};
(transaction, tx_in)
}
}
}
@ -109,12 +109,13 @@ impl TxRedeem {
pub fn new(tx_lock: &TxLock, redeem_address: &Address) -> Self {
// lock_input is the shared output that is now being used as an input for the
// redeem transaction
let (tx_redeem, lock_input) = tx_lock.build_spend_transaction(redeem_address, None);
let tx_redeem = tx_lock.build_spend_transaction(redeem_address, None);
let digest = SighashComponents::new(&tx_redeem).sighash_all(
&lock_input,
&tx_lock.output_descriptor.witness_script(),
let digest = SigHashCache::new(&tx_redeem).signature_hash(
0, // Only one input: lock_input (lock transaction)
&tx_lock.output_descriptor.witness_script(NullCtx),
tx_lock.lock_amount().as_sat(),
SigHashType::All,
);
Self {
@ -159,7 +160,7 @@ impl TxRedeem {
let mut tx_redeem = self.inner;
tx_lock
.output_descriptor
.satisfy(&mut tx_redeem.input[0], satisfier)?;
.satisfy(&mut tx_redeem.input[0], satisfier, NullCtx)?;
Ok(tx_redeem)
}
@ -238,20 +239,21 @@ impl TxCancel {
let tx_out = TxOut {
value: tx_lock.lock_amount().as_sat() - TX_FEE,
script_pubkey: cancel_output_descriptor.script_pubkey(),
script_pubkey: cancel_output_descriptor.script_pubkey(NullCtx),
};
let transaction = Transaction {
version: 2,
lock_time: 0,
input: vec![tx_in.clone()],
input: vec![tx_in],
output: vec![tx_out],
};
let digest = SighashComponents::new(&transaction).sighash_all(
&tx_in,
&tx_lock.output_descriptor.witness_script(),
let digest = SigHashCache::new(&transaction).signature_hash(
0, // Only one input: lock_input (lock transaction)
&tx_lock.output_descriptor.witness_script(NullCtx),
tx_lock.lock_amount().as_sat(),
SigHashType::All,
);
Self {
@ -305,7 +307,7 @@ impl TxCancel {
let mut tx_cancel = self.inner;
tx_lock
.output_descriptor
.satisfy(&mut tx_cancel.input[0], satisfier)?;
.satisfy(&mut tx_cancel.input[0], satisfier, NullCtx)?;
Ok(tx_cancel)
}
@ -314,7 +316,7 @@ impl TxCancel {
&self,
spend_address: &Address,
sequence: Option<u32>,
) -> (Transaction, TxIn) {
) -> Transaction {
let previous_output = self.as_outpoint();
let tx_in = TxIn {
@ -329,14 +331,12 @@ impl TxCancel {
script_pubkey: spend_address.script_pubkey(),
};
let transaction = Transaction {
Transaction {
version: 2,
lock_time: 0,
input: vec![tx_in.clone()],
input: vec![tx_in],
output: vec![tx_out],
};
(transaction, tx_in)
}
}
}
@ -348,12 +348,13 @@ pub struct TxRefund {
impl TxRefund {
pub fn new(tx_cancel: &TxCancel, refund_address: &Address) -> Self {
let (tx_punish, cancel_input) = tx_cancel.build_spend_transaction(refund_address, None);
let tx_punish = tx_cancel.build_spend_transaction(refund_address, None);
let digest = SighashComponents::new(&tx_punish).sighash_all(
&cancel_input,
&tx_cancel.output_descriptor.witness_script(),
let digest = SigHashCache::new(&tx_punish).signature_hash(
0, // Only one input: cancel transaction
&tx_cancel.output_descriptor.witness_script(NullCtx),
tx_cancel.amount().as_sat(),
SigHashType::All,
);
Self {
@ -398,7 +399,7 @@ impl TxRefund {
let mut tx_refund = self.inner;
tx_cancel
.output_descriptor
.satisfy(&mut tx_refund.input[0], satisfier)?;
.satisfy(&mut tx_refund.input[0], satisfier, NullCtx)?;
Ok(tx_refund)
}
@ -449,13 +450,13 @@ pub struct TxPunish {
impl TxPunish {
pub fn new(tx_cancel: &TxCancel, punish_address: &Address, punish_timelock: u32) -> Self {
let (tx_punish, lock_input) =
tx_cancel.build_spend_transaction(punish_address, Some(punish_timelock));
let tx_punish = tx_cancel.build_spend_transaction(punish_address, Some(punish_timelock));
let digest = SighashComponents::new(&tx_punish).sighash_all(
&lock_input,
&tx_cancel.output_descriptor.witness_script(),
let digest = SigHashCache::new(&tx_punish).signature_hash(
0, // Only one input: cancel transaction
&tx_cancel.output_descriptor.witness_script(NullCtx),
tx_cancel.amount().as_sat(),
SigHashType::All,
);
Self {
@ -500,7 +501,7 @@ impl TxPunish {
let mut tx_punish = self.inner;
tx_cancel
.output_descriptor
.satisfy(&mut tx_punish.input[0], satisfier)?;
.satisfy(&mut tx_punish.input[0], satisfier, NullCtx)?;
Ok(tx_punish)
}

View File

@ -180,7 +180,7 @@ where
}
let tx_redeem = bitcoin::TxRedeem::new(&tx_lock, &redeem_address);
let tx_redeem_encsig = b.encsign(S_a_bitcoin.clone(), tx_redeem.digest());
let tx_redeem_encsig = b.encsign(S_a_bitcoin, tx_redeem.digest());
co.yield_(Action::SendBtcRedeemEncsig(tx_redeem_encsig.clone()))
.await;
@ -221,8 +221,7 @@ where
}
if let Err(SwapFailed::AfterBtcLock(_)) = swap_result {
let tx_cancel =
bitcoin::TxCancel::new(&tx_lock, refund_timelock, A.clone(), b.public());
let tx_cancel = bitcoin::TxCancel::new(&tx_lock, refund_timelock, A, b.public());
let tx_cancel_txid = tx_cancel.txid();
let signed_tx_cancel = {
let sig_a = tx_cancel_sig_a.clone();
@ -230,7 +229,7 @@ where
tx_cancel
.clone()
.add_signatures(&tx_lock, (A.clone(), sig_a), (b.public(), sig_b))
.add_signatures(&tx_lock, (A, sig_a), (b.public(), sig_b))
.expect("sig_{a,b} to be valid signatures for tx_cancel")
};
@ -250,7 +249,7 @@ where
let sig_b = b.sign(tx_refund.digest());
tx_refund
.add_signatures(&tx_cancel, (A.clone(), sig_a), (b.public(), sig_b))
.add_signatures(&tx_cancel, (A, sig_a), (b.public(), sig_b))
.expect("sig_{a,b} to be valid signatures for tx_refund")
};
@ -412,8 +411,7 @@ impl State0 {
.ok_or_else(|| anyhow!("S_a is not a monero curve point"))?,
)?;
let tx_lock =
bitcoin::TxLock::new(wallet, self.btc, msg.A.clone(), self.b.public()).await?;
let tx_lock = bitcoin::TxLock::new(wallet, self.btc, msg.A, self.b.public()).await?;
let v = msg.v_a + self.v_b;
Ok(State1 {
@ -462,17 +460,12 @@ impl State1 {
}
pub fn receive(self, msg: alice::Message1) -> Result<State2> {
let tx_cancel = TxCancel::new(
&self.tx_lock,
self.refund_timelock,
self.A.clone(),
self.b.public(),
);
let tx_cancel = TxCancel::new(&self.tx_lock, self.refund_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)?;
bitcoin::verify_encsig(
self.A.clone(),
self.A,
self.s_b.into_secp256k1().into(),
&tx_refund.digest(),
&msg.tx_refund_encsig,
@ -522,12 +515,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.clone(),
self.b.public(),
);
let tx_cancel = TxCancel::new(&self.tx_lock, self.refund_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);
@ -636,12 +624,8 @@ impl State3 {
&self,
bitcoin_wallet: &W,
) -> Result<()> {
let tx_cancel = bitcoin::TxCancel::new(
&self.tx_lock,
self.refund_timelock,
self.A.clone(),
self.b.public(),
);
let tx_cancel =
bitcoin::TxCancel::new(&self.tx_lock, self.refund_timelock, self.A, self.b.public());
let tx_refund = bitcoin::TxRefund::new(&tx_cancel, &self.refund_address);
{
@ -650,7 +634,7 @@ impl State3 {
let signed_tx_cancel = tx_cancel.clone().add_signatures(
&self.tx_lock,
(self.A.clone(), sig_a),
(self.A, sig_a),
(self.b.public(), sig_b),
)?;
@ -668,7 +652,7 @@ impl State3 {
let signed_tx_refund = tx_refund.add_signatures(
&tx_cancel.clone(),
(self.A.clone(), sig_a),
(self.A, sig_a),
(self.b.public(), sig_b),
)?;
@ -707,26 +691,22 @@ pub struct State4 {
impl State4 {
pub fn next_message(&self) -> Message3 {
let tx_redeem = bitcoin::TxRedeem::new(&self.tx_lock, &self.redeem_address);
let tx_redeem_encsig = self.b.encsign(self.S_a_bitcoin.clone(), tx_redeem.digest());
let tx_redeem_encsig = self.b.encsign(self.S_a_bitcoin, tx_redeem.digest());
Message3 { tx_redeem_encsig }
}
pub fn tx_redeem_encsig(&self) -> EncryptedSignature {
let tx_redeem = bitcoin::TxRedeem::new(&self.tx_lock, &self.redeem_address);
self.b.encsign(self.S_a_bitcoin.clone(), tx_redeem.digest())
self.b.encsign(self.S_a_bitcoin, tx_redeem.digest())
}
pub async fn check_for_tx_cancel<W>(&self, bitcoin_wallet: &W) -> Result<Transaction>
where
W: GetRawTransaction,
{
let tx_cancel = bitcoin::TxCancel::new(
&self.tx_lock,
self.refund_timelock,
self.A.clone(),
self.b.public(),
);
let tx_cancel =
bitcoin::TxCancel::new(&self.tx_lock, self.refund_timelock, self.A, self.b.public());
// todo: check if this is correct
let sig_a = self.tx_cancel_sig_a.clone();
@ -734,11 +714,7 @@ impl State4 {
let tx_cancel = tx_cancel
.clone()
.add_signatures(
&self.tx_lock,
(self.A.clone(), sig_a),
(self.b.public(), sig_b),
)
.add_signatures(&self.tx_lock, (self.A, sig_a), (self.b.public(), sig_b))
.expect(
"sig_{a,b} to be valid signatures for
tx_cancel",
@ -753,12 +729,8 @@ impl State4 {
where
W: BroadcastSignedTransaction,
{
let tx_cancel = bitcoin::TxCancel::new(
&self.tx_lock,
self.refund_timelock,
self.A.clone(),
self.b.public(),
);
let tx_cancel =
bitcoin::TxCancel::new(&self.tx_lock, self.refund_timelock, self.A, self.b.public());
// todo: check if this is correct
let sig_a = self.tx_cancel_sig_a.clone();
@ -766,11 +738,7 @@ impl State4 {
let tx_cancel = tx_cancel
.clone()
.add_signatures(
&self.tx_lock,
(self.A.clone(), sig_a),
(self.b.public(), sig_b),
)
.add_signatures(&self.tx_lock, (self.A, sig_a), (self.b.public(), sig_b))
.expect(
"sig_{a,b} to be valid signatures for
tx_cancel",
@ -787,7 +755,7 @@ impl State4 {
W: WatchForRawTransaction,
{
let tx_redeem = bitcoin::TxRedeem::new(&self.tx_lock, &self.redeem_address);
let tx_redeem_encsig = self.b.encsign(self.S_a_bitcoin.clone(), tx_redeem.digest());
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())
@ -795,16 +763,16 @@ impl State4 {
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.clone(), tx_redeem_sig, tx_redeem_encsig)?;
let s_a = bitcoin::recover(self.S_a_bitcoin, tx_redeem_sig, tx_redeem_encsig)?;
let s_a = monero::private_key_from_secp256k1_scalar(s_a.into());
Ok(State5 {
A: self.A.clone(),
A: self.A,
b: self.b.clone(),
s_a,
s_b: self.s_b,
S_a_monero: self.S_a_monero,
S_a_bitcoin: self.S_a_bitcoin.clone(),
S_a_bitcoin: self.S_a_bitcoin,
v: self.v,
btc: self.btc,
xmr: self.xmr,

View File

@ -41,9 +41,9 @@ 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 BOB_TIME_TO_ACT: Lazy<Duration> = Lazy::new(|| Duration::from_secs(10));
pub static BITCOIN_FINALITY_CONFIRMATIONS: u32 = 1;
pub static BITCOIN_AVG_BLOCK_TIME: Lazy<Duration> = Lazy::new(|| Duration::from_secs(1));
pub static BITCOIN_AVG_BLOCK_TIME: Lazy<Duration> = Lazy::new(|| Duration::from_secs(5));
}