Skip to content

Commit ad238e2

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 92d8e53 commit ad238e2

File tree

2 files changed

+162
-197
lines changed

2 files changed

+162
-197
lines changed

src/ln/channel.rs

Lines changed: 36 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -748,7 +748,7 @@ impl Channel {
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.
750750
#[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>)>) {
751+
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>)>) {
752752
let obscured_commitment_transaction_number = self.get_commitment_transaction_number_obscure_factor() ^ (INITIAL_COMMITMENT_NUMBER - commitment_number);
753753

754754
let txins = {
@@ -915,30 +915,23 @@ impl Channel {
915915
transaction_utils::sort_outputs(&mut txouts);
916916

917917
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() + unincluded_htlc_sources.len());
920-
for (idx, out) in txouts.drain(..).enumerate() {
918+
let mut htlcs_included: Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)> = Vec::with_capacity(txouts.len() + unincluded_htlc_sources.len());
919+
for (idx, mut out) in txouts.drain(..).enumerate() {
921920
outputs.push(out.0);
922-
if let Some((mut htlc, source_option)) = out.1 {
921+
if let Some((mut htlc, source_option)) = out.1.take() {
923922
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 unincluded_htlc_sources.drain(..) {
931-
if let Some(source) = source_option {
932-
htlc_sources.push((htlc.payment_hash, source, None));
923+
htlcs_included.push((htlc, source_option));
933924
}
934925
}
926+
let non_dust_htlc_count = htlcs_included.len();
927+
htlcs_included.append(&mut unincluded_htlc_sources);
935928

936929
(Transaction {
937930
version: 2,
938931
lock_time: ((0x20 as u32) << 8*3) | ((obscured_commitment_transaction_number & 0xffffffu64) as u32),
939932
input: txins,
940933
output: outputs,
941-
}, htlcs_included, htlc_sources)
934+
}, non_dust_htlc_count, htlcs_included)
942935
}
943936

944937
#[inline]
@@ -1451,9 +1444,9 @@ impl Channel {
14511444

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

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());
1447+
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());
14551448
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());
1449+
self.channel_monitor.provide_latest_local_commitment_tx_info(local_initial_commitment_tx, local_keys, self.feerate_per_kw, Vec::new());
14571450
self.channel_state = ChannelState::FundingSent as u32;
14581451
self.channel_id = funding_txo.to_channel_id();
14591452
self.cur_remote_commitment_transaction_number -= 1;
@@ -1490,7 +1483,7 @@ impl Channel {
14901483
secp_check!(self.secp_ctx.verify(&local_sighash, &msg.signature, &self.their_funding_pubkey.unwrap()), "Invalid funding_signed signature from peer");
14911484

14921485
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());
1486+
self.channel_monitor.provide_latest_local_commitment_tx_info(local_initial_commitment_tx.clone(), local_keys, self.feerate_per_kw, Vec::new());
14941487
self.last_local_commitment_txn = vec![local_initial_commitment_tx];
14951488
self.channel_state = ChannelState::FundingSent as u32;
14961489
self.cur_local_commitment_transaction_number -= 1;
@@ -1693,7 +1686,7 @@ impl Channel {
16931686

16941687
let mut local_commitment_tx = {
16951688
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();
1689+
let htlcs_cloned: Vec<_> = commitment_tx.2.drain(..).map(|htlc| (htlc.0, htlc.1.map(|h| h.clone()))).collect();
16971690
(commitment_tx.0, commitment_tx.1, htlcs_cloned)
16981691
};
16991692
let local_commitment_txid = local_commitment_tx.0.txid();
@@ -1702,24 +1695,24 @@ impl Channel {
17021695

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

17081701
if self.channel_value_satoshis - self.value_to_self_msat / 1000 < total_fee + self.their_channel_reserve_satoshis {
17091702
return Err(ChannelError::Close("Funding remote cannot afford proposed new fee"));
17101703
}
17111704
}
17121705

1713-
if msg.htlc_signatures.len() != local_commitment_tx.1.len() {
1706+
if msg.htlc_signatures.len() != local_commitment_tx.1 {
17141707
return Err(ChannelError::Close("Got wrong number of HTLC signatures from remote"));
17151708
}
17161709

1717-
let mut new_local_commitment_txn = Vec::with_capacity(local_commitment_tx.1.len() + 1);
1710+
let mut new_local_commitment_txn = Vec::with_capacity(local_commitment_tx.1 + 1);
17181711
self.sign_commitment_transaction(&mut local_commitment_tx.0, &msg.signature);
17191712
new_local_commitment_txn.push(local_commitment_tx.0.clone());
17201713

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() {
1714+
let mut htlcs_and_sigs = Vec::with_capacity(local_commitment_tx.2.len());
1715+
for (idx, (htlc, source)) in local_commitment_tx.2.drain(..).enumerate() {
17231716
if let Some(_) = htlc.transaction_output_index {
17241717
let mut htlc_tx = self.build_htlc_transaction(&local_commitment_txid, &htlc, true, &local_keys, feerate_per_kw);
17251718
let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &local_keys);
@@ -1732,7 +1725,9 @@ impl Channel {
17321725
} else {
17331726
self.create_htlc_tx_signature(&htlc_tx, &htlc, &local_keys)?.1
17341727
};
1735-
htlcs_and_sigs.push((htlc, msg.htlc_signatures[idx], htlc_sig));
1728+
htlcs_and_sigs.push((htlc, Some((msg.htlc_signatures[idx], htlc_sig)), source));
1729+
} else {
1730+
htlcs_and_sigs.push((htlc, None, source));
17361731
}
17371732
}
17381733

@@ -1760,7 +1755,7 @@ impl Channel {
17601755
self.monitor_pending_order = None;
17611756
}
17621757

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

17651760
for htlc in self.pending_inbound_htlcs.iter_mut() {
17661761
let new_forward = if let &InboundHTLCState::RemoteAnnounced(ref forward_info) = &htlc.state {
@@ -3030,7 +3025,7 @@ impl Channel {
30303025
let temporary_channel_id = self.channel_id;
30313026

30323027
// 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());
3028+
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());
30343029
self.channel_state = ChannelState::FundingCreated as u32;
30353030
self.channel_id = funding_txo.to_channel_id();
30363031
self.cur_remote_commitment_transaction_number -= 1;
@@ -3262,23 +3257,23 @@ impl Channel {
32623257
}
32633258
}
32643259

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))) => {
3260+
let (res, remote_commitment_tx, htlcs) = match self.send_commitment_no_state_update() {
3261+
Ok((res, (remote_commitment_tx, mut htlcs))) => {
32673262
// 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)
3263+
let htlcs_no_ref = htlcs.drain(..).map(|(htlc, htlc_source)| (htlc, htlc_source.map(|source_ref| Box::new(source_ref.clone())))).collect();
3264+
(res, remote_commitment_tx, htlcs_no_ref)
32703265
},
32713266
Err(e) => return Err(e),
32723267
};
32733268

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());
3269+
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());
32753270
self.channel_state |= ChannelState::AwaitingRemoteRevoke as u32;
32763271
Ok((res, self.channel_monitor.clone()))
32773272
}
32783273

