Skip to content

Commit d2cb2df

Browse files
committed
Relax the requirements of building a CommitmentTransaction
Building `CommitmentTransaction` previously required a pointer to a `Vec<(HTLCOutputInCommitment, T)>`, where each item in the vector represented a non-dust htlc. This forced the caller to place all the non-dust htlcs and their auxiliary data in contiguous memory prior to building a `CommitmentTransaction`. This requirement was not necessary, so we remove it in this commit. Instead, we choose to ask for a `Vec<&mut HTLCOutputInCommitment>`, where each element is an exclusive reference to a non-dust htlc, so that `CommitmentTranscation` may populate their output indices during the build process.
1 parent 2e96e75 commit d2cb2df

File tree

5 files changed

+54
-63
lines changed

5 files changed

+54
-63
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3488,12 +3488,12 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
34883488
fn build_counterparty_commitment_tx(
34893489
&self, commitment_number: u64, their_per_commitment_point: &PublicKey,
34903490
to_broadcaster_value: u64, to_countersignatory_value: u64, feerate_per_kw: u32,
3491-
mut nondust_htlcs: Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>
3491+
nondust_htlcs: Vec<&mut HTLCOutputInCommitment>,
34923492
) -> CommitmentTransaction {
34933493
let channel_parameters =
34943494
&self.onchain_tx_handler.channel_transaction_parameters.as_counterparty_broadcastable();
3495-
CommitmentTransaction::new_with_auxiliary_htlc_data(commitment_number, their_per_commitment_point,
3496-
to_broadcaster_value, to_countersignatory_value, feerate_per_kw, &mut nondust_htlcs, channel_parameters, &self.onchain_tx_handler.secp_ctx)
3495+
CommitmentTransaction::new(commitment_number, their_per_commitment_point,
3496+
to_broadcaster_value, to_countersignatory_value, feerate_per_kw, nondust_htlcs, channel_parameters, &self.onchain_tx_handler.secp_ctx)
34973497
}
34983498

34993499
fn counterparty_commitment_txs_from_update(&self, update: &ChannelMonitorUpdate) -> Vec<CommitmentTransaction> {
@@ -3509,13 +3509,13 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
35093509
to_countersignatory_value_sat: Some(to_countersignatory_value)
35103510
} => {
35113511

3512-
let nondust_htlcs = htlc_outputs.iter().filter_map(|(htlc, _)| {
3513-
htlc.transaction_output_index.map(|_| (htlc.clone(), None))
3514-
}).collect::<Vec<_>>();
3512+
let mut nondust_htlcs = htlc_outputs.iter().filter_map(|(htlc, _)| {
3513+
htlc.transaction_output_index.map(|_| htlc)
3514+
}).cloned().collect::<Vec<_>>();
35153515

35163516
let commitment_tx = self.build_counterparty_commitment_tx(commitment_number,
35173517
&their_per_commitment_point, to_broadcaster_value,
3518-
to_countersignatory_value, feerate_per_kw, nondust_htlcs);
3518+
to_countersignatory_value, feerate_per_kw, nondust_htlcs.iter_mut().collect());
35193519

35203520
debug_assert_eq!(commitment_tx.trust().txid(), commitment_txid);
35213521

