Skip to content

Add support for debug comparing mismatching blocks when verification fails#8535

Open
turbolent wants to merge 3 commits into
masterfrom
bastian/compare-debug-tx-on-verification-mismatch
Open

Add support for debug comparing mismatching blocks when verification fails#8535
turbolent wants to merge 3 commits into
masterfrom
bastian/compare-debug-tx-on-verification-mismatch

Conversation

@turbolent

@turbolent turbolent commented Apr 8, 2026

Copy link
Copy Markdown
Member

Depends on #8534

When chunk verification fails, optionally allow running the remote-debugger based comparison for the blocks to automatically get further information (e.g. read/written registers, events, traces, etc.) which helps with figuring out why the chunk did not match – the current error only states there is a mismatch in the final state commitment hash or events hash

Summary by CodeRabbit

  • New Features

    • Added support for comparing transactions across multiple specified blocks.
    • Added configurable branch, access, and parallel-processing options for comparison workflows.
    • Verification failures now identify mismatched blocks and can automatically launch cross-branch diagnostics.
  • Bug Fixes

    • Verification can continue to comparison diagnostics when mismatched blocks are detected, instead of stopping immediately.
  • Tests

    • Expanded verification coverage to confirm mismatched block details are reported correctly.

@turbolent
turbolent requested review from a team April 8, 2026 20:47
@turbolent
turbolent requested a review from a team as a code owner April 8, 2026 20:47
@coderabbitai

coderabbitai Bot commented Apr 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Changes

The verifier now reports mismatched block IDs. verify_execution_result uses those IDs to optionally invoke a refactored compare-debug-tx command, which supports multiple blocks, explicit configuration, and parallel execution.

Mismatch comparison workflow

Layer / File(s) Summary
Propagate mismatched block IDs
engine/verification/verifier/verifiers.go, engine/verification/verifier/verifiers_test.go
Verification statistics record and aggregate block IDs associated with mismatches, with coverage for stop-on-mismatch behavior.
Configure multi-block comparison
cmd/util/cmd/compare-debug-tx/cmd.go
A Config structure, --block-ids input, per-block execution, deterministic output aggregation, and configuration-based debug-tx arguments are added.
Trigger comparison from verification
cmd/util/cmd/verify_execution_result/cmd.go
Comparison flags are validated, mismatch failures can continue into comparison, and mismatched block IDs are passed to compare-debug-tx.Run.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant VerifyExecutionResult
  participant Verifier
  participant compare_debug_tx.Run
  participant debug-tx
  VerifyExecutionResult->>Verifier: verify blocks
  Verifier-->>VerifyExecutionResult: return mismatched block IDs
  VerifyExecutionResult->>compare_debug_tx.Run: pass comparison config and block IDs
  compare_debug_tx.Run->>debug-tx: execute per-block comparisons
  debug-tx-->>compare_debug_tx.Run: return results and traces
Loading

Possibly related PRs

  • onflow/flow-go#8512: Related changes to multi-block compare-debug-tx execution and diff output.
  • onflow/flow-go#8534: Related verification statistics changes consumed by execution-result verification.

Suggested reviewers: janezpodhostnik, zhangchiqing

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding debug comparison for mismatching blocks after verification failures.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch bastian/compare-debug-tx-on-verification-mismatch

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.

@turbolent

Copy link
Copy Markdown
Member Author

@zhangchiqing PTAL 🙏

Base automatically changed from bastian/verification-statistics to master May 12, 2026 14:39
@github-actions github-actions Bot added the Stale Label used when marking an issue stale. label Jul 12, 2026
@github-actions github-actions Bot closed this Jul 20, 2026
@turbolent turbolent reopened this Jul 20, 2026
@turbolent turbolent removed the Stale Label used when marking an issue stale. label Jul 20, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@codecov-commenter

codecov-commenter commented Jul 20, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 3.80952% with 101 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
cmd/util/cmd/compare-debug-tx/cmd.go 0.00% 64 Missing ⚠️
cmd/util/cmd/verify_execution_result/cmd.go 0.00% 37 Missing ⚠️

