Move more domain knowledge onto the TxCancel type

This commit is contained in:
Thomas Eizinger 2021-03-18 12:36:29 +11:00
parent 75aec95b0c
commit c92f2dbc77
No known key found for this signature in database
GPG Key ID: 651AC83A6C6C8B96
3 changed files with 46 additions and 25 deletions

View File

@ -1,12 +1,12 @@
use crate::bitcoin;
use crate::bitcoin::wallet::Watchable; use crate::bitcoin::wallet::Watchable;
use crate::bitcoin::{ use crate::bitcoin::{
build_shared_output_descriptor, Address, Amount, BlockHeight, PublicKey, Transaction, TxLock, build_shared_output_descriptor, Address, Amount, BlockHeight, PublicKey, Transaction, TxLock,
TX_FEE, TX_FEE,
}; };
use ::bitcoin::util::bip143::SigHashCache; use ::bitcoin::util::bip143::SigHashCache;
use ::bitcoin::{OutPoint, SigHash, SigHashType, TxIn, TxOut, Txid}; use ::bitcoin::{OutPoint, Script, SigHash, SigHashType, TxIn, TxOut, Txid};
use anyhow::Result; use anyhow::Result;
use bitcoin::Script;
use ecdsa_fun::Signature; use ecdsa_fun::Signature;
use miniscript::{Descriptor, DescriptorTrait}; use miniscript::{Descriptor, DescriptorTrait};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -149,7 +149,39 @@ impl TxCancel {
OutPoint::new(self.inner.txid(), 0) OutPoint::new(self.inner.txid(), 0)
} }
pub fn add_signatures( pub fn complete_as_alice(
self,
a: bitcoin::SecretKey,
B: bitcoin::PublicKey,
tx_cancel_sig_B: bitcoin::Signature,
) -> Result<Transaction> {
let sig_a = a.sign(self.digest());
let sig_b = tx_cancel_sig_B;
let tx_cancel = self
.add_signatures((a.public(), sig_a), (B, sig_b))
.expect("sig_{a,b} to be valid signatures for tx_cancel");
Ok(tx_cancel)
}
pub fn complete_as_bob(
self,
A: bitcoin::PublicKey,
b: bitcoin::SecretKey,
tx_cancel_sig_A: bitcoin::Signature,
) -> Result<Transaction> {
let sig_a = tx_cancel_sig_A;
let sig_b = b.sign(self.digest());
let tx_cancel = self
.add_signatures((A, sig_a), (b.public(), sig_b))
.expect("sig_{a,b} to be valid signatures for tx_cancel");
Ok(tx_cancel)
}
fn add_signatures(
self, self,
(A, sig_a): (PublicKey, Signature), (A, sig_a): (PublicKey, Signature),
(B, sig_b): (PublicKey, Signature), (B, sig_b): (PublicKey, Signature),

View File

@ -1,6 +1,6 @@
use crate::bitcoin; use crate::bitcoin;
use crate::bitcoin::{CancelTimelock, PunishTimelock, TxCancel, TxLock, TxRefund}; use crate::bitcoin::{CancelTimelock, PunishTimelock, TxCancel, TxLock, TxRefund};
use anyhow::{bail, Result}; use anyhow::{bail, Context, Result};
pub async fn publish_cancel_transaction( pub async fn publish_cancel_transaction(
tx_lock: TxLock, tx_lock: TxLock,
@ -25,15 +25,12 @@ pub async fn publish_cancel_transaction(
// TODO(Franck): Maybe the cancel transaction is already mined, in this case, // TODO(Franck): Maybe the cancel transaction is already mined, in this case,
// the broadcast will error out. // the broadcast will error out.
let sig_a = a.sign(tx_cancel.digest()); let transaction = tx_cancel
let sig_b = tx_cancel_sig_bob.clone(); .complete_as_alice(a, B, tx_cancel_sig_bob)
.context("Failed to complete Bitcoin cancel transaction")?;
let tx_cancel = tx_cancel
.add_signatures((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? // TODO(Franck): Error handling is delicate, why can't we broadcast?
let (..) = bitcoin_wallet.broadcast(tx_cancel, "cancel").await?; let (..) = bitcoin_wallet.broadcast(transaction, "cancel").await?;
// TODO(Franck): Wait until transaction is mined and returned mined // TODO(Franck): Wait until transaction is mined and returned mined
// block height // block height

View File

@ -8,7 +8,7 @@ use crate::monero_ext::ScalarExt;
use crate::protocol::alice::{Message1, Message3}; use crate::protocol::alice::{Message1, Message3};
use crate::protocol::bob::{EncryptedSignature, Message0, Message2, Message4}; use crate::protocol::bob::{EncryptedSignature, Message0, Message2, Message4};
use crate::protocol::CROSS_CURVE_PROOF_SYSTEM; use crate::protocol::CROSS_CURVE_PROOF_SYSTEM;
use anyhow::{anyhow, bail, Result}; use anyhow::{anyhow, bail, Context, Result};
use ecdsa_fun::adaptor::{Adaptor, HashTranscript}; use ecdsa_fun::adaptor::{Adaptor, HashTranscript};
use ecdsa_fun::nonce::Deterministic; use ecdsa_fun::nonce::Deterministic;
use ecdsa_fun::Signature; use ecdsa_fun::Signature;
@ -441,20 +441,12 @@ impl State4 {
} }
pub async fn submit_tx_cancel(&self, bitcoin_wallet: &bitcoin::Wallet) -> Result<Txid> { pub async fn submit_tx_cancel(&self, bitcoin_wallet: &bitcoin::Wallet) -> Result<Txid> {
let tx_cancel = let transaction =
bitcoin::TxCancel::new(&self.tx_lock, self.cancel_timelock, self.A, self.b.public()); bitcoin::TxCancel::new(&self.tx_lock, self.cancel_timelock, self.A, self.b.public())
.complete_as_bob(self.A, self.b.clone(), self.tx_cancel_sig_a.clone())
.context("Failed to complete Bitcoin cancel transaction")?;
let sig_a = self.tx_cancel_sig_a.clone(); let (tx_id, _) = bitcoin_wallet.broadcast(transaction, "cancel").await?;
let sig_b = self.b.sign(tx_cancel.digest());
let tx_cancel = tx_cancel
.add_signatures((self.A, sig_a), (self.b.public(), sig_b))
.expect(
"sig_{a,b} to be valid signatures for
tx_cancel",
);
let (tx_id, _) = bitcoin_wallet.broadcast(tx_cancel, "cancel").await?;
Ok(tx_id) Ok(tx_id)
} }