Skip to content

Backport async reestablish point (upstream 1f7b24900) + keep uncached points non-fatal (on zeus-0.2.6) - #2

Merged
kaloudis merged 2 commits into
zeus-0.2.6from
zeus-0.2-async-reestablish-point
Sep 24, 2026
Merged

kaloudis merged 2 commits into
zeus-0.2.6from
zeus-0.2-async-reestablish-point

Conversation

@kaloudis

@kaloudis kaloudis commented Sep 24, 2026 •

Copy link
Copy Markdown

Backports upstream 1f7b24900 (Wilmer Paulino, "Support async fetching of commitment point during channel reestablish") to zeus-0.2.6, plus one ZEUS change for remote signers.

Base: zeus-0.2.6 (new): upstream v0.2.6 with the five Zeus patches from zeus-0.2 cherry-picked unchanged (LSPS7 client, coop-close feerate floor, route-hints override + its test, LSPS5 test fix). zeus-0.2 is untouched, so ZEUS mobile's pin keeps working; it can move to zeus-0.2.6 when ready. On zeus-0.2.6 alone: cargo test -p lightning --lib 1211 passed, -p lightning-liquidity all passed.

Why

With a remote signer (VLS in lnrod), channel_reestablish asked the signer for the point matching the peer's your_last_per_commitment_secret and .expect()ed it ("TODO: async signing is not yet supported…"). When vlsd was behind LDK after an enclave restart, the refusal panicked lnrod on every reconnect: the 2026-09-23 acme incident (54 crash-loops) and the last abort path left open by zeus-vls lightningdevkit#246/lightningdevkit#248.

Commits

  1. Backport of 1f7b24900 (clean cherry-pick). HolderCommitmentPoint caches the last two revoked points (persisted as TLVs 71/73, same numbers as upstream 0.3), so a reestablish from a peer at our state or one behind is verified without the signer. Only a peer claiming a state ahead of ours asks the signer; if it cannot answer, the peer is disconnected with a warning and the check finishes in signer_unblocked (stale-state panic if proven, force close if the secret is bogus, as upstream). Adaptation: one test call gains 0.2's is_check_discard_funding argument.
  2. ZEUS: uncached points are non-fatal. For a channel persisted before the cache existed, upstream derives both points from the signer while reading the ChannelManager and expects them. With VLS, a signer that lost or has not restored the channel refuses, which would abort every node restart. This leaves the point unset instead; at reestablish an uncached point is fetched from the signer and a refusal disconnects with a warning (no close, no panic). The next ChannelManager read retries the derivation until a write persists the points.

Effect on in-memory signers (ZEUS mobile)

None beyond upstream's: get_per_commitment_point never fails there, so the ZEUS fallback is never taken. The new TLVs are odd, so older readers ignore them, and they match upstream 0.3's.

Tests

  • cargo test -p lightning --lib: 1215 passed, 0 failed (on zeus-0.2.6 + these two commits).
  • New: test_reestablish_needs_no_signer_point_when_cached (signer refusing every point, reconnect succeeds, payments continue) and test_reestablish_disconnects_when_uncached_point_is_refused (cache cleared + signer refusing: warning + disconnect, channel stays open, reconnect succeeds after the signer answers; panics with upstream's expect restored).
  • Upstream's test_async_panic_on_stale_state and test_async_force_close_on_invalid_secret_for_stale_state pass.

Consumer: ZeusLN/zeus-vls#251 pins this branch's head (1b22c622). Please merge with a merge commit or fast-forward, not squash, so that rev stays on zeus-0.2.6.

wpaulino and others added 2 commits September 24, 2026 18:37
`HolderCommitmentPoint` currently tracks the current and next point used
on counterparty commitments, which are unrevoked. When we reestablish a
channel, the counterparty sends us the commitment height, along with the
corresponding secret, for the state they believe to be the latest. We
compare said secret to the derived point we fetch from the signer to
know if the peer is being honest.

Since the protocol does not allow peers (assuming no data loss) to be
behind the current state by more than one update, we can cache the two
latest revoked commitment points alongside `HolderCommitmentPoint`, such
that we no longer need to reach the signer asynchronously when handling
`channel_reestablish` messages throughout the happy path. By doing so,
we avoid complexity in needing to pause the state machine (which may
also result in needing to stash any update messages from the
counterparty) while the signer response is pending.

The only remaining case left to handle is when the counterparty presents
a `channel_reestablish` with a state later than what we know. This can
only result in two terminal cases: either they provided a valid
commitment secret proving we are behind and we need to panic, or they
lied and we force close the channel. This is the only case we choose to
handle asynchronously as it's relatively trivial to handle.

[ZEUS backport to 0.2: check_closed_event takes is_check_discard_funding
in the async_signer_tests case.]

(cherry picked from commit 1f7b249)
The backported reestablish fix derives the two cached revoked points
from the signer when reading a channel persisted before the cache
existed, and expects the result. With VLS, a signer that lost or has
not restored the channel refuses, which would abort every node restart
while reading the ChannelManager. Leave the point unset instead; at
channel_reestablish, ask the signer for an uncached point and
disconnect with a warning if it cannot answer, so the peer retries.
The channel stays open, and the next ChannelManager read tries the
derivation again until a write persists the points.

Tests: reestablish needs no signer call when the points are cached;
with the cache cleared and the signer refusing, reestablish
disconnects without panicking or closing, and a later reconnect
succeeds.
@kaloudis
kaloudis force-pushed the zeus-0.2-async-reestablish-point branch from 051b916 to 1b22c62 Compare September 24, 2026 22:38
@kaloudis
kaloudis changed the base branch from zeus-0.2 to zeus-0.2.6 September 24, 2026 22:38
@kaloudis kaloudis changed the title Backport async reestablish point (upstream 1f7b24900) + keep uncached points non-fatal Backport async reestablish point (upstream 1f7b24900) + keep uncached points non-fatal (on zeus-0.2.6) Sep 24, 2026
@kaloudis
kaloudis merged commit 5d31560 into zeus-0.2.6 Sep 24, 2026
16 of 43 checks passed
@kaloudis
kaloudis deleted the zeus-0.2-async-reestablish-point branch September 24, 2026 22:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants