Skip to content

Commit 3e1009d

Browse files
committed
Yield channel close bump events
1 parent 006777a commit 3e1009d

File tree

3 files changed

+185
-16
lines changed

3 files changed

+185
-16
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 74 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@
2121
//! ChannelMonitors to get out of the HSM and onto monitoring devices.
2222
2323
use bitcoin::blockdata::block::BlockHeader;
24-
use bitcoin::blockdata::transaction::{TxOut,Transaction};
25-
use bitcoin::blockdata::transaction::OutPoint as BitcoinOutPoint;
24+
use bitcoin::blockdata::transaction::{OutPoint as BitcoinOutPoint, TxOut, Transaction};
2625
use bitcoin::blockdata::script::{Script, Builder};
2726
use bitcoin::blockdata::opcodes;
2827

@@ -44,13 +43,13 @@ use chain::{BestBlock, WatchedOutput};
4443
use chain::chaininterface::{BroadcasterInterface, FeeEstimator, LowerBoundedFeeEstimator};
4544
use chain::transaction::{OutPoint, TransactionData};
4645
use chain::keysinterface::{SpendableOutputDescriptor, StaticPaymentOutputDescriptor, DelayedPaymentOutputDescriptor, Sign, KeysInterface};
47-
use chain::onchaintx::OnchainTxHandler;
46+
use chain::onchaintx::{ClaimEvent, OnchainTxHandler};
4847
use chain::package::{CounterpartyOfferedHTLCOutput, CounterpartyReceivedHTLCOutput, HolderFundingOutput, HolderHTLCOutput, PackageSolvingData, PackageTemplate, RevokedOutput, RevokedHTLCOutput};
4948
use chain::Filter;
5049
use util::logger::Logger;
5150
use util::ser::{Readable, ReadableArgs, MaybeReadable, Writer, Writeable, U48, OptionDeserWrapper};
5251
use util::byte_utils;
53-
use util::events::Event;
52+
use util::events::{AnchorDescriptor, CommitmentPendingHTLC, BumpTransaction, Event};
5453

5554
use prelude::*;
5655
use core::{cmp, mem};
@@ -1219,7 +1218,7 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
12191218
B::Target: BroadcasterInterface,
12201219
L::Target: Logger,
12211220
{
1222-
self.inner.lock().unwrap().broadcast_latest_holder_commitment_txn(broadcaster, logger)
1221+
self.inner.lock().unwrap().broadcast_latest_holder_commitment_txn(broadcaster, logger);
12231222
}
12241223

