Skip to content

Commit a39357e

Browse files
TheBlueMattdunxen
authored andcommitted
Add tx fee information to Balance::ClaimableOnChannelClose
`Balance::ClaimableOnChannelClose` excludes the commitment transaction fee, which makes it hard to use for current balance calculation. Here we add it, setting the value to zero for inbound channels (i.e. ones for which we don't pay the fee).
1 parent f1f28c6 commit a39357e

File tree

3 files changed

+44
-11
lines changed

3 files changed

+44
-11
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,13 @@ pub enum Balance {
622622
/// The amount available to claim, in satoshis, excluding the on-chain fees which will be
623623
/// required to do so.
624624
amount_satoshis: u64,
625+
/// The transaction fee we pay for the closing commitment transaction. This amount is not
626+
/// included in the [`Balance::ClaimableOnChannelClose::amount_satoshis`] value.
627+
///
628+
/// Note that if this channel is inbound (and thus our counterparty pays the commitment
629+
/// transaction fee) this value will be zero. For [`ChannelMonitor`]s created prior to LDK
630+
/// 0.0.124, the channel is always treated as outbound (and thus this value is never zero).
631+
transaction_fee_satoshis: u64,
625632
},
626633
/// The channel has been closed, and the given balance is ours but awaiting confirmations until
627634
/// we consider it spendable.
@@ -912,6 +919,10 @@ pub(crate) struct ChannelMonitorImpl<Signer: EcdsaChannelSigner> {
912919
// of block connection between ChannelMonitors and the ChannelManager.
913920
funding_spend_seen: bool,
914921

922+
/// True if the commitment transaction fee is paid by us.
923+
/// Added in 0.0.124.
924+
holder_pays_commitment_tx_fee: Option<bool>,
925+
915926
/// Set to `Some` of the confirmed transaction spending the funding input of the channel after
916927
/// reaching `ANTI_REORG_DELAY` confirmations.
917928
funding_spend_confirmed: Option<Txid>,
@@ -1160,6 +1171,7 @@ impl<Signer: EcdsaChannelSigner> Writeable for ChannelMonitorImpl<Signer> {
11601171
(17, self.initial_counterparty_commitment_info, option),
11611172
(19, self.channel_id, required),
11621173
(21, self.balances_empty_height, option),
1174+
(23, self.holder_pays_commitment_tx_fee, option),
11631175
});
11641176

11651177
Ok(())
@@ -1261,7 +1273,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
12611273

12621274
pub(crate) fn new(secp_ctx: Secp256k1<secp256k1::All>, keys: Signer, shutdown_script: Option<ScriptBuf>,
12631275
on_counterparty_tx_csv: u16, destination_script: &Script, funding_info: (OutPoint, ScriptBuf),
1264-
channel_parameters: &ChannelTransactionParameters,
1276+
channel_parameters: &ChannelTransactionParameters, holder_pays_commitment_tx_fee: bool,
12651277
funding_redeemscript: ScriptBuf, channel_value_satoshis: u64,
12661278
commitment_transaction_number_obscure_factor: u64,
12671279
initial_holder_commitment_tx: HolderCommitmentTransaction,
@@ -1353,6 +1365,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
13531365

13541366
onchain_tx_handler,
13551367

1368+
holder_pays_commitment_tx_fee: Some(holder_pays_commitment_tx_fee),
13561369
lockdown_from_offchain: false,
13571370
holder_tx_signed: false,
13581371
funding_spend_seen: false,
@@ -2306,8 +2319,11 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
23062319
}
23072320
} else {
23082321
let mut claimable_inbound_htlc_value_sat = 0;
2322+
let mut nondust_htlc_count = 0;
23092323
for (htlc, _, source) in us.current_holder_commitment_tx.htlc_outputs.iter() {
2310-
if htlc.transaction_output_index.is_none() { continue; }
2324+
if htlc.transaction_output_index.is_some() {
2325+
nondust_htlc_count += 1;
2326+
} else { continue; }
23112327
if htlc.offered {
23122328
let outbound_payment = match source {
23132329
None => {
@@ -2337,6 +2353,11 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
23372353
}
23382354
res.push(Balance::ClaimableOnChannelClose {
23392355
amount_satoshis: us.current_holder_commitment_tx.to_self_value_sat + claimable_inbound_htlc_value_sat,
2356+
transaction_fee_satoshis: if us.holder_pays_commitment_tx_fee.unwrap_or(true) {
2357+
chan_utils::commit_tx_fee_sat(
2358+
us.current_holder_commitment_tx.feerate_per_kw, nondust_htlc_count,
2359+
us.onchain_tx_handler.channel_type_features())
2360+
} else { 0 },
23402361
});
23412362
}
23422363

@@ -4743,6 +4764,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
47434764
let mut initial_counterparty_commitment_info = None;
47444765
let mut balances_empty_height = None;
47454766
let mut channel_id = None;
4767+
let mut holder_pays_commitment_tx_fee = None;
47464768
read_tlv_fields!(reader, {
47474769
(1, funding_spend_confirmed, option),
47484770
(3, htlcs_resolved_on_chain, optional_vec),
@@ -4755,6 +4777,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
47554777
(17, initial_counterparty_commitment_info, option),
47564778
(19, channel_id, option),
47574779
(21, balances_empty_height, option),
4780+
(23, holder_pays_commitment_tx_fee, option),
47584781
});
47594782

47604783
// `HolderForceClosedWithInfo` replaced `HolderForceClosed` in v0.0.122. If we have both
@@ -4824,6 +4847,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
48244847

48254848
lockdown_from_offchain,
48264849
holder_tx_signed,
4850+
holder_pays_commitment_tx_fee,
48274851
funding_spend_seen: funding_spend_seen.unwrap(),
48284852
funding_spend_confirmed,
48294853
confirmed_commitment_tx_counterparty_output,
@@ -5063,7 +5087,7 @@ mod tests {
50635087
let monitor = ChannelMonitor::new(Secp256k1::new(), keys,
50645088
Some(ShutdownScript::new_p2wpkh_from_pubkey(shutdown_pubkey).into_inner()), 0, &ScriptBuf::new(),
50655089
(OutPoint { txid: Txid::from_slice(&[43; 32]).unwrap(), index: 0 }, ScriptBuf::new()),
5066-
&channel_parameters, ScriptBuf::new(), 46, 0, HolderCommitmentTransaction::dummy(&mut Vec::new()),
5090+
&channel_parameters, true, ScriptBuf::new(), 46, 0, HolderCommitmentTransaction::dummy(&mut Vec::new()),
50675091
best_block, dummy_key, channel_id);
50685092

50695093
let mut htlcs = preimages_slice_to_htlcs!(preimages[0..10]);
@@ -5311,7 +5335,7 @@ mod tests {
53115335
let monitor = ChannelMonitor::new(Secp256k1::new(), keys,
53125336
Some(ShutdownScript::new_p2wpkh_from_pubkey(shutdown_pubkey).into_inner()), 0, &ScriptBuf::new(),
53135337
(OutPoint { txid: Txid::from_slice(&[43; 32]).unwrap(), index: 0 }, ScriptBuf::new()),
5314-
&channel_parameters, ScriptBuf::new(), 46, 0, HolderCommitmentTransaction::dummy(&mut Vec::new()),
5338+
&channel_parameters, true, ScriptBuf::new(), 46, 0, HolderCommitmentTransaction::dummy(&mut Vec::new()),
53155339
best_block, dummy_key, channel_id);
53165340

53175341
let chan_id = monitor.inner.lock().unwrap().channel_id();

lightning/src/ln/channel.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7861,7 +7861,7 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
78617861
let channel_monitor = ChannelMonitor::new(self.context.secp_ctx.clone(), monitor_signer,
78627862
shutdown_script, self.context.get_holder_selected_contest_delay(),
78637863
&self.context.destination_script, (funding_txo, funding_txo_script),
7864-
&self.context.channel_transaction_parameters,
7864+
&self.context.channel_transaction_parameters, self.context.is_outbound(),
78657865
funding_redeemscript.clone(), self.context.channel_value_satoshis,
78667866
obscure_factor,
78677867
holder_commitment_tx, best_block, self.context.counterparty_node_id, self.context.channel_id());
@@ -8173,7 +8173,7 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
81738173
let channel_monitor = ChannelMonitor::new(self.context.secp_ctx.clone(), monitor_signer,
81748174
shutdown_script, self.context.get_holder_selected_contest_delay(),
81758175
&self.context.destination_script, (funding_txo, funding_txo_script.clone()),
8176-
&self.context.channel_transaction_parameters,
8176+
&self.context.channel_transaction_parameters, self.context.is_outbound(),
81778177
funding_redeemscript.clone(), self.context.channel_value_satoshis,
81788178
obscure_factor,
81798179
holder_commitment_tx, best_block, self.context.counterparty_node_id, self.context.channel_id());

lightning/src/ln/monitor_tests.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -240,10 +240,11 @@ fn do_chanmon_claim_value_coop_close(anchors: bool) {
240240
let commitment_tx_fee = chan_feerate * chan_utils::commitment_tx_base_weight(&channel_type_features) / 1000;
241241
let anchor_outputs_value = if anchors { channel::ANCHOR_OUTPUT_VALUE_SATOSHI * 2 } else { 0 };
242242
assert_eq!(vec![Balance::ClaimableOnChannelClose {
243-
amount_satoshis: 1_000_000 - 1_000 - commitment_tx_fee - anchor_outputs_value
243+
amount_satoshis: 1_000_000 - 1_000 - commitment_tx_fee - anchor_outputs_value,
244+
transaction_fee_satoshis: commitment_tx_fee,
244245
}],
245246
nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances());
246-
assert_eq!(vec![Balance::ClaimableOnChannelClose { amount_satoshis: 1_000, }],
247+
assert_eq!(vec![Balance::ClaimableOnChannelClose { amount_satoshis: 1_000, transaction_fee_satoshis: 0 }],
247248
nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances());
248249

249250
nodes[0].node.close_channel(&chan_id, &nodes[1].node.get_our_node_id()).unwrap();
@@ -441,10 +442,12 @@ fn do_test_claim_value_force_close(anchors: bool, prev_commitment_tx: bool) {
441442
let anchor_outputs_value = if anchors { 2 * channel::ANCHOR_OUTPUT_VALUE_SATOSHI } else { 0 };
442443
assert_eq!(sorted_vec(vec![Balance::ClaimableOnChannelClose {
443444
amount_satoshis: 1_000_000 - 3_000 - 4_000 - 1_000 - 3 - commitment_tx_fee - anchor_outputs_value,
445+
transaction_fee_satoshis: commitment_tx_fee,
444446
}, sent_htlc_balance.clone(), sent_htlc_timeout_balance.clone()]),
445447
sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances()));
446448
assert_eq!(sorted_vec(vec![Balance::ClaimableOnChannelClose {
447449
amount_satoshis: 1_000,
450+
transaction_fee_satoshis: 0,
448451
}, received_htlc_balance.clone(), received_htlc_timeout_balance.clone()]),
449452
sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances()));
450453

@@ -491,6 +494,7 @@ fn do_test_claim_value_force_close(anchors: bool, prev_commitment_tx: bool) {
491494
3 - // The dust HTLC value in satoshis
492495
commitment_tx_fee - // The commitment transaction fee with two HTLC outputs
493496
anchor_outputs_value, // The anchor outputs value in satoshis
497+
transaction_fee_satoshis: commitment_tx_fee,
494498
}, sent_htlc_timeout_balance.clone()];
495499
if !prev_commitment_tx {
496500
a_expected_balances.push(sent_htlc_balance.clone());
@@ -499,6 +503,7 @@ fn do_test_claim_value_force_close(anchors: bool, prev_commitment_tx: bool) {
499503
sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances()));
500504
assert_eq!(vec![Balance::ClaimableOnChannelClose {
501505
amount_satoshis: 1_000 + 3_000 + 4_000,
506+
transaction_fee_satoshis: 0,
502507
}],
503508
nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances());
504509

@@ -977,15 +982,17 @@ fn test_no_preimage_inbound_htlc_balances() {
977982
// Both A and B will have an HTLC that's claimable on timeout and one that's claimable if they
978983
// receive the preimage. These will remain the same through the channel closure and until the
979984
// HTLC output is spent.
980-
985+
let commitment_tx_fee = chan_feerate *
986+
(chan_utils::commitment_tx_base_weight(&channel_type_features) + 2 * chan_utils::COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000;
981987
assert_eq!(sorted_vec(vec![Balance::ClaimableOnChannelClose {
982-
amount_satoshis: 1_000_000 - 500_000 - 10_000 - chan_feerate *
983-
(chan_utils::commitment_tx_base_weight(&channel_type_features) + 2 * chan_utils::COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000,
988+
amount_satoshis: 1_000_000 - 500_000 - 10_000 - commitment_tx_fee,
989+
transaction_fee_satoshis: commitment_tx_fee,
984990
}, a_received_htlc_balance.clone(), a_sent_htlc_balance.clone()]),
985991
sorted_vec(nodes[0].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances()));
986992

987993
assert_eq!(sorted_vec(vec![Balance::ClaimableOnChannelClose {
988994
amount_satoshis: 500_000 - 20_000,
995+
transaction_fee_satoshis: 0,
989996
}, b_received_htlc_balance.clone(), b_sent_htlc_balance.clone()]),
990997
sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(funding_outpoint).unwrap().get_claimable_balances()));
991998

@@ -1264,6 +1271,7 @@ fn do_test_revoked_counterparty_commitment_balances(anchors: bool, confirm_htlc_
12641271
// lists the two on-chain timeout-able HTLCs as claimable balances.
12651272
assert_eq!(sorted_vec(vec![Balance::ClaimableOnChannelClose {
12661273
amount_satoshis: 100_000 - 5_000 - 4_000 - 3 - 2_000 + 3_000,
1274+
transaction_fee_satoshis: 0,
12671275
}, Balance::MaybeTimeoutClaimableHTLC {
12681276
amount_satoshis: 2_000,
12691277
claimable_height: missing_htlc_cltv_timeout,
@@ -1817,6 +1825,7 @@ fn do_test_revoked_counterparty_aggregated_claims(anchors: bool) {
18171825

18181826
assert_eq!(sorted_vec(vec![Balance::ClaimableOnChannelClose {
18191827
amount_satoshis: 100_000 - 4_000 - 3_000,
1828+
transaction_fee_satoshis: 0,
18201829
}, Balance::MaybeTimeoutClaimableHTLC {
18211830
amount_satoshis: 4_000,
18221831
claimable_height: htlc_cltv_timeout,

0 commit comments

Comments
 (0)