Skip to content

Commit 071aa85

Browse files
authored
Merge pull request #3608 from TheBlueMatt/2025-02-better-block-constants
Correct and update confirmation target constant definitions
2 parents f25709c + e7c2a61 commit 071aa85

9 files changed

+195
-145
lines changed

lightning/src/chain/channelmonitor.rs

+11-19
Original file line numberDiff line numberDiff line change
@@ -223,16 +223,20 @@ impl_writeable_tlv_based!(HTLCUpdate, {
223223
/// transaction.
224224
pub(crate) const COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE: u32 = 12;
225225

226-
/// When we go to force-close a channel because an HTLC is expiring, we should ensure that the
227-
/// HTLC(s) expiring are not considered pinnable, allowing us to aggregate them with other HTLC(s)
228-
/// expiring at the same time.
229-
const _: () = assert!(CLTV_CLAIM_BUFFER > COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE);
226+
/// When we go to force-close a channel because an HTLC is expiring, by the time we've gotten the
227+
/// commitment transaction confirmed, we should ensure that the HTLC(s) expiring are not considered
228+
/// pinnable, allowing us to aggregate them with other HTLC(s) expiring at the same time.
229+
const _: () = assert!(MAX_BLOCKS_FOR_CONF > COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE);
230+
231+
/// The upper bound on how many blocks we think it can take for us to get a transaction confirmed.
232+
pub(crate) const MAX_BLOCKS_FOR_CONF: u32 = 18;
230233

231234
/// If an HTLC expires within this many blocks, force-close the channel to broadcast the
232235
/// HTLC-Success transaction.
233-
/// In other words, this is an upper bound on how many blocks we think it can take us to get a
234-
/// transaction confirmed (and we use it in a few more, equivalent, places).
235-
pub(crate) const CLTV_CLAIM_BUFFER: u32 = 18;
236+
///
237+
/// This is two times [`MAX_BLOCKS_FOR_CONF`] as we need to first get the commitment transaction
238+
/// confirmed, then get an HTLC transaction confirmed.
239+
pub(crate) const CLTV_CLAIM_BUFFER: u32 = MAX_BLOCKS_FOR_CONF * 2;
236240
/// Number of blocks by which point we expect our counterparty to have seen new blocks on the
237241
/// network and done a full update_fail_htlc/commitment_signed dance (+ we've updated all our
238242
/// copies of ChannelMonitors, including watchtowers). We could enforce the contract by failing
@@ -4512,18 +4516,6 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
45124516
// chain when our counterparty is waiting for expiration to off-chain fail an HTLC
45134517
// we give ourselves a few blocks of headroom after expiration before going
45144518
// on-chain for an expired HTLC.
4515-
// Note that, to avoid a potential attack whereby a node delays claiming an HTLC
4516-
// from us until we've reached the point where we go on-chain with the
4517-
// corresponding inbound HTLC, we must ensure that outbound HTLCs go on chain at
4518-
// least CLTV_CLAIM_BUFFER blocks prior to the inbound HTLC.
4519-
// aka outbound_cltv + LATENCY_GRACE_PERIOD_BLOCKS == height - CLTV_CLAIM_BUFFER
4520-
// inbound_cltv == height + CLTV_CLAIM_BUFFER
4521-
// outbound_cltv + LATENCY_GRACE_PERIOD_BLOCKS + CLTV_CLAIM_BUFFER <= inbound_cltv - CLTV_CLAIM_BUFFER
4522-
// LATENCY_GRACE_PERIOD_BLOCKS + 2*CLTV_CLAIM_BUFFER <= inbound_cltv - outbound_cltv
4523-
// CLTV_EXPIRY_DELTA <= inbound_cltv - outbound_cltv (by check in ChannelManager::decode_update_add_htlc_onion)
4524-
// LATENCY_GRACE_PERIOD_BLOCKS + 2*CLTV_CLAIM_BUFFER <= CLTV_EXPIRY_DELTA
4525-
// The final, above, condition is checked for statically in channelmanager
4526-
// with CHECK_CLTV_EXPIRY_SANITY_2.
45274519
let htlc_outbound = $holder_tx == htlc.offered;
45284520
if ( htlc_outbound && htlc.cltv_expiry + LATENCY_GRACE_PERIOD_BLOCKS <= height) ||
45294521
(!htlc_outbound && htlc.cltv_expiry <= height + CLTV_CLAIM_BUFFER && self.payment_preimages.contains_key(&htlc.payment_hash)) {

lightning/src/ln/async_payments_tests.rs

+19
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,13 @@ fn async_receive_mpp() {
540540
create_announced_chan_between_nodes(&nodes, 0, 2);
541541
create_unannounced_chan_between_nodes_with_value(&nodes, 1, 3, 1_000_000, 0);
542542
create_unannounced_chan_between_nodes_with_value(&nodes, 2, 3, 1_000_000, 0);
543+
544+
// Ensure all nodes start at the same height.
545+
connect_blocks(&nodes[0], 4 * CHAN_CONFIRM_DEPTH + 1 - nodes[0].best_block_info().1);
546+
connect_blocks(&nodes[1], 4 * CHAN_CONFIRM_DEPTH + 1 - nodes[1].best_block_info().1);
547+
connect_blocks(&nodes[2], 4 * CHAN_CONFIRM_DEPTH + 1 - nodes[2].best_block_info().1);
548+
connect_blocks(&nodes[3], 4 * CHAN_CONFIRM_DEPTH + 1 - nodes[3].best_block_info().1);
549+
543550
let (offer, static_invoice) = create_static_invoice(&nodes[1], &nodes[3], None, &secp_ctx);
544551

545552
// In other tests we hardcode the sender's random bytes so we can predict the keysend preimage to
@@ -622,6 +629,12 @@ fn amount_doesnt_match_invreq() {
622629
create_unannounced_chan_between_nodes_with_value(&nodes, 1, 3, 1_000_000, 0);
623630
create_unannounced_chan_between_nodes_with_value(&nodes, 2, 3, 1_000_000, 0);
624631

632+
// Ensure all nodes start at the same height.
633+
connect_blocks(&nodes[0], 4 * CHAN_CONFIRM_DEPTH + 1 - nodes[0].best_block_info().1);
634+
connect_blocks(&nodes[1], 4 * CHAN_CONFIRM_DEPTH + 1 - nodes[1].best_block_info().1);
635+
connect_blocks(&nodes[2], 4 * CHAN_CONFIRM_DEPTH + 1 - nodes[2].best_block_info().1);
636+
connect_blocks(&nodes[3], 4 * CHAN_CONFIRM_DEPTH + 1 - nodes[3].best_block_info().1);
637+
625638
let (offer, static_invoice) = create_static_invoice(&nodes[1], &nodes[3], None, &secp_ctx);
626639

627640
// Set the random bytes so we can predict the payment preimage and hash.
@@ -815,9 +828,15 @@ fn invalid_async_receive_with_retry<F1, F2>(
815828
let node_chanmgrs =
816829
create_node_chanmgrs(3, &node_cfgs, &[None, Some(allow_priv_chan_fwds_cfg), None]);
817830
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
831+
818832
create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0);
819833
create_unannounced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0);
820834

835+
// Ensure all nodes start at the same height.
836+
connect_blocks(&nodes[0], 2 * CHAN_CONFIRM_DEPTH + 1 - nodes[0].best_block_info().1);
837+
connect_blocks(&nodes[1], 2 * CHAN_CONFIRM_DEPTH + 1 - nodes[1].best_block_info().1);
838+
connect_blocks(&nodes[2], 2 * CHAN_CONFIRM_DEPTH + 1 - nodes[2].best_block_info().1);
839+
821840
let blinded_paths_to_always_online_node = nodes[1]
822841
.message_router
823842
.create_blinded_paths(

lightning/src/ln/blinded_payment_tests.rs

+20
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,12 @@ fn mpp_to_one_hop_blinded_path() {
204204
let chan_upd_1_3 = create_announced_chan_between_nodes(&nodes, 1, 3).0.contents;
205205
create_announced_chan_between_nodes(&nodes, 2, 3).0.contents;
206206

207+
// Ensure all nodes start at the same height.
208+
connect_blocks(&nodes[0], 4*CHAN_CONFIRM_DEPTH + 1 - nodes[0].best_block_info().1);
209+
connect_blocks(&nodes[1], 4*CHAN_CONFIRM_DEPTH + 1 - nodes[1].best_block_info().1);
210+
connect_blocks(&nodes[2], 4*CHAN_CONFIRM_DEPTH + 1 - nodes[2].best_block_info().1);
211+
connect_blocks(&nodes[3], 4*CHAN_CONFIRM_DEPTH + 1 - nodes[3].best_block_info().1);
212+
207213
let amt_msat = 15_000_000;
208214
let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[3], Some(amt_msat), None);
209215
let payee_tlvs = UnauthenticatedReceiveTlvs {
@@ -267,6 +273,14 @@ fn mpp_to_three_hop_blinded_paths() {
267273
let chan_upd_3_5 = create_announced_chan_between_nodes(&nodes, 3, 5).0.contents;
268274
let chan_upd_4_5 = create_announced_chan_between_nodes(&nodes, 4, 5).0.contents;
269275

276+
// Start every node on the same block height to make reasoning about timeouts easier
277+
connect_blocks(&nodes[0], 6*CHAN_CONFIRM_DEPTH + 1 - nodes[0].best_block_info().1);
278+
connect_blocks(&nodes[1], 6*CHAN_CONFIRM_DEPTH + 1 - nodes[1].best_block_info().1);
279+
connect_blocks(&nodes[2], 6*CHAN_CONFIRM_DEPTH + 1 - nodes[2].best_block_info().1);
280+
connect_blocks(&nodes[3], 6*CHAN_CONFIRM_DEPTH + 1 - nodes[3].best_block_info().1);
281+
connect_blocks(&nodes[4], 6*CHAN_CONFIRM_DEPTH + 1 - nodes[4].best_block_info().1);
282+
connect_blocks(&nodes[5], 6*CHAN_CONFIRM_DEPTH + 1 - nodes[5].best_block_info().1);
283+
270284
let amt_msat = 15_000_000;
271285
let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[5], Some(amt_msat), None);
272286
let route_params = {
@@ -1070,6 +1084,12 @@ fn blinded_path_retries() {
10701084
let chan_1_3 = create_announced_chan_between_nodes_with_value(&nodes, 1, 3, 1_000_000, 0);
10711085
let chan_2_3 = create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 1_000_000, 0);
10721086

1087+
// Ensure all nodes start at the same height.
1088+
connect_blocks(&nodes[0], 4*CHAN_CONFIRM_DEPTH + 1 - nodes[0].best_block_info().1);
1089+
connect_blocks(&nodes[1], 4*CHAN_CONFIRM_DEPTH + 1 - nodes[1].best_block_info().1);
1090+
connect_blocks(&nodes[2], 4*CHAN_CONFIRM_DEPTH + 1 - nodes[2].best_block_info().1);
1091+
connect_blocks(&nodes[3], 4*CHAN_CONFIRM_DEPTH + 1 - nodes[3].best_block_info().1);
1092+
10731093
let amt_msat = 5000;
10741094
let (_, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[3], Some(amt_msat), None);
10751095
let route_params = {

lightning/src/ln/channelmanager.rs

+32-17
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ use crate::blinded_path::payment::{AsyncBolt12OfferContext, BlindedPaymentPath,
4040
use crate::chain;
4141
use crate::chain::{Confirm, ChannelMonitorUpdateStatus, Watch, BestBlock};
4242
use crate::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator, LowerBoundedFeeEstimator};
43-
use crate::chain::channelmonitor::{Balance, ChannelMonitor, ChannelMonitorUpdate, WithChannelMonitor, ChannelMonitorUpdateStep, HTLC_FAIL_BACK_BUFFER, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ANTI_REORG_DELAY, MonitorEvent};
43+
use crate::chain::channelmonitor::{Balance, ChannelMonitor, ChannelMonitorUpdate, WithChannelMonitor, ChannelMonitorUpdateStep, HTLC_FAIL_BACK_BUFFER, MAX_BLOCKS_FOR_CONF, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ANTI_REORG_DELAY, MonitorEvent};
4444
use crate::chain::transaction::{OutPoint, TransactionData};
4545
use crate::events::{self, Event, EventHandler, EventsProvider, InboundChannelFunds, ClosureReason, HTLCDestination, PaymentFailureReason, ReplayEvent};
4646
// Since this struct is returned in `list_channels` methods, expose it here in case users want to
@@ -2824,7 +2824,7 @@ pub const BREAKDOWN_TIMEOUT: u16 = 6 * 24;
28242824
pub(crate) const MAX_LOCAL_BREAKDOWN_TIMEOUT: u16 = 2 * 6 * 24 * 7;
28252825

28262826
/// The minimum number of blocks between an inbound HTLC's CLTV and the corresponding outbound
2827-
/// HTLC's CLTV. The current default represents roughly seven hours of blocks at six blocks/hour.
2827+
/// HTLC's CLTV. The current default represents roughly eight hours of blocks at six blocks/hour.
28282828
///
28292829
/// This can be increased (but not decreased) through [`ChannelConfig::cltv_expiry_delta`]
28302830
///
@@ -2833,7 +2833,7 @@ pub(crate) const MAX_LOCAL_BREAKDOWN_TIMEOUT: u16 = 2 * 6 * 24 * 7;
28332833
// i.e. the node we forwarded the payment on to should always have enough room to reliably time out
28342834
// the HTLC via a full update_fail_htlc/commitment_signed dance before we hit the
28352835
// CLTV_CLAIM_BUFFER point (we static assert that it's at least 3 blocks more).
2836-
pub const MIN_CLTV_EXPIRY_DELTA: u16 = 6*7;
2836+
pub const MIN_CLTV_EXPIRY_DELTA: u16 = 6*8;
28372837
// This should be long enough to allow a payment path drawn across multiple routing hops with substantial
28382838
// `cltv_expiry_delta`. Indeed, the length of those values is the reaction delay offered to a routing node
28392839
// in case of HTLC on-chain settlement. While appearing less competitive, a node operator could decide to
@@ -2850,19 +2850,34 @@ pub(super) const CLTV_FAR_FAR_AWAY: u32 = 14 * 24 * 6;
28502850
// a payment was being routed, so we add an extra block to be safe.
28512851
pub const MIN_FINAL_CLTV_EXPIRY_DELTA: u16 = HTLC_FAIL_BACK_BUFFER as u16 + 3;
28522852

2853-
// Check that our CLTV_EXPIRY is at least CLTV_CLAIM_BUFFER + ANTI_REORG_DELAY + LATENCY_GRACE_PERIOD_BLOCKS,
2854-
// ie that if the next-hop peer fails the HTLC within
2855-
// LATENCY_GRACE_PERIOD_BLOCKS then we'll still have CLTV_CLAIM_BUFFER left to timeout it onchain,
2856-
// then waiting ANTI_REORG_DELAY to be reorg-safe on the outbound HLTC and
2857-
// failing the corresponding htlc backward, and us now seeing the last block of ANTI_REORG_DELAY before
2858-
// LATENCY_GRACE_PERIOD_BLOCKS.
2859-
#[allow(dead_code)]
2860-
const CHECK_CLTV_EXPIRY_SANITY: u32 = MIN_CLTV_EXPIRY_DELTA as u32 - LATENCY_GRACE_PERIOD_BLOCKS - CLTV_CLAIM_BUFFER - ANTI_REORG_DELAY - LATENCY_GRACE_PERIOD_BLOCKS;
2853+
// Check that our MIN_CLTV_EXPIRY_DELTA gives us enough time to get everything on chain and locked
2854+
// in with enough time left to fail the corresponding HTLC back to our inbound edge before they
2855+
// force-close on us.
2856+
// In other words, if the next-hop peer fails HTLC LATENCY_GRACE_PERIOD_BLOCKS after our
2857+
// CLTV_CLAIM_BUFFER (because that's how many blocks we allow them after expiry), we'll still have
2858+
// 2*MAX_BLOCKS_FOR_CONF + ANTI_REORG_DELAY left to get two transactions on chain and the second
2859+
// fully locked in before the peer force-closes on us (LATENCY_GRACE_PERIOD_BLOCKS before the
2860+
// expiry, i.e. assuming the peer force-closes right at the expiry and we're behind by
2861+
// LATENCY_GRACE_PERIOD_BLOCKS).
2862+
const _CHECK_CLTV_EXPIRY_SANITY: () = assert!(
2863+
MIN_CLTV_EXPIRY_DELTA as u32 >= 2*LATENCY_GRACE_PERIOD_BLOCKS + 2*MAX_BLOCKS_FOR_CONF + ANTI_REORG_DELAY
2864+
);
2865+
2866+
// Check that our MIN_CLTV_EXPIRY_DELTA gives us enough time to get the HTLC preimage back to our
2867+
// counterparty if the outbound edge gives us the preimage only one block before we'd force-close
2868+
// the channel.
2869+
// ie they provide the preimage LATENCY_GRACE_PERIOD_BLOCKS - 1 after the HTLC expires, then we
2870+
// pass the preimage back, which takes LATENCY_GRACE_PERIOD_BLOCKS to complete, and we want to make
2871+
// sure this all happens at least N blocks before the inbound HTLC expires (where N is the
2872+
// counterparty's CLTV_CLAIM_BUFFER or equivalent).
2873+
const _ASSUMED_COUNTERPARTY_CLTV_CLAIM_BUFFER: u32 = 6 * 6;
28612874

2862-
// Check for ability of an attacker to make us fail on-chain by delaying an HTLC claim. See
2863-
// ChannelMonitor::should_broadcast_holder_commitment_txn for a description of why this is needed.
2864-
#[allow(dead_code)]
2865-
const CHECK_CLTV_EXPIRY_SANITY_2: u32 = MIN_CLTV_EXPIRY_DELTA as u32 - LATENCY_GRACE_PERIOD_BLOCKS - 2*CLTV_CLAIM_BUFFER;
2875+
const _CHECK_COUNTERPARTY_REALISTIC: () =
2876+
assert!(_ASSUMED_COUNTERPARTY_CLTV_CLAIM_BUFFER >= CLTV_CLAIM_BUFFER);
2877+
2878+
const _CHECK_CLTV_EXPIRY_OFFCHAIN: () = assert!(
2879+
MIN_CLTV_EXPIRY_DELTA as u32 >= 2*LATENCY_GRACE_PERIOD_BLOCKS - 1 + _ASSUMED_COUNTERPARTY_CLTV_CLAIM_BUFFER
2880+
);
28662881

28672882
/// The number of ticks of [`ChannelManager::timer_tick_occurred`] until expiry of incomplete MPPs
28682883
pub(crate) const MPP_TIMEOUT_TICKS: u8 = 3;
@@ -15979,15 +15994,15 @@ mod tests {
1597915994
let current_height: u32 = node[0].node.best_block.read().unwrap().height;
1598015995
let result = create_recv_pending_htlc_info(msgs::InboundOnionPayload::Receive(msgs::InboundOnionReceivePayload {
1598115996
sender_intended_htlc_amt_msat: 100,
15982-
cltv_expiry_height: 22,
15997+
cltv_expiry_height: TEST_FINAL_CLTV,
1598315998
payment_metadata: None,
1598415999
keysend_preimage: None,
1598516000
payment_data: Some(msgs::FinalOnionHopData {
1598616001
payment_secret: PaymentSecret([0; 32]),
1598716002
total_msat: 100,
1598816003
}),
1598916004
custom_tlvs: Vec::new(),
15990-
}), [0; 32], PaymentHash([0; 32]), 100, 23, None, true, None, current_height);
16005+
}), [0; 32], PaymentHash([0; 32]), 100, TEST_FINAL_CLTV + 1, None, true, None, current_height);
1599116006

1599216007
// Should not return an error as this condition:
1599316008
// https://github.com/lightning/bolts/blob/4dcc377209509b13cf89a4b91fde7d478f5b46d8/04-onion-routing.md?plain=1#L334

0 commit comments

Comments
 (0)