📢 Thoughts on this report? Let us know!

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cmd/util/cmd/compare-debug-tx/cmd.go`:
- Around line 203-213: Update the result and trace diff condition in Run to also
execute when cfg.BlockIDs is empty, covering the tx-only invocation handled by
runAllBlocks. Preserve the existing single-block behavior and continue using
result1, result2, trace1, and trace2 for the diff output.
- Around line 145-153: Update the conditional around resolveBlockChain in the
command argument handling to check whether --block-id was explicitly provided,
rather than whether flagBlockCount is greater than zero. Preserve validation
requiring --block-count with --block-id and allow the default positional
transaction-ID flow to leave cfg.BlockIDs empty for runAllBlocks.
🪄 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: 8711d7b3-c19f-49ba-ae91-a7a795f90248

📥 Commits

Reviewing files that changed from the base of the PR and between ad55d25 and 5b72d7f.

📒 Files selected for processing (4)
  • cmd/util/cmd/compare-debug-tx/cmd.go
  • cmd/util/cmd/verify_execution_result/cmd.go
  • engine/verification/verifier/verifiers.go
  • engine/verification/verifier/verifiers_test.go

Comment on lines +145 to 153
} else if flagBlockCount > 0 {
if flagBlockID == "" {
log.Fatal().Msg("--block-count requires --block-id to be set")
}
if len(args) > 0 {
log.Fatal().Msg("--block-count cannot be used with positional transaction IDs")
}
blockIDs = resolveBlockChain(flagBlockID, flagBlockCount)
cfg.BlockIDs = resolveBlockChain(flagAccessAddress, flagBlockID, flagBlockCount)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

Default invocation (no --block-id/--block-ids) always fatals.

flagBlockCount defaults to 1, so flagBlockCount > 0 is always true when --block-ids isn't set — even if the user never touched --block-id/--block-count at all. This means the plain/basic usage (compare-debug-tx txID1 txID2 --branch1 ... --branch2 ...) always hits log.Fatal().Msg("--block-count requires --block-id to be set"), even though runAllBlocks explicitly supports and expects this tx-only mode when cfg.BlockIDs is empty.

The gate should be on whether --block-id was actually set, not on the always-nonzero default count.

🐛 Proposed fix
-	} else if flagBlockCount > 0 {
-		if flagBlockID == "" {
-			log.Fatal().Msg("--block-count requires --block-id to be set")
-		}
+	} else if flagBlockID != "" {
 		if len(args) > 0 {
-			log.Fatal().Msg("--block-count cannot be used with positional transaction IDs")
+			log.Fatal().Msg("--block-id cannot be used with positional transaction IDs")
 		}
 		cfg.BlockIDs = resolveBlockChain(flagAccessAddress, flagBlockID, flagBlockCount)
+	} else if flagBlockCount > 1 {
+		log.Fatal().Msg("--block-count > 1 requires --block-id to be set")
 	}
📝 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
} else if flagBlockCount > 0 {
if flagBlockID == "" {
log.Fatal().Msg("--block-count requires --block-id to be set")
}
if len(args) > 0 {
log.Fatal().Msg("--block-count cannot be used with positional transaction IDs")
}
blockIDs = resolveBlockChain(flagBlockID, flagBlockCount)
cfg.BlockIDs = resolveBlockChain(flagAccessAddress, flagBlockID, flagBlockCount)
}
} else if flagBlockID != "" {
if len(args) > 0 {
log.Fatal().Msg("--block-id cannot be used with positional transaction IDs")
}
cfg.BlockIDs = resolveBlockChain(flagAccessAddress, flagBlockID, flagBlockCount)
} else if flagBlockCount > 1 {
log.Fatal().Msg("--block-count > 1 requires --block-id to be set")
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cmd/util/cmd/compare-debug-tx/cmd.go` around lines 145 - 153, Update the
conditional around resolveBlockChain in the command argument handling to check
whether --block-id was explicitly provided, rather than whether flagBlockCount
is greater than zero. Preserve validation requiring --block-count with
--block-id and allow the default positional transaction-ID flow to leave
cfg.BlockIDs empty for runAllBlocks.

