Fix comment spelling and clarify algebra a bit.
[rust-lightning] / src / ln / channel.rs
index 5bc5fdf8be126063437f3ffe65dc7f5076a4b882..237ccd840f561a86d89d915bf2c4c635157f37b7 100644 (file)
@@ -2,12 +2,13 @@ use bitcoin::blockdata::block::BlockHeader;
 use bitcoin::blockdata::script::{Script,Builder};
 use bitcoin::blockdata::transaction::{TxIn, TxOut, Transaction, SigHashType};
 use bitcoin::blockdata::opcodes;
-use bitcoin::util::hash::{BitcoinHash, Sha256dHash, Hash160};
+use bitcoin::util::hash::{BitcoinHash, Sha256dHash};
 use bitcoin::util::bip143;
 use bitcoin::consensus::encode::{self, Encodable, Decodable};
 
 use bitcoin_hashes::{Hash, HashEngine};
 use bitcoin_hashes::sha256::Hash as Sha256;
+use bitcoin_hashes::hash160::Hash as Hash160;
 
 use secp256k1::key::{PublicKey,SecretKey};
 use secp256k1::{Secp256k1,Message,Signature};
@@ -131,18 +132,6 @@ struct OutboundHTLCOutput {
        fail_reason: Option<HTLCFailReason>,
 }
 
