Skip to content

recovery: L402 and static address recovery from local backup file#1121

Open
hieblmi wants to merge 10 commits into
lightninglabs:masterfrom
hieblmi:recover-l402-static
Open

recovery: L402 and static address recovery from local backup file#1121
hieblmi wants to merge 10 commits into
lightninglabs:masterfrom
hieblmi:recover-l402-static

Conversation

@hieblmi

@hieblmi hieblmi commented Apr 14, 2026

Copy link
Copy Markdown
Collaborator

only last commit is relevant for this PR, the rest is rebased on the dyn-conf-tracker PR

Adds encrypted local recovery for static-address/L402 state.

The recovery backup is written once per paid L402 generation and contains the paid l402.token, Bitcoin network, L402 token metadata, the L402-bound static-address server key, protocol/expiry, main/change key families, first address height, and the V0 client pubkey needed to recreate the current concrete static-address row.

On fresh installs, Loop restores the latest valid backup before creating a new paid L402 generation. Existing installs backfill the immutable backup for their active generation. loop recover restores a specific backup file, or the latest valid backup in the active network directory when no file is provided.

The backup intentionally does not store mutable address cursors, per-address rows, server xpubs, pkScript, Taproot address strings, deposit FSM state, or scan gap/lookahead policy. These values are either derivable or recovered through wallet/chain scanning and reconciliation.

@hieblmi hieblmi marked this pull request as draft April 14, 2026 10:09
@gemini-code-assist

Copy link
Copy Markdown

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the resilience of Loop by introducing a robust local recovery system. It allows users to restore their static address and L402 client state from an encrypted backup, ensuring continuity of operations even after data loss or a fresh installation. The changes include automated backup creation on startup, a new CLI command for restoration, and a dedicated recovery service that handles encryption, key derivation, and integration with existing static address and deposit management functionalities.

Highlights

  • Local Recovery for Static Address and L402 State: Introduced a phase-1 local recovery mechanism for Loop's static address and L402 client state, allowing restoration from an encrypted backup file.
  • Automated Backup Creation: Implemented automatic creation of an encrypted backup file in the active Loop data directory when loopd starts and finds existing static address or L402 token state.
  • New Recovery Package and CLI Command: Added a dedicated recovery package to orchestrate backup/restore operations, handle file formats and encryption, and introduced a loop recover CLI command for manual restoration.
  • Integrated Restoration Process: Enabled the static-address manager to support restoration by reusing existing address import logic and integrated a deposit-manager reconciliation entrypoint for best-effort deposit discovery after state import.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a local recovery mechanism for Loop static addresses and L402 authentication state. It includes a new recovery package for managing encrypted backups, a recover CLI command, and a gRPC service to trigger the restoration process. On the daemon side, backups are automatically generated during startup. Feedback suggests that backup failures during startup should not prevent the daemon from running and recommends enhancing the atomic file writing logic with explicit synchronization and better temporary file cleanup.

Comment thread loopd/daemon.go Outdated
Comment thread recovery/service.go Outdated
@hieblmi hieblmi force-pushed the recover-l402-static branch 3 times, most recently from a2e5f02 to 83e2547 Compare April 14, 2026 14:53
@hieblmi hieblmi force-pushed the recover-l402-static branch 8 times, most recently from 5790124 to dddf020 Compare April 20, 2026 10:11
@hieblmi hieblmi force-pushed the recover-l402-static branch from dddf020 to 5dfa10c Compare April 30, 2026 12:07
@hieblmi hieblmi marked this pull request as ready for review April 30, 2026 12:10
@hieblmi hieblmi force-pushed the recover-l402-static branch 13 times, most recently from d71f3a2 to 405e610 Compare May 11, 2026 09:34
@hieblmi hieblmi force-pushed the recover-l402-static branch 10 times, most recently from afff0cc to eff46ef Compare May 15, 2026 14:55
@hieblmi hieblmi force-pushed the recover-l402-static branch from eff46ef to 239b90a Compare May 26, 2026 12:33
@hieblmi hieblmi force-pushed the recover-l402-static branch 3 times, most recently from b018815 to d3096f6 Compare June 23, 2026 14:46
hieblmi added 10 commits June 25, 2026 10:47
Derive confirmation heights from a stable wallet view, retain unconfirmed static-address deposits, mark vanished deposits as replaced after repeated misses, and replay the startup block to recovered deposit FSMs so expiry handling is not missed after restart.
Return static-address UTXOs only once they have active deposit records, report unconfirmed value separately, and reject unconfirmed deposits from withdrawal and channel-open paths that still require confirmed inputs.
Allow static loop-ins to select unconfirmed deposits, persist the original selected outpoints, validate that those outpoints are still available before HTLC signing, and align autoloop expiry ordering with static loop-in selection.
Subscribe to static loop-in confirmation-risk notifications, start the payment deadline only after server acceptance or legacy confirmation fallback, refresh selected deposits before the legacy fallback so recovered monitors use current confirmation heights, and cancel the swap invoice when the server rejects the risk wait.
Record server confirmation-risk decisions durably, wire notification persistence through loopd, recover payment-deadline timers after restart, and keep notification fanout cache state deduplicated by swap hash.
Low-confirmation static deposits can be accepted by the server only after
asynchronous confirmation-risk policy permits them, so a CLI user may see a
delay after confirming the swap. The warning must also reflect the deposits
selected by automatic coin selection, not just manually provided outpoints.

Add a static loop-in warning for selected deposits below the conservative
six-confirmation threshold, mirror automatic selection for warning output, and
cover manual and auto-selected warning cases in CLI tests.
Static loop-in replay sessions changed once low-confirmation warnings and payment-timeout prompts were added. The fixtures need to reflect the new CLI interaction sequence.

Add replay fixtures for static loop-in warning prompts, and refresh payment-timeout and fee replay variants.
@hieblmi hieblmi force-pushed the recover-l402-static branch from d3096f6 to 2d70936 Compare June 25, 2026 13:23
@lightninglabs-deploy

Copy link
Copy Markdown

@hieblmi, remember to re-request review from reviewers when ready

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants