Track HTLCSource in ChannelMonitor
authorAntoine Riard <ariard@student.42.fr>
Fri, 30 Nov 2018 15:58:44 +0000 (10:58 -0500)
committerMatt Corallo <git@bluematt.me>
Thu, 13 Dec 2018 16:12:07 +0000 (11:12 -0500)
Insert it in current_local_signed_tx, prev_local_signed_tx,
remote_claimable_outpoints. For so get it provided by
Channel calls to provide_latest_{local,remote}_tx

src/ln/channel.rs
src/ln/channelmanager.rs
src/ln/channelmonitor.rs
src/ln/router.rs

index cbcec942d80661dafb83e13f98826dfc2cceb2d1..de6588e7a8ba96c0f47210e1ecfd1a0603535c9a 100644 (file)
@@ -751,7 +751,7 @@ impl Channel {
        /// 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.
        #[inline]
-       fn build_commitment_transaction(&self, commitment_number: u64, keys: &TxCreationKeys, local: bool, generated_by_local: bool, feerate_per_kw: u64) -> (Transaction, Vec<HTLCOutputInCommitment>) {
+       fn build_commitment_transaction(&self, commitment_number: u64, keys: &TxCreationKeys, local: bool, generated_by_local: bool, feerate_per_kw: u64) -> (Transaction, Vec<HTLCOutputInCommitment>, Vec<([u8; 32], HTLCSource, Option<u32>)>) {
                let obscured_commitment_transaction_number = self.get_commitment_transaction_number_obscure_factor() ^ (INITIAL_COMMITMENT_NUMBER - commitment_number);
 
                let txins = {
@@ -765,7 +765,8 @@ impl Channel {
                        ins
                };
 
-               let mut txouts: Vec<(TxOut, Option<HTLCOutputInCommitment>)> = Vec::with_capacity(self.pending_inbound_htlcs.len() + self.pending_outbound_htlcs.len() + 2);
+               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<([u8; 32], HTLCSource, Option<u32>)> = 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;
@@ -773,14 +774,18 @@ impl Channel {
                let mut value_to_self_msat_offset = 0;
 
                macro_rules! add_htlc_output {
-                       ($htlc: expr, $outbound: expr) => {
+                       ($htlc: expr, $outbound: expr, $source: expr) => {
                                if $outbound == local { // "offered HTLC output"
                                        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)));
+                                               }, Some((htlc_in_tx, $source))));
+                                       } else {
+                                               if let Some(source) = $source {
+                                                       unincluded_htlc_sources.push(($htlc.payment_hash, source, None));
+                                               }
                                        }
                                } else {
                                        if $htlc.amount_msat / 1000 >= dust_limit_satoshis + (feerate_per_kw * HTLC_SUCCESS_TX_WEIGHT / 1000) {
@@ -788,7 +793,11 @@ impl Channel {
                                                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)));
+                                               }, Some((htlc_in_tx, $source))));
+                                       } else {
+                                               if let Some(source) = $source {
+                                                       unincluded_htlc_sources.push(($htlc.payment_hash, source, None));
+                                               }
                                        }
                                }
                        }