-macro_rules! get_htlc_in_commitment {
-       ($htlc: expr, $offered: expr) => {
-               HTLCOutputInCommitment {
-                       offered: $offered,
-                       amount_msat: $htlc.amount_msat,
-                       cltv_expiry: $htlc.cltv_expiry,
-                       payment_hash: $htlc.payment_hash,
-                       transaction_output_index: 0
-               }
-       }
-}
-
 /// See AwaitingRemoteRevoke ChannelState for more info
 enum HTLCUpdateAwaitingACK {
        AddHTLC {
@@ -314,6 +303,9 @@ pub(super) struct Channel {
        funding_tx_confirmations: u64,
 
        their_dust_limit_satoshis: u64,
+       #[cfg(test)]
+       pub(super) our_dust_limit_satoshis: u64,
+       #[cfg(not(test))]
        our_dust_limit_satoshis: u64,
        their_max_htlc_value_in_flight_msat: u64,
        //get_our_max_htlc_value_in_flight_msat(): u64,
@@ -345,7 +337,7 @@ pub(super) struct Channel {
        logger: Arc<Logger>,
 }
 
-const OUR_MAX_HTLCS: u16 = 5; //TODO
+const OUR_MAX_HTLCS: u16 = 50; //TODO
 /// Confirmation count threshold at which we close a channel. Ideally we'd keep the channel around
 /// on ice until the funding transaction gets more confirmations, but the LN protocol doesn't
 /// really allow for this, so instead we're stuck closing it out at that point.
@@ -755,8 +747,12 @@ impl Channel {
        /// have not yet committed it. Such HTLCs will only be included in transactions which are being
        /// generated by the peer which proposed adding the HTLCs, and thus we need to understand both
        /// which peer generated this transaction and "to whom" this transaction flows.
+       /// Returns (the transaction built, the number of HTLC outputs which were present in the
+       /// transaction, the list of HTLCs which were not ignored when building the transaction).
+       /// Note that below-dust HTLCs are included in the third return value, but not the second, and
+       /// sources are provided only for outbound HTLCs in the third return value.
        #[inline]
-       fn build_commitment_transaction(&self, commitment_number: u64, keys: &TxCreationKeys, local: bool, generated_by_local: bool, feerate_per_kw: u64) -> (Transaction, Vec<HTLCOutputInCommitment>, Vec<(PaymentHash, &HTLCSource, Option<u32>)>) {
+       fn build_commitment_transaction(&self, commitment_number: u64, keys: &TxCreationKeys, local: bool, generated_by_local: bool, feerate_per_kw: u64) -> (Transaction, usize, Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)>) {
                let obscured_commitment_transaction_number = self.get_commitment_transaction_number_obscure_factor() ^ (INITIAL_COMMITMENT_NUMBER - commitment_number);
 
                let txins = {
@@ -771,38 +767,46 @@ impl Channel {
                };
 
                let mut txouts: Vec<(TxOut, Option<(HTLCOutputInCommitment, Option<&HTLCSource>)>)> = Vec::with_capacity(self.pending_inbound_htlcs.len() + self.pending_outbound_htlcs.len() + 2);
-               let mut unincluded_htlc_sources: Vec<(PaymentHash, &HTLCSource, Option<u32>)> = Vec::new();
+               let mut included_dust_htlcs: Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)> = Vec::new();
 
                let dust_limit_satoshis = if local { self.our_dust_limit_satoshis } else { self.their_dust_limit_satoshis };
                let mut remote_htlc_total_msat = 0;
                let mut local_htlc_total_msat = 0;
                let mut value_to_self_msat_offset = 0;
 
+               macro_rules! get_htlc_in_commitment {
+                       ($htlc: expr, $offered: expr) => {
+                               HTLCOutputInCommitment {
+                                       offered: $offered,
+                                       amount_msat: $htlc.amount_msat,
+                                       cltv_expiry: $htlc.cltv_expiry,
+                                       payment_hash: $htlc.payment_hash,
+                                       transaction_output_index: None
+                               }
+                       }
+               }
+
                macro_rules! add_htlc_output {
                        ($htlc: expr, $outbound: expr, $source: expr) => {
                                if $outbound == local { // "offered HTLC output"
+                                       let htlc_in_tx = get_htlc_in_commitment!($htlc, true);
                                        if $htlc.amount_msat / 1000 >= dust_limit_satoshis + (feerate_per_kw * HTLC_TIMEOUT_TX_WEIGHT / 1000) {
-                                               let htlc_in_tx = get_htlc_in_commitment!($htlc, true);
                                                txouts.push((TxOut {
                                                        script_pubkey: chan_utils::get_htlc_redeemscript(&htlc_in_tx, &keys).to_v0_p2wsh(),
                                                        value: $htlc.amount_msat / 1000
                                                }, Some((htlc_in_tx, $source))));
                                        } else {
-                                               if let Some(source) = $source {
-                                                       unincluded_htlc_sources.push(($htlc.payment_hash, source, None));
-                                               }
+                                               included_dust_htlcs.push((htlc_in_tx, $source));
                                        }
                                } else {
+                                       let htlc_in_tx = get_htlc_in_commitment!($htlc, false);
                                        if $htlc.amount_msat / 1000 >= dust_limit_satoshis + (feerate_per_kw * HTLC_SUCCESS_TX_WEIGHT / 1000) {
-                                               let htlc_in_tx = get_htlc_in_commitment!($htlc, false);
                                                txouts.push((TxOut { // "received HTLC output"
                                                        script_pubkey: chan_utils::get_htlc_redeemscript(&htlc_in_tx, &keys).to_v0_p2wsh(),
                                                        value: $htlc.amount_msat / 1000
                                                }, Some((htlc_in_tx, $source))));
                                        } else {
-                                               if let Some(source) = $source {
-                                                       unincluded_htlc_sources.push(($htlc.payment_hash, source, None));
-                                               }
+                                               included_dust_htlcs.push((htlc_in_tx, $source));
                                        }
                                }
                        }
@@ -906,7 +910,7 @@ impl Channel {
                if value_to_b >= (dust_limit_satoshis as i64) {
                        txouts.push((TxOut {
                                script_pubkey: Builder::new().push_opcode(opcodes::All::OP_PUSHBYTES_0)
-                                                            .push_slice(&Hash160::from_data(&keys.b_payment_key.serialize())[..])
+                                                            .push_slice(&Hash160::hash(&keys.b_payment_key.serialize())[..])
                                                             .into_script(),
                                value: value_to_b as u64
                        }, None));
@@ -915,31 +919,28 @@ impl Channel {
                transaction_utils::sort_outputs(&mut txouts);
 
                let mut outputs: Vec<TxOut> = Vec::with_capacity(txouts.len());
-               let mut htlcs_included: Vec<HTLCOutputInCommitment> = Vec::with_capacity(txouts.len());
-               let mut htlc_sources: Vec<(PaymentHash, &HTLCSource, Option<u32>)> = Vec::with_capacity(txouts.len() + unincluded_htlc_sources.len());
-               for (idx, out) in txouts.drain(..).enumerate() {
+               let mut htlcs_included: Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)> = Vec::with_capacity(txouts.len() + included_dust_htlcs.len());
+               for (idx, mut out) in txouts.drain(..).enumerate() {
                        outputs.push(out.0);
-                       if let Some((mut htlc, source_option)) = out.1 {
-                               htlc.transaction_output_index = idx as u32;
-                               if let Some(source) = source_option {
-                                       htlc_sources.push((htlc.payment_hash, source, Some(idx as u32)));
-                               }
-                               htlcs_included.push(htlc);
+                       if let Some((mut htlc, source_option)) = out.1.take() {
+                               htlc.transaction_output_index = Some(idx as u32);
+                               htlcs_included.push((htlc, source_option));
                        }
                }
-               htlc_sources.append(&mut unincluded_htlc_sources);
+               let non_dust_htlc_count = htlcs_included.len();
+               htlcs_included.append(&mut included_dust_htlcs);
 
                (Transaction {
                        version: 2,
                        lock_time: ((0x20 as u32) << 8*3) | ((obscured_commitment_transaction_number & 0xffffffu64) as u32),
                        input: txins,
                        output: outputs,
-               }, htlcs_included, htlc_sources)
+               }, non_dust_htlc_count, htlcs_included)
        }
 
        #[inline]
        fn get_closing_scriptpubkey(&self) -> Script {
-               let our_channel_close_key_hash = Hash160::from_data(&self.shutdown_pubkey.serialize());
+               let our_channel_close_key_hash = Hash160::hash(&self.shutdown_pubkey.serialize());
                Builder::new().push_opcode(opcodes::All::OP_PUSHBYTES_0).push_slice(&our_channel_close_key_hash[..]).into_script()
        }
 
@@ -1310,16 +1311,6 @@ impl Channel {
                }))
        }
 
-       pub fn get_update_fail_htlc_and_commit(&mut self, htlc_id: u64, err_packet: msgs::OnionErrorPacket) -> Result<Option<(msgs::UpdateFailHTLC, msgs::CommitmentSigned, ChannelMonitor)>, ChannelError> {
-               match self.get_update_fail_htlc(htlc_id, err_packet)? {
-                       Some(update_fail_htlc) => {
-                               let (commitment, monitor_update) = self.send_commitment_no_status_check()?;
-                               Ok(Some((update_fail_htlc, commitment, monitor_update)))
-                       },
-                       None => Ok(None)
-               }
-       }
-
        // Message handlers:
 
        pub fn accept_channel(&mut self, msg: &msgs::AcceptChannel, config: &UserConfig) -> Result<(), ChannelError> {
@@ -1457,9 +1448,9 @@ impl Channel {
 
                // Now that we're past error-generating stuff, update our local state:
 
-               self.channel_monitor.provide_latest_remote_commitment_tx_info(&remote_initial_commitment_tx, Vec::new(), Vec::new(), self.cur_remote_commitment_transaction_number, self.their_cur_commitment_point.unwrap());
+               self.channel_monitor.provide_latest_remote_commitment_tx_info(&remote_initial_commitment_tx, Vec::new(), self.cur_remote_commitment_transaction_number, self.their_cur_commitment_point.unwrap());
                self.last_local_commitment_txn = vec![local_initial_commitment_tx.clone()];
-               self.channel_monitor.provide_latest_local_commitment_tx_info(local_initial_commitment_tx, local_keys, self.feerate_per_kw, Vec::new(), Vec::new());
+               self.channel_monitor.provide_latest_local_commitment_tx_info(local_initial_commitment_tx, local_keys, self.feerate_per_kw, Vec::new());
                self.channel_state = ChannelState::FundingSent as u32;
                self.channel_id = funding_txo.to_channel_id();
                self.cur_remote_commitment_transaction_number -= 1;
@@ -1496,7 +1487,7 @@ impl Channel {
                secp_check!(self.secp_ctx.verify(&local_sighash, &msg.signature, &self.their_funding_pubkey.unwrap()), "Invalid funding_signed signature from peer");
 
                self.sign_commitment_transaction(&mut local_initial_commitment_tx, &msg.signature);
-               self.channel_monitor.provide_latest_local_commitment_tx_info(local_initial_commitment_tx.clone(), local_keys, self.feerate_per_kw, Vec::new(), Vec::new());
+               self.channel_monitor.provide_latest_local_commitment_tx_info(local_initial_commitment_tx.clone(), local_keys, self.feerate_per_kw, Vec::new());
                self.last_local_commitment_txn = vec![local_initial_commitment_tx];
                self.channel_state = ChannelState::FundingSent as u32;
                self.cur_local_commitment_transaction_number -= 1;
@@ -1699,7 +1690,7 @@ impl Channel {
 
                let mut local_commitment_tx = {
                        let mut commitment_tx = self.build_commitment_transaction(self.cur_local_commitment_transaction_number, &local_keys, true, false, feerate_per_kw);
-                       let htlcs_cloned: Vec<_> = commitment_tx.2.drain(..).map(|htlc_source| (htlc_source.0, htlc_source.1.clone(), htlc_source.2)).collect();
+                       let htlcs_cloned: Vec<_> = commitment_tx.2.drain(..).map(|htlc| (htlc.0, htlc.1.map(|h| h.clone()))).collect();
                        (commitment_tx.0, commitment_tx.1, htlcs_cloned)
                };
                let local_commitment_txid = local_commitment_tx.0.txid();
@@ -1708,7 +1699,7 @@ impl Channel {
 
                //If channel fee was updated by funder confirm funder can afford the new fee rate when applied to the current local commitment transaction
                if update_fee {
-                       let num_htlcs = local_commitment_tx.1.len();
+                       let num_htlcs = local_commitment_tx.1;
                        let total_fee: u64 = feerate_per_kw as u64 * (COMMITMENT_TX_BASE_WEIGHT + (num_htlcs as u64) * COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000;
 
                        if self.channel_value_satoshis - self.value_to_self_msat / 1000 < total_fee + self.their_channel_reserve_satoshis {
@@ -1716,28 +1707,32 @@ impl Channel {
                        }
                }
 
-               if msg.htlc_signatures.len() != local_commitment_tx.1.len() {
+               if msg.htlc_signatures.len() != local_commitment_tx.1 {
                        return Err(ChannelError::Close("Got wrong number of HTLC signatures from remote"));
                }
 
-               let mut new_local_commitment_txn = Vec::with_capacity(local_commitment_tx.1.len() + 1);
+               let mut new_local_commitment_txn = Vec::with_capacity(local_commitment_tx.1 + 1);
                self.sign_commitment_transaction(&mut local_commitment_tx.0, &msg.signature);
                new_local_commitment_txn.push(local_commitment_tx.0.clone());
 
-               let mut htlcs_and_sigs = Vec::with_capacity(local_commitment_tx.1.len());
-               for (idx, htlc) in local_commitment_tx.1.drain(..).enumerate() {
-                       let mut htlc_tx = self.build_htlc_transaction(&local_commitment_txid, &htlc, true, &local_keys, feerate_per_kw);
-                       let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &local_keys);
-                       let htlc_sighash = Message::from_slice(&bip143::SighashComponents::new(&htlc_tx).sighash_all(&htlc_tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]).unwrap();
-                       secp_check!(self.secp_ctx.verify(&htlc_sighash, &msg.htlc_signatures[idx], &local_keys.b_htlc_key), "Invalid HTLC tx signature from peer");
-                       let htlc_sig = if htlc.offered {
-                               let htlc_sig = self.sign_htlc_transaction(&mut htlc_tx, &msg.htlc_signatures[idx], &None, &htlc, &local_keys)?;
-                               new_local_commitment_txn.push(htlc_tx);
-                               htlc_sig
+               let mut htlcs_and_sigs = Vec::with_capacity(local_commitment_tx.2.len());
+               for (idx, (htlc, source)) in local_commitment_tx.2.drain(..).enumerate() {
+                       if let Some(_) = htlc.transaction_output_index {
+                               let mut htlc_tx = self.build_htlc_transaction(&local_commitment_txid, &htlc, true, &local_keys, feerate_per_kw);
+                               let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &local_keys);
+                               let htlc_sighash = Message::from_slice(&bip143::SighashComponents::new(&htlc_tx).sighash_all(&htlc_tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]).unwrap();
+                               secp_check!(self.secp_ctx.verify(&htlc_sighash, &msg.htlc_signatures[idx], &local_keys.b_htlc_key), "Invalid HTLC tx signature from peer");
+                               let htlc_sig = if htlc.offered {
+                                       let htlc_sig = self.sign_htlc_transaction(&mut htlc_tx, &msg.htlc_signatures[idx], &None, &htlc, &local_keys)?;
+                                       new_local_commitment_txn.push(htlc_tx);
+                                       htlc_sig
+                               } else {
+                                       self.create_htlc_tx_signature(&htlc_tx, &htlc, &local_keys)?.1
+                               };
+                               htlcs_and_sigs.push((htlc, Some((msg.htlc_signatures[idx], htlc_sig)), source));
                        } else {
-                               self.create_htlc_tx_signature(&htlc_tx, &htlc, &local_keys)?.1
-                       };
-                       htlcs_and_sigs.push((htlc, msg.htlc_signatures[idx], htlc_sig));
+                               htlcs_and_sigs.push((htlc, None, source));
+                       }
                }
 
                let next_per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &self.build_local_commitment_secret(self.cur_local_commitment_transaction_number - 1));
@@ -1764,7 +1759,7 @@ impl Channel {
                        self.monitor_pending_order = None;
                }
 
-               self.channel_monitor.provide_latest_local_commitment_tx_info(local_commitment_tx.0, local_keys, self.feerate_per_kw, htlcs_and_sigs, local_commitment_tx.2);
+               self.channel_monitor.provide_latest_local_commitment_tx_info(local_commitment_tx.0, local_keys, self.feerate_per_kw, htlcs_and_sigs);
 
                for htlc in self.pending_inbound_htlcs.iter_mut() {
                        let new_forward = if let &InboundHTLCState::RemoteAnnounced(ref forward_info) = &htlc.state {
@@ -3034,7 +3029,7 @@ impl Channel {
                let temporary_channel_id = self.channel_id;
 
                // Now that we're past error-generating stuff, update our local state:
-               self.channel_monitor.provide_latest_remote_commitment_tx_info(&commitment_tx, Vec::new(), Vec::new(), self.cur_remote_commitment_transaction_number, self.their_cur_commitment_point.unwrap());
+               self.channel_monitor.provide_latest_remote_commitment_tx_info(&commitment_tx, Vec::new(), self.cur_remote_commitment_transaction_number, self.their_cur_commitment_point.unwrap());
                self.channel_state = ChannelState::FundingCreated as u32;
                self.channel_id = funding_txo.to_channel_id();
                self.cur_remote_commitment_transaction_number -= 1;
@@ -3124,6 +3119,7 @@ impl Channel {
        /// waiting on the remote peer to send us a revoke_and_ack during which time we cannot add new
        /// HTLCs on the wire or we wouldn't be able to determine what they actually ACK'ed.
        /// You MUST call send_commitment prior to any other calls on this Channel
+       /// If an Err is returned, its a ChannelError::Ignore!
        pub fn send_htlc(&mut self, amount_msat: u64, payment_hash: PaymentHash, cltv_expiry: u32, source: HTLCSource, onion_routing_packet: msgs::OnionPacket) -> Result<Option<msgs::UpdateAddHTLC>, ChannelError> {
                if (self.channel_state & (ChannelState::ChannelFunded as u32 | BOTH_SIDES_SHUTDOWN_MASK)) != (ChannelState::ChannelFunded as u32) {
                        return Err(ChannelError::Ignore("Cannot send HTLC until channel is fully established and we haven't started shutting down"));
@@ -3235,6 +3231,12 @@ impl Channel {
                        }
                        if have_updates { break; }
                }
+               for htlc in self.pending_inbound_htlcs.iter() {
+                       if let InboundHTLCState::LocalRemoved(_) = htlc.state {
+                               have_updates = true;
+                       }
+                       if have_updates { break; }
+               }
                if !have_updates {
                        panic!("Cannot create commitment tx until we have some updates to send");
                }
@@ -3259,23 +3261,23 @@ impl Channel {
                        }
                }
 
-               let (res, remote_commitment_tx, htlcs, htlc_sources) = match self.send_commitment_no_state_update() {
-                       Ok((res, (remote_commitment_tx, htlcs, mut htlc_sources))) => {
+               let (res, remote_commitment_tx, htlcs) = match self.send_commitment_no_state_update() {
+                       Ok((res, (remote_commitment_tx, mut htlcs))) => {
                                // Update state now that we've passed all the can-fail calls...
-                               let htlc_sources_no_ref = htlc_sources.drain(..).map(|htlc_source| (htlc_source.0, htlc_source.1.clone(), htlc_source.2)).collect();
-                               (res, remote_commitment_tx, htlcs, htlc_sources_no_ref)
+                               let htlcs_no_ref = htlcs.drain(..).map(|(htlc, htlc_source)| (htlc, htlc_source.map(|source_ref| Box::new(source_ref.clone())))).collect();
+                               (res, remote_commitment_tx, htlcs_no_ref)
                        },
                        Err(e) => return Err(e),
                };
 
-               self.channel_monitor.provide_latest_remote_commitment_tx_info(&remote_commitment_tx, htlcs, htlc_sources, self.cur_remote_commitment_transaction_number, self.their_cur_commitment_point.unwrap());
+               self.channel_monitor.provide_latest_remote_commitment_tx_info(&remote_commitment_tx, htlcs, self.cur_remote_commitment_transaction_number, self.their_cur_commitment_point.unwrap());
                self.channel_state |= ChannelState::AwaitingRemoteRevoke as u32;
                Ok((res, self.channel_monitor.clone()))
        }
 
        /// Only fails in case of bad keys. Used for channel_reestablish commitment_signed generation
        /// when we shouldn't change HTLC/channel state.
-       fn send_commitment_no_state_update(&self) -> Result<(msgs::CommitmentSigned, (Transaction, Vec<HTLCOutputInCommitment>, Vec<(PaymentHash, &HTLCSource, Option<u32>)>)), ChannelError> {
+       fn send_commitment_no_state_update(&self) -> Result<(msgs::CommitmentSigned, (Transaction, Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)>)), ChannelError> {
                let funding_script = self.get_funding_redeemscript();
 
                let mut feerate_per_kw = self.feerate_per_kw;
@@ -3291,21 +3293,22 @@ impl Channel {
                let remote_sighash = Message::from_slice(&bip143::SighashComponents::new(&remote_commitment_tx.0).sighash_all(&remote_commitment_tx.0.input[0], &funding_script, self.channel_value_satoshis)[..]).unwrap();
                let our_sig = self.secp_ctx.sign(&remote_sighash, &self.local_keys.funding_key);
 
-               let mut htlc_sigs = Vec::new();
-
-               for ref htlc in remote_commitment_tx.1.iter() {
-                       let htlc_tx = self.build_htlc_transaction(&remote_commitment_txid, htlc, false, &remote_keys, feerate_per_kw);
-                       let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &remote_keys);
-                       let htlc_sighash = Message::from_slice(&bip143::SighashComponents::new(&htlc_tx).sighash_all(&htlc_tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]).unwrap();
-                       let our_htlc_key = secp_check!(chan_utils::derive_private_key(&self.secp_ctx, &remote_keys.per_commitment_point, &self.local_keys.htlc_base_key), "Derived invalid key, peer is maliciously selecting parameters");
-                       htlc_sigs.push(self.secp_ctx.sign(&htlc_sighash, &our_htlc_key));
+               let mut htlc_sigs = Vec::with_capacity(remote_commitment_tx.1);
+               for &(ref htlc, _) in remote_commitment_tx.2.iter() {
+                       if let Some(_) = htlc.transaction_output_index {
+                               let htlc_tx = self.build_htlc_transaction(&remote_commitment_txid, htlc, false, &remote_keys, feerate_per_kw);
+                               let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &remote_keys);
+                               let htlc_sighash = Message::from_slice(&bip143::SighashComponents::new(&htlc_tx).sighash_all(&htlc_tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]).unwrap();
+                               let our_htlc_key = secp_check!(chan_utils::derive_private_key(&self.secp_ctx, &remote_keys.per_commitment_point, &self.local_keys.htlc_base_key), "Derived invalid key, peer is maliciously selecting parameters");
+                               htlc_sigs.push(self.secp_ctx.sign(&htlc_sighash, &our_htlc_key));
+                       }
                }
 
                Ok((msgs::CommitmentSigned {
                        channel_id: self.channel_id,
                        signature: our_sig,
                        htlc_signatures: htlc_sigs,
-               }, remote_commitment_tx))
+               }, (remote_commitment_tx.0, remote_commitment_tx.2)))
        }
 
        /// Adds a pending outbound HTLC to this channel, and creates a signed commitment transaction
@@ -4019,8 +4022,11 @@ mod tests {
                macro_rules! test_commitment {
                        ( $their_sig_hex: expr, $our_sig_hex: expr, $tx_hex: expr) => {
                                unsigned_tx = {
-                                       let res = chan.build_commitment_transaction(0xffffffffffff - 42, &keys, true, false, chan.feerate_per_kw);
-                                       (res.0, res.1)
+                                       let mut res = chan.build_commitment_transaction(0xffffffffffff - 42, &keys, true, false, chan.feerate_per_kw);
+                                       let htlcs = res.2.drain(..)
+                                               .filter_map(|(htlc, _)| if htlc.transaction_output_index.is_some() { Some(htlc) } else { None })
+                                               .collect();
+                                       (res.0, htlcs)
                                };
                                let their_signature = Signature::from_der(&secp_ctx, &hex::decode($their_sig_hex).unwrap()[..]).unwrap();
                                let sighash = Message::from_slice(&bip143::SighashComponents::new(&unsigned_tx.0).sighash_all(&unsigned_tx.0.input[0], &chan.get_funding_redeemscript(), chan.channel_value_satoshis)[..]).unwrap();