Skip to content

Commit c7519b4

Browse files
committed
Fail HTLC backwards before upstream claims on-chain
Fail inbound HTLCs if they expire within a certain number of blocks from the current height. If we haven't seen the preimage for an HTLC by the time the previous hop's timeout expires, we've lost that HTLC, so we might as well fail it back instead of having our counterparty force-close the channel.
1 parent 76ea388 commit c7519b4

File tree

2 files changed

+184
-6
lines changed

2 files changed

+184
-6
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ use crate::ln::{PaymentHash, PaymentPreimage};
3838
use crate::ln::msgs::DecodeError;
3939
use crate::ln::chan_utils;
4040
use crate::ln::chan_utils::{CommitmentTransaction, CounterpartyCommitmentSecrets, HTLCOutputInCommitment, HTLCClaim, ChannelTransactionParameters, HolderCommitmentTransaction, TxCreationKeys};
41-
use crate::ln::channelmanager::{HTLCSource, SentHTLCId};
41+
use crate::ln::channelmanager::{HTLCSource, SentHTLCId, HTLCPreviousHopData};
4242
use crate::chain;
4343
use crate::chain::{BestBlock, WatchedOutput};
4444
use crate::chain::chaininterface::{BroadcasterInterface, FeeEstimator, LowerBoundedFeeEstimator};
@@ -243,6 +243,15 @@ pub const ANTI_REORG_DELAY: u32 = 6;
243243
/// in a race condition between the user connecting a block (which would fail it) and the user
244244
/// providing us the preimage (which would claim it).
245245
pub(crate) const HTLC_FAIL_BACK_BUFFER: u32 = CLTV_CLAIM_BUFFER + LATENCY_GRACE_PERIOD_BLOCKS;
246+
/// Number of blocks before an inbound HTLC expires at which we fail it backwards.
247+
///
248+
/// If we have forwarded an HTLC to a peer and they have not claimed it on or off-chain by the
249+
/// time the previous hop's HTLC timeout expires, we're probably going to lose the inbound HTLC.
250+
/// Instead of also losing the channel, we fail the HTLC backwards.
251+
///
252+
/// To give us some buffer in case we're slow to process blocks, we fail a few blocks before the
253+
/// timeout officially expires to ensure we fail back before our counterparty force closes.
254+
pub(crate) const TIMEOUT_FAIL_BACK_BUFFER: u32 = 3;
246255

247256
// TODO(devrandom) replace this with HolderCommitmentTransaction
248257
#[derive(Clone, PartialEq, Eq)]
@@ -3515,6 +3524,61 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
35153524
}
35163525
}
35173526

