Move completing of Bitcoin redeem tx onto RedeemTx

This allows us to have access to RedeemTx from within the scope
of the state transition which we are going to need for more
efficient watching of what happens to this TX on the blockchain.
pull/307/head
Thomas Eizinger 3 years ago
parent 21429f24b2
commit dd6c66a594
No known key found for this signature in database
GPG Key ID: 651AC83A6C6C8B96

@ -1,12 +1,16 @@
use crate::bitcoin::{ use crate::bitcoin::{
verify_sig, Address, EmptyWitnessStack, NoInputs, NotThreeWitnesses, PublicKey, TooManyInputs, verify_encsig, verify_sig, Address, EmptyWitnessStack, EncryptedSignature, NoInputs,
Transaction, TxLock, NotThreeWitnesses, PublicKey, SecretKey, TooManyInputs, Transaction, TxLock,
}; };
use ::bitcoin::util::bip143::SigHashCache; use ::bitcoin::util::bip143::SigHashCache;
use ::bitcoin::{SigHash, SigHashType, Txid}; use ::bitcoin::{SigHash, SigHashType, Txid};
use anyhow::{bail, Context, Result}; use anyhow::{bail, Context, Result};
use ecdsa_fun::adaptor::{Adaptor, HashTranscript};
use ecdsa_fun::fun::Scalar;
use ecdsa_fun::nonce::Deterministic;
use ecdsa_fun::Signature; use ecdsa_fun::Signature;
use miniscript::{Descriptor, DescriptorTrait}; use miniscript::{Descriptor, DescriptorTrait};
use sha2::Sha256;
use std::collections::HashMap; use std::collections::HashMap;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -44,17 +48,31 @@ impl TxRedeem {
self.digest self.digest
} }
pub fn add_signatures( pub fn complete(
self, mut self,
(A, sig_a): (PublicKey, Signature), encrypted_signature: EncryptedSignature,
(B, sig_b): (PublicKey, Signature), a: SecretKey,
s_a: Scalar,
B: PublicKey,
) -> Result<Transaction> { ) -> Result<Transaction> {
verify_encsig(
B,
PublicKey::from(s_a.clone()),
&self.digest(),
&encrypted_signature,
)
.context("Invalid encrypted signature received")?;
let sig_a = a.sign(self.digest());
let adaptor = Adaptor::<HashTranscript<Sha256>, Deterministic<Sha256>>::default();
let sig_b = adaptor.decrypt_signature(&s_a, encrypted_signature);
let satisfier = { let satisfier = {
let mut satisfier = HashMap::with_capacity(2); let mut satisfier = HashMap::with_capacity(2);
let A = ::bitcoin::PublicKey { let A = ::bitcoin::PublicKey {
compressed: true, compressed: true,
key: A.0.into(), key: a.public.into(),
}; };
let B = ::bitcoin::PublicKey { let B = ::bitcoin::PublicKey {
compressed: true, compressed: true,
@ -68,11 +86,11 @@ impl TxRedeem {
satisfier satisfier
}; };
let mut tx_redeem = self.inner;
self.lock_output_descriptor self.lock_output_descriptor
.satisfy(&mut tx_redeem.input[0], satisfier)?; .satisfy(&mut self.inner.input[0], satisfier)
.context("Failed to sign Bitcoin redeem transaction")?;
Ok(tx_redeem) Ok(self.inner)
} }
pub fn extract_signature_by_key( pub fn extract_signature_by_key(

@ -7,12 +7,9 @@ use crate::protocol::alice::event_loop::EventLoopHandle;
use crate::protocol::alice::TransferProof; use crate::protocol::alice::TransferProof;
use crate::{bitcoin, monero}; use crate::{bitcoin, monero};
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use ecdsa_fun::adaptor::{Adaptor, HashTranscript};
use ecdsa_fun::nonce::Deterministic;
use futures::future::{select, Either}; use futures::future::{select, Either};
use futures::pin_mut; use futures::pin_mut;
use libp2p::PeerId; use libp2p::PeerId;
use sha2::Sha256;
pub async fn lock_xmr( pub async fn lock_xmr(
bob_peer_id: PeerId, bob_peer_id: PeerId,
@ -56,36 +53,6 @@ pub async fn wait_for_bitcoin_encrypted_signature(
Ok(msg3.tx_redeem_encsig) Ok(msg3.tx_redeem_encsig)
} }
pub fn build_bitcoin_redeem_transaction(
encrypted_signature: EncryptedSignature,
tx_lock: &TxLock,
a: bitcoin::SecretKey,
s_a: ecdsa_fun::fun::Scalar,
B: bitcoin::PublicKey,
redeem_address: &bitcoin::Address,
) -> Result<bitcoin::Transaction> {
let adaptor = Adaptor::<HashTranscript<Sha256>, Deterministic<Sha256>>::default();
let tx_redeem = bitcoin::TxRedeem::new(tx_lock, redeem_address);
bitcoin::verify_encsig(
B,
bitcoin::PublicKey::from(s_a.clone()),
&tx_redeem.digest(),
&encrypted_signature,
)
.context("Invalid encrypted signature received")?;
let sig_a = a.sign(tx_redeem.digest());
let sig_b = adaptor.decrypt_signature(&s_a, encrypted_signature);
let tx = tx_redeem
.add_signatures((a.public(), sig_a), (B, sig_b))
.context("Failed to sign Bitcoin redeem transaction")?;
Ok(tx)
}
pub async fn publish_cancel_transaction( pub async fn publish_cancel_transaction(
tx_lock: TxLock, tx_lock: TxLock,
a: bitcoin::SecretKey, a: bitcoin::SecretKey,

@ -1,15 +1,14 @@
//! Run an XMR/BTC swap in the role of Alice. //! Run an XMR/BTC swap in the role of Alice.
//! Alice holds XMR and wishes receive BTC. //! Alice holds XMR and wishes receive BTC.
use crate::bitcoin::ExpiredTimelocks; use crate::bitcoin::{ExpiredTimelocks, TxRedeem};
use crate::database::Database; use crate::database::Database;
use crate::execution_params::ExecutionParams; use crate::execution_params::ExecutionParams;
use crate::monero_ext::ScalarExt; use crate::monero_ext::ScalarExt;
use crate::protocol::alice; use crate::protocol::alice;
use crate::protocol::alice::event_loop::EventLoopHandle; use crate::protocol::alice::event_loop::EventLoopHandle;
use crate::protocol::alice::steps::{ use crate::protocol::alice::steps::{
build_bitcoin_punish_transaction, build_bitcoin_redeem_transaction, extract_monero_private_key, build_bitcoin_punish_transaction, extract_monero_private_key, lock_xmr,
lock_xmr, publish_cancel_transaction, wait_for_bitcoin_encrypted_signature, publish_cancel_transaction, wait_for_bitcoin_encrypted_signature, wait_for_bitcoin_refund,
wait_for_bitcoin_refund,
}; };
use crate::protocol::alice::AliceState; use crate::protocol::alice::AliceState;
use crate::{bitcoin, database, monero}; use crate::{bitcoin, database, monero};
@ -203,13 +202,13 @@ async fn run_until_internal(
} => { } => {
let state = match state3.expired_timelocks(bitcoin_wallet.as_ref()).await? { let state = match state3.expired_timelocks(bitcoin_wallet.as_ref()).await? {
ExpiredTimelocks::None => { ExpiredTimelocks::None => {
match build_bitcoin_redeem_transaction( let tx_redeem = TxRedeem::new(&state3.tx_lock, &state3.redeem_address);
match tx_redeem.complete(
*encrypted_signature, *encrypted_signature,
&state3.tx_lock,
state3.a.clone(), state3.a.clone(),
state3.s_a.to_secpfun_scalar(), state3.s_a.to_secpfun_scalar(),
state3.B, state3.B,
&state3.redeem_address,
) { ) {
Ok(tx) => match bitcoin_wallet.broadcast(tx, "redeem").await { Ok(tx) => match bitcoin_wallet.broadcast(tx, "redeem").await {
Ok(txid) => { Ok(txid) => {

Loading…
Cancel
Save