12251224
/// Updates a ChannelMonitor on the basis of some new information provided by the Channel
@@ -2214,6 +2213,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
22142213
panic!("Attempted to apply ChannelMonitorUpdates out of order, check the update_id before passing an update to update_monitor!");
22152214
}
22162215
let mut ret = Ok(());
2216+
let bounded_fee_estimator = LowerBoundedFeeEstimator::new(&*fee_estimator);
22172217
for update in updates.updates.iter() {
22182218
match update {
22192219
ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo { commitment_tx, htlc_outputs } => {
@@ -2231,7 +2231,6 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
22312231
},
22322232
ChannelMonitorUpdateStep::PaymentPreimage { payment_preimage } => {
22332233
log_trace!(logger, "Updating ChannelMonitor with payment preimage");
2234-
let bounded_fee_estimator = LowerBoundedFeeEstimator::new(&*fee_estimator);
22352234
self.provide_payment_preimage(&PaymentHash(Sha256::hash(&payment_preimage.0[..]).into_inner()), &payment_preimage, broadcaster, &bounded_fee_estimator, logger)
22362235
},
22372236
ChannelMonitorUpdateStep::CommitmentSecret { idx, secret } => {
@@ -2247,6 +2246,25 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
22472246
self.lockdown_from_offchain = true;
22482247
if *should_broadcast {
22492248
self.broadcast_latest_holder_commitment_txn(broadcaster, logger);
2249+
// If the channel supports anchor outputs, we'll need to emit an external
2250+
// event to be consumed such that a child transaction is broadcast with a
2251+
// high enough feerate for the parent commitment transaction to confirm.
2252+
if self.onchain_tx_handler.opt_anchors() {
2253+
let funding_output = HolderFundingOutput::build(
2254+
self.funding_redeemscript.clone(), self.channel_value_satoshis,
2255+
self.onchain_tx_handler.opt_anchors(),
2256+
);
2257+
let best_block_height = self.best_block.height();
2258+
let commitment_package = PackageTemplate::build_package(
2259+
self.funding_info.0.txid.clone(), self.funding_info.0.index as u32,
2260+
PackageSolvingData::HolderFundingOutput(funding_output),
2261+
best_block_height, false, best_block_height,
2262+
);
2263+
self.onchain_tx_handler.update_claims_view(
2264+
&[], vec![commitment_package], best_block_height, best_block_height,
2265+
broadcaster, &bounded_fee_estimator, logger,
2266+
);
2267+
}
22502268
} else if !self.holder_tx_signed {
22512269
log_error!(logger, "You have a toxic holder commitment transaction avaible in channel monitor, read comment in ChannelMonitor::get_latest_holder_commitment_txn to be informed of manual action to take");
22522270
} else {
@@ -2299,6 +2317,43 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
22992317
pub fn get_and_clear_pending_events(&mut self) -> Vec<Event> {
23002318
let mut ret = Vec::new();
23012319
mem::swap(&mut ret, &mut self.pending_events);
2320+
for claim_event in self.onchain_tx_handler.get_and_clear_pending_claim_events().drain(..) {
2321+
match claim_event {
2322+
ClaimEvent::BumpCommitment {
2323+
package_target_feerate_sat_per_1000_weight, commitment_tx, anchor_output_idx,
2324+
} => {
2325+
let commitment_txid = commitment_tx.txid();
2326+
debug_assert_eq!(self.current_holder_commitment_tx.txid, commitment_txid);
2327+
let pending_htlcs = self.current_holder_commitment_tx.htlc_outputs.iter()
2328+
.filter_map(|(htlc, _, _)| {
2329+
if let Some(_) = htlc.transaction_output_index {
2330+
Some(CommitmentPendingHTLC {
2331+
outbound: htlc.offered,
2332+
amount_sat: htlc.amount_msat / 1000,
2333+
expiry: htlc.cltv_expiry,
2334+
output_index: htlc.transaction_output_index.unwrap(),
2335+
})
2336+
} else {
2337+
None
2338+
}
2339+
})
2340+
.collect();
2341+
ret.push(Event::BumpTransaction(BumpTransaction::ChannelClose {
2342+
package_target_feerate_sat_per_1000_weight,
2343+
commitment_tx,
2344+
anchor_descriptor: AnchorDescriptor {
2345+
channel_keys_id: self.channel_keys_id,
2346+
channel_value_satoshis: self.channel_value_satoshis,
2347+
outpoint: BitcoinOutPoint {
2348+
txid: commitment_txid,
2349+
vout: anchor_output_idx,
2350+
},
2351+
},
2352+
pending_htlcs,
2353+
}));
2354+
},
2355+
}
2356+
}
23022357
ret
23032358
}
23042359

@@ -2880,15 +2935,20 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
28802935
self.pending_monitor_events.push(MonitorEvent::CommitmentTxConfirmed(self.funding_info.0));
28812936
let commitment_tx = self.onchain_tx_handler.get_fully_signed_holder_tx(&self.funding_redeemscript);
28822937
self.holder_tx_signed = true;
2883-
// Because we're broadcasting a commitment transaction, we should construct the package
2884-
// assuming it gets confirmed in the next block. Sadly, we have code which considers
2885-
// "not yet confirmed" things as discardable, so we cannot do that here.
2886-
let (mut new_outpoints, _) = self.get_broadcasted_holder_claims(&self.current_holder_commitment_tx, self.best_block.height());
2887-
let new_outputs = self.get_broadcasted_holder_watch_outputs(&self.current_holder_commitment_tx, &commitment_tx);
2888-
if !new_outputs.is_empty() {
2889-
watch_outputs.push((self.current_holder_commitment_tx.txid.clone(), new_outputs));
2938+
// We can't broadcast our HTLC transactions while the commitment transaction is
2939+
// unconfirmed. We'll delay doing so until we detect the confirmed commitment in
2940+
// `transactions_confirmed`.
2941+
if !self.onchain_tx_handler.opt_anchors() {
2942+
// Because we're broadcasting a commitment transaction, we should construct the package
2943+
// assuming it gets confirmed in the next block. Sadly, we have code which considers
2944+
// "not yet confirmed" things as discardable, so we cannot do that here.
2945+
let (mut new_outpoints, _) = self.get_broadcasted_holder_claims(&self.current_holder_commitment_tx, self.best_block.height());
2946+
let new_outputs = self.get_broadcasted_holder_watch_outputs(&self.current_holder_commitment_tx, &commitment_tx);
2947+
if !new_outputs.is_empty() {
2948+
watch_outputs.push((self.current_holder_commitment_tx.txid.clone(), new_outputs));
2949+
}
2950+
claimable_outpoints.append(&mut new_outpoints);
28902951
}
2891-
claimable_outpoints.append(&mut new_outpoints);
28922952
}
28932953

28942954
// Find which on-chain events have reached their confirmation threshold.

lightning/src/chain/onchaintx.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ use prelude::*;
3838
use alloc::collections::BTreeMap;
3939
use core::cmp;
4040
use core::ops::Deref;
41-
use core::mem::replace;
41+
use core::mem::{replace, swap};
4242
use bitcoin::hashes::Hash;
4343

4444
const MAX_ALLOC_SIZE: usize = 64*1024;
@@ -163,6 +163,7 @@ impl Writeable for Option<Vec<Option<(usize, Signature)>>> {
163163
}
164164
}
165165

166+
#[derive(PartialEq, Eq, PartialOrd, Ord)]
166167
pub(crate) enum ClaimEvent {
167168
BumpCommitment {
168169
package_target_feerate_sat_per_1000_weight: u32,
@@ -390,6 +391,14 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
390391
self.holder_commitment.to_broadcaster_value_sat()
391392
}
392393

394+
pub(crate) fn get_and_clear_pending_claim_events(&mut self) -> Vec<ClaimEvent> {
395+
let mut ret = HashMap::new();
396+
swap(&mut ret, &mut self.pending_claim_events);
397+
let mut ret = ret.into_iter().map(|(_, event)| event).collect::<Vec<_>>();
398+
ret.sort_unstable();
399+
ret
400+
}
401+
393402
/// Lightning security model (i.e being able to redeem/timeout HTLC or penalize counterparty
394403
/// onchain) lays on the assumption of claim transactions getting confirmed before timelock
395404
/// expiration (CSV or CLTV following cases). In case of high-fee spikes, claim tx may get stuck

lightning/src/util/events.rs

Lines changed: 101 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use routing::gossip::NetworkUpdate;
2525
use util::ser::{BigSize, FixedLengthReader, Writeable, Writer, MaybeReadable, Readable, VecReadWrapper, VecWriteWrapper};
2626
use routing::router::{RouteHop, RouteParameters};
2727

28-
use bitcoin::{PackedLockTime, Transaction};
28+
use bitcoin::{PackedLockTime, Transaction, OutPoint};
2929
use bitcoin::blockdata::script::Script;
3030
use bitcoin::hashes::Hash;
3131
use bitcoin::hashes::sha256::Hash as Sha256;
@@ -196,6 +196,94 @@ impl_writeable_tlv_based_enum_upgradable!(HTLCDestination,
196196
}
197197
);
198198

199+
/// A descriptor used to sign for a commitment transaction's anchor output.
200+
#[derive(Clone, Debug)]
201+
pub struct AnchorDescriptor {
202+
/// A unique identifier used along with `channel_value_satoshis` to re-derive the
203+
/// [`InMemorySigner`] required to sign `input`.
204+
///
205+
/// [`InMemorySigner`]: crate::chain::keysinterface::InMemorySigner
206+
pub channel_keys_id: [u8; 32],
207+
/// The value in satoshis of the channel we're attempting to spend the anchor output of. This is
208+
/// used along with `channel_keys_id` to re-derive the [`InMemorySigner`] required to sign
209+
/// `input`.
210+
///
211+
/// [`InMemorySigner`]: crate::chain::keysinterface::InMemorySigner
212+
pub channel_value_satoshis: u64,
213+
/// The transaction input's outpoint corresponding to the commitment transaction's anchor
214+
/// output.
215+
pub outpoint: OutPoint,
216+
}
217+
218+
/// Describes a pending HTLC in a commitment transaction.
219+
#[derive(Clone, Debug)]
220+
pub struct CommitmentPendingHTLC {
221+
/// Whether the pending HTLC originated from LDK.
222+
pub outbound: bool,
223+
/// The amount, in satoshis, of the pending HTLC's output in the commitment transaction.
224+
pub amount_sat: u64,
225+
/// The absolute height in the chain at which the pending HTLC expires and can be claimed back
226+
/// by its originator.
227+
pub expiry: u32,
228+
/// The index of the pending HTLC's output in the commitment transaction.
229+
pub output_index: u32,
230+
}
231+
232+
/// Represents the different types of transactions, originating from LDK, to be bumped.
233+
#[derive(Clone, Debug)]
234+
pub enum BumpTransaction {
235+
/// Indicates that a channel featuring anchors outputs is to be closed by broadcasting the local
236+
/// commitment transaction. Since commitment transactions have a static feerate pre-agreed upon,
237+
/// they may need additional fees to be attached through a child transaction using the popular
238+
/// [Child-Pays-For-Parent](https://bitcoinops.org/en/topics/cpfp) fee bumping technique. This
239+
/// child transaction must include the anchor input described within `anchor_descriptor` along
240+
/// with additional inputs to meet the target feerate. Failure to meet the target feerate
241+
/// decreases the confirmation odds of the transaction package (which includes the commitment
242+
/// and child anchor transactions), possibly resulting in a loss of funds. Once the transaction
243+
/// is constructed, it must be fully signed for and broadcasted by the consumer of the event
244+
/// along with the `commitment_tx` enclosed. Note that the `commitment_tx` must always be
245+
/// broadcast first, as the child anchor transaction depends on it.
246+
///
247+
/// The consumer should be able to sign for any of the additional inputs included within the
248+
/// child anchor transaction. To sign its anchor input, an [`InMemorySigner`] should be
249+
/// re-derived through [`KeysManager::derive_channel_keys`] with the help of
250+
/// [`AnchorDescriptor::channel_keys_id`] and [`AnchorDescriptor::channel_value_satoshis`].
251+
///
252+
/// It is possible to receive more than an instance of this event if a valid child anchor
253+
/// transaction is never broadcast or is but not with a sufficient fee to be mined. Care should
254+
/// be taken by the consumer of the event to ensure any future iterations of the child anchor
255+
/// transaction adhere to the [Replace-By-Fee
256+
/// rules](https://github.com/bitcoin/bitcoin/blob/master/doc/policy/mempool-replacements.md)
257+
/// for fee bumps to be accepted into the mempool, and eventually the chain. As the frequency of
258+
/// these events is not user-controlled, users may ignore/drop the event if they are no longer
259+
/// to commit external confirmed funds to the child anchor transaction.
260+
///
261+
/// The set of `pending_htlcs` on the commitment transaction to be broadcast can be inspected to
262+
/// determine whether a significant portion of the channel's funds are allocated to HTLCs,
263+
/// enabling users to make their own decisions regarding the importance of the commitment
264+
/// transaction's confirmation. On commitments with no HTLCs (indicated by those with an empty
265+
/// `pending_htlcs`), confirmation of the commitment transaction can be considered to be not
266+
/// urgent.
267+
///
268+
/// [`InMemorySigner`]: crate::chain::keysinterface::InMemorySigner
269+
/// [`KeysManager::derive_channel_keys`]: crate::chain::keysinterface::KeysManager::derive_channel_keys
270+
ChannelClose {
271+
/// The target feerate that the transaction package, which consists of the commitment
272+
/// transaction and the to-be-crafted child anchor transaction, must meet.
273+
package_target_feerate_sat_per_1000_weight: u32,
274+
/// The channel's commitment transaction to bump the fee of. This transaction should be
275+
/// broadcast along with the anchor transaction constructed as a result of consuming this
276+
/// event.
277+
commitment_tx: Transaction,
278+
/// The descriptor to sign the anchor input of the anchor transaction constructed as a
279+
/// result of consuming this event.
280+
anchor_descriptor: AnchorDescriptor,
281+
/// The set of pending HTLCs on the commitment transaction that need to be resolved once the
282+
/// commitment transaction confirms.
283+
pending_htlcs: Vec<CommitmentPendingHTLC>,
284+
},
285+
}
286+
199287
/// An Event which you should probably take some action in response to.
200288
///
201289
/// Note that while Writeable and Readable are implemented for Event, you probably shouldn't use
@@ -602,6 +690,9 @@ pub enum Event {
602690
/// Destination of the HTLC that failed to be processed.
603691
failed_next_destination: HTLCDestination,
604692
},
693+
/// Indicates that a transaction originating from LDK needs to have its fee bumped. This event
694+
/// requires confirmed external funds to be readily available to spend.
695+
BumpTransaction(BumpTransaction),
605696
}
606697

607698
impl Writeable for Event {
@@ -753,6 +844,15 @@ impl Writeable for Event {
753844
(2, failed_next_destination, required),
754845
})
755846
},
847+
&Event::BumpTransaction(ref event)=> {
848+
27u8.write(writer)?;
849+
match event {
850+
// We never write the ChannelClose events as they'll be replayed upon restarting
851+
// anyway if the commitment transaction remains
852+
// unconfirmed.
853+
BumpTransaction::ChannelClose { .. } => {}
854+
}
855+
}
756856
// Note that, going forward, all new events must only write data inside of
757857
// `write_tlv_fields`. Versions 0.0.101+ will ignore odd-numbered events that write
758858
// data via `write_tlv_fields`.

0 commit comments

Comments
 (0)