Skip to content

Commit f08af5f

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 f6c6c4f commit f08af5f

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
@@ -3482,12 +3482,12 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
34823482
fn build_counterparty_commitment_tx(
34833483
&self, commitment_number: u64, their_per_commitment_point: &PublicKey,
34843484
to_broadcaster_value: u64, to_countersignatory_value: u64, feerate_per_kw: u32,
3485-
mut nondust_htlcs: Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>
3485+
nondust_htlcs: Vec<&mut HTLCOutputInCommitment>,
34863486
) -> CommitmentTransaction {
34873487
let channel_parameters =
34883488
&self.onchain_tx_handler.channel_transaction_parameters.as_counterparty_broadcastable();
3489-
CommitmentTransaction::new_with_auxiliary_htlc_data(commitment_number, their_per_commitment_point,
3490-
to_broadcaster_value, to_countersignatory_value, feerate_per_kw, &mut nondust_htlcs, channel_parameters, &self.onchain_tx_handler.secp_ctx)
3489+
CommitmentTransaction::new(commitment_number, their_per_commitment_point,
3490+
to_broadcaster_value, to_countersignatory_value, feerate_per_kw, nondust_htlcs, channel_parameters, &self.onchain_tx_handler.secp_ctx)
34913491
}
34923492

34933493
fn counterparty_commitment_txs_from_update(&self, update: &ChannelMonitorUpdate) -> Vec<CommitmentTransaction> {
@@ -3503,13 +3503,13 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
35033503
to_countersignatory_value_sat: Some(to_countersignatory_value)
35043504
} => {
35053505

3506-
let nondust_htlcs = htlc_outputs.iter().filter_map(|(htlc, _)| {
3507-
htlc.transaction_output_index.map(|_| (htlc.clone(), None))
3508-
}).collect::<Vec<_>>();
3506+
let mut nondust_htlcs = htlc_outputs.iter().filter_map(|(htlc, _)| {
3507+
htlc.transaction_output_index.map(|_| htlc)
3508+
}).cloned().collect::<Vec<_>>();
35093509

35103510
let commitment_tx = self.build_counterparty_commitment_tx(commitment_number,
35113511
&their_per_commitment_point, to_broadcaster_value,
3512-
to_countersignatory_value, feerate_per_kw, nondust_htlcs);
3512+
to_countersignatory_value, feerate_per_kw, nondust_htlcs.iter_mut().collect());
35133513

35143514
debug_assert_eq!(commitment_tx.trust().txid(), commitment_txid);
35153515

