Skip to content

Commit 777e5c3

Browse files
committed
Correct sanity checking of MIN_CLTV_EXPIRY_DELTA constants
The `CHECK_CLTV_EXPIRY_SANITY_2` check actually made no sense - its use of `2*CLTV_CLAIM_BUFFER` implicitly assumed that we were failing HTLCs `CLTV_CLAIM_BUFFER` after they expired, which is nonsense. Instead, we improve the readability of the docs on `_CHECK_CLTV_EXPIRY_SANITY` and add a new `_CHECK_CLTV_EXPIRY_OFFCHAIN` that correctly tests for what the `CHECK_CLTV_EXPIRY_SANITY_2` check was supposed to look at.
1 parent 2d2c542 commit 777e5c3

File tree

2 files changed

+29
-25
lines changed

2 files changed

+29
-25
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4508,18 +4508,6 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
45084508
// chain when our counterparty is waiting for expiration to off-chain fail an HTLC
45094509
// we give ourselves a few blocks of headroom after expiration before going
45104510
// on-chain for an expired HTLC.
4511-
// Note that, to avoid a potential attack whereby a node delays claiming an HTLC
4512-
// from us until we've reached the point where we go on-chain with the
4513-
// corresponding inbound HTLC, we must ensure that outbound HTLCs go on chain at
4514-
// least CLTV_CLAIM_BUFFER blocks prior to the inbound HTLC.
4515-
// aka outbound_cltv + LATENCY_GRACE_PERIOD_BLOCKS == height - CLTV_CLAIM_BUFFER
4516-
// inbound_cltv == height + CLTV_CLAIM_BUFFER
4517-
// outbound_cltv + LATENCY_GRACE_PERIOD_BLOCKS + CLTV_CLAIM_BUFFER <= inbound_cltv - CLTV_CLAIM_BUFFER
4518-
// LATENCY_GRACE_PERIOD_BLOCKS + 2*CLTV_CLAIM_BUFFER <= inbound_cltv - outbound_cltv
4519-
// CLTV_EXPIRY_DELTA <= inbound_cltv - outbound_cltv (by check in ChannelManager::decode_update_add_htlc_onion)
4520-
// LATENCY_GRACE_PERIOD_BLOCKS + 2*CLTV_CLAIM_BUFFER <= CLTV_EXPIRY_DELTA
4521-
// The final, above, condition is checked for statically in channelmanager
4522-
// with CHECK_CLTV_EXPIRY_SANITY_2.
45234511
let htlc_outbound = $holder_tx == htlc.offered;
45244512
if ( htlc_outbound && htlc.cltv_expiry + LATENCY_GRACE_PERIOD_BLOCKS <= height) ||
45254513
(!htlc_outbound && htlc.cltv_expiry <= height + CLTV_CLAIM_BUFFER && self.payment_preimages.contains_key(&htlc.payment_hash)) {

lightning/src/ln/channelmanager.rs

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2840,19 +2840,35 @@ pub(super) const CLTV_FAR_FAR_AWAY: u32 = 14 * 24 * 6;
28402840
// a payment was being routed, so we add an extra block to be safe.
28412841
pub const MIN_FINAL_CLTV_EXPIRY_DELTA: u16 = HTLC_FAIL_BACK_BUFFER as u16 + 3;
28422842

2843-
// Check that our CLTV_EXPIRY is at least CLTV_CLAIM_BUFFER + ANTI_REORG_DELAY + LATENCY_GRACE_PERIOD_BLOCKS,
2844-
// ie that if the next-hop peer fails the HTLC within
2845-
// LATENCY_GRACE_PERIOD_BLOCKS then we'll still have CLTV_CLAIM_BUFFER left to timeout it onchain,
2846-
// then waiting ANTI_REORG_DELAY to be reorg-safe on the outbound HLTC and
2847-
// failing the corresponding htlc backward, and us now seeing the last block of ANTI_REORG_DELAY before
2848-
// LATENCY_GRACE_PERIOD_BLOCKS.
2849-
#[allow(dead_code)]
2850-
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;
2851-
2852-
// Check for ability of an attacker to make us fail on-chain by delaying an HTLC claim. See
2853-
// ChannelMonitor::should_broadcast_holder_commitment_txn for a description of why this is needed.
2854-
#[allow(dead_code)]
2855-
const CHECK_CLTV_EXPIRY_SANITY_2: u32 = MIN_CLTV_EXPIRY_DELTA as u32 - LATENCY_GRACE_PERIOD_BLOCKS - 2*CLTV_CLAIM_BUFFER;
2843+
// Check that our MIN_CLTV_EXPIRY_DELTA gives us enough time to get everything on chain and locked
2844+
// in with enough time left to fail the corresponding HTLC back to our inbound edge before they
2845+
// force-close on us.
2846+
// ie that if the next-hop peer fails the HTLC LATENCY_GRACE_PERIOD_BLOCKS after our
2847+
// CLTV_CLAIM_BUFFER (because that's how many blocks we allow them after expiry), we'll still have
2848+
// CLTV_CLAIM_BUFFER + ANTI_REORG_DELAY left to get two transactions on chain and the second
2849+
// fully locked in before the peer force-closes on us (LATENCY_GRACE_PERIOD_BOLOCKS before the
2850+
// expiry, i.e. assuming the peer force-closes right at the expiry and we're behind by
2851+
// LATENCY_GRACE_PERIOD_BLOCKS).
2852+
// second fully locked in before the peer force-closes on us.
2853+
const _CHECK_CLTV_EXPIRY_SANITY: () = assert!(
2854+
MIN_CLTV_EXPIRY_DELTA as u32 >= 2*LATENCY_GRACE_PERIOD_BLOCKS + CLTV_CLAIM_BUFFER + ANTI_REORG_DELAY
2855+
);
2856+
2857+
// Check that our MIN_CLTV_EXPIRY_DELTA gives us enough time to get the HTLC preimage back to our
2858+
// counterparty if the outbound edge gives us the preimage only one block before we'd force-close
2859+
// the channel.
2860+
// ie they provide the preimage LATENCY_GRACE_PERIOD_BLOCKS - 1 after the HTLC expires, then we
2861+
// pass the preimage back, which takes LATENCY_GRACE_PERIOD_BLOCKS to complete, and we want to make
2862+
// sure this all happens at least N blocks before the inbound HTLC expires (where N is the
2863+
// counterparty's CLTV_CLAIM_BUFFER or equivalent).
2864+
const _ASSUMED_COUNTERPARTY_CLTV_CLAIM_BUFFER: u32 = 6 * 6;
2865+
2866+
const _CHECK_COUNTERPARTY_REALISTIC: () =
2867+
assert!(_ASSUMED_COUNTERPARTY_CLTV_CLAIM_BUFFER >= CLTV_CLAIM_BUFFER);
2868+
2869+
const _CHECK_CLTV_EXPIRY_OFFCHAIN: () = assert!(
2870+
MIN_CLTV_EXPIRY_DELTA as u32 >= 2*LATENCY_GRACE_PERIOD_BLOCKS - 1 + _ASSUMED_COUNTERPARTY_CLTV_CLAIM_BUFFER
2871+
);
28562872

28572873
/// The number of ticks of [`ChannelManager::timer_tick_occurred`] until expiry of incomplete MPPs
28582874
pub(crate) const MPP_TIMEOUT_TICKS: u8 = 3;

0 commit comments

Comments
 (0)