Add integration test to verify that fundMax uses the protocol-level
maximum channel size instead of the user-configured maxChanSize. The
test uses a table-driven approach to cover both non-wumbo and wumbo
scenarios, creating nodes with restrictive maxChanSize (5M sats) and
verifying that fundMax still creates channels at the protocol maximum.
The maxChanSize config option is documented to only apply to incoming
channel requests. However, when using fundMax with OpenChannel, the code
was incorrectly using maxChanSize as the upper bound for the outgoing
channel size.
This commit fixes the issue by using the protocol-level maximum
(MaxBtcFundingAmount or MaxBtcFundingAmountWumbo depending on wumbo
support) as the upper bound for fundMax operations.
Fixes#10468.
In this commit, we extend the panic recovery mechanism to cover the
serial processing path for AnnounceSignatures1 messages. Unlike other
gossip messages which are processed in parallel goroutines, announcement
signatures are processed serially in the main networkHandler loop.
A panic during this serial processing would previously crash the entire
gossiper. This change wraps the processing in an anonymous function with
a deferred panic recovery, ensuring resilience without changing the
serial processing semantics.
Since AnnounceSignatures bypass the validation barrier, we pass nil for
the jobID parameter.
In this commit, we add a centralized panic recovery mechanism for gossip
goroutines. This increases the robustness of message processing in the
gossiper, as now we are able to keep on trucking in the face of logic
errors that may lead to panics.
We ensure that any deps are freed and we log the panic trace to help
catch bugs in the future.
In this commit, we add validation for channel updates and node
announcements to ensure that we reject gossip messages with zero
timestamps at the discovery layer.
From BOLT 7:
"MUST set timestamp to greater than 0, AND to greater than any
previously-sent channel_update for this short_channel_id."
This validation is performed in the gossip handlers (handleNodeAnnouncement
and handleChanUpdate) rather than at the wire protocol level. This approach
ensures we can still decode messages from disk or embedded in onion errors
while rejecting invalid gossip from peers.
Remote peers sending zero-timestamp gossip will have their ban score
incremented.
In the previous iteration with endorsement
signaling, the recommendation was for the sender to
set it to 1 and that could have had privacy concerns
when first deploying given that the default was to
downgrade the signal to 0. In the latest proposal
the recommended default for both sending and
forwarding nodes is to set `accountable` to 0.
As a result, the dates have been removed given
that there are no privacy risks associated
with relaying the signal with zero values.
This commit fixes a critical race condition in MarkChanFullyClosed and
pruneLinkNode where link nodes could be incorrectly deleted despite
having pending or open channels.
The race occurred because the check for open channels and the link node
deletion happened in separate database transactions:
Thread A: TX1 checks open channels → [] (empty)
Thread A: TX1 commits
Thread B: Opens new channel with same peer
Thread A: TX2 deletes link node (using stale data)
Result: Link node deleted despite pending channel existing
This creates a TOCTOU (time-of-check to time-of-use) vulnerability where
database state changes between reading the channel count and deleting
the node.
Fix for MarkChanFullyClosed:
- Move link node deletion into the same transaction as the channel
closing check, making the check-and-delete operation atomic
Fix for pruneLinkNode:
- Add double-check within the write transaction to verify no channels
were opened since the caller's initial check
- Maintains performance by keeping early return for common case
- Prevents deletion if channels exist at delete time
This ensures the invariant: "link node exists iff channels exist"
is never violated, preventing database corruption and potential
connection issues.
For a Result[T], FlatMap should apply f when the result is Ok, and
propagate the error unchanged when it's Err. The original code returns r
on Ok and tries to use r.left when Err, which is wrong. This commit
fixes that.
Secondly, the group of FlatMap/AndThen and OrElse functions and methods
are now properly tested with new unit tests.
fixes#10401
This commit improves TLV decoding safety and consistency across multiple
packages by enforcing fixed-length requirements and adding unit tests to
prevent malformed TLV records from being accepted.
Changes include:
- lnwire:
* Enforce 8-byte length in Fee TLV decoder.
* Enforce PubNonceSize in Musig2Nonce TLV decoder.
* Enforce 8-byte length in ShortChannelID TLV decoder.
* Added roundtrip and invalid length tests for Fee, Musig2Nonce,
and ShortChannelID records.
- routing/route:
* Enforce Vertex TLV length (33 bytes).
* Added encode/decode and invalid length tests for Vertex.
- tlv:
* Enforce correct length in DBytes33 decoder (33 bytes).
* Added tests ensuring all fixed-size primitive decoders reject
incorrect TLV lengths.
By strictly validating TLV lengths, we prevent malformed or corrupted
TLV records from being silently accepted, improving protocol safety.
In this commit we updated the IsPublicV1Node query to use UNION
instead of OR, since sqlite struggles to efficiently use
multiple indexes in a single query involving OR conditions across
different columns.
We use UNION ALL since the query doesn't care about duplicates.
Fix bug where setSelfNode compared only the seconds component of
timestamps instead of the full timestamp. This caused the node to
attempt persisting an older timestamp than what existed in the
database during restart, resulting in "sql: no rows in result set"
errors.
CI started panicking in TestRbfChannelFlushingTransitions/early_offer /
TestRbfCloseClosingNegotiationRemote (see GitHub Actions run
https://github.com/lightningnetwork/lnd/actions/runs/19155841408/job/54756127218?pr=10352)
because the cached remote offer could fire before the test harness
registered its mock CloseSigner expectations. When that happened,
the mock complained that CreateCloseProposal was unexpected:
panic:
assert: mock: I don't know what to return because the method call was unexpected.
Fix this by having assertSingleRemoteRbfIteration take a sendEvent callback
that receives the context and initial offer, so tests can install expectations
first and then fire the event via SendEvent (or the early-offer test's custom
flush sender).
Reproduction (on master)
------------------------
1. Modify lnwallet/chancloser/rbf_coop_test.go
Add time.Sleep(10 * time.Millisecond) before the first call of
closeHarness.assertSingleRemoteRbfIteration (in function
TestRbfChannelFlushingTransitions).
2. go test ./lnwallet/chancloser -run TestRbfChannelFlushingTransitions/early_offer
3. The panic reproduces immediately.
-Due to a newer version we need to use add_labels instead of just
labels
-The backport PR will now also copy the milestones in case the
milstones were set
This commit adds detailed documentation for the automated backport
workflow and updates the contribution guidelines to reference it.
New documentation (docs/backport-workflow.md):
- Complete overview of the automated backport process
- Step-by-step usage instructions with examples
- Detailed explanation of workflow triggers and label format
- Technical details about workflow implementation
- Conflict resolution procedures and best practices
- Multiple backport scenarios and examples
- Comprehensive troubleshooting guide
Updated contribution guidelines (docs/code_contribution_guidelines.md):
- Replaced detailed backport instructions with brief overview
- Added reference to the new detailed documentation
- Keeps contribution guidelines focused and concise
The detailed documentation provides:
- How to use backport labels correctly
- What happens when labels are added before/after merge
- How the workflow validates branches and handles errors
- Step-by-step conflict resolution instructions
- Solutions for common problems and edge cases
- Examples of valid vs invalid label formats
This documentation ensures contributors and maintainers have clear
guidance on using the automated backport workflow effectively.
This commit introduces an automated GitHub Actions workflow to streamline
the backporting process for merged PRs from master to release branches.
Key features:
- Triggers on merged PRs with labels matching 'backport-v*' pattern
(e.g., backport-v0.20.x-branch)
- Validates that target branches exist before attempting backport
- Creates separate backport PRs for each target branch
- Automatically adds 'no-changelog' label to backport PRs
- Handles merge conflicts by creating draft PRs with conflict markers
- Supports multiple simultaneous backports via multiple labels
Workflow steps:
1. Checkout repository with full git history
2. Validate all target branches exist in the remote repository
3. For each valid backport label:
- Create a new branch (backport-<pr-num>-to-<target-branch>)
- Cherry-pick commits from the master PR
- Create a new PR targeting the release branch
- Link back to the original PR
4. If conflicts occur, create a draft PR for manual resolution
Label format:
- Valid: backport-v0.20.x-branch, backport-v0.19.x-branch
- Invalid: backport candidate, backport-candidate, backport-needed
This automation reduces manual work and ensures consistency in the
backporting process while maintaining full visibility and control
for maintainers.