Comment on lines +203 to +213
if len(cfg.BlockIDs) == 1 {
fmt.Printf("=== Result diff (%s vs %s) ===\n", cfg.Branch1, cfg.Branch2)
diffFiles(result1.Name(), result2.Name(), cfg.Branch1, cfg.Branch2)

if flagShowTraceDiff {
fmt.Printf("=== Trace diff (%s vs %s) ===\n", flagBranch1, flagBranch2)
diffFiles(trace1.Name(), trace2.Name(), flagBranch1, flagBranch2)
if cfg.ShowTraceDiff {
fmt.Printf("=== Trace diff (%s vs %s) ===\n", cfg.Branch1, cfg.Branch2)
diffFiles(trace1.Name(), trace2.Name(), cfg.Branch1, cfg.Branch2)
}
}

printMismatchStats(blockIDs, perBlock1, perBlock2)
printMismatchStats(cfg.BlockIDs, perBlock1, perBlock2)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Result/trace diff never prints for the default (no-block) invocation.

runAllBlocks treats len(cfg.BlockIDs) == 0 as a valid single-invocation mode driven by cfg.TxIDs (lines 240-245), but Run only prints the result/trace diff when len(cfg.BlockIDs) == 1. For the plain tx-only mode, cfg.BlockIDs is empty, so this core diff output — the tool's primary purpose — is silently skipped, even though result1/result2 were populated. Only printMismatchStats (which produces "0/0" summaries in this case) runs.

🐛 Proposed fix
-	if len(cfg.BlockIDs) == 1 {
+	if len(cfg.BlockIDs) <= 1 {
 		fmt.Printf("=== Result diff (%s vs %s) ===\n", cfg.Branch1, cfg.Branch2)
 		diffFiles(result1.Name(), result2.Name(), cfg.Branch1, cfg.Branch2)
📝 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
if len(cfg.BlockIDs) == 1 {
fmt.Printf("=== Result diff (%s vs %s) ===\n", cfg.Branch1, cfg.Branch2)
diffFiles(result1.Name(), result2.Name(), cfg.Branch1, cfg.Branch2)
if flagShowTraceDiff {
fmt.Printf("=== Trace diff (%s vs %s) ===\n", flagBranch1, flagBranch2)
diffFiles(trace1.Name(), trace2.Name(), flagBranch1, flagBranch2)
if cfg.ShowTraceDiff {
fmt.Printf("=== Trace diff (%s vs %s) ===\n", cfg.Branch1, cfg.Branch2)
diffFiles(trace1.Name(), trace2.Name(), cfg.Branch1, cfg.Branch2)
}
}
printMismatchStats(blockIDs, perBlock1, perBlock2)
printMismatchStats(cfg.BlockIDs, perBlock1, perBlock2)
if len(cfg.BlockIDs) <= 1 {
fmt.Printf("=== Result diff (%s vs %s) ===\n", cfg.Branch1, cfg.Branch2)
diffFiles(result1.Name(), result2.Name(), cfg.Branch1, cfg.Branch2)
if cfg.ShowTraceDiff {
fmt.Printf("=== Trace diff (%s vs %s) ===\n", cfg.Branch1, cfg.Branch2)
diffFiles(trace1.Name(), trace2.Name(), cfg.Branch1, cfg.Branch2)
}
}
printMismatchStats(cfg.BlockIDs, perBlock1, perBlock2)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cmd/util/cmd/compare-debug-tx/cmd.go` around lines 203 - 213, Update the
result and trace diff condition in Run to also execute when cfg.BlockIDs is
empty, covering the tx-only invocation handled by runAllBlocks. Preserve the
existing single-block behavior and continue using result1, result2, trace1, and
trace2 for the diff output.

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.

5 participants