Skip to content

Commit 92424eb

Browse files
committed
Merge tracking of HTLCs-in-commitment with outbound-HTLCs
This simplifies a few things, deduplicates a some small memory overhead, and, most importantly, is a first step to fixing would_broadcast_at_height.
1 parent 09919d2 commit 92424eb

File tree

2 files changed

+173
-204
lines changed

2 files changed

+173
-204
lines changed

src/ln/channel.rs

Lines changed: 40 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -747,8 +747,12 @@ impl Channel {
747747
/// have not yet committed it. Such HTLCs will only be included in transactions which are being
748748
/// generated by the peer which proposed adding the HTLCs, and thus we need to understand both
749749
/// which peer generated this transaction and "to whom" this transaction flows.
750+
/// Returns (the transaction built, the number of HTLC outputs which were present in the
751+
/// transaction, the list of HTLCs which were not ignored when building the transaction).
752+
/// Note that below-dust HTLCs are included in the third return value, but not the second, and
753+
/// sources are provided only for outbound HTLCs in the third return value.
750754
#[inline]
751-
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>)>) {
755+
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>)>) {
752756
let obscured_commitment_transaction_number = self.get_commitment_transaction_number_obscure_factor() ^ (INITIAL_COMMITMENT_NUMBER - commitment_number);
753757

754758
let txins = {
@@ -915,30 +919,23 @@ impl Channel {
915919
transaction_utils::sort_outputs(&mut txouts);
916920

917921
let mut outputs: Vec<TxOut> = Vec::with_capacity(txouts.len());
918-
let mut htlcs_included: Vec<HTLCOutputInCommitment> = Vec::with_capacity(txouts.len());
919-
let mut htlc_sources: Vec<(PaymentHash, &HTLCSource, Option<u32>)> = Vec::with_capacity(txouts.len() + included_dust_htlcs.len());
920-
for (idx, out) in txouts.drain(..).enumerate() {
922+
let mut htlcs_included: Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)> = Vec::with_capacity(txouts.len() + included_dust_htlcs.len());
923+
for (idx, mut out) in txouts.drain(..).enumerate() {
921924
outputs.push(out.0);
922-
if let Some((mut htlc, source_option)) = out.1 {
925+
if let Some((mut htlc, source_option)) = out.1.take() {
923926
htlc.transaction_output_index = Some(idx as u32);
924-
if let Some(source) = source_option {
925-
htlc_sources.push((htlc.payment_hash, source, Some(idx as u32)));
926-
}
927-
htlcs_included.push(htlc);
928-
}
929-
}
930-
for (htlc, source_option) in included_dust_htlcs.drain(..) {
931-
if let Some(source) = source_option {
932-
htlc_sources.push((htlc.payment_hash, source, None));
927+
htlcs_included.push((htlc, source_option));
933928
}
934929
}
930+
let non_dust_htlc_count = htlcs_included.len();
931+
htlcs_included.append(&mut included_dust_htlcs);
935932

936933
(Transaction {
937934
version: 2,
938935
lock_time: ((0x20 as u32) << 8*3) | ((obscured_commitment_transaction_number & 0xffffffu64) as u32),
939936
input: txins,
940937
output: outputs,
941-
}, htlcs_included, htlc_sources)
938+
}, non_dust_htlc_count, htlcs_included)
942939
}
943940

944941
#[inline]
@@ -1451,9 +1448,9 @@ impl Channel {
14511448

14521449
// Now that we're past error-generating stuff, update our local state:
14531450

1454-
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());
1451+
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());
14551452
self.last_local_commitment_txn = vec![local_initial_commitment_tx.clone()];
1456-
self.channel_monitor.provide_latest_local_commitment_tx_info(local_initial_commitment_tx, local_keys, self.feerate_per_kw, Vec::new(), Vec::new());
1453+
self.channel_monitor.provide_latest_local_commitment_tx_info(local_initial_commitment_tx, local_keys, self.feerate_per_kw, Vec::new());
14571454
self.channel_state = ChannelState::FundingSent as u32;
14581455
self.channel_id = funding_txo.to_channel_id();
14591456
self.cur_remote_commitment_transaction_number -= 1;
@@ -1490,7 +1487,7 @@ impl Channel {
14901487
secp_check!(self.secp_ctx.verify(&local_sighash, &msg.signature, &self.their_funding_pubkey.unwrap()), "Invalid funding_signed signature from peer");
14911488

14921489
self.sign_commitment_transaction(&mut local_initial_commitment_tx, &msg.signature);
1493-
self.channel_monitor.provide_latest_local_commitment_tx_info(local_initial_commitment_tx.clone(), local_keys, self.feerate_per_kw, Vec::new(), Vec::new());
1490+
self.channel_monitor.provide_latest_local_commitment_tx_info(local_initial_commitment_tx.clone(), local_keys, self.feerate_per_kw, Vec::new());
14941491
self.last_local_commitment_txn = vec![local_initial_commitment_tx];
14951492
self.channel_state = ChannelState::FundingSent as u32;
14961493
self.cur_local_commitment_transaction_number -= 1;
@@ -1693,7 +1690,7 @@ impl Channel {
16931690

16941691
let mut local_commitment_tx = {
16951692
let mut commitment_tx = self.build_commitment_transaction(self.cur_local_commitment_transaction_number, &local_keys, true, false, feerate_per_kw);
1696-
let htlcs_cloned: Vec<_> = commitment_tx.2.drain(..).map(|htlc_source| (htlc_source.0, htlc_source.1.clone(), htlc_source.2)).collect();
1693+
let htlcs_cloned: Vec<_> = commitment_tx.2.drain(..).map(|htlc| (htlc.0, htlc.1.map(|h| h.clone()))).collect();
16971694
(commitment_tx.0, commitment_tx.1, htlcs_cloned)
16981695
};
16991696
let local_commitment_txid = local_commitment_tx.0.txid();
@@ -1702,24 +1699,24 @@ impl Channel {
17021699

17031700
//If channel fee was updated by funder confirm funder can afford the new fee rate when applied to the current local commitment transaction
17041701
if update_fee {
1705-
let num_htlcs = local_commitment_tx.1.len();
1702+
let num_htlcs = local_commitment_tx.1;
17061703
let total_fee: u64 = feerate_per_kw as u64 * (COMMITMENT_TX_BASE_WEIGHT + (num_htlcs as u64) * COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000;
17071704

17081705
if self.channel_value_satoshis - self.value_to_self_msat / 1000 < total_fee + self.their_channel_reserve_satoshis {
17091706
return Err(ChannelError::Close("Funding remote cannot afford proposed new fee"));
17101707
}
17111708
}
17121709

1713-
if msg.htlc_signatures.len() != local_commitment_tx.1.len() {
1710+
if msg.htlc_signatures.len() != local_commitment_tx.1 {
17141711
return Err(ChannelError::Close("Got wrong number of HTLC signatures from remote"));
17151712
}
17161713

1717-
let mut new_local_commitment_txn = Vec::with_capacity(local_commitment_tx.1.len() + 1);
1714+
let mut new_local_commitment_txn = Vec::with_capacity(local_commitment_tx.1 + 1);
17181715
self.sign_commitment_transaction(&mut local_commitment_tx.0, &msg.signature);
17191716
new_local_commitment_txn.push(local_commitment_tx.0.clone());
17201717

1721-
let mut htlcs_and_sigs = Vec::with_capacity(local_commitment_tx.1.len());
1722-
for (idx, htlc) in local_commitment_tx.1.drain(..).enumerate() {
1718+
let mut htlcs_and_sigs = Vec::with_capacity(local_commitment_tx.2.len());
1719+
for (idx, (htlc, source)) in local_commitment_tx.2.drain(..).enumerate() {
17231720
if let Some(_) = htlc.transaction_output_index {
17241721
let mut htlc_tx = self.build_htlc_transaction(&local_commitment_txid, &htlc, true, &local_keys, feerate_per_kw);
17251722
let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &local_keys);
@@ -1732,7 +1729,9 @@ impl Channel {
17321729
} else {
17331730
self.create_htlc_tx_signature(&htlc_tx, &htlc, &local_keys)?.1
17341731
};
1735-
htlcs_and_sigs.push((htlc, msg.htlc_signatures[idx], htlc_sig));
1732+
htlcs_and_sigs.push((htlc, Some((msg.htlc_signatures[idx], htlc_sig)), source));
1733+
} else {
1734+
htlcs_and_sigs.push((htlc, None, source));
17361735
}
17371736
}
17381737

@@ -1760,7 +1759,7 @@ impl Channel {
17601759
self.monitor_pending_order = None;
17611760
}
17621761

1763-
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);
1762+
self.channel_monitor.provide_latest_local_commitment_tx_info(local_commitment_tx.0, local_keys, self.feerate_per_kw, htlcs_and_sigs);
17641763

17651764
for htlc in self.pending_inbound_htlcs.iter_mut() {
17661765
let new_forward = if let &InboundHTLCState::RemoteAnnounced(ref forward_info) = &htlc.state {
@@ -3030,7 +3029,7 @@ impl Channel {
30303029
let temporary_channel_id = self.channel_id;
30313030

30323031
// Now that we're past error-generating stuff, update our local state:
3033-
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());
3032+
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());
30343033
self.channel_state = ChannelState::FundingCreated as u32;
30353034
self.channel_id = funding_txo.to_channel_id();
30363035
self.cur_remote_commitment_transaction_number -= 1;
@@ -3262,23 +3261,23 @@ impl Channel {
32623261
}
32633262
}
32643263

3265-
let (res, remote_commitment_tx, htlcs, htlc_sources) = match self.send_commitment_no_state_update() {
3266-
Ok((res, (remote_commitment_tx, htlcs, mut htlc_sources))) => {
3264+
let (res, remote_commitment_tx, htlcs) = match self.send_commitment_no_state_update() {
3265+
Ok((res, (remote_commitment_tx, mut htlcs))) => {
32673266
// Update state now that we've passed all the can-fail calls...
3268-
let htlc_sources_no_ref = htlc_sources.drain(..).map(|htlc_source| (htlc_source.0, htlc_source.1.clone(), htlc_source.2)).collect();
3269-
(res, remote_commitment_tx, htlcs, htlc_sources_no_ref)
3267+
let htlcs_no_ref = htlcs.drain(..).map(|(htlc, htlc_source)| (htlc, htlc_source.map(|source_ref| Box::new(source_ref.clone())))).collect();
3268+
(res, remote_commitment_tx, htlcs_no_ref)
32703269
},
32713270
Err(e) => return Err(e),
32723271
};
32733272

3274-
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());
3273+
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());
32753274
self.channel_state |= ChannelState::AwaitingRemoteRevoke as u32;
32763275
Ok((res, self.channel_monitor.clone()))
32773276
}
32783277

32793278
/// Only fails in case of bad keys. Used for channel_reestablish commitment_signed generation
32803279
/// when we shouldn't change HTLC/channel state.
3281-
fn send_commitment_no_state_update(&self) -> Result<(msgs::CommitmentSigned, (Transaction, Vec<HTLCOutputInCommitment>, Vec<(PaymentHash, &HTLCSource, Option<u32>)>)), ChannelError> {
3280+
fn send_commitment_no_state_update(&self) -> Result<(msgs::CommitmentSigned, (Transaction, Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)>)), ChannelError> {
32823281
let funding_script = self.get_funding_redeemscript();
32833282

32843283
let mut feerate_per_kw = self.feerate_per_kw;
@@ -3294,9 +3293,8 @@ impl Channel {
32943293
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();
32953294
let our_sig = self.secp_ctx.sign(&remote_sighash, &self.local_keys.funding_key);
32963295

3297-
let mut htlc_sigs = Vec::new();
3298-
3299-
for ref htlc in remote_commitment_tx.1.iter() {
3296+
let mut htlc_sigs = Vec::with_capacity(remote_commitment_tx.1);
3297+
for &(ref htlc, _) in remote_commitment_tx.2.iter() {
33003298
if let Some(_) = htlc.transaction_output_index {
33013299
let htlc_tx = self.build_htlc_transaction(&remote_commitment_txid, htlc, false, &remote_keys, feerate_per_kw);
33023300
let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &remote_keys);
@@ -3310,7 +3308,7 @@ impl Channel {
33103308
channel_id: self.channel_id,
33113309
signature: our_sig,
33123310
htlc_signatures: htlc_sigs,
3313-
}, remote_commitment_tx))
3311+
}, (remote_commitment_tx.0, remote_commitment_tx.2)))
33143312
}
33153313

33163314
/// Adds a pending outbound HTLC to this channel, and creates a signed commitment transaction
@@ -4024,8 +4022,11 @@ mod tests {
40244022
macro_rules! test_commitment {
40254023
( $their_sig_hex: expr, $our_sig_hex: expr, $tx_hex: expr) => {
40264024
unsigned_tx = {
4027-
let res = chan.build_commitment_transaction(0xffffffffffff - 42, &keys, true, false, chan.feerate_per_kw);
4028-
(res.0, res.1)
4025+
let mut res = chan.build_commitment_transaction(0xffffffffffff - 42, &keys, true, false, chan.feerate_per_kw);
4026+
let htlcs = res.2.drain(..)
4027+
.filter_map(|(htlc, _)| if htlc.transaction_output_index.is_some() { Some(htlc) } else { None })
4028+
.collect();
4029+
(res.0, htlcs)
40294030
};
40304031
let their_signature = Signature::from_der(&secp_ctx, &hex::decode($their_sig_hex).unwrap()[..]).unwrap();
40314032
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();

0 commit comments

Comments
 (0)