Skip to content

fix(lighthouse): use depth tracking to avoid CPI false positives#180

Open
6figpsolseeker wants to merge 1 commit intodcccrypto:mainfrom
6figpsolseeker:fix/lighthouse-cpi-depth-tracking
Open

fix(lighthouse): use depth tracking to avoid CPI false positives#180
6figpsolseeker wants to merge 1 commit intodcccrypto:mainfrom
6figpsolseeker:fix/lighthouse-cpi-depth-tracking

Conversation

@6figpsolseeker
Copy link
Copy Markdown

@6figpsolseeker 6figpsolseeker commented Apr 9, 2026

Summary

isLighthouseFailureInLogs used a boolean insideLighthouse flag that was set on any Lighthouse invoke and only cleared on success. When Lighthouse CPIs into a sub-program (e.g. Pyth oracle) and that sub-program fails, the log contains "Program Pyth failed: ..." while insideLighthouse is still true. The old code matched /failed/i on that line and incorrectly returned true — even though Lighthouse itself may succeed on the very next line.

Example false-positive scenario:

Program L2TExMF... invoke [1]      ← insideLighthouse = true
Program Pyth invoke [2]            ← sub-invoke
Program Pyth failed: stale price   ← OLD: returns true (WRONG)
Program L2TExMF... success         ← Lighthouse actually succeeded

Changes

  • src/runtime/lighthouse.ts:159-191 — replaced boolean with lighthouseDepth counter. Only explicit "Program <LIGHTHOUSE_ID> failed" lines are now treated as failures. The generic "any failed line while inside Lighthouse" check is removed.

Test plan

  • npm run lint clean
  • npx vitest run test/lighthouse.test.ts — all 37 tests pass
  • Full vitest run: same 14 pre-existing failures, zero new failures
  • Recommended: add test case with CPI sub-program failure logs to prevent regression

Summary by CodeRabbit

  • Bug Fixes
    • Improved accuracy of Lighthouse failure detection to eliminate false positives from sub-program failures that occur during Lighthouse execution. The system now correctly distinguishes between actual Lighthouse failures and failures from other programs running within the same context.

isLighthouseFailureInLogs used a boolean insideLighthouse flag that was
set to true on any Lighthouse invoke and only cleared on success. When
Lighthouse CPIs into a sub-program (e.g. Pyth oracle) and that sub-
program fails, the log contains "Program Pyth failed: ..." while
insideLighthouse is still true. The old code matched /failed/i on that
line and incorrectly returned true — even though Lighthouse itself
may succeed on the very next log line.

This caused false Lighthouse failure classifications on transactions
where a CPI target errored but Lighthouse handled the error gracefully.

The fix replaces the boolean with a depth counter (lighthouseDepth).
Only explicit "Program <LIGHTHOUSE_ID> failed" lines are now treated
as Lighthouse failures. The generic "any failed line while inside
Lighthouse" check is removed because it cannot distinguish sub-program
failures from Lighthouse's own failures.

The depth counter also correctly handles nested re-entrant invocations
(unlikely but defensive).

