Include witness weights in FundingNegotiationContext
What changed, and why it matters
This commit is a straightforward internal refactoring in the Lightning Dev Kit codebase. It changes how transaction 'witness weights' (a measure of data size) are stored alongside funding inputs during channel creation and splicing. The weights are now kept in a shared negotiation context so they can be used later when calculating change outputs. There is no indication this fixes a security bug; it appears to be preparatory cleanup for upcoming dual-funding and splicing features.
No security action required. Treat as normal code-review/merge for the dual-funding/splicing feature work.
Security signals we found
No security-relevant signal: refactor-only change to data structure shape
No new validation, no privilege changes, no cryptographic changes
No mention of vulnerability, CVE, bug, or security fix in commit message or diff
Evidence from the diff
The patch modifies FundingNegotiationContext to store funding inputs as Vec<(TxIn, Transaction, Weight)> instead of Vec<(TxIn, Transaction)>, carrying witness weights through the funding/splicing flow. It updates call sites in channel.rs and interactivetxs.rs to account for the new tuple element, and adjusts dual_funding_tests.rs to stop stripping the weight. The weight is currently stored but not yet consumed in fee/change calculations beyond the structural plumbing. No bounds checks, validation logic, or cryptographic operations are changed in a security-relevant way.
Changed components
lightning/src/ln/channel.rslightning/src/ln/dual_funding_tests.rslightning/src/ln/interactivetxs.rsInspect captured patch +17 / −17
diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs
index 60f35b9..2edeaa4 100644
--- a/lightning/src/ln/channel.rs
+++ b/lightning/src/ln/channel.rs
@@ -5979,7 +5979,7 @@ pub(super) struct FundingNegotiationContext {
pub shared_funding_input: Option<SharedOwnedInput>,
/// The funding inputs we will be contributing to the channel.
#[allow(dead_code)] // TODO(dual_funding): Remove once contribution to V2 channels is enabled.
- pub our_funding_inputs: Vec<(TxIn, Transaction)>,
+ pub our_funding_inputs: Vec<(TxIn, Transaction, Weight)>,
/// The change output script. This will be used if needed or -- if not set -- generated using
/// `SignerProvider::get_destination_script`.
#[allow(dead_code)] // TODO(splicing): Remove once splicing is enabled.
@@ -6051,6 +6051,9 @@ impl FundingNegotiationContext {
}
}
+ let funding_inputs =
+ self.our_funding_inputs.into_iter().map(|(txin, tx, _)| (txin, tx)).collect();
+
let constructor_args = InteractiveTxConstructorArgs {
entropy_source,
holder_node_id,
@@ -6059,7 +6062,7 @@ impl FundingNegotiationContext {
feerate_sat_per_kw: self.funding_feerate_sat_per_1000_weight,
is_initiator: self.is_initiator,
funding_tx_locktime: self.funding_tx_locktime,
- inputs_to_contribute: self.our_funding_inputs,
+ inputs_to_contribute: funding_inputs,
shared_funding_input: self.shared_funding_input,
shared_funding_output: SharedOwnedOutput::new(
shared_funding_output,
@@ -10669,9 +10672,8 @@ where
err,
),
})?;
- // Convert inputs
- let mut funding_inputs = Vec::new();
- for (txin, tx, _) in our_funding_inputs.into_iter() {
+
+ for (txin, tx, _) in our_funding_inputs.iter() {
const MESSAGE_TEMPLATE: msgs::TxAddInput = msgs::TxAddInput {
channel_id: ChannelId([0; 32]),
serial_id: 0,
@@ -10689,8 +10691,6 @@ where
),
});
}
-
- funding_inputs.push((txin, tx));
}
let prev_funding_input = self.funding.to_splice_funding_input();
@@ -10700,7 +10700,7 @@ where
funding_tx_locktime: LockTime::from_consensus(locktime),
funding_feerate_sat_per_1000_weight: funding_feerate_per_kw,
shared_funding_input: Some(prev_funding_input),
- our_funding_inputs: funding_inputs,
+ our_funding_inputs,
change_script,
};
@@ -12469,7 +12469,7 @@ where
pub fn new_outbound<ES: Deref, F: Deref, L: Deref>(
fee_estimator: &LowerBoundedFeeEstimator<F>, entropy_source: &ES, signer_provider: &SP,
counterparty_node_id: PublicKey, their_features: &InitFeatures, funding_satoshis: u64,
- funding_inputs: Vec<(TxIn, Transaction)>, user_id: u128, config: &UserConfig,
+ funding_inputs: Vec<(TxIn, Transaction, Weight)>, user_id: u128, config: &UserConfig,
current_chain_height: u32, outbound_scid_alias: u64, funding_confirmation_target: ConfirmationTarget,
logger: L,
) -> Result<Self, APIError>
@@ -12683,6 +12683,8 @@ where
value: Amount::from_sat(funding.get_value_satoshis()),
script_pubkey: funding.get_funding_redeemscript().to_p2wsh(),
};
+ let inputs_to_contribute =
+ our_funding_inputs.into_iter().map(|(txin, tx, _)| (txin, tx)).collect();
let interactive_tx_constructor = Some(InteractiveTxConstructor::new(
InteractiveTxConstructorArgs {
@@ -12693,7 +12695,7 @@ where
feerate_sat_per_kw: funding_negotiation_context.funding_feerate_sat_per_1000_weight,
funding_tx_locktime: funding_negotiation_context.funding_tx_locktime,
is_initiator: false,
- inputs_to_contribute: our_funding_inputs,
+ inputs_to_contribute,
shared_funding_input: None,
shared_funding_output: SharedOwnedOutput::new(shared_funding_output, our_funding_contribution_sats),
outputs_to_contribute: Vec::new(),
diff --git a/lightning/src/ln/dual_funding_tests.rs b/lightning/src/ln/dual_funding_tests.rs
index ab968c3..ee23cd6 100644
--- a/lightning/src/ln/dual_funding_tests.rs
+++ b/lightning/src/ln/dual_funding_tests.rs
@@ -48,10 +48,7 @@ fn do_test_v2_channel_establishment(session: V2ChannelEstablishmentTestSession)
let initiator_funding_inputs: Vec<_> = create_dual_funding_utxos_with_prev_txs(
&nodes[0],
&[session.initiator_input_value_satoshis],
- )
- .into_iter()
- .map(|(txin, tx, _)| (txin, tx))
- .collect();
+ );
// Alice creates a dual-funded channel as initiator.
let funding_satoshis = session.funding_input_sats;
diff --git a/lightning/src/ln/interactivetxs.rs b/lightning/src/ln/interactivetxs.rs
index 9fdd35e..d88edfb 100644
--- a/lightning/src/ln/interactivetxs.rs
+++ b/lightning/src/ln/interactivetxs.rs
@@ -2075,7 +2075,7 @@ pub(super) fn calculate_change_output_value(
let mut total_input_satoshis = 0u64;
let mut our_funding_inputs_weight = 0u64;
- for (txin, tx) in context.our_funding_inputs.iter() {
+ for (txin, tx, _) in context.our_funding_inputs.iter() {
let txid = tx.compute_txid();
if txin.previous_output.txid != txid {
return Err(AbortReason::PrevTxOutInvalid);
@@ -3160,9 +3160,10 @@ mod tests {
sequence: Sequence::ZERO,
witness: Witness::new(),
};
- (txin, tx)
+ let weight = Weight::ZERO;
+ (txin, tx, weight)
})
- .collect::<Vec<(TxIn, Transaction)>>();
+ .collect::<Vec<(TxIn, Transaction, Weight)>>();
let our_contributed = 110_000;
let txout = TxOut { value: Amount::from_sat(10_000), script_pubkey: ScriptBuf::new() };
let outputs = vec![txout];
Why this scored 12/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.