Skip to content

htlcswitch+lnwallet: log signer-side commit tx on invalid commit sig#10740

Open
ziggie1984 wants to merge 1 commit intolightningnetwork:masterfrom
ziggie1984:improve/log-signed-commit-tx
Open

htlcswitch+lnwallet: log signer-side commit tx on invalid commit sig#10740
ziggie1984 wants to merge 1 commit intolightningnetwork:masterfrom
ziggie1984:improve/log-signed-commit-tx

Conversation

@ziggie1984
Copy link
Copy Markdown
Collaborator

@ziggie1984 ziggie1984 commented Apr 16, 2026

Problem

When a peer rejects our CommitSig with an Error message, the
InvalidCommitSigError it sends back contains the commitment
transaction the peer built on their side (logged via the existing error
handling). We never logged the commitment transaction we signed,
making it impossible to determine whether the failure was caused by a
state divergence (the two peers derived different transactions) or a
genuine signing bug.

This gap was observed in a CI failure on
#10628
(run:
the zero_conf-channel_policy_update_public_zero_conf itest got stuck
with a payment IN_FLIGHT due to an InvalidCommitSigError at
commit_height=5 on Carol's side. Carol's commit_tx was visible in
the error log, but Dave's was not, leaving the root cause unresolvable.

Solution

Add BuildLastSignedRemoteCommitTx to LightningChannel. The method
re-derives the commitment transaction most recently signed for the
remote party by mirroring the exact index snapshot used in
SignNextCommitment. It must be called before a subsequent
RevokeAndAck from the remote rotates RemoteNextRevocation to a new
commitment point (which is guaranteed on the error path since the peer
sends Error instead of RevokeAndAck).

processRemoteError in the htlcswitch now calls this method and logs
the result alongside the peer's error. Comparing the two commit_tx
fields immediately reveals any state divergence without requiring a
live debugger or a second reproduction of the failure.

Identifying divergence from logs

With this change, a future failure would log:

# Carol's side (existing):
invalid_commit_sig commit_tx=<carol_tx> sig_hash=<h> ...

# Dave's side (new):
signer-side commit_tx=<dave_tx> (compare with commit_tx in the peer error above ...)

If <carol_tx> != <dave_tx> the two peers derived different
transactions from the same state — that is the root cause. If they
match, the signature itself is broken and the sighash / signing path
needs investigation.

@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 improved diagnostic capabilities for identifying state divergence between peers in the Lightning Network. By enabling the logging of the locally signed commitment transaction during an error event, developers can now compare it against the peer's reported transaction to pinpoint whether a failure stems from a state mismatch or a signing error.

Highlights

  • Diagnostic Logging: Added a new method to re-derive the last signed remote commitment transaction, allowing for easier debugging of state divergence issues.
  • Error Handling: Updated the remote error processing logic to log the locally derived commitment transaction when a peer rejects a commitment signature.

🧠 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.

@github-actions github-actions bot added the severity-critical Requires expert review - security/consensus critical label Apr 16, 2026
@github-actions
Copy link
Copy Markdown

🔴 PR Severity: CRITICAL

Automated classification | 2 files | 74 lines changed

🔴 Critical (2 files)
  • htlcswitch/link.go - htlcswitch/* package: HTLC forwarding and payment routing state machine
  • lnwallet/channel.go - lnwallet/* package: Wallet operations, channel funding, signing, commitment transactions

Analysis

Both changed files fall squarely in CRITICAL packages:

  • htlcswitch/link.go is part of the HTLC switch, which manages the core payment forwarding state machine. Any changes here directly affect how payments are routed and could impact fund safety.
  • lnwallet/channel.go is part of the wallet channel management, handling commitment transactions, signing, and channel state. Changes here are among the most sensitive in the entire codebase.

Additionally, this PR touches two distinct critical packages (htlcswitch and lnwallet), which further reinforces the CRITICAL classification. Expert review is required before merging.


To override, add a severity-override-{critical,high,medium,low} label.
<!-- pr-severity-bot -->

@ziggie1984 ziggie1984 added severity-override-low Manual override to low labels Apr 16, 2026
@ziggie1984 ziggie1984 self-assigned this Apr 16, 2026
@ziggie1984 ziggie1984 force-pushed the improve/log-signed-commit-tx branch from c044523 to 058ae08 Compare April 16, 2026 20:01
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 introduces a diagnostic method, BuildLastSignedRemoteCommitTx, to re-derive and log the last signed remote commitment transaction when a peer error occurs. This is intended to help identify state divergence. However, the current implementation re-derives the transaction from the update logs, which is redundant and susceptible to race conditions if the log index advances before the method is called. It is recommended to instead retrieve the transaction directly from the tail of the remote commitment chain, which already stores the exact transaction that was signed.

Comment thread lnwallet/channel.go
When a peer rejects our CommitSig with an Error message, the
InvalidCommitSigError it sends back contains the commitment transaction
the peer built on their side. We never logged the commitment transaction
we signed, making it impossible to determine whether the failure was
caused by a state divergence (the two peers derived different
transactions) or a genuine signing bug.
@ziggie1984 ziggie1984 force-pushed the improve/log-signed-commit-tx branch from 058ae08 to 6103db9 Compare April 17, 2026 06:17
@github-actions github-actions bot added severity-low Best-effort review and removed severity-critical Requires expert review - security/consensus critical labels Apr 17, 2026
@github-actions
Copy link
Copy Markdown

⚠️ Severity changed: CRITICALLOW (files changed since last classification)

🟢 PR Severity: LOW

Override applied | severity-override-low label detected

Analysis

A severity-override-low label is present on this PR, which takes precedence over the automatically determined severity. The previous automated classification was CRITICAL, but a maintainer has explicitly overridden this to LOW.

The override is respected as-is — no file-level classification is performed when an override label exists.


To change the override, replace the severity-override-low label with severity-override-{critical,high,medium,low} or remove it to allow automatic classification.
<!-- pr-severity-bot -->

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

Labels

no-changelog severity-low Best-effort review severity-override-low Manual override to low

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant