The channel-restriction rule was previously fragile because it failed to
initialize when a restricted channel was closed while the session was
inactive. This often caused unnecessary session invalidation and blocked
users from managing their nodes.
This change makes the rule resilient by allowing it to start even if
some channels in the deny-list are missing from the node's current
active set. To maintain high performance, this implements a negative
cache that tracks unknown channel IDs, shielding LND from redundant RPC
calls during request evaluation.
Only having a negative cache without invalidation can be a security
problem. Someone could apply a rule with a future guessed channel id
such that the channel restriction populates the checkedIDs map with it.
After the channel was opened, we'd then allow making actions on the
channel because we don't know about the channel's id in the getChannelID
check.
To ensure security isn't compromised by the cache, this adds a
self-healing retry mechanism. If the firewall encounters an unknown
channel outpoint while it still has unmapped restricted IDs, it clears
the negative cache and forces a single retry in the next RPC call. This
ensures that any newly opened restricted channels are correctly
identified and blocked without adding latency to the common path.
Note: This approach deliberately accepts potential cache thrashing in the
edge case where a user repeatedly requests an unknown channel point
while a permanently missing ID exists in the deny list. This trade-off
is accepted to prioritize security (fail close) over performance in this
specific invalid state.
When a PR originates from a fork, the PR branch doesn't exist in the
origin remote. This adds a step that uses `gh pr checkout` before
running the Claude action, which properly handles fork PRs by adding
the fork as a remote and fetching the branch from there.
From other repos, we have seen that it can get quite spammy. So removing
for now. Users can instead comment `@claude review this` once the PR is
ready for review.
Prior to this commit, logs were not correctly uploaded on failure as the
logs were being written under itest/.logs, but the workflow zipped only
itest/ **/*.log. Because .logs is a hidden directory, the glob doesn’t
match it, so 7z creates an empty archive.
We also move the logs to a non-hidden directory when being uploaded to
avoid that the logs are downloaded as a hidden directory.
Add --match 'v*' to the VERSION_TAG git describe command to exclude
non-version tags like perms/*, litrpc/*, and autopilotserverrpc/*. These
tags contain forward slashes which cause the release script to fail when
constructing output filenames.
Adds a separate 'build-itest' job that builds the itest binaries prior
to the actual itest jobs being kicked off. With this change we'll
rebuild the itest binaries at most once, instead of at most four times.
The setup-go@v5 action caches GOMODCACHE and GOCACHE by default when
there's a go.sum file present. The cache is immutable, and keys have the
form:
setup-go-{os}-{arch}-{os-version}-go-{version}-{hash}
where 'hash' comes from go.sum. These keys don't take build tags into
account, and whichever job finishes first writes to the cache.
Consider the 'main' workflow, in which a bunch of jobs are kicked off to
run concurrently. A job like 'lint', which runs quickly, gets privileges
to write to the cache, but an issue is that its artifacts are built with
different tags than are e.g. the itest jobs. Thus, when an itest job
later gets a cache hit, the cached entry doesn't actually contain the Go
archive files that the itest needs.
The changes introduced in this commit use the existing 'key-prefix'
argument to avoid this problem. Setting 'key-prefix' bypasses the
default setup-go cache, using a separate cache with keys that depend
on the supplied prefix.
The full keys in this case are:
{key_prefix}-go-{os}-{arch}-{go-version}-{hash}
For the itest jobs, key-prefix is simply set to 'itest', so itest
artifacts will be cached with keys prefixed by 'itest' that won't be
preempted with irrelevant entries from faster-running jobs like 'lint'.
The -test.run pattern was missing the tranche prefix, so terminal and
custom_channels tests weren't actually running. The fix simply grafts
the pattern used in taproot-assets to ensure the tests are run.
Here we fix a nil pointer panic that is caused by an 'err' var being
deferenced before first checking that it is not nil. This was caused by
an oversite in a refactor commit that was attempting to improve line
length.
The mock oracle uses a self-signed certificate for TLS, but we're not
concerned with having tapd verify it in the itest environment. This
commit adds the 'experimental.rfq.priceoracletlsinsecure' flag added in
lightninglabs/taproot-assets#1775 to the litd args list, instructing
tapd not to verify certificates.
- Replace occurrences of `// nolint:lll` with `// nolint:ll` across
files for consistency.
- Reformat multiline strings, comments, and function parameters to
improve clarity and adhere to style guidelines.
- Add `// nolint:ll` comments where necessary to prevent linter
warnings.
- Replace the default `lll` with a custom `ll` linter, enabling
configurable exclusions for specific `S` log lines.
- Integrate custom `ll` linter into the build system and `Makefile`.
- Include relevant test cases and configuration for `golangci-lint`.
- add tranche splitting/shuffling flags to the itest harness
- add itest-parallel target and scripts to run tranches concurrently
- write per-tranche logs under .logs/trancheN and tail failures for
clarity
Move the LiT/LND compatibility matrix into docs/compatibility.md for
archival so future releases no longer require README updates to adjust
the table.
Update README to direct users to release notes for minimum lnd versions
and fall back to the archived table when not specified.