Skip to content

Commit 71b4bd0

Browse files
committed
Rework get_latest_holder_commitment_txn to broadcast for users
This method is meant to be used as a last resort when a user is forced to broadcast the current state, even if it is stale, in an attempt to claim their funds in the channel. Previously, we'd return the commitment and HTLC transactions such that they broadcast them themselves. Doing so required a different code path, one which was not tested, to obtain these transactions than our usual path when force closing. It's not worth maintaining both, and it's much simpler for us to broadcast instead.
1 parent e0323ec commit 71b4bd0

File tree

3 files changed

+20
-55
lines changed

3 files changed

+20
-55
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 14 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1562,28 +1562,30 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitor<Signer> {
15621562
self.inner.lock().unwrap().counterparty_node_id
15631563
}
15641564

1565-
/// Used by [`ChannelManager`] deserialization to broadcast the latest holder state if its copy
1566-
/// of the channel state was out-of-date.
1567-
///
1568-
/// You may also use this to broadcast the latest local commitment transaction, either because
1565+
/// You may use this to broadcast the latest local commitment transaction, either because
15691566
/// a monitor update failed or because we've fallen behind (i.e. we've received proof that our
15701567
/// counterparty side knows a revocation secret we gave them that they shouldn't know).
15711568
///
1572-
/// Broadcasting these transactions in the second case is UNSAFE, as they allow counterparty
1569+
/// Broadcasting these transactions in this manner is UNSAFE, as they allow counterparty
15731570
/// side to punish you. Nevertheless you may want to broadcast them if counterparty doesn't
15741571
/// close channel with their commitment transaction after a substantial amount of time. Best
15751572
/// may be to contact the other node operator out-of-band to coordinate other options available
15761573
/// to you.
1577-
///
1578-
/// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
1579-
pub fn get_latest_holder_commitment_txn<L: Deref>(&self, logger: &L) -> Vec<Transaction>
1580-
where L::Target: Logger {
1574+
pub fn broadcast_latest_holder_commitment_txn<B: Deref, F: Deref, L: Deref>(
1575+
&self, broadcaster: &B, fee_estimator: &F, logger: &L
1576+
)
1577+
where
1578+
B::Target: BroadcasterInterface,
1579+
F::Target: FeeEstimator,
1580+
L::Target: Logger
1581+
{
15811582
let mut inner = self.inner.lock().unwrap();
1583+
let fee_estimator = LowerBoundedFeeEstimator::new(&**fee_estimator);
15821584
let logger = WithChannelMonitor::from_impl(logger, &*inner);
1583-
inner.get_latest_holder_commitment_txn(&logger)
1585+
inner.queue_latest_holder_commitment_txn_for_broadcast(broadcaster, &fee_estimator, &logger);
15841586
}
15851587

1586-
/// Unsafe test-only version of get_latest_holder_commitment_txn used by our test framework
1588+
/// Unsafe test-only version of `broadcast_latest_holder_commitment_txn` used by our test framework
15871589
/// to bypass HolderCommitmentTransaction state update lockdown after signature and generate
15881590
/// revoked commitment transaction.
15891591
#[cfg(any(test, feature = "unsafe_revoked_tx_signing"))]
@@ -2855,7 +2857,7 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
28552857
} else if !self.holder_tx_signed {
28562858
log_error!(logger, "WARNING: You have a potentially-unsafe holder commitment transaction available to broadcast");
28572859
log_error!(logger, " in channel monitor for channel {}!", &self.channel_id());
2858-
log_error!(logger, " Read the docs for ChannelMonitor::get_latest_holder_commitment_txn and take manual action!");
2860+
log_error!(logger, " Read the docs for ChannelMonitor::broadcast_latest_holder_commitment_txn to take manual action!");
28592861
} else {
28602862
// If we generated a MonitorEvent::HolderForceClosed, the ChannelManager
28612863
// will still give us a ChannelForceClosed event with !should_broadcast, but we
@@ -3502,45 +3504,6 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
35023504
}
35033505
}
35043506

