Skip to content

Commit df3c8fa

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 87d2945 commit df3c8fa

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.
@@ -906,6 +913,10 @@ pub(crate) struct ChannelMonitorImpl<Signer: EcdsaChannelSigner> {
906913
// of block connection between ChannelMonitors and the ChannelManager.
907914
funding_spend_seen: bool,
908915

916+
/// True if the commitment transaction fee is paid by us.
917+
/// Added in 0.0.124.
918+
holder_pays_commitment_tx_fee: Option<bool>,
919+
909920
/// Set to `Some` of the confirmed transaction spending the funding input of the channel after
910921
/// reaching `ANTI_REORG_DELAY` confirmations.
911922
funding_spend_confirmed: Option<Txid>,
@@ -1154,6 +1165,7 @@ impl<Signer: EcdsaChannelSigner> Writeable for ChannelMonitorImpl<Signer> {
11541165
(17, self.initial_counterparty_commitment_info, option),
11551166
(19, self.channel_id, required),
11561167
(21, self.balances_empty_height, option),
1168+
(23, self.holder_pays_commitment_tx_fee, option),
11571169
});
11581170

11591171
Ok(())
@@ -1255,7 +1267,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
12551267

12561268
pub(crate) fn new(secp_ctx: Secp256k1<secp256k1::All>, keys: Signer, shutdown_script: Option<ScriptBuf>,
12571269
on_counterparty_tx_csv: u16, destination_script: &Script, funding_info: (OutPoint, ScriptBuf),
1258-
channel_parameters: &ChannelTransactionParameters,
1270+
channel_parameters: &ChannelTransactionParameters, holder_pays_commitment_tx_fee: bool,
12591271
funding_redeemscript: ScriptBuf, channel_value_satoshis: u64,
12601272
commitment_transaction_number_obscure_factor: u64,
12611273
initial_holder_commitment_tx: HolderCommitmentTransaction,
@@ -1347,6 +1359,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
13471359

13481360
onchain_tx_handler,
13491361

1362+
holder_pays_commitment_tx_fee: Some(holder_pays_commitment_tx_fee),
13501363
lockdown_from_offchain: false,
13511364
holder_tx_signed: false,
13521365
funding_spend_seen: false,
@@ -2300,8 +2313,11 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
23002313
}
23012314
} else {
23022315
let mut claimable_inbound_htlc_value_sat = 0;
2316+
let mut nondust_htlc_count = 0;
23032317
for (htlc, _, source) in us.current_holder_commitment_tx.htlc_outputs.iter() {
2304-
if htlc.transaction_output_index.is_none() { continue; }
2318+
if htlc.transaction_output_index.is_some() {
2319+
nondust_htlc_count += 1;
2320+
} else { continue; }
23052321
if htlc.offered {
23062322
let outbound_payment = match source {
23072323
None => {
@@ -2331,6 +2347,11 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
23312347
}
23322348
res.push(Balance::ClaimableOnChannelClose {
23332349
amount_satoshis: us.current_holder_commitment_tx.to_self_value_sat + claimable_inbound_htlc_value_sat,
2350+
transaction_fee_satoshis: if us.holder_pays_commitment_tx_fee.unwrap_or(true) {
2351+
chan_utils::commit_tx_fee_sat(
2352+
us.current_holder_commitment_tx.feerate_per_kw, nondust_htlc_count,
2353+
us.onchain_tx_handler.channel_type_features())
2354+
} else { 0 },
23342355
});
23352356
}
23362357

@@ -4737,6 +4758,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
47374758
let mut initial_counterparty_commitment_info = None;
47384759
let mut balances_empty_height = None;
47394760
let mut channel_id = None;
4761+
let mut holder_pays_commitment_tx_fee = None;
47404762
read_tlv_fields!(reader, {
47414763
(1, funding_spend_confirmed, option),
47424764
(3, htlcs_resolved_on_chain, optional_vec),
@@ -4749,6 +4771,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
47494771
(17, initial_counterparty_commitment_info, option),
47504772
(19, channel_id, option),
47514773
(21, balances_empty_height, option),
4774+
(23, holder_pays_commitment_tx_fee, option),
47524775
});
47534776

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

48194842
lockdown_from_offchain,
48204843
holder_tx_signed,
4844+
holder_pays_commitment_tx_fee,
48214845
funding_spend_seen: funding_spend_seen.unwrap(),
48224846
funding_spend_confirmed,
48234847
confirmed_commitment_tx_counterparty_output,
@@ -5057,7 +5081,7 @@ mod tests {
50575081
let monitor = ChannelMonitor::new(Secp256k1::new(), keys,
50585082
Some(ShutdownScript::new_p2wpkh_from_pubkey(shutdown_pubkey).into_inner()), 0, &ScriptBuf::new(),
50595083
(OutPoint { txid: Txid::from_slice(&[43; 32]).unwrap(), index: 0 }, ScriptBuf::new()),
5060-
&channel_parameters, ScriptBuf::new(), 46, 0, HolderCommitmentTransaction::dummy(&mut Vec::new()),
5084+
&channel_parameters, true, ScriptBuf::new(), 46, 0, HolderCommitmentTransaction::dummy(&mut Vec::new()),
50615085
best_block, dummy_key, channel_id);
50625086

50635087
let mut htlcs = preimages_slice_to_htlcs!(preimages[0..10]);
@@ -5305,7 +5329,7 @@ mod tests {
53055329
let monitor = ChannelMonitor::new(Secp256k1::new(), keys,
53065330
Some(ShutdownScript::new_p2wpkh_from_pubkey(shutdown_pubkey).into_inner()), 0, &ScriptBuf::new(),
53075331
(OutPoint { txid: Txid::from_slice(&[43; 32]).unwrap(), index: 0 }, ScriptBuf::new()),
5308-
&channel_parameters, ScriptBuf::new(), 46, 0, HolderCommitmentTransaction::dummy(&mut Vec::new()),
5332+
&channel_parameters, true, ScriptBuf::new(), 46, 0, HolderCommitmentTransaction::dummy(&mut Vec::new()),
53095333
best_block, dummy_key, channel_id);
53105334

53115335
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)