use ln::{PaymentHash, PaymentPreimage};
use ln::msgs::DecodeError;
use util::ser::{Readable, Writeable, Writer};
-use util::byte_utils;
+use util::{byte_utils, transaction_utils};
use bitcoin::hash_types::WPubkeyHash;
use bitcoin::secp256k1::key::{SecretKey, PublicKey};
res
}
+/// Build a closing transaction
+pub fn build_closing_transaction(to_holder_value_sat: u64, to_counterparty_value_sat: u64, to_holder_script: Script, to_counterparty_script: Script, funding_outpoint: OutPoint) -> Transaction {
+ let txins = {
+ let mut ins: Vec<TxIn> = Vec::new();
+ ins.push(TxIn {
+ previous_output: funding_outpoint,
+ script_sig: Script::new(),
+ sequence: 0xffffffff,
+ witness: Vec::new(),
+ });
+ ins
+ };
+
+ let mut txouts: Vec<(TxOut, ())> = Vec::new();
+
+ if to_counterparty_value_sat > 0 {
+ txouts.push((TxOut {
+ script_pubkey: to_counterparty_script,
+ value: to_counterparty_value_sat
+ }, ()));
+ }
+
+ if to_holder_value_sat > 0 {
+ txouts.push((TxOut {
+ script_pubkey: to_holder_script,
+ value: to_holder_value_sat
+ }, ()));
+ }
+
+ transaction_utils::sort_outputs(&mut txouts, |_, _| { cmp::Ordering::Equal }); // Ordering doesnt matter if they used our pubkey...
+
+ let mut outputs: Vec<TxOut> = Vec::new();
+ for out in txouts.drain(..) {
+ outputs.push(out.0);
+ }
+
+ Transaction {
+ version: 2,
+ lock_time: 0,
+ input: txins,
+ output: outputs,
+ }
+}
+
/// Implements the per-commitment secret storage scheme from
/// [BOLT 3](https://github.com/lightningnetwork/lightning-rfc/blob/dcbf8583976df087c79c3ce0b535311212e6812d/03-transactions.md#efficient-per-commitment-secret-storage).
///
}
}
-/// This class tracks the per-transaction information needed to build a commitment transaction and to
+/// This class tracks the per-transaction information needed to build a closing transaction and will
+/// actually build it and sign.
+///
+/// This class can be used inside a signer implementation to generate a signature given the relevant
+/// secret key.
+pub struct ClosingTransaction {
+ to_holder_value_sat: u64,
+ to_counterparty_value_sat: u64,
+ to_holder_script: Script,
+ to_counterparty_script: Script,
+ built: Transaction,
+}
+
+impl ClosingTransaction {
+ /// Construct an object of the class
+ pub fn new(
+ to_holder_value_sat: u64,
+ to_counterparty_value_sat: u64,
+ to_holder_script: Script,
+ to_counterparty_script: Script,
+ funding_outpoint: OutPoint,
+ ) -> Self {
+ let built = build_closing_transaction(
+ to_holder_value_sat, to_counterparty_value_sat,
+ to_holder_script.clone(), to_counterparty_script.clone(),
+ funding_outpoint
+ );
+ ClosingTransaction {
+ to_holder_value_sat,
+ to_counterparty_value_sat,
+ to_holder_script,
+ to_counterparty_script,
+ built
+ }
+ }
+
+ /// Trust our pre-built transaction.
+ ///
+ /// Applies a wrapper which allows access to the transaction.
+ ///
+ /// This should only be used if you fully trust the builder of this object. It should not
+ /// be used by an external signer - instead use the verify function.
+ pub fn trust(&self) -> TrustedClosingTransaction {
+ TrustedClosingTransaction { inner: self }
+ }
+
+ /// Verify our pre-built transaction.
+ ///
+ /// Applies a wrapper which allows access to the transaction.
+ ///
+ /// An external validating signer must call this method before signing
+ /// or using the built transaction.
+ pub fn verify(&self, funding_outpoint: OutPoint) -> Result<TrustedClosingTransaction, ()> {
+ let built = build_closing_transaction(
+ self.to_holder_value_sat, self.to_counterparty_value_sat,
+ self.to_holder_script.clone(), self.to_counterparty_script.clone(),
+ funding_outpoint
+ );
+ if self.built != built {
+ return Err(())
+ }
+ Ok(TrustedClosingTransaction { inner: self })
+ }
+
+ /// The value to be sent to the holder, or zero if the output will be omitted
+ pub fn to_holder_value_sat(&self) -> u64 {
+ self.to_holder_value_sat
+ }
+
+ /// The value to be sent to the counterparty, or zero if the output will be omitted
+ pub fn to_counterparty_value_sat(&self) -> u64 {
+ self.to_counterparty_value_sat
+ }
+
+ /// The destination of the holder's output
+ pub fn to_holder_script(&self) -> &Script {
+ &self.to_holder_script
+ }
+
+ /// The destination of the counterparty's output
+ pub fn to_counterparty_script(&self) -> &Script {
+ &self.to_counterparty_script
+ }
+}
+
+/// A wrapper on ClosingTransaction indicating that the built bitcoin
+/// transaction is trusted.
+///
+/// See trust() and verify() functions on CommitmentTransaction.
+///
+/// This structure implements Deref.
+pub struct TrustedClosingTransaction<'a> {
+ inner: &'a ClosingTransaction,
+}
+
+impl<'a> Deref for TrustedClosingTransaction<'a> {
+ type Target = ClosingTransaction;
+
+ fn deref(&self) -> &Self::Target { self.inner }
+}
+
+impl<'a> TrustedClosingTransaction<'a> {
+ /// The pre-built Bitcoin commitment transaction
+ pub fn built_transaction(&self) -> &Transaction {
+ &self.inner.built
+ }
+
+ /// Get the SIGHASH_ALL sighash value of the transaction.
+ ///
+ /// This can be used to verify a signature.
+ pub fn get_sighash_all(&self, funding_redeemscript: &Script, channel_value_satoshis: u64) -> Message {
+ let sighash = &bip143::SigHashCache::new(&self.inner.built).signature_hash(0, funding_redeemscript, channel_value_satoshis, SigHashType::All)[..];
+ hash_to_message!(sighash)
+ }
+
+ /// Sign a transaction, either because we are counter-signing the counterparty's transaction or
+ /// because we are about to broadcast a holder transaction.
+ pub fn sign<T: secp256k1::Signing>(&self, funding_key: &SecretKey, funding_redeemscript: &Script, channel_value_satoshis: u64, secp_ctx: &Secp256k1<T>) -> Signature {
+ let sighash = self.get_sighash_all(funding_redeemscript, channel_value_satoshis);
+ secp_ctx.sign(&sighash, funding_key)
+ }
+}
+
+/// This class tracks the per-transaction information needed to build a commitment transaction and will
/// actually build it and sign. It is used for holder transactions that we sign only when needed
/// and for transactions we sign for the counterparty.
///
/// Applies a wrapper which allows access to these fields.
///
/// This should only be used if you fully trust the builder of this object. It should not
- /// be used by an external signer - instead use the verify function.
+ /// be used by an external signer - instead use the verify function.
pub fn trust(&self) -> TrustedCommitmentTransaction {
TrustedCommitmentTransaction { inner: self }
}