3505-
fn get_latest_holder_commitment_txn<L: Deref>(
3506-
&mut self, logger: &WithChannelMonitor<L>,
3507-
) -> Vec<Transaction> where L::Target: Logger {
3508-
log_debug!(logger, "Getting signed latest holder commitment transaction!");
3509-
self.holder_tx_signed = true;
3510-
let commitment_tx = self.onchain_tx_handler.get_fully_signed_holder_tx(&self.funding_redeemscript);
3511-
let txid = commitment_tx.txid();
3512-
let mut holder_transactions = vec![commitment_tx];
3513-
// When anchor outputs are present, the HTLC transactions are only valid once the commitment
3514-
// transaction confirms.
3515-
if self.onchain_tx_handler.channel_type_features().supports_anchors_zero_fee_htlc_tx() {
3516-
return holder_transactions;
3517-
}
3518-
for htlc in self.current_holder_commitment_tx.htlc_outputs.iter() {
3519-
if let Some(vout) = htlc.0.transaction_output_index {
3520-
let preimage = if !htlc.0.offered {
3521-
if let Some(preimage) = self.payment_preimages.get(&htlc.0.payment_hash) { Some(preimage.clone()) } else {
3522-
// We can't build an HTLC-Success transaction without the preimage
3523-
continue;
3524-
}
3525-
} else if htlc.0.cltv_expiry > self.best_block.height() + 1 {
3526-
// Don't broadcast HTLC-Timeout transactions immediately as they don't meet the
3527-
// current locktime requirements on-chain. We will broadcast them in
3528-
// `block_confirmed` when `should_broadcast_holder_commitment_txn` returns true.
3529-
// Note that we add + 1 as transactions are broadcastable when they can be
3530-
// confirmed in the next block.
3531-
continue;
3532-
} else { None };
3533-
if let Some(htlc_tx) = self.onchain_tx_handler.get_fully_signed_htlc_tx(
3534-
&::bitcoin::OutPoint { txid, vout }, &preimage) {
3535-
holder_transactions.push(htlc_tx);
3536-
}
3537-
}
3538-
}
3539-
// We throw away the generated waiting_first_conf data as we aren't (yet) confirmed and we don't actually know what the caller wants to do.
3540-
// The data will be re-generated and tracked in check_spend_holder_transaction if we get a confirmation.
3541-
holder_transactions
3542-
}
3543-
35443507
#[cfg(any(test,feature = "unsafe_revoked_tx_signing"))]
35453508
/// Note that this includes possibly-locktimed-in-the-future transactions!
35463509
fn unsafe_get_latest_holder_commitment_txn<L: Deref>(

lightning/src/ln/channelmanager.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3021,8 +3021,8 @@ where
30213021
/// the latest local transaction(s). Fails if `channel_id` is unknown to the manager, or if the
30223022
/// `counterparty_node_id` isn't the counterparty of the corresponding channel.
30233023
///
3024-
/// You can always get the latest local transaction(s) to broadcast from
3025-
/// [`ChannelMonitor::get_latest_holder_commitment_txn`].
3024+
/// You can always broadcast the latest local transaction(s) via
3025+
/// [`ChannelMonitor::broadcast_latest_holder_commitment_txn`].
30263026
pub fn force_close_without_broadcasting_txn(&self, channel_id: &ChannelId, counterparty_node_id: &PublicKey)
30273027
-> Result<(), APIError> {
30283028
self.force_close_sending_error(channel_id, counterparty_node_id, false)

lightning/src/ln/monitor_tests.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2755,7 +2755,9 @@ fn do_test_monitor_claims_with_random_signatures(anchors: bool, confirm_counterp
27552755
(&nodes[0], &nodes[1])
27562756
};
27572757

2758-
closing_node.node.force_close_broadcasting_latest_txn(&chan_id, &other_node.node.get_our_node_id()).unwrap();
2758+
get_monitor!(closing_node, chan_id).broadcast_latest_holder_commitment_txn(
2759+
&closing_node.tx_broadcaster, &closing_node.fee_estimator, &closing_node.logger
2760+
);
27592761

27602762
// The commitment transaction comes first.
27612763
let commitment_tx = {
@@ -2768,7 +2770,7 @@ fn do_test_monitor_claims_with_random_signatures(anchors: bool, confirm_counterp
27682770
mine_transaction(closing_node, &commitment_tx);
27692771
check_added_monitors!(closing_node, 1);
27702772
check_closed_broadcast!(closing_node, true);
2771-
check_closed_event!(closing_node, 1, ClosureReason::HolderForceClosed, [other_node.node.get_our_node_id()], 1_000_000);
2773+
check_closed_event!(closing_node, 1, ClosureReason::CommitmentTxConfirmed, [other_node.node.get_our_node_id()], 1_000_000);
27722774

27732775
mine_transaction(other_node, &commitment_tx);
27742776
check_added_monitors!(other_node, 1);

0 commit comments

Comments
 (0)