@@ -5381,21 +5381,21 @@ mod tests {
53815381
{
53825382
let mut res = Vec::new();
53835383
for (idx, preimage) in $preimages_slice.iter().enumerate() {
5384-
res.push((HTLCOutputInCommitment {
5384+
res.push(HTLCOutputInCommitment {
53855385
offered: true,
53865386
amount_msat: 0,
53875387
cltv_expiry: 0,
53885388
payment_hash: preimage.1.clone(),
53895389
transaction_output_index: Some(idx as u32),
5390-
}, ()));
5390+
});
53915391
}
53925392
res
53935393
}
53945394
}
53955395
}
53965396
macro_rules! preimages_slice_to_htlc_outputs {
53975397
($preimages_slice: expr) => {
5398-
preimages_slice_to_htlcs!($preimages_slice).into_iter().map(|(htlc, _)| (htlc, None)).collect()
5398+
preimages_slice_to_htlcs!($preimages_slice).into_iter().map(|htlc| (htlc, None)).collect()
53995399
}
54005400
}
54015401
let dummy_sig = crate::crypto::utils::sign(&secp_ctx,
@@ -5458,7 +5458,7 @@ mod tests {
54585458
let dummy_commitment_tx = HolderCommitmentTransaction::dummy(0, &mut htlcs);
54595459

54605460
monitor.provide_latest_holder_commitment_tx(dummy_commitment_tx.clone(),
5461-
htlcs.into_iter().map(|(htlc, _)| (htlc, Some(dummy_sig), None)).collect());
5461+
htlcs.into_iter().map(|htlc| (htlc, Some(dummy_sig), None)).collect());
54625462
monitor.provide_latest_counterparty_commitment_tx(Txid::from_byte_array(Sha256::hash(b"1").to_byte_array()),
54635463
preimages_slice_to_htlc_outputs!(preimages[5..15]), 281474976710655, dummy_key, &logger);
54645464
monitor.provide_latest_counterparty_commitment_tx(Txid::from_byte_array(Sha256::hash(b"2").to_byte_array()),
@@ -5496,7 +5496,7 @@ mod tests {
54965496
let mut htlcs = preimages_slice_to_htlcs!(preimages[0..5]);
54975497
let dummy_commitment_tx = HolderCommitmentTransaction::dummy(0, &mut htlcs);
54985498
monitor.provide_latest_holder_commitment_tx(dummy_commitment_tx.clone(),
5499-
htlcs.into_iter().map(|(htlc, _)| (htlc, Some(dummy_sig), None)).collect());
5499+
htlcs.into_iter().map(|htlc| (htlc, Some(dummy_sig), None)).collect());
55005500
secret[0..32].clone_from_slice(&<Vec<u8>>::from_hex("2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8").unwrap());
55015501
monitor.provide_secret(281474976710653, secret.clone()).unwrap();
55025502
assert_eq!(monitor.inner.lock().unwrap().payment_preimages.len(), 12);
@@ -5507,7 +5507,7 @@ mod tests {
55075507
let mut htlcs = preimages_slice_to_htlcs!(preimages[0..3]);
55085508
let dummy_commitment_tx = HolderCommitmentTransaction::dummy(0, &mut htlcs);
55095509
monitor.provide_latest_holder_commitment_tx(dummy_commitment_tx,
5510-
htlcs.into_iter().map(|(htlc, _)| (htlc, Some(dummy_sig), None)).collect());
5510+
htlcs.into_iter().map(|htlc| (htlc, Some(dummy_sig), None)).collect());
55115511
secret[0..32].clone_from_slice(&<Vec<u8>>::from_hex("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116").unwrap());
55125512
monitor.provide_secret(281474976710652, secret.clone()).unwrap();
55135513
assert_eq!(monitor.inner.lock().unwrap().payment_preimages.len(), 5);

lightning/src/chain/onchaintx.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1363,16 +1363,15 @@ mod tests {
13631363
for i in 0..3 {
13641364
let preimage = PaymentPreimage([i; 32]);
13651365
let hash = PaymentHash(Sha256::hash(&preimage.0[..]).to_byte_array());
1366-
htlcs.push((
1366+
htlcs.push(
13671367
HTLCOutputInCommitment {
13681368
offered: true,
13691369
amount_msat: 10000,
13701370
cltv_expiry: i as u32,
13711371
payment_hash: hash,
13721372
transaction_output_index: Some(i as u32),
13731373
},
1374-
(),
1375-
));
1374+
);
13761375
}
13771376
let holder_commit = HolderCommitmentTransaction::dummy(1000000, &mut htlcs);
13781377
let mut tx_handler = OnchainTxHandler::new(
@@ -1400,7 +1399,7 @@ mod tests {
14001399
// Request claiming of each HTLC on the holder's commitment, with current block height 1.
14011400
let holder_commit_txid = tx_handler.get_unsigned_holder_commitment_tx().compute_txid();
14021401
let mut requests = Vec::new();
1403-
for (htlc, _) in htlcs {
1402+
for htlc in htlcs {
14041403
requests.push(PackageTemplate::build_package(
14051404
holder_commit_txid,
14061405
htlc.transaction_output_index.unwrap(),

lightning/src/ln/chan_utils.rs

Lines changed: 24 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1145,7 +1145,7 @@ impl_writeable_tlv_based!(HolderCommitmentTransaction, {
11451145

11461146
impl HolderCommitmentTransaction {
11471147
#[cfg(test)]
1148-
pub fn dummy(channel_value_satoshis: u64, htlcs: &mut Vec<(HTLCOutputInCommitment, ())>) -> Self {
1148+
pub fn dummy(channel_value_satoshis: u64, nondust_htlcs: &mut Vec<HTLCOutputInCommitment>) -> Self {
11491149
let secp_ctx = Secp256k1::new();
11501150
let dummy_key = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
11511151
let dummy_sig = sign(&secp_ctx, &secp256k1::Message::from_digest([42; 32]), &SecretKey::from_slice(&[42; 32]).unwrap());
@@ -1168,11 +1168,11 @@ impl HolderCommitmentTransaction {
11681168
channel_value_satoshis,
11691169
};
11701170
let mut counterparty_htlc_sigs = Vec::new();
1171-
for _ in 0..htlcs.len() {
1171+
for _ in 0..nondust_htlcs.len() {
11721172
counterparty_htlc_sigs.push(dummy_sig);
11731173
}
1174-
let inner = CommitmentTransaction::new_with_auxiliary_htlc_data(0, &dummy_key.clone(), 0, 0, 0, htlcs, &channel_parameters.as_counterparty_broadcastable(), &secp_ctx);
1175-
htlcs.sort_by_key(|htlc| htlc.0.transaction_output_index);
1174+
let inner = CommitmentTransaction::new(0, &dummy_key.clone(), 0, 0, 0, nondust_htlcs.iter_mut().collect(), &channel_parameters.as_counterparty_broadcastable(), &secp_ctx);
1175+
nondust_htlcs.sort_by_key(|htlc| htlc.transaction_output_index);
11761176
HolderCommitmentTransaction {
11771177
inner,
11781178
counterparty_sig: dummy_sig,
@@ -1471,23 +1471,16 @@ impl Readable for CommitmentTransaction {
14711471
}
14721472

14731473
impl CommitmentTransaction {
1474-
/// Construct an object of the class while assigning transaction output indices to HTLCs.
1474+
/// Construct an object of the class while assigning transaction output indices to HTLCs in `nondust_htlcs`.
14751475
///
1476-
/// Populates HTLCOutputInCommitment.transaction_output_index in htlcs_with_aux.
1477-
///
1478-
/// The generic T allows the caller to match the HTLC output index with auxiliary data.
1479-
/// This auxiliary data is not stored in this object.
1480-
///
1481-
/// Only include HTLCs that are above the dust limit for the channel.
1482-
///
1483-
/// This is not exported to bindings users due to the generic though we likely should expose a version without
1484-
pub fn new_with_auxiliary_htlc_data<T>(commitment_number: u64, per_commitment_point: &PublicKey, to_broadcaster_value_sat: u64, to_countersignatory_value_sat: u64, feerate_per_kw: u32, htlcs_with_aux: &mut Vec<(HTLCOutputInCommitment, T)>, channel_parameters: &DirectedChannelTransactionParameters, secp_ctx: &Secp256k1<secp256k1::All>) -> CommitmentTransaction {
1476+
/// `nondust_htlcs` should only include HTLCs that are above the dust limit for the channel.
1477+
pub fn new(commitment_number: u64, per_commitment_point: &PublicKey, to_broadcaster_value_sat: u64, to_countersignatory_value_sat: u64, feerate_per_kw: u32, nondust_htlcs: Vec<&mut HTLCOutputInCommitment>, channel_parameters: &DirectedChannelTransactionParameters, secp_ctx: &Secp256k1<secp256k1::All>) -> CommitmentTransaction {
14851478
let to_broadcaster_value_sat = Amount::from_sat(to_broadcaster_value_sat);
14861479
let to_countersignatory_value_sat = Amount::from_sat(to_countersignatory_value_sat);
14871480
let keys = TxCreationKeys::from_channel_static_keys(per_commitment_point, channel_parameters.broadcaster_pubkeys(), channel_parameters.countersignatory_pubkeys(), secp_ctx);
14881481

1489-
// Sort outputs and populate output indices while keeping track of the auxiliary data
1490-
let (outputs, htlcs) = Self::internal_build_outputs(&keys, to_broadcaster_value_sat, to_countersignatory_value_sat, htlcs_with_aux, channel_parameters).unwrap();
1482+
// Sort outputs and populate output indices
1483+
let (outputs, nondust_htlcs) = Self::internal_build_outputs(&keys, to_broadcaster_value_sat, to_countersignatory_value_sat, nondust_htlcs, channel_parameters).unwrap();
14911484

14921485
let (obscured_commitment_transaction_number, txins) = Self::internal_build_inputs(commitment_number, channel_parameters);
14931486
let transaction = Self::make_transaction(obscured_commitment_transaction_number, txins, outputs);
@@ -1498,7 +1491,7 @@ impl CommitmentTransaction {
14981491
to_countersignatory_value_sat,
14991492
to_broadcaster_delay: Some(channel_parameters.contest_delay()),
15001493
feerate_per_kw,
1501-
htlcs,
1494+
htlcs: nondust_htlcs,
15021495
channel_type_features: channel_parameters.channel_type_features().clone(),
15031496
keys,
15041497
built: BuiltCommitmentTransaction {
@@ -1519,8 +1512,8 @@ impl CommitmentTransaction {
15191512
fn internal_rebuild_transaction(&self, keys: &TxCreationKeys, channel_parameters: &DirectedChannelTransactionParameters) -> Result<BuiltCommitmentTransaction, ()> {
15201513
let (obscured_commitment_transaction_number, txins) = Self::internal_build_inputs(self.commitment_number, channel_parameters);
15211514

1522-
let mut htlcs_with_aux = self.htlcs.iter().map(|h| (h.clone(), ())).collect();
1523-
let (outputs, _) = Self::internal_build_outputs(keys, self.to_broadcaster_value_sat, self.to_countersignatory_value_sat, &mut htlcs_with_aux, channel_parameters)?;
1515+
let mut nondust_htlcs = self.htlcs.clone();
1516+
let (outputs, _) = Self::internal_build_outputs(keys, self.to_broadcaster_value_sat, self.to_countersignatory_value_sat, nondust_htlcs.iter_mut().collect(), channel_parameters)?;
15241517

15251518
let transaction = Self::make_transaction(obscured_commitment_transaction_number, txins, outputs);
15261519
let txid = transaction.compute_txid();
@@ -1544,7 +1537,7 @@ impl CommitmentTransaction {
15441537
// - initial sorting of outputs / HTLCs in the constructor, in which case T is auxiliary data the
15451538
// caller needs to have sorted together with the HTLCs so it can keep track of the output index
15461539
// - building of a bitcoin transaction during a verify() call, in which case T is just ()
1547-
fn internal_build_outputs<T>(keys: &TxCreationKeys, to_broadcaster_value_sat: Amount, to_countersignatory_value_sat: Amount, htlcs_with_aux: &mut Vec<(HTLCOutputInCommitment, T)>, channel_parameters: &DirectedChannelTransactionParameters) -> Result<(Vec<TxOut>, Vec<HTLCOutputInCommitment>), ()> {
1540+
fn internal_build_outputs(keys: &TxCreationKeys, to_broadcaster_value_sat: Amount, to_countersignatory_value_sat: Amount, nondust_htlcs: Vec<&mut HTLCOutputInCommitment>, channel_parameters: &DirectedChannelTransactionParameters) -> Result<(Vec<TxOut>, Vec<HTLCOutputInCommitment>), ()> {
15481541
let countersignatory_pubkeys = channel_parameters.countersignatory_pubkeys();
15491542
let broadcaster_funding_key = &channel_parameters.broadcaster_pubkeys().funding_pubkey;
15501543
let countersignatory_funding_key = &countersignatory_pubkeys.funding_pubkey;
@@ -1583,7 +1576,7 @@ impl CommitmentTransaction {
15831576
}
15841577

15851578
if channel_parameters.channel_type_features().supports_anchors_zero_fee_htlc_tx() {
1586-
if to_broadcaster_value_sat > Amount::ZERO || !htlcs_with_aux.is_empty() {
1579+
if to_broadcaster_value_sat > Amount::ZERO || !nondust_htlcs.is_empty() {
15871580
let anchor_script = get_anchor_redeemscript(broadcaster_funding_key);
15881581
txouts.push((
15891582
TxOut {
@@ -1594,7 +1587,7 @@ impl CommitmentTransaction {
15941587
));
15951588
}
15961589

1597-
if to_countersignatory_value_sat > Amount::ZERO || !htlcs_with_aux.is_empty() {
1590+
if to_countersignatory_value_sat > Amount::ZERO || !nondust_htlcs.is_empty() {
15981591
let anchor_script = get_anchor_redeemscript(countersignatory_funding_key);
15991592
txouts.push((
16001593
TxOut {
@@ -1606,8 +1599,8 @@ impl CommitmentTransaction {
16061599
}
16071600
}
16081601

1609-
let mut htlcs = Vec::with_capacity(htlcs_with_aux.len());
1610-
for (htlc, _) in htlcs_with_aux {
1602+
let mut htlcs = Vec::with_capacity(nondust_htlcs.len());
1603+
for htlc in nondust_htlcs {
16111604
let script = get_htlc_redeemscript(&htlc, &channel_parameters.channel_type_features(), &keys);
16121605
let txout = TxOut {
16131606
script_pubkey: script.to_p2wsh(),
@@ -1951,7 +1944,7 @@ mod tests {
19511944
commitment_number: u64,
19521945
per_commitment_point: PublicKey,
19531946
feerate_per_kw: u32,
1954-
htlcs_with_aux: Vec<(HTLCOutputInCommitment, ())>,
1947+
nondust_htlcs: Vec<HTLCOutputInCommitment>,
19551948
channel_parameters: ChannelTransactionParameters,
19561949
counterparty_pubkeys: ChannelPublicKeys,
19571950
secp_ctx: Secp256k1::<secp256k1::All>,
@@ -1979,23 +1972,23 @@ mod tests {
19791972
channel_type_features: ChannelTypeFeatures::only_static_remote_key(),
19801973
channel_value_satoshis: 3000,
19811974
};
1982-
let htlcs_with_aux = Vec::new();
1975+
let nondust_htlcs = Vec::new();
19831976

19841977
Self {
19851978
commitment_number: 0,
19861979
per_commitment_point,
19871980
feerate_per_kw: 1,
1988-
htlcs_with_aux,
1981+
nondust_htlcs,
19891982
channel_parameters,
19901983
counterparty_pubkeys,
19911984
secp_ctx,
19921985
}
19931986
}
19941987

19951988
fn build(&mut self, to_broadcaster_sats: u64, to_countersignatory_sats: u64) -> CommitmentTransaction {
1996-
CommitmentTransaction::new_with_auxiliary_htlc_data(
1989+
CommitmentTransaction::new(
19971990
self.commitment_number, &self.per_commitment_point, to_broadcaster_sats, to_countersignatory_sats, self.feerate_per_kw,
1998-
&mut self.htlcs_with_aux, &self.channel_parameters.as_holder_broadcastable(), &self.secp_ctx
1991+
self.nondust_htlcs.iter_mut().collect(), &self.channel_parameters.as_holder_broadcastable(), &self.secp_ctx
19991992
)
20001993
}
20011994
}
@@ -2041,7 +2034,7 @@ mod tests {
20412034

20422035
// Generate broadcaster output and received and offered HTLC outputs, w/o anchors
20432036
builder.channel_parameters.channel_type_features = ChannelTypeFeatures::only_static_remote_key();
2044-
builder.htlcs_with_aux = vec![(received_htlc.clone(), ()), (offered_htlc.clone(), ())];
2037+
builder.nondust_htlcs = vec![received_htlc.clone(), offered_htlc.clone()];
20452038
let tx = builder.build(3000, 0);
20462039
let keys = &tx.trust().keys();
20472040
assert_eq!(tx.built.transaction.output.len(), 3);
@@ -2054,7 +2047,7 @@ mod tests {
20542047

20552048
// Generate broadcaster output and received and offered HTLC outputs, with anchors
20562049
builder.channel_parameters.channel_type_features = ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies();
2057-
builder.htlcs_with_aux = vec![(received_htlc.clone(), ()), (offered_htlc.clone(), ())];
2050+
builder.nondust_htlcs = vec![received_htlc.clone(), offered_htlc.clone()];
20582051
let tx = builder.build(3000, 0);
20592052
assert_eq!(tx.built.transaction.output.len(), 5);
20602053
assert_eq!(tx.built.transaction.output[2].script_pubkey, get_htlc_redeemscript(&received_htlc, &ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(), &keys).to_p2wsh());

lightning/src/ln/channel.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3791,14 +3791,14 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
37913791
let channel_parameters =
37923792
if local { funding.channel_transaction_parameters.as_holder_broadcastable() }
37933793
else { funding.channel_transaction_parameters.as_counterparty_broadcastable() };
3794-
let tx = CommitmentTransaction::new_with_auxiliary_htlc_data(commitment_number,
3795-
&keys.per_commitment_point,
3796-
value_to_a as u64,
3797-
value_to_b as u64,
3798-
feerate_per_kw,
3799-
&mut included_non_dust_htlcs,
3800-
&channel_parameters,
3801-
&self.secp_ctx,
3794+
let tx = CommitmentTransaction::new(commitment_number,
3795+
&keys.per_commitment_point,
3796+
value_to_a as u64,
3797+
value_to_b as u64,
3798+
feerate_per_kw,
3799+
included_non_dust_htlcs.iter_mut().map(|(htlc, _)| htlc).collect(),
3800+
&channel_parameters,
3801+
&self.secp_ctx,
38023802
);
38033803
let mut htlcs_included = included_non_dust_htlcs;
38043804
// The unwrap is safe, because all non-dust HTLCs have been assigned an output index

0 commit comments

Comments
 (0)