Skip to content

Commit d66f65e

Browse files
committed
Yield BumpChannelClose events
1 parent a1eb3a6 commit d66f65e

File tree

3 files changed

+143
-18
lines changed

3 files changed

+143
-18
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 77 additions & 16 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, Sequence, 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, Input, 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, Event};
5453

5554
use prelude::*;
5655
use core::{cmp, mem};
@@ -1188,7 +1187,7 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
11881187
B::Target: BroadcasterInterface,
11891188
L::Target: Logger,
11901189
{
1191-
self.inner.lock().unwrap().broadcast_latest_holder_commitment_txn(broadcaster, logger)
1190+
let _ = self.inner.lock().unwrap().broadcast_latest_holder_commitment_txn(broadcaster, logger);
11921191
}
11931192

11941193
/// Updates a ChannelMonitor on the basis of some new information provided by the Channel
@@ -2152,13 +2151,38 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
21522151
where B::Target: BroadcasterInterface,
21532152
L::Target: Logger,
21542153
{
2155-
for tx in self.get_latest_holder_commitment_txn(logger).iter() {
2154+
let txn = self.get_latest_holder_commitment_txn(logger);
2155+
for tx in &txn {
21562156
log_info!(logger, "Broadcasting local {}", log_tx!(tx));
2157-
broadcaster.broadcast_transaction(tx);
2157+
broadcaster.broadcast_transaction(&tx);
21582158
}
21592159
self.pending_monitor_events.push(MonitorEvent::CommitmentTxConfirmed(self.funding_info.0));
21602160
}
21612161

2162+
fn construct_bump_channel_close_event(
2163+
&self, target_feerate_sat_per_1000_weight: u32, commitment_tx: Transaction, anchor_output_idx: u32,
2164+
) -> Event {
2165+
let commitment_txid = commitment_tx.txid();
2166+
debug_assert_eq!(self.current_holder_commitment_tx.txid, commitment_txid);
2167+
Event::BumpChannelClose {
2168+
target_feerate_sat_per_1000_weight,
2169+
commitment_tx,
2170+
anchor_descriptor: AnchorDescriptor {
2171+
channel_keys_id: self.channel_keys_id,
2172+
channel_value_satoshis: self.channel_value_satoshis,
2173+
input: bitcoin::TxIn {
2174+
previous_output: bitcoin::OutPoint {
2175+
txid: commitment_txid,
2176+
vout: anchor_output_idx,
2177+
},
2178+
script_sig: Default::default(),
2179+
sequence: Sequence::ZERO,
2180+
witness: Default::default(),
2181+
},
2182+
},
2183+
}
2184+
}
2185+
21622186
pub fn update_monitor<B: Deref, F: Deref, L: Deref>(&mut self, updates: &ChannelMonitorUpdate, broadcaster: &B, fee_estimator: F, logger: &L) -> Result<(), ()>
21632187
where B::Target: BroadcasterInterface,
21642188
F::Target: FeeEstimator,
@@ -2183,6 +2207,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
21832207
panic!("Attempted to apply ChannelMonitorUpdates out of order, check the update_id before passing an update to update_monitor!");
21842208
}
21852209
let mut ret = Ok(());
2210+
let bounded_fee_estimator = LowerBoundedFeeEstimator::new(&*fee_estimator);
21862211
for update in updates.updates.iter() {
21872212
match update {
21882213
ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo { commitment_tx, htlc_outputs } => {
@@ -2200,7 +2225,6 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
22002225
},
22012226
ChannelMonitorUpdateStep::PaymentPreimage { payment_preimage } => {
22022227
log_trace!(logger, "Updating ChannelMonitor with payment preimage");
2203-
let bounded_fee_estimator = LowerBoundedFeeEstimator::new(&*fee_estimator);
22042228
self.provide_payment_preimage(&PaymentHash(Sha256::hash(&payment_preimage.0[..]).into_inner()), &payment_preimage, broadcaster, &bounded_fee_estimator, logger)
22052229
},
22062230
ChannelMonitorUpdateStep::CommitmentSecret { idx, secret } => {
@@ -2216,6 +2240,27 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
22162240
self.lockdown_from_offchain = true;
22172241
if *should_broadcast {
22182242
self.broadcast_latest_holder_commitment_txn(broadcaster, logger);
2243+
// If the channel supports anchor outputs, we'll need to emit an external
2244+
// event to be consumed such that a child transaction is broadcast with a
2245+
// high enough feerate for the parent commitment transaction to confirm.
2246+
if self.onchain_tx_handler.opt_anchors() {
2247+
let funding_outp = HolderFundingOutput::build(
2248+
self.funding_redeemscript.clone(), self.channel_value_satoshis,
2249+
);
2250+
let funding_input = Input::new(
2251+
PackageSolvingData::HolderFundingOutput(funding_outp),
2252+
self.onchain_tx_handler.opt_anchors(),
2253+
);
2254+
let best_block_height = self.best_block.height();
2255+
let commitment_package = PackageTemplate::build_package(
2256+
self.funding_info.0.txid.clone(), self.funding_info.0.index as u32,
2257+
funding_input, best_block_height, false, best_block_height,
2258+
);
2259+
self.onchain_tx_handler.update_claims_view(
2260+
&[], vec![commitment_package], best_block_height, best_block_height,
2261+
broadcaster, &bounded_fee_estimator, logger,
2262+
);
2263+
}
22192264
} else if !self.holder_tx_signed {
22202265
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");
22212266
} else {
@@ -2268,6 +2313,17 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
22682313
pub fn get_and_clear_pending_events(&mut self) -> Vec<Event> {
22692314
let mut ret = Vec::new();
22702315
mem::swap(&mut ret, &mut self.pending_events);
2316+
for claim_event in self.onchain_tx_handler.get_and_clear_pending_claim_events().drain(..) {
2317+
match claim_event {
2318+
ClaimEvent::BumpCommitment {
2319+
target_feerate_sat_per_1000_weight, commitment_tx, anchor_output_idx,
2320+
} => {
2321+
ret.push(self.construct_bump_channel_close_event(
2322+
target_feerate_sat_per_1000_weight, commitment_tx, anchor_output_idx,
2323+
));
2324+
},
2325+
}
2326+
}
22712327
ret
22722328
}
22732329

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

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

lightning/src/chain/onchaintx.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ use alloc::collections::BTreeMap;
3939
use core::cmp;
4040
use core::convert::TryInto;
4141
use core::ops::Deref;
42-
use core::mem::replace;
42+
use core::mem::{replace, swap};
4343
use bitcoin::hashes::Hash;
4444

4545
const MAX_ALLOC_SIZE: usize = 64*1024;
@@ -391,6 +391,12 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
391391
self.holder_commitment.to_broadcaster_value_sat()
392392
}
393393

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+
ret.into_values().collect()
398+
}
399+
394400
/// Lightning security model (i.e being able to redeem/timeout HTLC or penalize coutnerparty onchain) lays on the assumption of claim transactions getting confirmed before timelock expiration
395401
/// (CSV or CLTV following cases). In case of high-fee spikes, claim tx may stuck in the mempool, so you need to bump its feerate quickly using Replace-By-Fee or Child-Pay-For-Parent.
396402
/// Panics if there are signing errors, because signing operations in reaction to on-chain events

lightning/src/util/events.rs

Lines changed: 59 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, TxIn};
2929
use bitcoin::blockdata::script::Script;
3030
use bitcoin::hashes::Hash;
3131
use bitcoin::hashes::sha256::Hash as Sha256;
@@ -196,6 +196,24 @@ 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 input corresponding to the commitment transaction's anchor output.
214+
pub input: TxIn,
215+
}
216+
199217
/// An Event which you should probably take some action in response to.
200218
///
201219
/// Note that while Writeable and Readable are implemented for Event, you probably shouldn't use
@@ -602,6 +620,41 @@ pub enum Event {
602620
/// Destination of the HTLC that failed to be processed.
603621
failed_next_destination: HTLCDestination,
604622
},
623+
/// Indicates that a channel featuring anchors outputs is to be closed by broadcasting the local
624+
/// commitment transaction. Since commitment transactions have a static feerate pre-agreed upon,
625+
/// they may need additional fees to be attached through a child transaction using the popular
626+
/// Child-Pays-For-Parent (CPFP) fee bumping technique. This child transaction must include the
627+
/// anchor input found within `anchor_descriptor` along with additional inputs to meet the
628+
/// target feerate. Once the transaction is constructed, it must be fully signed for and
629+
/// broadcasted by the consumer of the event along with the `commitment_tx` enclosed. Note that
630+
/// the `commitment_tx` must always be broadcast first, as the child anchor transaction depends
631+
/// on it.
632+
///
633+
/// The consumer should be able to sign for any of the additional inputs included within the
634+
/// child anchor transaction. To sign its anchor input, a [`InMemorySigner`] should be
635+
/// re-derived through [`KeysManager::derive_channel_keys`] with the help of
636+
/// [`AnchorDescriptor::channel_keys_id`] and [`AnchorDescriptor::channel_value_satoshis`].
637+
///
638+
/// It is possible to receive more than an instance of this event if a valid child anchor
639+
/// transaction is never broadcast or is but not with a sufficient fee to be mined. Care should
640+
/// be taken by the consumer of the event to ensure any future iterations of the child anchor
641+
/// transaction adhere to the Replace-By-Fee (RBF) rules for fee bumps to be accepted into the
642+
/// mempool, and eventually the chain.
643+
///
644+
/// [`InMemorySigner`]: crate::chain::keysinterface::InMemorySigner
645+
/// [`KeysManager::derive_channel_keys`]: crate::chain::keysinterface::KeysManager::derive_channel_keys
646+
BumpChannelClose {
647+
/// The target feerate to use for the child transaction spending the anchor output of the
648+
/// channel's commitment transaction to broadcast and bump the fee of.
649+
target_feerate_sat_per_1000_weight: u32,
650+
/// The channel's commitment transaction to bump the fee of. This transaction should be
651+
/// broadcast along with the anchor transaction constructed as a result of consuming this
652+
/// event.
653+
commitment_tx: Transaction,
654+
/// The descriptor to sign the anchor input of the anchor transaction constructed as a
655+
/// result of consuming this event.
656+
anchor_descriptor: AnchorDescriptor,
657+
},
605658
}
606659

607660
impl Writeable for Event {
@@ -753,6 +806,11 @@ impl Writeable for Event {
753806
(2, failed_next_destination, required),
754807
})
755808
},
809+
&Event::BumpChannelClose { .. } => {
810+
// We never write the BumpChannelClose events as they'll be replayed upon restarting
811+
// anyway if the commitment transaction remains unconfirmed.
812+
27u8.write(writer)?;
813+
}
756814
// Note that, going forward, all new events must only write data inside of
757815
// `write_tlv_fields`. Versions 0.0.101+ will ignore odd-numbered events that write
758816
// data via `write_tlv_fields`.

0 commit comments

Comments
 (0)