From e579e3665390637cbfd22b776d8f4fba6da7e687 Mon Sep 17 00:00:00 2001 From: Calvin Zachman Date: Mon, 17 Aug 2026 20:30:25 -0400 Subject: [PATCH] router: surface auto-fail height on intercepted htlcs lnd sends, on every htlc interception, the block height at which it will auto-fail the held htlc to keep the channel from force-closing. The conversion into InterceptedHtlc dropped this field, so callers could not see it and had to reason against IncomingExpiryHeight instead. That is the wrong deadline: the auto-fail height is earlier by lnd's FinalCltvRejectDelta, so a hold-and-forward consumer believes it has more runway than it does. --- router_client.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/router_client.go b/router_client.go index afbd55b..87a5e23 100644 --- a/router_client.go +++ b/router_client.go @@ -386,6 +386,14 @@ type InterceptedHtlc struct { // InWireCustomRecords are custom records sent by the sender that were // only present in the wire message and not the onion itself. InWireCustomRecords map[uint64][]byte + + // AutoFailHeight is the block height at which lnd will auto-fail this + // held htlc to keep the channel from force-closing. It is earlier than + // IncomingExpiryHeight by lnd's FinalCltvRejectDelta and is the real + // deadline for work against a held htlc. A zero value means unknown + // (for example an older lnd that predates the field) and should be + // treated conservatively, not as a literal height of 0. + AutoFailHeight int32 } // HtlcInterceptHandler is a function signature for handling code for htlc @@ -1071,6 +1079,7 @@ func (r *routerClient) InterceptHtlcs(ctx context.Context, CustomRecords: request.CustomRecords, OnionBlob: request.OnionBlob, InWireCustomRecords: inWireCustomRecords, + AutoFailHeight: request.AutoFailHeight, } // Try to send our interception request, failing on