3527+
// Fail back HTLCs on backwards channels if they expire within `TIMEOUT_FAIL_BACK_BUFFER`
3528+
// blocks. If we haven't seen the preimage for an HTLC by the time the previous hop's
3529+
// timeout expires, we've lost that HTLC, so we might as well fail it back instead of having our
3530+
// counterparty force-close the channel.
3531+
let height = self.best_block.height();
3532+
macro_rules! fail_soon_to_expire_htlcs {
3533+
($htlcs: expr) => {{
3534+
for (htlc, source_opt) in $htlcs {
3535+
// Only check forwarded HTLCs' previous hops
3536+
let source = match source_opt {
3537+
Some(source) => source,
3538+
None => continue,
3539+
};
3540+
let cltv_expiry = match source {
3541+
HTLCSource::PreviousHopData(HTLCPreviousHopData { cltv_expiry: Some(cltv_expiry), .. }) => *cltv_expiry,
3542+
_ => continue,
3543+
};
3544+
if cltv_expiry <= height + TIMEOUT_FAIL_BACK_BUFFER {
3545+
let duplicate_event = self.pending_monitor_events.iter().any(
3546+
|update| if let &MonitorEvent::HTLCEvent(ref upd) = update {
3547+
upd.source == *source
3548+
} else { false });
3549+
if !duplicate_event {
3550+
log_debug!(logger, "Failing back HTLC {} upstream to preserve the \
3551+
channel as the forward HTLC hasn't resolved and our backward HTLC \
3552+
expires soon at {}", log_bytes!(htlc.payment_hash.0), cltv_expiry);
3553+
self.pending_monitor_events.push(MonitorEvent::HTLCEvent(HTLCUpdate {
3554+
source: source.clone(),
3555+
payment_preimage: None,
3556+
payment_hash: htlc.payment_hash,
3557+
htlc_value_satoshis: Some(htlc.amount_msat / 1000),
3558+
awaiting_downstream_confirmation: true,
3559+
}));
3560+
}
3561+
}
3562+
}
3563+
}}
3564+
}
3565+
3566+
let current_holder_htlcs = self.current_holder_commitment_tx.htlc_outputs.iter()
3567+
.map(|&(ref a, _, ref b)| (a, b.as_ref()));
3568+
fail_soon_to_expire_htlcs!(current_holder_htlcs);
3569+
3570+
if let Some(ref txid) = self.current_counterparty_commitment_txid {
3571+
if let Some(ref htlc_outputs) = self.counterparty_claimable_outpoints.get(txid) {
3572+
fail_soon_to_expire_htlcs!(htlc_outputs.iter().map(|&(ref a, ref b)| (a, (b.as_ref().clone()).map(|boxed| &**boxed))));
3573+
}
3574+
};
3575+
3576+
if let Some(ref txid) = self.prev_counterparty_commitment_txid {
3577+
if let Some(ref htlc_outputs) = self.counterparty_claimable_outpoints.get(txid) {
3578+
fail_soon_to_expire_htlcs!(htlc_outputs.iter().map(|&(ref a, ref b)| (a, (b.as_ref().clone()).map(|boxed| &**boxed))));
3579+
}
3580+
};
3581+
35183582
// Find which on-chain events have reached their confirmation threshold.
35193583
let onchain_events_awaiting_threshold_conf =
35203584
self.onchain_events_awaiting_threshold_conf.drain(..).collect::<Vec<_>>();

lightning/src/ln/functional_tests.rs

Lines changed: 119 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
use crate::chain;
1515
use crate::chain::{ChannelMonitorUpdateStatus, Confirm, Listen, Watch};
1616
use crate::chain::chaininterface::LowerBoundedFeeEstimator;
17-
use crate::chain::channelmonitor;
17+
use crate::chain::channelmonitor::{self, TIMEOUT_FAIL_BACK_BUFFER};
1818
use crate::chain::channelmonitor::{CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ANTI_REORG_DELAY};
1919
use crate::chain::transaction::OutPoint;
2020
use crate::sign::{ChannelSigner, EcdsaChannelSigner, EntropySource, SignerProvider};
@@ -2214,6 +2214,120 @@ fn channel_reserve_in_flight_removes() {
22142214
claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_3);
22152215
}
22162216