All 37 existing lighthouse tests continue to pass — they test direct
Lighthouse failure lines (which still match) and non-Lighthouse logs
(which still don't match).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 9, 2026

📝 Walkthrough

Walkthrough

Modified isLighthouseFailureInLogs function to track Lighthouse program invocation depth using a counter instead of a boolean flag. The function increments depth on invoke log lines, decrements on success lines, and returns true only for explicit failed log lines, eliminating false positives from nested CPI sub-program failures.

Changes

Cohort / File(s) Summary
Lighthouse Failure Detection
src/runtime/lighthouse.ts
Replaced boolean "inside Lighthouse" flag with depth counter (lighthouseDepth) to track nested program invocations. Increments on invoke, decrements (clamped at 0) on success, and only flags explicit failed log lines, preventing false positives from CPI sub-program failures occurring during Lighthouse execution.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Poem

🐰 A depth counter hops where booleans once stood,
Tracking Lighthouse invokes through the program's good wood,
No false failures now from CPI's nested dance,
Just explicit failed gets the scrutiny glance! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(lighthouse): use depth tracking to avoid CPI false positives' directly and clearly describes the main change: replacing a boolean flag with depth tracking to fix false positives in CPI scenarios.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/runtime/lighthouse.ts (1)

162-173: Add a regression test for “sub-program failed, Lighthouse success”.

This exact log shape is the behavior this patch is protecting; a dedicated test case will prevent future regressions.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/runtime/lighthouse.ts` around lines 162 - 173, Add a regression test that
reproduces the log sequence where Lighthouse (module src/runtime/lighthouse.ts)
invokes a sub-program which fails (e.g., "Program Pyth failed: ...") but the
Lighthouse program later succeeds, to ensure lighthouseDepth tracking prevents
misattribution; write a test that simulates or mocks a Lighthouse invocation
calling a CPI sub-program, emits logs in the order shown in the comment, asserts
that the failure is attributed to the sub-program (not Lighthouse) and that
lighthouseDepth increments/decrements correctly (reference the lighthouseDepth
tracking logic and any helpers around insideLighthouse or log-attribute
functions), and include this test in the relevant test suite so future changes
to lighthouseDepth behavior will fail the test if regressed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/runtime/lighthouse.ts`:
- Around line 179-193: The current substring checks on lines containing
LIGHTHOUSE_PROGRAM_ID_STR produce false positives; instead update the logic in
the block that manipulates lighthouseDepth and returns on failure (the checks
using line.includes and the variable LIGHTHOUSE_PROGRAM_ID_STR) to only match
anchored runtime status lines like "Program <id> <status>" — e.g., first verify
the line starts with "Program " (or use a regex anchored at line start) then
parse the program id and status and only increment lighthouseDepth when id ===
LIGHTHOUSE_PROGRAM_ID_STR and status === "invoke", decrement when status ===
"success", and return true only when status === "failed". Ensure you modify the
three checks that currently use includes(...) so they only trigger on these
anchored matches.

---

Nitpick comments:
In `@src/runtime/lighthouse.ts`:
- Around line 162-173: Add a regression test that reproduces the log sequence
where Lighthouse (module src/runtime/lighthouse.ts) invokes a sub-program which
fails (e.g., "Program Pyth failed: ...") but the Lighthouse program later
succeeds, to ensure lighthouseDepth tracking prevents misattribution; write a
test that simulates or mocks a Lighthouse invocation calling a CPI sub-program,
emits logs in the order shown in the comment, asserts that the failure is
attributed to the sub-program (not Lighthouse) and that lighthouseDepth
increments/decrements correctly (reference the lighthouseDepth tracking logic
and any helpers around insideLighthouse or log-attribute functions), and include
this test in the relevant test suite so future changes to lighthouseDepth
behavior will fail the test if regressed.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b186e6c0-a4b4-473d-b35e-378b7e956c35

📥 Commits

Reviewing files that changed from the base of the PR and between 2f80d79 and f8699a3.

📒 Files selected for processing (1)
  • src/runtime/lighthouse.ts

Comment thread src/runtime/lighthouse.ts
Comment on lines +179 to 193
// Lighthouse invoke — increment depth
if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} invoke`)) {
insideLighthouse = true;
lighthouseDepth++;
continue;
}

// Lighthouse program returned success — reset
// Lighthouse success — decrement depth
if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} success`)) {
insideLighthouse = false;
lighthouseDepth = Math.max(0, lighthouseDepth - 1);
continue;
}

// Error while inside a Lighthouse invocation
if (insideLighthouse && /failed/i.test(line)) {
return true;
}

// Explicit Lighthouse failure log
// Explicit Lighthouse failure (the program ID is in the "failed" line)
if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} failed`)) {
return true;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Use anchored program-status matching instead of substring matching.

At Line 192 (and similarly Line 180 and Line 186), includes(...) can match "Program log: Program <LIGHTHOUSE_ID> failed" emitted by arbitrary programs, which reintroduces false positives. Match only runtime status lines (Program <id> ...) with anchored checks.

Proposed fix
-    if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} invoke`)) {
+    if (line.startsWith(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} invoke`)) {
       lighthouseDepth++;
       continue;
     }

-    if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} success`)) {
+    if (line.startsWith(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} success`)) {
       lighthouseDepth = Math.max(0, lighthouseDepth - 1);
       continue;
     }

-    if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} failed`)) {
+    if (line.startsWith(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} failed`)) {
       return true;
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Lighthouse invoke — increment depth
if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} invoke`)) {
insideLighthouse = true;
lighthouseDepth++;
continue;
}
// Lighthouse program returned success — reset
// Lighthouse success — decrement depth
if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} success`)) {
insideLighthouse = false;
lighthouseDepth = Math.max(0, lighthouseDepth - 1);
continue;
}
// Error while inside a Lighthouse invocation
if (insideLighthouse && /failed/i.test(line)) {
return true;
}
// Explicit Lighthouse failure log
// Explicit Lighthouse failure (the program ID is in the "failed" line)
if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} failed`)) {
return true;
// Lighthouse invoke — increment depth
if (line.startsWith(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} invoke`)) {
lighthouseDepth++;
continue;
}
// Lighthouse success — decrement depth
if (line.startsWith(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} success`)) {
lighthouseDepth = Math.max(0, lighthouseDepth - 1);
continue;
}
// Explicit Lighthouse failure (the program ID is in the "failed" line)
if (line.startsWith(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} failed`)) {
return true;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/runtime/lighthouse.ts` around lines 179 - 193, The current substring
checks on lines containing LIGHTHOUSE_PROGRAM_ID_STR produce false positives;
instead update the logic in the block that manipulates lighthouseDepth and
returns on failure (the checks using line.includes and the variable
LIGHTHOUSE_PROGRAM_ID_STR) to only match anchored runtime status lines like
"Program <id> <status>" — e.g., first verify the line starts with "Program " (or
use a regex anchored at line start) then parse the program id and status and
only increment lighthouseDepth when id === LIGHTHOUSE_PROGRAM_ID_STR and status
=== "invoke", decrement when status === "success", and return true only when
status === "failed". Ensure you modify the three checks that currently use
includes(...) so they only trigger on these anchored matches.

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