32793274
/// Only fails in case of bad keys. Used for channel_reestablish commitment_signed generation
32803275
/// 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> {
3276+
fn send_commitment_no_state_update(&self) -> Result<(msgs::CommitmentSigned, (Transaction, Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)>)), ChannelError> {
32823277
let funding_script = self.get_funding_redeemscript();
32833278

32843279
let mut feerate_per_kw = self.feerate_per_kw;
@@ -3294,9 +3289,8 @@ impl Channel {
32943289
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();
32953290
let our_sig = self.secp_ctx.sign(&remote_sighash, &self.local_keys.funding_key);
32963291

3297-
let mut htlc_sigs = Vec::new();
3298-
3299-
for ref htlc in remote_commitment_tx.1.iter() {
3292+
let mut htlc_sigs = Vec::with_capacity(remote_commitment_tx.1);
3293+
for &(ref htlc, _) in remote_commitment_tx.2.iter() {
33003294
if let Some(_) = htlc.transaction_output_index {
33013295
let htlc_tx = self.build_htlc_transaction(&remote_commitment_txid, htlc, false, &remote_keys, feerate_per_kw);
33023296
let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &remote_keys);
@@ -3310,7 +3304,7 @@ impl Channel {
33103304
channel_id: self.channel_id,
33113305
signature: our_sig,
33123306
htlc_signatures: htlc_sigs,
3313-
}, remote_commitment_tx))
3307+
}, (remote_commitment_tx.0, remote_commitment_tx.2)))
33143308
}
33153309

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