From 160d63dba094d5d93c1ee5e8ccfe95c7037187e9 Mon Sep 17 00:00:00 2001 From: Antoine Riard Date: Fri, 30 Nov 2018 10:58:44 -0500 Subject: [PATCH] Track HTLCSource in ChannelMonitor 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 | 57 ++++++++++++++-------- src/ln/channelmanager.rs | 4 +- src/ln/channelmonitor.rs | 103 ++++++++++++++++++++++++++++++--------- src/ln/router.rs | 4 +- 4 files changed, 121 insertions(+), 47 deletions(-) diff --git a/src/ln/channel.rs b/src/ln/channel.rs index cbcec942..de6588e7 100644 --- a/src/ln/channel.rs +++ b/src/ln/channel.rs @@ -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) { + fn build_commitment_transaction(&self, commitment_number: u64, keys: &TxCreationKeys, local: bool, generated_by_local: bool, feerate_per_kw: u64) -> (Transaction, Vec, Vec<([u8; 32], HTLCSource, Option)>) { 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)> = Vec::with_capacity(self.pending_inbound_htlcs.len() + self.pending_outbound_htlcs.len() + 2); + let mut txouts: Vec<(TxOut, Option<(HTLCOutputInCommitment, Option)>)> = Vec::with_capacity(self.pending_inbound_htlcs.len() + self.pending_outbound_htlcs.len() + 2); + let mut unincluded_htlc_sources: Vec<([u8; 32], HTLCSource, Option)> = 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 = Vec::with_capacity(txouts.len()); - let mut htlcs_used: Vec = Vec::with_capacity(txouts.len()); + let mut htlcs_included: Vec = Vec::with_capacity(txouts.len()); + let mut htlc_sources: Vec<([u8; 32], HTLCSource, Option)> = 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)), ChannelError> { + fn send_commitment_no_state_update(&self) -> Result<(msgs::CommitmentSigned, (Transaction, Vec, Vec<([u8; 32], HTLCSource, Option)>)), 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(); diff --git a/src/ln/channelmanager.rs b/src/ln/channelmanager.rs index 438602d8..26224dc5 100644 --- a/src/ln/channelmanager.rs +++ b/src/ln/channelmanager.rs @@ -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 { diff --git a/src/ln/channelmonitor.rs b/src/ln/channelmonitor.rs index ed940375..15be91c3 100644 --- a/src/ln/channelmonitor.rs +++ b/src/ln/channelmonitor.rs @@ -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)>, } const SERIALIZATION_VERSION: u8 = 1; @@ -283,7 +285,7 @@ pub struct ChannelMonitor { their_to_self_delay: Option, old_secrets: [([u8; 32], u64); 49], - remote_claimable_outpoints: HashMap>, + remote_claimable_outpoints: HashMap, Vec<([u8; 32], HTLCSource, Option)>)>, /// 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, 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, htlc_sources: Vec<([u8; 32], HTLCSource, Option)>, 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)>) { 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 ReadableArgs> for (Sha256dHash, ChannelM } } + macro_rules! read_htlc_source { + () => { + { + (Readable::read(reader)?, Readable::read(reader)?, + match >::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 ReadableArgs> 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 ReadableArgs> 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); diff --git a/src/ln/router.rs b/src/ln/router.rs index 3de73ccc..3920d44f 100644 --- a/src/ln/router.rs +++ b/src/ln/router.rs @@ -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 -- 2.30.2