@@ -804,7 +813,7 @@ impl Channel {
                        };
 
                        if include {
-                               add_htlc_output!(htlc, false);
+                               add_htlc_output!(htlc, false, None);
                                remote_htlc_total_msat += htlc.amount_msat;
                        } else {
                                match &htlc.state {
@@ -830,7 +839,7 @@ impl Channel {
                        };
 
                        if include {
-                               add_htlc_output!(htlc, true);
+                               add_htlc_output!(htlc, true, Some(htlc.source.clone()));
                                local_htlc_total_msat += htlc.amount_msat;
                        } else {
                                match htlc.state {
@@ -901,21 +910,26 @@ impl Channel {
                transaction_utils::sort_outputs(&mut txouts);
 
                let mut outputs: Vec<TxOut> = Vec::with_capacity(txouts.len());
-               let mut htlcs_used: Vec<HTLCOutputInCommitment> = Vec::with_capacity(txouts.len());
+               let mut htlcs_included: Vec<HTLCOutputInCommitment> = Vec::with_capacity(txouts.len());
+               let mut htlc_sources: Vec<([u8; 32], HTLCSource, Option<u32>)> = Vec::with_capacity(txouts.len() + unincluded_htlc_sources.len());
                for (idx, out) in txouts.drain(..).enumerate() {
                        outputs.push(out.0);
-                       if let Some(out_htlc) = out.1 {
-                               htlcs_used.push(out_htlc);
-                               htlcs_used.last_mut().unwrap().transaction_output_index = idx as u32;
+                       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);
                        }
                }
+               htlc_sources.append(&mut unincluded_htlc_sources);
 
                (Transaction {
                        version: 2,
                        lock_time: ((0x20 as u32) << 8*3) | ((obscured_commitment_transaction_number & 0xffffffu64) as u32),
                        input: txins,
                        output: outputs,
-               }, htlcs_used)
+               }, htlcs_included, htlc_sources)
        }
 
        #[inline]
@@ -1424,9 +1438,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(), 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(), 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());
+               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_state = ChannelState::FundingSent as u32;
                self.channel_id = funding_txo.to_channel_id();
                self.cur_remote_commitment_transaction_number -= 1;
@@ -1463,7 +1477,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());
+               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.last_local_commitment_txn = vec![local_initial_commitment_tx];
                self.channel_state = ChannelState::FundingSent as u32;
                self.cur_local_commitment_transaction_number -= 1;
@@ -1731,7 +1745,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);
+               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);
 
                for htlc in self.pending_inbound_htlcs.iter_mut() {
                        let new_forward = if let &InboundHTLCState::RemoteAnnounced(ref forward_info) = &htlc.state {
@@ -3001,7 +3015,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(), 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(), 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;
@@ -3229,7 +3243,7 @@ impl Channel {
                match self.send_commitment_no_state_update() {
                        Ok((res, remote_commitment_tx)) => {
                                // Update state now that we've passed all the can-fail calls...
-                               self.channel_monitor.provide_latest_remote_commitment_tx_info(&remote_commitment_tx.0, remote_commitment_tx.1, self.cur_remote_commitment_transaction_number, self.their_cur_commitment_point.unwrap());
+                               self.channel_monitor.provide_latest_remote_commitment_tx_info(&remote_commitment_tx.0, remote_commitment_tx.1, remote_commitment_tx.2, 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()))
                        },
@@ -3239,7 +3253,7 @@ impl Channel {
 
        /// 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>)), ChannelError> {
+       fn send_commitment_no_state_update(&self) -> Result<(msgs::CommitmentSigned, (Transaction, Vec<HTLCOutputInCommitment>, Vec<([u8; 32], HTLCSource, Option<u32>)>)), ChannelError> {
                let funding_script = self.get_funding_redeemscript();
 
                let mut feerate_per_kw = self.feerate_per_kw;
@@ -3982,7 +3996,10 @@ mod tests {
 
                macro_rules! test_commitment {
                        ( $their_sig_hex: expr, $our_sig_hex: expr, $tx_hex: expr) => {
-                               unsigned_tx = chan.build_commitment_transaction(0xffffffffffff - 42, &keys, true, false, chan.feerate_per_kw);
+                               unsigned_tx = {
+                                       let res = chan.build_commitment_transaction(0xffffffffffff - 42, &keys, true, false, chan.feerate_per_kw);
+                                       (res.0, res.1)
+                               };
                                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();
                                secp_ctx.verify(&sighash, &their_signature, &chan.their_funding_pubkey.unwrap()).unwrap();
index 438602d8c0291db8d7d09fe2bb8c831ed153b053..26224dc548691bfab1047e99019a7d76f817ddec 100644 (file)
@@ -90,7 +90,7 @@ mod channel_held_info {
        }
 
        /// Tracks the inbound corresponding to an outbound HTLC
-       #[derive(Clone)]
+       #[derive(Clone, PartialEq)]
        pub struct HTLCPreviousHopData {
                pub(super) short_channel_id: u64,
                pub(super) htlc_id: u64,
@@ -98,7 +98,7 @@ mod channel_held_info {
        }
 
        /// Tracks the inbound corresponding to an outbound HTLC
-       #[derive(Clone)]
+       #[derive(Clone, PartialEq)]
        pub enum HTLCSource {
                PreviousHopData(HTLCPreviousHopData),
                OutboundRoute {
index ed940375bea3f7f16ad5f36c9199dbc208d4015f..15be91c30e760548b1cccaae96a411d6d3d702d1 100644 (file)
@@ -29,6 +29,7 @@ use secp256k1;
 use ln::msgs::DecodeError;
 use ln::chan_utils;
 use ln::chan_utils::HTLCOutputInCommitment;
+use ln::channelmanager::HTLCSource;
 use chain::chaininterface::{ChainListener, ChainWatchInterface, BroadcasterInterface};
 use chain::transaction::OutPoint;
 use chain::keysinterface::SpendableOutputDescriptor;
@@ -259,6 +260,7 @@ struct LocalSignedTx {
        delayed_payment_key: PublicKey,
        feerate_per_kw: u64,
        htlc_outputs: Vec<(HTLCOutputInCommitment, Signature, Signature)>,
+       htlc_sources: Vec<([u8; 32], HTLCSource, Option<u32>)>,
 }
 
 const SERIALIZATION_VERSION: u8 = 1;
@@ -283,7 +285,7 @@ pub struct ChannelMonitor {
        their_to_self_delay: Option<u16>,
 
        old_secrets: [([u8; 32], u64); 49],
-       remote_claimable_outpoints: HashMap<Sha256dHash, Vec<HTLCOutputInCommitment>>,
+       remote_claimable_outpoints: HashMap<Sha256dHash, (Vec<HTLCOutputInCommitment>, Vec<([u8; 32], HTLCSource, Option<u32>)>)>,
        /// We cannot identify HTLC-Success or HTLC-Timeout transactions by themselves on the chain.
        /// Nor can we figure out their commitment numbers without the commitment transaction they are
        /// spending. Thus, in order to claim them via revocation key, we track all the remote
@@ -471,15 +473,20 @@ impl ChannelMonitor {
        /// The monitor watches for it to be broadcasted and then uses the HTLC information (and
        /// possibly future revocation/preimage information) to claim outputs where possible.
        /// We cache also the mapping hash:commitment number to lighten pruning of old preimages by watchtowers.
-       pub(super) fn provide_latest_remote_commitment_tx_info(&mut self, unsigned_commitment_tx: &Transaction, htlc_outputs: Vec<HTLCOutputInCommitment>, commitment_number: u64, their_revocation_point: PublicKey) {
+       pub(super) fn provide_latest_remote_commitment_tx_info(&mut self, unsigned_commitment_tx: &Transaction, htlc_outputs: Vec<HTLCOutputInCommitment>, htlc_sources: Vec<([u8; 32], HTLCSource, Option<u32>)>, commitment_number: u64, their_revocation_point: PublicKey) {
                // TODO: Encrypt the htlc_outputs data with the single-hash of the commitment transaction
                // so that a remote monitor doesn't learn anything unless there is a malicious close.
                // (only maybe, sadly we cant do the same for local info, as we need to be aware of
                // timeouts)
-               for htlc in &htlc_outputs {
+               for ref htlc in &htlc_outputs {
                        self.remote_hash_commitment_number.insert(htlc.payment_hash, commitment_number);
                }
-               self.remote_claimable_outpoints.insert(unsigned_commitment_tx.txid(), htlc_outputs);
+               // We prune old claimable outpoints, useless to pass backward state when remote commitment
+               // tx get revoked, optimize for storage
+               for (_, htlc_data) in self.remote_claimable_outpoints.iter_mut() {
+                       htlc_data.1 = Vec::new();
+               }
+               self.remote_claimable_outpoints.insert(unsigned_commitment_tx.txid(), (htlc_outputs, htlc_sources));
                self.current_remote_commitment_number = commitment_number;
                //TODO: Merge this into the other per-remote-transaction output storage stuff
                match self.their_cur_revocation_points {
@@ -509,7 +516,7 @@ impl ChannelMonitor {
        /// Panics if set_their_to_self_delay has never been called.
        /// Also update Storage with latest local per_commitment_point to derive local_delayedkey in
        /// case of onchain HTLC tx
-       pub(super) fn provide_latest_local_commitment_tx_info(&mut self, signed_commitment_tx: Transaction, local_keys: chan_utils::TxCreationKeys, feerate_per_kw: u64, htlc_outputs: Vec<(HTLCOutputInCommitment, Signature, Signature)>) {
+       pub(super) fn provide_latest_local_commitment_tx_info(&mut self, signed_commitment_tx: Transaction, local_keys: chan_utils::TxCreationKeys, feerate_per_kw: u64, htlc_outputs: Vec<(HTLCOutputInCommitment, Signature, Signature)>, htlc_sources: Vec<([u8; 32], HTLCSource, Option<u32>)>) {
                assert!(self.their_to_self_delay.is_some());
                self.prev_local_signed_commitment_tx = self.current_local_signed_commitment_tx.take();
                self.current_local_signed_commitment_tx = Some(LocalSignedTx {
@@ -521,6 +528,7 @@ impl ChannelMonitor {
                        delayed_payment_key: local_keys.a_delayed_payment_key,
                        feerate_per_kw,
                        htlc_outputs,
+                       htlc_sources,
                });
 
                if let Storage::Local { ref mut latest_per_commitment_point, .. } = self.key_storage {
@@ -753,13 +761,31 @@ impl ChannelMonitor {
                        }
                }
 
+               macro_rules! serialize_htlc_source {
+                       ($htlc_source: expr) => {
+                               $htlc_source.0.write(writer)?;
+                               $htlc_source.1.write(writer)?;
+                               if let &Some(ref txo) = &$htlc_source.2 {
+                                       writer.write_all(&[1; 1])?;
+                                       txo.write(writer)?;
+                               } else {
+                                       writer.write_all(&[0; 1])?;
+                               }
+                       }
+               }
+
+
                writer.write_all(&byte_utils::be64_to_array(self.remote_claimable_outpoints.len() as u64))?;
-               for (ref txid, ref htlc_outputs) in self.remote_claimable_outpoints.iter() {
+               for (ref txid, &(ref htlc_infos, ref htlc_sources)) in self.remote_claimable_outpoints.iter() {
                        writer.write_all(&txid[..])?;
-                       writer.write_all(&byte_utils::be64_to_array(htlc_outputs.len() as u64))?;
-                       for htlc_output in htlc_outputs.iter() {
+                       writer.write_all(&byte_utils::be64_to_array(htlc_infos.len() as u64))?;
+                       for ref htlc_output in htlc_infos.iter() {
                                serialize_htlc_in_commitment!(htlc_output);
                        }
+                       writer.write_all(&byte_utils::be64_to_array(htlc_sources.len() as u64))?;
+                       for ref htlc_source in htlc_sources.iter() {
+                               serialize_htlc_source!(htlc_source);
+                       }
                }
 
                writer.write_all(&byte_utils::be64_to_array(self.remote_commitment_txn_on_chain.len() as u64))?;
@@ -803,6 +829,10 @@ impl ChannelMonitor {
                                        writer.write_all(&their_sig.serialize_compact(&self.secp_ctx))?;
                                        writer.write_all(&our_sig.serialize_compact(&self.secp_ctx))?;
                                }
+                               writer.write_all(&byte_utils::be64_to_array($local_tx.htlc_sources.len() as u64))?;
+                               for ref htlc_source in $local_tx.htlc_sources.iter() {
+                                       serialize_htlc_source!(htlc_source);
+                               }
                        }
                }
 
@@ -985,7 +1015,7 @@ impl ChannelMonitor {
                                                let (sig, redeemscript) = match self.key_storage {
                                                        Storage::Local { ref revocation_base_key, .. } => {
                                                                let redeemscript = if $htlc_idx.is_none() { revokeable_redeemscript.clone() } else {
-                                                                       let htlc = &per_commitment_option.unwrap()[$htlc_idx.unwrap()];
+                                                                       let htlc = &per_commitment_option.unwrap().0[$htlc_idx.unwrap()];
                                                                        chan_utils::get_htlc_redeemscript_with_explicit_keys(htlc, &a_htlc_key, &b_htlc_key, &revocation_pubkey)
                                                                };
                                                                let sighash = ignore_error!(Message::from_slice(&$sighash_parts.sighash_all(&$input, &redeemscript, $amount)[..]));
@@ -1008,10 +1038,10 @@ impl ChannelMonitor {
                                }
                        }
 
-                       if let Some(per_commitment_data) = per_commitment_option {
+                       if let Some(&(ref per_commitment_data, _)) = per_commitment_option {
                                inputs.reserve_exact(per_commitment_data.len());
 
-                               for (idx, htlc) in per_commitment_data.iter().enumerate() {
+                               for (idx, ref htlc) in per_commitment_data.iter().enumerate() {
                                        let expected_script = chan_utils::get_htlc_redeemscript_with_explicit_keys(&htlc, &a_htlc_key, &b_htlc_key, &revocation_pubkey);
                                        if htlc.transaction_output_index as usize >= tx.output.len() ||
                                                        tx.output[htlc.transaction_output_index as usize].value != htlc.amount_msat / 1000 ||
@@ -1140,7 +1170,7 @@ impl ChannelMonitor {
                                                        {
                                                                let (sig, redeemscript) = match self.key_storage {
                                                                        Storage::Local { ref htlc_base_key, .. } => {
-                                                                               let htlc = &per_commitment_option.unwrap()[$input.sequence as usize];
+                                                                               let htlc = &per_commitment_option.unwrap().0[$input.sequence as usize];
                                                                                let redeemscript = chan_utils::get_htlc_redeemscript_with_explicit_keys(htlc, &a_htlc_key, &b_htlc_key, &revocation_pubkey);
                                                                                let sighash = ignore_error!(Message::from_slice(&$sighash_parts.sighash_all(&$input, &redeemscript, $amount)[..]));
                                                                                let htlc_key = ignore_error!(chan_utils::derive_private_key(&self.secp_ctx, revocation_point, &htlc_base_key));
@@ -1158,7 +1188,7 @@ impl ChannelMonitor {
                                                }
                                        }
 
-                                       for (idx, htlc) in per_commitment_data.iter().enumerate() {
+                                       for (idx, ref htlc) in per_commitment_data.0.iter().enumerate() {
                                                let expected_script = chan_utils::get_htlc_redeemscript_with_explicit_keys(&htlc, &a_htlc_key, &b_htlc_key, &revocation_pubkey);
                                                if htlc.transaction_output_index as usize >= tx.output.len() ||
                                                                tx.output[htlc.transaction_output_index as usize].value != htlc.amount_msat / 1000 ||
@@ -1692,6 +1722,20 @@ impl<R: ::std::io::Read> ReadableArgs<R, Arc<Logger>> for (Sha256dHash, ChannelM
                        }
                }
 
+               macro_rules! read_htlc_source {
+                       () => {
+                               {
+                                       (Readable::read(reader)?, Readable::read(reader)?,
+                                               match <u8 as Readable<R>>::read(reader)? {
+                                                       0 => None,
+                                                       1 => Some(Readable::read(reader)?),
+                                                       _ => return Err(DecodeError::InvalidValue),
+                                               }
+                                       )
+                               }
+                       }
+               }
+
                let remote_claimable_outpoints_len: u64 = Readable::read(reader)?;
                let mut remote_claimable_outpoints = HashMap::with_capacity(cmp::min(remote_claimable_outpoints_len as usize, MAX_ALLOC_SIZE / 64));
                for _ in 0..remote_claimable_outpoints_len {
@@ -1701,7 +1745,12 @@ impl<R: ::std::io::Read> ReadableArgs<R, Arc<Logger>> for (Sha256dHash, ChannelM
                        for _ in 0..outputs_count {
                                outputs.push(read_htlc_in_commitment!());
                        }
-                       if let Some(_) = remote_claimable_outpoints.insert(txid, outputs) {
+                       let sources_count: u64 = Readable::read(reader)?;
+                       let mut sources = Vec::with_capacity(cmp::min(sources_count as usize, MAX_ALLOC_SIZE / 32));
+                       for _ in 0..sources_count {
+                               sources.push(read_htlc_source!());
+                       }
+                       if let Some(_) = remote_claimable_outpoints.insert(txid, (outputs, sources)) {
                                return Err(DecodeError::InvalidValue);
                        }
                }
@@ -1756,12 +1805,20 @@ impl<R: ::std::io::Read> ReadableArgs<R, Arc<Logger>> for (Sha256dHash, ChannelM
                                        let htlc_outputs_len: u64 = Readable::read(reader)?;
                                        let mut htlc_outputs = Vec::with_capacity(cmp::min(htlc_outputs_len as usize, MAX_ALLOC_SIZE / 128));
                                        for _ in 0..htlc_outputs_len {
-                                               htlc_outputs.push((read_htlc_in_commitment!(), Readable::read(reader)?, Readable::read(reader)?));
+                                               let out = read_htlc_in_commitment!();
+                                               let sigs = (Readable::read(reader)?, Readable::read(reader)?);
+                                               htlc_outputs.push((out, sigs.0, sigs.1));
+                                       }
+
+                                       let htlc_sources_len: u64 = Readable::read(reader)?;
+                                       let mut htlc_sources = Vec::with_capacity(cmp::min(htlc_outputs_len as usize, MAX_ALLOC_SIZE / 128));
+                                       for _ in 0..htlc_sources_len {
+                                               htlc_sources.push(read_htlc_source!());
                                        }
 
                                        LocalSignedTx {
                                                txid: tx.txid(),
-                                               tx, revocation_key, a_htlc_key, b_htlc_key, delayed_payment_key, feerate_per_kw, htlc_outputs
+                                               tx, revocation_key, a_htlc_key, b_htlc_key, delayed_payment_key, feerate_per_kw, htlc_outputs, htlc_sources
                                        }
                                }
                        }
@@ -2280,11 +2337,11 @@ mod tests {
                let mut monitor = ChannelMonitor::new(&SecretKey::from_slice(&secp_ctx, &[42; 32]).unwrap(), &SecretKey::from_slice(&secp_ctx, &[43; 32]).unwrap(), &SecretKey::from_slice(&secp_ctx, &[44; 32]).unwrap(), &SecretKey::from_slice(&secp_ctx, &[44; 32]).unwrap(), &PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &[45; 32]).unwrap()), 0, Script::new(), logger.clone());
                monitor.set_their_to_self_delay(10);
 
-               monitor.provide_latest_local_commitment_tx_info(dummy_tx.clone(), dummy_keys!(), 0, preimages_to_local_htlcs!(preimages[0..10]));
-               monitor.provide_latest_remote_commitment_tx_info(&dummy_tx, preimages_slice_to_htlc_outputs!(preimages[5..15]), 281474976710655, dummy_key);
-               monitor.provide_latest_remote_commitment_tx_info(&dummy_tx, preimages_slice_to_htlc_outputs!(preimages[15..20]), 281474976710654, dummy_key);
-               monitor.provide_latest_remote_commitment_tx_info(&dummy_tx, preimages_slice_to_htlc_outputs!(preimages[17..20]), 281474976710653, dummy_key);
-               monitor.provide_latest_remote_commitment_tx_info(&dummy_tx, preimages_slice_to_htlc_outputs!(preimages[18..20]), 281474976710652, dummy_key);
+               monitor.provide_latest_local_commitment_tx_info(dummy_tx.clone(), dummy_keys!(), 0, preimages_to_local_htlcs!(preimages[0..10]), Vec::new());
+               monitor.provide_latest_remote_commitment_tx_info(&dummy_tx, preimages_slice_to_htlc_outputs!(preimages[5..15]), Vec::new(), 281474976710655, dummy_key);
+               monitor.provide_latest_remote_commitment_tx_info(&dummy_tx, preimages_slice_to_htlc_outputs!(preimages[15..20]), Vec::new(), 281474976710654, dummy_key);
+               monitor.provide_latest_remote_commitment_tx_info(&dummy_tx, preimages_slice_to_htlc_outputs!(preimages[17..20]), Vec::new(), 281474976710653, dummy_key);
+               monitor.provide_latest_remote_commitment_tx_info(&dummy_tx, preimages_slice_to_htlc_outputs!(preimages[18..20]), Vec::new(), 281474976710652, dummy_key);
                for &(ref preimage, ref hash) in preimages.iter() {
                        monitor.provide_payment_preimage(hash, preimage);
                }
@@ -2306,7 +2363,7 @@ mod tests {
 
                // Now update local commitment tx info, pruning only element 18 as we still care about the
                // previous commitment tx's preimages too
-               monitor.provide_latest_local_commitment_tx_info(dummy_tx.clone(), dummy_keys!(), 0, preimages_to_local_htlcs!(preimages[0..5]));
+               monitor.provide_latest_local_commitment_tx_info(dummy_tx.clone(), dummy_keys!(), 0, preimages_to_local_htlcs!(preimages[0..5]), Vec::new());
                secret[0..32].clone_from_slice(&hex::decode("2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8").unwrap());
                monitor.provide_secret(281474976710653, secret.clone()).unwrap();
                assert_eq!(monitor.payment_preimages.len(), 12);
@@ -2314,7 +2371,7 @@ mod tests {
                test_preimages_exist!(&preimages[18..20], monitor);
 
                // But if we do it again, we'll prune 5-10
-               monitor.provide_latest_local_commitment_tx_info(dummy_tx.clone(), dummy_keys!(), 0, preimages_to_local_htlcs!(preimages[0..3]));
+               monitor.provide_latest_local_commitment_tx_info(dummy_tx.clone(), dummy_keys!(), 0, preimages_to_local_htlcs!(preimages[0..3]), Vec::new());
                secret[0..32].clone_from_slice(&hex::decode("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116").unwrap());
                monitor.provide_secret(281474976710652, secret.clone()).unwrap();
                assert_eq!(monitor.payment_preimages.len(), 5);
index 3de73ccc059ae8159b09f856ca4508fbedf7a278..3920d44fc7abddc65c94edab16cc864e0e6f4747 100644 (file)
@@ -25,7 +25,7 @@ use std::collections::btree_map::Entry as BtreeEntry;
 use std;
 
 /// A hop in a route
-#[derive(Clone)]
+#[derive(Clone, PartialEq)]
 pub struct RouteHop {
        /// The node_id of the node at this hop.
        pub pubkey: PublicKey,
@@ -39,7 +39,7 @@ pub struct RouteHop {
 }
 
 /// A route from us through the network to a destination
-#[derive(Clone)]
+#[derive(Clone, PartialEq)]
 pub struct Route {
        /// The list of hops, NOT INCLUDING our own, where the last hop is the destination. Thus, this
        /// must always be at least length one. By protocol rules, this may not currently exceed 20 in