From eebc0a921e94e4bdf2aec15b0a58269674568dc4 Mon Sep 17 00:00:00 2001 From: Devrandom Date: Wed, 1 Sep 2021 14:56:50 +0200 Subject: [PATCH] Use ClosingTransaction in BaseSign --- lightning/src/chain/keysinterface.rs | 15 +++-------- lightning/src/ln/chan_utils.rs | 14 +++++------ lightning/src/ln/channel.rs | 28 ++++++++++----------- lightning/src/util/enforcing_trait_impls.rs | 6 +++-- 4 files changed, 29 insertions(+), 34 deletions(-) diff --git a/lightning/src/chain/keysinterface.rs b/lightning/src/chain/keysinterface.rs index 44a03d09..2da9e575 100644 --- a/lightning/src/chain/keysinterface.rs +++ b/lightning/src/chain/keysinterface.rs @@ -34,7 +34,7 @@ use util::ser::{Writeable, Writer, Readable}; use chain::transaction::OutPoint; use ln::chan_utils; -use ln::chan_utils::{HTLCOutputInCommitment, make_funding_redeemscript, ChannelPublicKeys, HolderCommitmentTransaction, ChannelTransactionParameters, CommitmentTransaction}; +use ln::chan_utils::{HTLCOutputInCommitment, make_funding_redeemscript, ChannelPublicKeys, HolderCommitmentTransaction, ChannelTransactionParameters, CommitmentTransaction, ClosingTransaction}; use ln::msgs::UnsignedChannelAnnouncement; use ln::script::ShutdownScript; @@ -322,7 +322,7 @@ pub trait BaseSign { /// /// Note that, due to rounding, there may be one "missing" satoshi, and either party may have /// chosen to forgo their output as dust. - fn sign_closing_transaction(&self, closing_tx: &Transaction, secp_ctx: &Secp256k1) -> Result; + fn sign_closing_transaction(&self, closing_tx: &ClosingTransaction, secp_ctx: &Secp256k1) -> Result; /// Signs a channel announcement message with our funding key, proving it comes from one /// of the channel participants. @@ -671,17 +671,10 @@ impl BaseSign for InMemorySigner { Err(()) } - fn sign_closing_transaction(&self, closing_tx: &Transaction, secp_ctx: &Secp256k1) -> Result { - if closing_tx.input.len() != 1 { return Err(()); } - if closing_tx.input[0].witness.len() != 0 { return Err(()); } - if closing_tx.output.len() > 2 { return Err(()); } - + fn sign_closing_transaction(&self, closing_tx: &ClosingTransaction, secp_ctx: &Secp256k1) -> Result { let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key); let channel_funding_redeemscript = make_funding_redeemscript(&funding_pubkey, &self.counterparty_pubkeys().funding_pubkey); - - let sighash = hash_to_message!(&bip143::SigHashCache::new(closing_tx) - .signature_hash(0, &channel_funding_redeemscript, self.channel_value_satoshis, SigHashType::All)[..]); - Ok(secp_ctx.sign(&sighash, &self.funding_key)) + Ok(closing_tx.trust().sign(&self.funding_key, &channel_funding_redeemscript, self.channel_value_satoshis, secp_ctx)) } fn sign_channel_announcement(&self, msg: &UnsignedChannelAnnouncement, secp_ctx: &Secp256k1) -> Result { diff --git a/lightning/src/ln/chan_utils.rs b/lightning/src/ln/chan_utils.rs index e4573155..994e1c27 100644 --- a/lightning/src/ln/chan_utils.rs +++ b/lightning/src/ln/chan_utils.rs @@ -81,7 +81,7 @@ pub fn build_commitment_secret(commitment_seed: &[u8; 32], idx: u64) -> [u8; 32] } /// Build a closing transaction -pub fn build_closing_transaction(value_to_holder: u64, value_to_counterparty: u64, holder_shutdown_script: Script, counterparty_shutdown_script: Script, funding_outpoint: OutPoint) -> 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 = Vec::new(); ins.push(TxIn { @@ -95,17 +95,17 @@ pub fn build_closing_transaction(value_to_holder: u64, value_to_counterparty: u6 let mut txouts: Vec<(TxOut, ())> = Vec::new(); - if value_to_counterparty > 0 { + if to_counterparty_value_sat > 0 { txouts.push((TxOut { - script_pubkey: counterparty_shutdown_script, - value: value_to_counterparty + script_pubkey: to_counterparty_script, + value: to_counterparty_value_sat }, ())); } - if value_to_holder > 0 { + if to_holder_value_sat > 0 { txouts.push((TxOut { - script_pubkey: holder_shutdown_script, - value: value_to_holder + script_pubkey: to_holder_script, + value: to_holder_value_sat }, ())); } diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index 2c835080..4b5b9c86 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -28,7 +28,7 @@ use ln::msgs; use ln::msgs::{DecodeError, OptionalField, DataLossProtect}; use ln::script::ShutdownScript; use ln::channelmanager::{PendingHTLCStatus, HTLCSource, HTLCFailReason, HTLCFailureMsg, PendingHTLCInfo, RAACommitmentOrder, BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA, MAX_LOCAL_BREAKDOWN_TIMEOUT}; -use ln::chan_utils::{CounterpartyCommitmentSecrets, TxCreationKeys, HTLCOutputInCommitment, HTLC_SUCCESS_TX_WEIGHT, HTLC_TIMEOUT_TX_WEIGHT, make_funding_redeemscript, ChannelPublicKeys, CommitmentTransaction, HolderCommitmentTransaction, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, MAX_HTLCS, get_commitment_transaction_number_obscure_factor, build_closing_transaction}; +use ln::chan_utils::{CounterpartyCommitmentSecrets, TxCreationKeys, HTLCOutputInCommitment, HTLC_SUCCESS_TX_WEIGHT, HTLC_TIMEOUT_TX_WEIGHT, make_funding_redeemscript, ChannelPublicKeys, CommitmentTransaction, HolderCommitmentTransaction, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, MAX_HTLCS, get_commitment_transaction_number_obscure_factor, ClosingTransaction}; use ln::chan_utils; use chain::BestBlock; use chain::chaininterface::{FeeEstimator,ConfirmationTarget}; @@ -1285,7 +1285,7 @@ impl Channel { } #[inline] - fn build_closing_transaction(&self, proposed_total_fee_satoshis: u64, skip_remote_output: bool) -> (Transaction, u64) { + fn build_closing_transaction(&self, proposed_total_fee_satoshis: u64, skip_remote_output: bool) -> (ClosingTransaction, u64) { assert!(self.pending_inbound_htlcs.is_empty()); assert!(self.pending_outbound_htlcs.is_empty()); assert!(self.pending_update_fee.is_none()); @@ -1315,7 +1315,8 @@ impl Channel { let counterparty_shutdown_script = self.counterparty_shutdown_scriptpubkey.clone().unwrap(); let funding_outpoint = self.funding_outpoint().into_bitcoin_outpoint(); - (build_closing_transaction(value_to_holder as u64, value_to_counterparty as u64, holder_shutdown_script, counterparty_shutdown_script, funding_outpoint), total_fee_satoshis) + let closing_transaction = ClosingTransaction::new(value_to_holder as u64, value_to_counterparty as u64, holder_shutdown_script, counterparty_shutdown_script, funding_outpoint); + (closing_transaction, total_fee_satoshis) } fn funding_outpoint(&self) -> OutPoint { @@ -3583,10 +3584,8 @@ impl Channel { Ok((shutdown, monitor_update, dropped_outbound_htlcs)) } - fn build_signed_closing_transaction(&self, tx: &mut Transaction, counterparty_sig: &Signature, sig: &Signature) { - if tx.input.len() != 1 { panic!("Tried to sign closing transaction that had input count != 1!"); } - if tx.input[0].witness.len() != 0 { panic!("Tried to re-sign closing transaction"); } - if tx.output.len() > 2 { panic!("Tried to sign bogus closing transaction"); } + fn build_signed_closing_transaction(&self, closing_tx: &ClosingTransaction, counterparty_sig: &Signature, sig: &Signature) -> Transaction { + let mut tx = closing_tx.trust().built_transaction().clone(); tx.input[0].witness.push(Vec::new()); // First is the multisig dummy @@ -3603,6 +3602,7 @@ impl Channel { tx.input[0].witness[2].push(SigHashType::All as u8); tx.input[0].witness.push(self.get_funding_redeemscript().into_bytes()); + tx } pub fn closing_signed(&mut self, fee_estimator: &F, msg: &msgs::ClosingSigned) -> Result<(Option, Option), ChannelError> @@ -3635,7 +3635,7 @@ impl Channel { if used_total_fee != msg.fee_satoshis { return Err(ChannelError::Close(format!("Remote sent us a closing_signed with a fee other than the value they can claim. Fee in message: {}. Actual closing tx fee: {}", msg.fee_satoshis, used_total_fee))); } - let mut sighash = hash_to_message!(&bip143::SigHashCache::new(&closing_tx).signature_hash(0, &funding_redeemscript, self.channel_value_satoshis, SigHashType::All)[..]); + let sighash = closing_tx.trust().get_sighash_all(&funding_redeemscript, self.channel_value_satoshis); match self.secp_ctx.verify(&sighash, &msg.signature, &self.get_counterparty_pubkeys().funding_pubkey) { Ok(_) => {}, @@ -3643,7 +3643,7 @@ impl Channel { // The remote end may have decided to revoke their output due to inconsistent dust // limits, so check for that case by re-checking the signature here. closing_tx = self.build_closing_transaction(msg.fee_satoshis, true).0; - sighash = hash_to_message!(&bip143::SigHashCache::new(&closing_tx).signature_hash(0, &funding_redeemscript, self.channel_value_satoshis, SigHashType::All)[..]); + let sighash = closing_tx.trust().get_sighash_all(&funding_redeemscript, self.channel_value_satoshis); secp_check!(self.secp_ctx.verify(&sighash, &msg.signature, self.counterparty_funding_pubkey()), "Invalid closing tx signature from peer".to_owned()); }, }; @@ -3651,10 +3651,10 @@ impl Channel { assert!(self.shutdown_scriptpubkey.is_some()); if let Some((last_fee, sig)) = self.last_sent_closing_fee { if last_fee == msg.fee_satoshis { - self.build_signed_closing_transaction(&mut closing_tx, &msg.signature, &sig); + let tx = self.build_signed_closing_transaction(&mut closing_tx, &msg.signature, &sig); self.channel_state = ChannelState::ShutdownComplete as u32; self.update_time_counter += 1; - return Ok((None, Some(closing_tx))); + return Ok((None, Some(tx))); } } @@ -3662,20 +3662,20 @@ impl Channel { macro_rules! propose_fee { ($new_fee: expr) => { - let (mut tx, used_fee) = if $new_fee == msg.fee_satoshis { + let (closing_tx, used_fee) = if $new_fee == msg.fee_satoshis { (closing_tx, $new_fee) } else { self.build_closing_transaction($new_fee, false) }; let sig = self.holder_signer - .sign_closing_transaction(&tx, &self.secp_ctx) + .sign_closing_transaction(&closing_tx, &self.secp_ctx) .map_err(|_| ChannelError::Close("External signer refused to sign closing transaction".to_owned()))?; let signed_tx = if $new_fee == msg.fee_satoshis { self.channel_state = ChannelState::ShutdownComplete as u32; self.update_time_counter += 1; - self.build_signed_closing_transaction(&mut tx, &msg.signature, &sig); + let tx = self.build_signed_closing_transaction(&closing_tx, &msg.signature, &sig); Some(tx) } else { None }; diff --git a/lightning/src/util/enforcing_trait_impls.rs b/lightning/src/util/enforcing_trait_impls.rs index b7dfe767..b905665c 100644 --- a/lightning/src/util/enforcing_trait_impls.rs +++ b/lightning/src/util/enforcing_trait_impls.rs @@ -7,7 +7,7 @@ // You may not use this file except in accordance with one or both of these // licenses. -use ln::chan_utils::{HTLCOutputInCommitment, ChannelPublicKeys, HolderCommitmentTransaction, CommitmentTransaction, ChannelTransactionParameters, TrustedCommitmentTransaction}; +use ln::chan_utils::{HTLCOutputInCommitment, ChannelPublicKeys, HolderCommitmentTransaction, CommitmentTransaction, ChannelTransactionParameters, TrustedCommitmentTransaction, ClosingTransaction}; use ln::{chan_utils, msgs}; use chain::keysinterface::{Sign, InMemorySigner, BaseSign}; @@ -182,7 +182,9 @@ impl BaseSign for EnforcingSigner { Ok(self.inner.sign_counterparty_htlc_transaction(htlc_tx, input, amount, per_commitment_point, htlc, secp_ctx).unwrap()) } - fn sign_closing_transaction(&self, closing_tx: &Transaction, secp_ctx: &Secp256k1) -> Result { + fn sign_closing_transaction(&self, closing_tx: &ClosingTransaction, secp_ctx: &Secp256k1) -> Result { + closing_tx.verify(self.inner.funding_outpoint().into_bitcoin_outpoint()) + .expect("derived different closing transaction"); Ok(self.inner.sign_closing_transaction(closing_tx, secp_ctx).unwrap()) } -- 2.30.2