Skip to content

instantout: harden instant out error handling#1143

Closed
hieblmi wants to merge 4 commits into
lightninglabs:masterfrom
hieblmi:codex/instantout-review-fixes
Closed

instantout: harden instant out error handling#1143
hieblmi wants to merge 4 commits into
lightninglabs:masterfrom
hieblmi:codex/instantout-review-fixes

Conversation

@hieblmi
Copy link
Copy Markdown
Collaborator

@hieblmi hieblmi commented May 20, 2026

Summary

This PR applies small hardening fixes for the instant out implementation:

  • validate peer MuSig nonce/signature slice lengths before indexing
  • store active swaps under the real swap hash after initialization
  • treat closed payment streams and nil payment errors as failures
  • use fresh timeout contexts for reservation unlock and server cancel cleanup

Why

The previous logic could panic on malformed peer MuSig data, keep active swaps under the zero hash, return nil for failed payment stream paths, or skip cleanup when the caller context was already canceled.

Validation

  • go test ./instantout/...

hieblmi added 4 commits May 20, 2026 21:42
The instant out client indexes peer nonces and signatures by reservation index while signing and finalizing MuSig transactions. A server response with too few peer values can panic loopd before an error is returned. Validate the peer-provided slice counts against the reservation inputs before indexing them.
New instant outs were added to the active swap map before the start action generated the swap preimage and hash. That stores the FSM under the zero hash, so later lookups by the real hash fail and concurrent swaps can overwrite the same zero-hash entry. Insert the active FSM only after initialization reaches the expected state and the real hash is available.
The payment polling action read from the payment status and error channels without checking whether they were closed. A closed error channel yielded a nil error, and context cancellation also passed nil into HandleError, allowing the observer's abort-on-error path to return nil for a failed swap. Convert closed channels, nil channel errors, and cancellation into explicit errors before failing the FSM.
The error cleanup path derived unlock and cancel contexts from the caller context. When the caller context was already canceled, cleanup could fail immediately; the async server cancel also captured a context that was canceled by the parent function's defer. Use independent timeout contexts for local reservation unlocks and the server cancel RPC.
@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 introduces several hardening fixes to the instant out implementation. The changes focus on improving the robustness of the finite state machine (FSM) by addressing edge cases in error handling, validating critical data structures before indexing, and ensuring that resource cleanup tasks are not prematurely aborted by canceled contexts.

Highlights

  • Error Handling Improvements: Enhanced error handling in the FSM by validating channel states and ensuring proper cleanup when payment streams close or return nil errors.
  • MuSig2 Validation: Added length validation for MuSig2 sessions, nonces, and signatures to prevent potential panics during transaction processing.
  • Context Management: Switched to background contexts for reservation unlocking and swap cancellation to ensure cleanup operations complete even if the caller context is canceled.
  • State Management: Updated the manager to register active swaps only after successful initialization, ensuring they are tracked under the correct swap hash.
New Features

🧠 You can now enable Memory (public preview) 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 the 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 counterproductive. 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.

@hieblmi hieblmi changed the title [codex] harden instant out error handling instantout: harden instant out error handling May 20, 2026
Copy link
Copy Markdown

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

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 enhances the robustness of the instantout package by adding channel closure checks, validating MuSig2 session and signature lengths, and refactoring mutex locking in the manager. It also ensures that cleanup operations like unlocking reservations use a fresh background context to avoid failures when the parent context is canceled. Review feedback suggested renaming a shadowed context variable in a goroutine to improve code clarity and maintain consistency with other parts of the file.

Comment thread instantout/actions.go
Comment on lines +655 to 660
ctx, cancel := context.WithTimeout(
context.Background(), time.Second*30,
)
defer cancel()
_, cancelErr := f.cfg.InstantOutClient.CancelInstantSwap(
ctx, &swapserverrpc.CancelInstantSwapRequest{
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

For consistency with the context handling for UnlockReservation a few lines above (which uses unlockCtx), it would be clearer to use a distinct name for this new context instead of shadowing the parent function's ctx variable. This improves readability and reduces the chance of accidentally using the outer, possibly canceled, context in the future.

Suggested change
ctx, cancel := context.WithTimeout(
context.Background(), time.Second*30,
)
defer cancel()
_, cancelErr := f.cfg.InstantOutClient.CancelInstantSwap(
ctx, &swapserverrpc.CancelInstantSwapRequest{
cancelCtx, cancel := context.WithTimeout(
context.Background(), time.Second*30,
)
defer cancel()
_, cancelErr := f.cfg.InstantOutClient.CancelInstantSwap(
cancelCtx, &swapserverrpc.CancelInstantSwapRequest{

@hieblmi
Copy link
Copy Markdown
Collaborator Author

hieblmi commented May 20, 2026

Superseded by #1144.

@hieblmi hieblmi closed this May 20, 2026
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.

1 participant