2021-03-16 04:11:14 -04:00
|
|
|
use crate::bitcoin::wallet::Watchable;
|
2021-04-28 20:40:04 -04:00
|
|
|
use crate::bitcoin::{self, Address, Amount, PunishTimelock, Transaction, TxCancel, Txid};
|
2021-03-03 19:28:58 -05:00
|
|
|
use ::bitcoin::util::bip143::SigHashCache;
|
|
|
|
use ::bitcoin::{SigHash, SigHashType};
|
2021-03-16 03:02:31 -04:00
|
|
|
use anyhow::{Context, Result};
|
2021-03-16 04:11:14 -04:00
|
|
|
use bdk::bitcoin::Script;
|
2021-02-24 21:52:05 -05:00
|
|
|
use miniscript::{Descriptor, DescriptorTrait};
|
2021-02-15 00:09:42 -05:00
|
|
|
use std::collections::HashMap;
|
|
|
|
|
2021-03-16 04:11:14 -04:00
|
|
|
#[derive(Debug)]
|
2021-02-15 00:09:42 -05:00
|
|
|
pub struct TxPunish {
|
|
|
|
inner: Transaction,
|
|
|
|
digest: SigHash,
|
2021-02-24 21:52:05 -05:00
|
|
|
cancel_output_descriptor: Descriptor<::bitcoin::PublicKey>,
|
2021-03-16 04:11:14 -04:00
|
|
|
watch_script: Script,
|
2021-02-15 00:09:42 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
impl TxPunish {
|
|
|
|
pub fn new(
|
|
|
|
tx_cancel: &TxCancel,
|
|
|
|
punish_address: &Address,
|
|
|
|
punish_timelock: PunishTimelock,
|
2021-04-28 20:40:04 -04:00
|
|
|
spending_fee: Amount,
|
2021-02-15 00:09:42 -05:00
|
|
|
) -> Self {
|
2021-04-28 20:40:04 -04:00
|
|
|
let tx_punish =
|
|
|
|
tx_cancel.build_spend_transaction(punish_address, Some(punish_timelock), spending_fee);
|
2021-02-15 00:09:42 -05:00
|
|
|
|
|
|
|
let digest = SigHashCache::new(&tx_punish).signature_hash(
|
|
|
|
0, // Only one input: cancel transaction
|
2021-02-17 21:33:50 -05:00
|
|
|
&tx_cancel.output_descriptor.script_code(),
|
2021-02-15 00:09:42 -05:00
|
|
|
tx_cancel.amount().as_sat(),
|
|
|
|
SigHashType::All,
|
|
|
|
);
|
|
|
|
|
|
|
|
Self {
|
|
|
|
inner: tx_punish,
|
|
|
|
digest,
|
2021-02-24 21:52:05 -05:00
|
|
|
cancel_output_descriptor: tx_cancel.output_descriptor.clone(),
|
2021-03-16 04:11:14 -04:00
|
|
|
watch_script: punish_address.script_pubkey(),
|
2021-02-15 00:09:42 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn digest(&self) -> SigHash {
|
|
|
|
self.digest
|
|
|
|
}
|
|
|
|
|
2021-03-16 03:02:31 -04:00
|
|
|
pub fn complete(
|
2021-02-15 00:09:42 -05:00
|
|
|
self,
|
2021-03-16 03:02:31 -04:00
|
|
|
tx_punish_sig_bob: bitcoin::Signature,
|
|
|
|
a: bitcoin::SecretKey,
|
|
|
|
B: bitcoin::PublicKey,
|
2021-02-15 00:09:42 -05:00
|
|
|
) -> Result<Transaction> {
|
2021-03-16 03:02:31 -04:00
|
|
|
let sig_a = a.sign(self.digest());
|
|
|
|
let sig_b = tx_punish_sig_bob;
|
|
|
|
|
2021-02-15 00:09:42 -05:00
|
|
|
let satisfier = {
|
|
|
|
let mut satisfier = HashMap::with_capacity(2);
|
|
|
|
|
2021-03-16 03:02:31 -04:00
|
|
|
let A = a.public().into();
|
|
|
|
let B = B.into();
|
2021-02-15 00:09:42 -05:00
|
|
|
|
|
|
|
// The order in which these are inserted doesn't matter
|
|
|
|
satisfier.insert(A, (sig_a.into(), ::bitcoin::SigHashType::All));
|
|
|
|
satisfier.insert(B, (sig_b.into(), ::bitcoin::SigHashType::All));
|
|
|
|
|
|
|
|
satisfier
|
|
|
|
};
|
|
|
|
|
|
|
|
let mut tx_punish = self.inner;
|
2021-02-24 21:52:05 -05:00
|
|
|
self.cancel_output_descriptor
|
2021-03-16 03:02:31 -04:00
|
|
|
.satisfy(&mut tx_punish.input[0], satisfier)
|
|
|
|
.context("Failed to satisfy inputs with given signatures")?;
|
2021-02-15 00:09:42 -05:00
|
|
|
|
|
|
|
Ok(tx_punish)
|
|
|
|
}
|
2021-05-03 03:35:41 -04:00
|
|
|
|
|
|
|
pub fn weight() -> usize {
|
|
|
|
548
|
|
|
|
}
|
2021-02-15 00:09:42 -05:00
|
|
|
}
|
2021-03-16 04:11:14 -04:00
|
|
|
|
|
|
|
impl Watchable for TxPunish {
|
|
|
|
fn id(&self) -> Txid {
|
|
|
|
self.inner.txid()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn script(&self) -> Script {
|
|
|
|
self.watch_script.clone()
|
|
|
|
}
|
|
|
|
}
|