@@ -5387,21 +5387,21 @@ mod tests {
53875387
{
53885388
let mut res = Vec::new();
53895389
for (idx, preimage) in $preimages_slice.iter().enumerate() {
5390-
res.push((HTLCOutputInCommitment {
5390+
res.push(HTLCOutputInCommitment {
53915391
offered: true,
53925392
amount_msat: 0,
53935393
cltv_expiry: 0,
53945394
payment_hash: preimage.1.clone(),
53955395
transaction_output_index: Some(idx as u32),
5396-
}, ()));
5396+
});
53975397
}
53985398
res
53995399
}
54005400
}
54015401
}
54025402
macro_rules! preimages_slice_to_htlc_outputs {
54035403
($preimages_slice: expr) => {
5404-
preimages_slice_to_htlcs!($preimages_slice).into_iter().map(|(htlc, _)| (htlc, None)).collect()
5404+
preimages_slice_to_htlcs!($preimages_slice).into_iter().map(|htlc| (htlc, None)).collect()
54055405
}
54065406
}
54075407
let dummy_sig = crate::crypto::utils::sign(&secp_ctx,
@@ -5463,7 +5463,7 @@ mod tests {
54635463
let dummy_commitment_tx = HolderCommitmentTransaction::dummy(0, &mut htlcs);
54645464

54655465
monitor.provide_latest_holder_commitment_tx(dummy_commitment_tx.clone(),
5466-
htlcs.into_iter().map(|(htlc, _)| (htlc, Some(dummy_sig), None)).collect());
5466+
htlcs.into_iter().map(|htlc| (htlc, Some(dummy_sig), None)).collect());
54675467
monitor.provide_latest_counterparty_commitment_tx(Txid::from_byte_array(Sha256::hash(b"1").to_byte_array()),
54685468
preimages_slice_to_htlc_outputs!(preimages[5..15]), 281474976710655, dummy_key, &logger);
54695469
monitor.provide_latest_counterparty_commitment_tx(Txid::from_byte_array(Sha256::hash(b"2").to_byte_array()),
@@ -5501,7 +5501,7 @@ mod tests {
55015501
let mut htlcs = preimages_slice_to_htlcs!(preimages[0..5]);
55025502
let dummy_commitment_tx = HolderCommitmentTransaction::dummy(0, &mut htlcs);
55035503
monitor.provide_latest_holder_commitment_tx(dummy_commitment_tx.clone(),
5504-
htlcs.into_iter().map(|(htlc, _)| (htlc, Some(dummy_sig), None)).collect());
5504+
htlcs.into_iter().map(|htlc| (htlc, Some(dummy_sig), None)).collect());
55055505
secret[0..32].clone_from_slice(&<Vec<u8>>::from_hex("2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8").unwrap());
55065506
monitor.provide_secret(281474976710653, secret.clone()).unwrap();
55075507
assert_eq!(monitor.inner.lock().unwrap().payment_preimages.len(), 12);
@@ -5512,7 +5512,7 @@ mod tests {
55125512
let mut htlcs = preimages_slice_to_htlcs!(preimages[0..3]);
55135513
let dummy_commitment_tx = HolderCommitmentTransaction::dummy(0, &mut htlcs);
55145514
monitor.provide_latest_holder_commitment_tx(dummy_commitment_tx,
5515-
htlcs.into_iter().map(|(htlc, _)| (htlc, Some(dummy_sig), None)).collect());
5515+
htlcs.into_iter().map(|htlc| (htlc, Some(dummy_sig), None)).collect());
55165516
secret[0..32].clone_from_slice(&<Vec<u8>>::from_hex("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116").unwrap());
55175517
monitor.provide_secret(281474976710652, secret.clone()).unwrap();
55185518
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
@@ -1362,16 +1362,15 @@ mod tests {
13621362
for i in 0..3 {
13631363
let preimage = PaymentPreimage([i; 32]);
13641364
let hash = PaymentHash(Sha256::hash(&preimage.0[..]).to_byte_array());
1365-
htlcs.push((
1365+
htlcs.push(
13661366
HTLCOutputInCommitment {
13671367
offered: true,
13681368
amount_msat: 10000,
13691369
cltv_expiry: i as u32,
13701370
payment_hash: hash,
13711371
transaction_output_index: Some(i as u32),
13721372
},
1373-
(),
1374-
));
1373+
);
13751374
}
13761375
let holder_commit = HolderCommitmentTransaction::dummy(1000000, &mut htlcs);
13771376
let mut tx_handler = OnchainTxHandler::new(
@@ -1399,7 +1398,7 @@ mod tests {
13991398
// Request claiming of each HTLC on the holder's commitment, with current block height 1.
14001399
let holder_commit_txid = tx_handler.get_unsigned_holder_commitment_tx().compute_txid();
14011400
let mut requests = Vec::new();
1402-
for (htlc, _) in htlcs {
1401+
for htlc in htlcs {
14031402
requests.push(PackageTemplate::build_package(
14041403
holder_commit_txid,
14051404
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
@@ -1129,7 +1129,7 @@ impl_writeable_tlv_based!(HolderCommitmentTransaction, {
11291129

11301130
impl HolderCommitmentTransaction {
11311131
#[cfg(test)]
1132-
pub fn dummy(channel_value_satoshis: u64, htlcs: &mut Vec<(HTLCOutputInCommitment, ())>) -> Self {
1132+
pub fn dummy(channel_value_satoshis: u64, nondust_htlcs: &mut Vec<HTLCOutputInCommitment>) -> Self {
11331133
let secp_ctx = Secp256k1::new();
11341134
let dummy_key = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
11351135
let dummy_sig = sign(&secp_ctx, &secp256k1::Message::from_digest([42; 32]), &SecretKey::from_slice(&[42; 32]).unwrap());
@@ -1151,11 +1151,11 @@ impl HolderCommitmentTransaction {
11511151
channel_value_satoshis,
11521152
};
11531153
let mut counterparty_htlc_sigs = Vec::new();
1154-
for _ in 0..htlcs.len() {
1154+
for _ in 0..nondust_htlcs.len() {
11551155
counterparty_htlc_sigs.push(dummy_sig);
11561156
}
1157-
let inner = CommitmentTransaction::new_with_auxiliary_htlc_data(0, &dummy_key.clone(), 0, 0, 0, htlcs, &channel_parameters.as_counterparty_broadcastable(), &secp_ctx);
1158-
htlcs.sort_by_key(|htlc| htlc.0.transaction_output_index);
1157+
let inner = CommitmentTransaction::new(0, &dummy_key.clone(), 0, 0, 0, nondust_htlcs.iter_mut().collect(), &channel_parameters.as_counterparty_broadcastable(), &secp_ctx);
1158+
nondust_htlcs.sort_by_key(|htlc| htlc.transaction_output_index);
11591159
HolderCommitmentTransaction {
11601160
inner,
11611161
counterparty_sig: dummy_sig,
@@ -1454,23 +1454,16 @@ impl Readable for CommitmentTransaction {
14541454
}
14551455

14561456
impl CommitmentTransaction {
1457-
/// Construct an object of the class while assigning transaction output indices to HTLCs.
1457+
/// Construct an object of the class while assigning transaction output indices to HTLCs in `nondust_htlcs`.
14581458
///
1459-
/// Populates HTLCOutputInCommitment.transaction_output_index in htlcs_with_aux.
1460-
///
1461-
/// The generic T allows the caller to match the HTLC output index with auxiliary data.
1462-
/// This auxiliary data is not stored in this object.
1463-
///
1464-
/// Only include HTLCs that are above the dust limit for the channel.
1465-
///
1466-
/// This is not exported to bindings users due to the generic though we likely should expose a version without
1467-
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 {
1459+
/// `nondust_htlcs` should only include HTLCs that are above the dust limit for the channel.
1460+
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 {
14681461
let to_broadcaster_value_sat = Amount::from_sat(to_broadcaster_value_sat);
14691462
let to_countersignatory_value_sat = Amount::from_sat(to_countersignatory_value_sat);
14701463
let keys = TxCreationKeys::from_channel_static_keys(per_commitment_point, channel_parameters.broadcaster_pubkeys(), channel_parameters.countersignatory_pubkeys(), secp_ctx);
14711464

1472-
// Sort outputs and populate output indices while keeping track of the auxiliary data
1473-
let (outputs, htlcs) = Self::internal_build_outputs(&keys, to_broadcaster_value_sat, to_countersignatory_value_sat, htlcs_with_aux, channel_parameters).unwrap();
1465+
// Sort outputs and populate output indices
1466+
let (outputs, nondust_htlcs) = Self::internal_build_outputs(&keys, to_broadcaster_value_sat, to_countersignatory_value_sat, nondust_htlcs, channel_parameters).unwrap();
14741467

14751468
let (obscured_commitment_transaction_number, txins) = Self::internal_build_inputs(commitment_number, channel_parameters);
14761469
let transaction = Self::make_transaction(obscured_commitment_transaction_number, txins, outputs);
@@ -1481,7 +1474,7 @@ impl CommitmentTransaction {
14811474
to_countersignatory_value_sat,
14821475
to_broadcaster_delay: Some(channel_parameters.contest_delay()),
14831476
feerate_per_kw,
1484-
htlcs,
1477+
htlcs: nondust_htlcs,
14851478
channel_type_features: channel_parameters.channel_type_features().clone(),
14861479
keys,
14871480
built: BuiltCommitmentTransaction {
@@ -1502,8 +1495,8 @@ impl CommitmentTransaction {
15021495
fn internal_rebuild_transaction(&self, keys: &TxCreationKeys, channel_parameters: &DirectedChannelTransactionParameters) -> Result<BuiltCommitmentTransaction, ()> {
15031496
let (obscured_commitment_transaction_number, txins) = Self::internal_build_inputs(self.commitment_number, channel_parameters);
15041497

1505-
let mut htlcs_with_aux = self.htlcs.iter().map(|h| (h.clone(), ())).collect();
1506-
let (outputs, _) = Self::internal_build_outputs(keys, self.to_broadcaster_value_sat, self.to_countersignatory_value_sat, &mut htlcs_with_aux, channel_parameters)?;
1498+
let mut nondust_htlcs = self.htlcs.clone();
1499+
let (outputs, _) = Self::internal_build_outputs(keys, self.to_broadcaster_value_sat, self.to_countersignatory_value_sat, nondust_htlcs.iter_mut().collect(), channel_parameters)?;
15071500

15081501
let transaction = Self::make_transaction(obscured_commitment_transaction_number, txins, outputs);
15091502
let txid = transaction.compute_txid();
@@ -1527,7 +1520,7 @@ impl CommitmentTransaction {
15271520
// - initial sorting of outputs / HTLCs in the constructor, in which case T is auxiliary data the
15281521
// caller needs to have sorted together with the HTLCs so it can keep track of the output index
15291522
// - building of a bitcoin transaction during a verify() call, in which case T is just ()
1530-
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>), ()> {
1523+
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>), ()> {
15311524
let countersignatory_pubkeys = channel_parameters.countersignatory_pubkeys();
15321525
let broadcaster_funding_key = &channel_parameters.broadcaster_pubkeys().funding_pubkey;
15331526
let countersignatory_funding_key = &countersignatory_pubkeys.funding_pubkey;
@@ -1566,7 +1559,7 @@ impl CommitmentTransaction {
15661559
}
15671560

15681561
if channel_parameters.channel_type_features().supports_anchors_zero_fee_htlc_tx() {
1569-
if to_broadcaster_value_sat > Amount::ZERO || !htlcs_with_aux.is_empty() {
1562+
if to_broadcaster_value_sat > Amount::ZERO || !nondust_htlcs.is_empty() {
15701563
let anchor_script = get_anchor_redeemscript(broadcaster_funding_key);
15711564
txouts.push((
15721565
TxOut {
@@ -1577,7 +1570,7 @@ impl CommitmentTransaction {
15771570
));
15781571
}
15791572

1580-
if to_countersignatory_value_sat > Amount::ZERO || !htlcs_with_aux.is_empty() {
1573+
if to_countersignatory_value_sat > Amount::ZERO || !nondust_htlcs.is_empty() {
15811574
let anchor_script = get_anchor_redeemscript(countersignatory_funding_key);
15821575
txouts.push((
15831576
TxOut {
@@ -1589,8 +1582,8 @@ impl CommitmentTransaction {
15891582
}
15901583
}
15911584

1592-
let mut htlcs = Vec::with_capacity(htlcs_with_aux.len());
1593-
for (htlc, _) in htlcs_with_aux {
1585+
let mut htlcs = Vec::with_capacity(nondust_htlcs.len());
1586+
for htlc in nondust_htlcs {
15941587
let script = get_htlc_redeemscript(&htlc, &channel_parameters.channel_type_features(), &keys);
15951588
let txout = TxOut {
15961589
script_pubkey: script.to_p2wsh(),
@@ -1934,7 +1927,7 @@ mod tests {
19341927
commitment_number: u64,
19351928
per_commitment_point: PublicKey,
19361929
feerate_per_kw: u32,
1937-
htlcs_with_aux: Vec<(HTLCOutputInCommitment, ())>,
1930+
nondust_htlcs: Vec<HTLCOutputInCommitment>,
19381931
channel_parameters: ChannelTransactionParameters,
19391932
counterparty_pubkeys: ChannelPublicKeys,
19401933
secp_ctx: Secp256k1::<secp256k1::All>,
@@ -1961,23 +1954,23 @@ mod tests {
19611954
channel_type_features: ChannelTypeFeatures::only_static_remote_key(),
19621955
channel_value_satoshis: 3000,
19631956
};
1964-
let htlcs_with_aux = Vec::new();
1957+
let nondust_htlcs = Vec::new();
19651958

19661959
Self {
19671960
commitment_number: 0,
19681961
per_commitment_point,
19691962
feerate_per_kw: 1,
1970-
htlcs_with_aux,
1963+
nondust_htlcs,
19711964
channel_parameters,
19721965
counterparty_pubkeys,
19731966
secp_ctx,
19741967
}
19751968
}
19761969

19771970
fn build(&mut self, to_broadcaster_sats: u64, to_countersignatory_sats: u64) -> CommitmentTransaction {
1978-
CommitmentTransaction::new_with_auxiliary_htlc_data(
1971+
CommitmentTransaction::new(
19791972
self.commitment_number, &self.per_commitment_point, to_broadcaster_sats, to_countersignatory_sats, self.feerate_per_kw,
1980-
&mut self.htlcs_with_aux, &self.channel_parameters.as_holder_broadcastable(), &self.secp_ctx
1973+
self.nondust_htlcs.iter_mut().collect(), &self.channel_parameters.as_holder_broadcastable(), &self.secp_ctx
19811974
)
19821975
}
19831976
}
@@ -2023,7 +2016,7 @@ mod tests {
20232016

20242017
// Generate broadcaster output and received and offered HTLC outputs, w/o anchors
20252018
builder.channel_parameters.channel_type_features = ChannelTypeFeatures::only_static_remote_key();
2026-
builder.htlcs_with_aux = vec![(received_htlc.clone(), ()), (offered_htlc.clone(), ())];
2019+
builder.nondust_htlcs = vec![received_htlc.clone(), offered_htlc.clone()];
20272020
let tx = builder.build(3000, 0);
20282021
let keys = &tx.trust().keys();
20292022
assert_eq!(tx.built.transaction.output.len(), 3);
@@ -2036,7 +2029,7 @@ mod tests {
20362029

20372030
// Generate broadcaster output and received and offered HTLC outputs, with anchors
20382031
builder.channel_parameters.channel_type_features = ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies();
2039-
builder.htlcs_with_aux = vec![(received_htlc.clone(), ()), (offered_htlc.clone(), ())];
2032+
builder.nondust_htlcs = vec![received_htlc.clone(), offered_htlc.clone()];
20402033
let tx = builder.build(3000, 0);
20412034
assert_eq!(tx.built.transaction.output.len(), 5);
20422035
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
@@ -3661,14 +3661,14 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
36613661
let channel_parameters =
36623662
if local { funding.channel_transaction_parameters.as_holder_broadcastable() }
36633663
else { funding.channel_transaction_parameters.as_counterparty_broadcastable() };
3664-
let tx = CommitmentTransaction::new_with_auxiliary_htlc_data(commitment_number,
3665-
&keys.per_commitment_point,
3666-
value_to_a as u64,
3667-
value_to_b as u64,
3668-
feerate_per_kw,
3669-
&mut included_non_dust_htlcs,
3670-
&channel_parameters,
3671-
&self.secp_ctx,
3664+
let tx = CommitmentTransaction::new(commitment_number,
3665+
&keys.per_commitment_point,
3666+
value_to_a as u64,
3667+
value_to_b as u64,
3668+
feerate_per_kw,
3669+
included_non_dust_htlcs.iter_mut().map(|(htlc, _)| htlc).collect(),
3670+
&channel_parameters,
3671+
&self.secp_ctx,
36723672
);
36733673
let mut htlcs_included = included_non_dust_htlcs;
36743674
// The unwrap is safe, because all non-dust HTLCs have been assigned an output index

0 commit comments

Comments
 (0)