2217+
enum PostFailBackAction {
2218+
TimeoutOnChain,
2219+
ClaimOnChain,
2220+
FailOffChain,
2221+
ClaimOffChain,
2222+
}
2223+
2224+
#[test]
2225+
fn test_fail_back_before_backwards_timeout() {
2226+
do_test_fail_back_before_backwards_timeout(PostFailBackAction::TimeoutOnChain);
2227+
do_test_fail_back_before_backwards_timeout(PostFailBackAction::ClaimOnChain);
2228+
do_test_fail_back_before_backwards_timeout(PostFailBackAction::FailOffChain);
2229+
do_test_fail_back_before_backwards_timeout(PostFailBackAction::ClaimOffChain);
2230+
}
2231+
2232+
fn do_test_fail_back_before_backwards_timeout(post_fail_back_action: PostFailBackAction) {
2233+
// Test that we fail an HTLC upstream if we are still waiting for confirmation downstream
2234+
// just before the upstream timeout expires
2235+
let chanmon_cfgs = create_chanmon_cfgs(3);
2236+
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
2237+
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
2238+
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
2239+
2240+
create_announced_chan_between_nodes(&nodes, 0, 1);
2241+
let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2);
2242+
2243+
connect_blocks(&nodes[0], 2*CHAN_CONFIRM_DEPTH + 1 - nodes[0].best_block_info().1);
2244+
connect_blocks(&nodes[1], 2*CHAN_CONFIRM_DEPTH + 1 - nodes[1].best_block_info().1);
2245+
connect_blocks(&nodes[2], 2*CHAN_CONFIRM_DEPTH + 1 - nodes[2].best_block_info().1);
2246+
2247+
let (payment_preimage, payment_hash, _) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 3_000_000);
2248+
2249+
// Force close downstream with timeout
2250+
nodes[1].node.force_close_broadcasting_latest_txn(&chan_2.2, &nodes[2].node.get_our_node_id()).unwrap();
2251+
check_added_monitors!(nodes[1], 1);
2252+
check_closed_broadcast!(nodes[1], true);
2253+
2254+
connect_blocks(&nodes[1], TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS + 1);
2255+
let node_1_txn = test_txn_broadcast(&nodes[1], &chan_2, None, HTLCType::TIMEOUT);
2256+
check_closed_event(&nodes[1], 1, ClosureReason::HolderForceClosed, false,
2257+
&[nodes[2].node.get_our_node_id(); 1], 100_000);
2258+
2259+
// Nothing is confirmed for a while
2260+
connect_blocks(&nodes[1], MIN_CLTV_EXPIRY_DELTA as u32 - LATENCY_GRACE_PERIOD_BLOCKS - TIMEOUT_FAIL_BACK_BUFFER);
2261+
2262+
// Check that nodes[1] fails the HTLC upstream
2263+
expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_2.2 }]);
2264+
check_added_monitors!(nodes[1], 1);
2265+
let events = nodes[1].node.get_and_clear_pending_msg_events();
2266+
assert_eq!(events.len(), 1);
2267+
let (update_fail, commitment_signed) = match events[0] {
2268+
MessageSendEvent::UpdateHTLCs { node_id: _, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, ref update_fee, ref commitment_signed } } => {
2269+
assert!(update_add_htlcs.is_empty());
2270+
assert!(update_fulfill_htlcs.is_empty());
2271+
assert_eq!(update_fail_htlcs.len(), 1);
2272+
assert!(update_fail_malformed_htlcs.is_empty());
2273+
assert!(update_fee.is_none());
2274+
(update_fail_htlcs[0].clone(), commitment_signed.clone())
2275+
},
2276+
_ => panic!("Unexpected event"),
2277+
};
2278+
2279+
nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &update_fail);
2280+
commitment_signed_dance!(nodes[0], nodes[1], commitment_signed, false);
2281+
expect_payment_failed_conditions(&nodes[0], payment_hash, false, PaymentFailedConditions::new().blamed_chan_closed(true));
2282+
2283+
// Make sure we handle possible duplicate fails or extra messages after failing back
2284+
match post_fail_back_action {
2285+
PostFailBackAction::TimeoutOnChain => {
2286+
// Confirm nodes[1]'s claim with timeout, make sure we don't fail upstream again
2287+
mine_transaction(&nodes[1], &node_1_txn[0]); // Commitment
2288+
mine_transaction(&nodes[1], &node_1_txn[1]); // HTLC timeout
2289+
},
2290+
PostFailBackAction::ClaimOnChain => {
2291+
nodes[2].node.claim_funds(payment_preimage);
2292+
expect_payment_claimed!(nodes[2], payment_hash, 3_000_000);
2293+
check_added_monitors!(nodes[2], 1);
2294+
get_htlc_update_msgs(&nodes[2], &nodes[1].node.get_our_node_id());
2295+
2296+
connect_blocks(&nodes[2], TEST_FINAL_CLTV - CLTV_CLAIM_BUFFER + 2);
2297+
let node_2_txn = test_txn_broadcast(&nodes[2], &chan_2, None, HTLCType::SUCCESS);
2298+
check_closed_broadcast!(nodes[2], true);
2299+
check_closed_event(&nodes[2], 1, ClosureReason::CommitmentTxConfirmed, false,
2300+
&[nodes[1].node.get_our_node_id(); 1], 100_000);
2301+
check_added_monitors!(nodes[2], 1);
2302+
2303+
mine_transaction(&nodes[1], &node_2_txn[0]); // Commitment
2304+
mine_transaction(&nodes[1], &node_2_txn[1]); // HTLC success
2305+
},
2306+
PostFailBackAction::FailOffChain => {
2307+
nodes[2].node.fail_htlc_backwards(&payment_hash);
2308+
expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[2], vec![HTLCDestination::FailedPayment { payment_hash: payment_hash.clone() }]);
2309+
check_added_monitors!(nodes[2], 1);
2310+
let commitment_update = get_htlc_update_msgs(&nodes[2], &nodes[1].node.get_our_node_id());
2311+
let update_fail = commitment_update.update_fail_htlcs[0].clone();
2312+
2313+
nodes[1].node.handle_update_fail_htlc(&nodes[2].node.get_our_node_id(), &update_fail);
2314+
let err_msg = get_err_msg(&nodes[1], &nodes[2].node.get_our_node_id());
2315+
assert_eq!(err_msg.channel_id, chan_2.2);
2316+
},
2317+
PostFailBackAction::ClaimOffChain => {
2318+
nodes[2].node.claim_funds(payment_preimage);
2319+
expect_payment_claimed!(nodes[2], payment_hash, 3_000_000);
2320+
check_added_monitors!(nodes[2], 1);
2321+
let commitment_update = get_htlc_update_msgs(&nodes[2], &nodes[1].node.get_our_node_id());
2322+
let update_fulfill = commitment_update.update_fulfill_htlcs[0].clone();
2323+
2324+
nodes[1].node.handle_update_fulfill_htlc(&nodes[2].node.get_our_node_id(), &update_fulfill);
2325+
let err_msg = get_err_msg(&nodes[1], &nodes[2].node.get_our_node_id());
2326+
assert_eq!(err_msg.channel_id, chan_2.2);
2327+
},
2328+
};
2329+
}
2330+
22172331
#[test]
22182332
fn channel_monitor_network_test() {
22192333
// Simple test which builds a network of ChannelManagers, connects them to each other, and
@@ -2310,7 +2424,7 @@ fn channel_monitor_network_test() {
23102424
let node2_commitment_txid;
23112425
{
23122426
let node_txn = test_txn_broadcast(&nodes[2], &chan_3, None, HTLCType::NONE);
2313-
connect_blocks(&nodes[2], TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS + MIN_CLTV_EXPIRY_DELTA as u32 + 1);
2427+
connect_blocks(&nodes[2], TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS);
23142428
test_txn_broadcast(&nodes[2], &chan_3, None, HTLCType::TIMEOUT);
23152429
node2_commitment_txid = node_txn[0].txid();
23162430

@@ -3060,9 +3174,9 @@ fn do_test_htlc_on_chain_timeout(connect_style: ConnectStyle) {
30603174
// Broadcast timeout transaction by B on received output from C's commitment tx on B's chain
30613175
// Verify that B's ChannelManager is able to detect that HTLC is timeout by its own tx and react backward in consequence
30623176
mine_transaction(&nodes[1], &commitment_tx[0]);
3063-
check_closed_event!(&nodes[1], 1, ClosureReason::CommitmentTxConfirmed, false
3064-
, [nodes[2].node.get_our_node_id()], 100000);
3065-
connect_blocks(&nodes[1], 200 - nodes[2].best_block_info().1);
3177+
check_closed_event(&nodes[1], 1, ClosureReason::CommitmentTxConfirmed, false,
3178+
&[nodes[2].node.get_our_node_id()], 100000);
3179+
connect_blocks(&nodes[1], 100 - nodes[2].best_block_info().1);
30663180
let timeout_tx = {
30673181
let mut txn = nodes[1].tx_broadcaster.txn_broadcast();
30683182
if nodes[1].connect_style.borrow().skips_blocks() {

0 commit comments

Comments
 (0)