Skip to content

feat: Imporve Remove GER tool#1563

Merged
arnaubennassar merged 9 commits intodevelopfrom
feat/fix-removeger-tool-docs
Apr 16, 2026
Merged

feat: Imporve Remove GER tool#1563
arnaubennassar merged 9 commits intodevelopfrom
feat/fix-removeger-tool-docs

Conversation

@arnaubennassar
Copy link
Copy Markdown
Collaborator

@arnaubennassar arnaubennassar commented Mar 27, 2026

🔄 Changes Summary

  • Compared with develop, this PR expands the remove_ger tool in four areas:
    • adds a new scan-invalid-claims subcommand that scans L2 claim logs, reconstructs the GER used by each claim, validates that GER against L1, and reports invalid GERs that are still tied to active claims
    • hardens diagnose/recover so it can continue when the invalid GER was already removed from L2 but related claims are still active, filters out already-unset claims, and avoids trying to remove a GER that no longer exists
    • fixes generated cast send commands by properly quoting bytes32[32] proof arrays
    • updates the remove_ger README and the runbook to document the new scan flow and clarify the existing RemoveGER.L2NetworkID requirement for diagnose/recover

⚠️ Breaking Changes

None.

📋 Config Updates

None

✅ Testing

  • 🤖 Automatic: go test ./tools/remove_ger/...

🐞 Issues

  • No linked issue.

🔗 Related PRs

  • None.

📝 Notes

  • scan-invalid-claims supports both DetailedClaimEvent and legacy ClaimEvent logs. For legacy claim events, it reconstructs the GER from the transaction calldata before validating it on L1.
  • The scan and diagnose paths now only surface claims that are still active on L2, which prevents false positives from already-unset claims.
  • Recovery now fails early if the bridge is already in emergency state before attempting activateEmergencyState, instead of submitting a redundant transaction.

@claude
Copy link
Copy Markdown

claude bot commented Mar 27, 2026

Claude finished @arnaubennassar's task in 55s —— View job


Code Review Complete ✅

Tasks

  • View PR diff to understand changes
  • Read modified files for context
  • Review documentation updates
  • Review code changes
  • Provide feedback and summary

🚀 What's New

This PR adds documentation for the required L2NetworkID configuration field in the remove_ger tool. The field was previously undocumented despite being required for the diagnose/recover command. Additionally, it fixes a quote escaping issue in the generated cast commands for the testing scenario.

🐛 Bug Fixes

  • Fixed quote escaping in generated cast send commands for the claimAsset function call. The byte32 array parameters now properly wrap the array literal in quotes to prevent shell parsing issues (tools/remove_ger/generate.go:173-174).

📋 Config Updates

The [RemoveGER] section now documents the required L2NetworkID field:

[RemoveGER]
BridgeServiceURL = "http://localhost:8080"
L2NetworkID = 12  # New: required uint32 field for L2 network ID
SovereignAdminKey = { Method = "local", Path = "/path/to/keystore.json", Password = "pass" }

⚠️ Breaking Changes

None. This PR only adds documentation for an existing field and fixes a command generation bug.


Review Feedback

🟢 Overall Assessment

This is a clean documentation improvement with a minor bug fix. The changes are straightforward and improve usability of the remove_ger tool.

Changes Reviewed

✅ Documentation Updates (README.md)

Lines 29, 47, 71-74: Added L2NetworkID field documentation

Strengths:

  • Clear description of the field as "required for diagnose/recover"
  • Good example value (12) in the config snippet
  • Explicit clarification that both BridgeServiceURL and L2NetworkID are required for the default command
  • Properly notes the field is NOT required for the generate command (line 121 already stated this)

🟢 Optional Suggestion:
The documentation could mention what happens if the field is missing (does it fail with a validation error? default to 0?), but this is a minor enhancement.

✅ Code Fix (generate.go)

Lines 173-174: Fixed quote escaping for byte32 arrays in cast command generation

Before:

formatBytes32ArrayForCast(r.ProofLocal),
formatBytes32ArrayForCast(r.ProofRollup),

After:

"\""+formatBytes32ArrayForCast(r.ProofLocal)+"\"",
"\""+formatBytes32ArrayForCast(r.ProofRollup)+"\"",

Strengths:

  • Fixes a real bug where the generated cast send command would fail due to shell parsing issues with unquoted array literals
  • The fix ensures the arrays are properly quoted when interpolated into the command string
  • Consistent with how other string parameters are handled in the same command

🟢 Note:
This is the correct fix. Without the quotes, bash would interpret the square brackets and commas as special characters rather than part of a string argument.

Code Quality Assessment

Aspect Rating Notes
Correctness ✅ Excellent Both changes are correct and improve the tool
Documentation ✅ Excellent Clear, comprehensive documentation of the required field
Security ✅ No Issues No security implications
Performance ✅ No Impact Documentation and string formatting only
Testing ✅ Adequate The generate command can be manually tested; documentation changes don't need tests

Summary

No blocking issues found. The PR successfully:

  1. Documents a previously undocumented required configuration field
  2. Fixes a command generation bug that would cause the generated cast commands to fail
  3. Maintains consistency with the existing documentation style
  4. Properly clarifies when the field is and isn't required

Recommendation: Approve and merge

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR expands the tools/remove_ger utility beyond “diagnose & recover” by adding a new scan-invalid-claims subcommand to discover invalid GER usage directly from L2 logs, and updates the recovery/diagnosis flow and documentation to support additional scenarios (e.g., claims still active after GER removal).

Changes:

  • Add scan-invalid-claims command that scans L2 claim logs, derives GERs per claim, validates them on L1, and reports invalid GER usage aggregated by GER.
  • Refactor recovery/diagnosis to support “claims exist even if GER already removed,” including gating GER removal steps and filtering inactive/unset claims.
  • Update docs (README + runbook) and tests; introduce Env abstractions to improve testability (receipt waiting, L2 bridge interface).

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tools/remove_ger/scan.go Implements log-based scanning and invalid-GER aggregation logic; adds scan env setup + CLI action.
tools/remove_ger/scan_test.go Unit tests for calldata GER decode and invalid-GER usage aggregation.
tools/remove_ger/run.go Refactors Env (bridge interface + receipt waiting hook) and updates main execution gating.
tools/remove_ger/recovery.go Makes recovery conditional on required actions; adds emergency-state precheck; routes receipt waiting via Env.
tools/remove_ger/recovery_test.go Adds test coverage for new emergency-state precheck behavior.
tools/remove_ger/helpers.go Adds Env.waitReceipt(...) helper to enable test injection/fallback receipt waiting.
tools/remove_ger/generate.go Adjusts generated cast command formatting for bytes32[32] array arguments.
tools/remove_ger/diagnosis.go Adds recovery-action helpers, filters inactive claims, and improves recovery plan printing.
tools/remove_ger/diagnosis_test.go Adds tests for new recovery-action predicates, plan building, and claim filtering.
tools/remove_ger/cmd/main.go Wires in the new scan-invalid-claims CLI subcommand and flags.
tools/remove_ger/README.md Documents scan-invalid-claims usage and clarifies config requirements (incl. L2NetworkID).
docs/remove_ger_runbook.md Adds runbook section describing how to use the scan command for discovery.

Comment thread tools/remove_ger/scan.go
const defaultScanChunkSize uint64 = 5000

var (
scanClaimEventSignature = crypto.Keccak256Hash([]byte("ClaimEvent(uint256,uint32,address,address,uint256)"))
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

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

scan-invalid-claims currently filters only the Etrog ClaimEvent signature plus DetailedClaimEvent. This will miss pre-Etrog ClaimEvent logs (different signature: ClaimEvent(uint32,uint32,address,address,uint256)), which the codebase already handles elsewhere. Consider adding the pre-Etrog signature to the topic filter and adding parsing logic for that event type (e.g., using the polygonzkevmbridge binding and converting Index -> GlobalIndex) so older claims are included in scans.

Suggested change
scanClaimEventSignature = crypto.Keccak256Hash([]byte("ClaimEvent(uint256,uint32,address,address,uint256)"))
scanClaimEventSignature = crypto.Keccak256Hash([]byte("ClaimEvent(uint256,uint32,address,address,uint256)"))
scanLegacyClaimEventSignature = crypto.Keccak256Hash([]byte("ClaimEvent(uint32,uint32,address,address,uint256)"))

Copilot uses AI. Check for mistakes.
return fmt.Errorf("check IsEmergencyState before activateEmergencyState: %w", err)
}
if inEmergency {
return fmt.Errorf("bridge is already in emergency state before activateEmergencyState")
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

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

stepFreezeBridge returns an error if the bridge is already in emergency state. This makes the recovery flow non-resumable after a partial failure (e.g., if a previous run froze the bridge and then crashed), forcing manual intervention even though the desired state is already reached. Consider treating "already in emergency state" as a successful no-op (log and continue), and only sending ActivateEmergencyState when the bridge is not yet in emergency state.

Suggested change
return fmt.Errorf("bridge is already in emergency state before activateEmergencyState")
fmt.Println(" Bridge is already in emergency state; skipping activateEmergencyState")
return nil

Copilot uses AI. Check for mistakes.
Comment on lines +39 to +59
{
Name: "scan-invalid-claims",
Usage: "Scan L2 claims from a starting block and report GERs that are invalid on L1",
Flags: []cli.Flag{
&cli.Uint64Flag{
Name: "from-block",
Usage: "Starting L2 block number to scan (inclusive)",
Required: true,
},
&cli.Uint64Flag{
Name: "to-block",
Usage: "Ending L2 block number to scan (inclusive, defaults to latest L2 block)",
},
&cli.Uint64Flag{
Name: "chunk-size",
Usage: "Maximum L2 block range per eth_getLogs query",
Value: 5000,
},
},
Action: remove_ger.RunScanInvalidClaims,
},
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

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

The PR title/description suggest a documentation-only change, but this diff also introduces a new CLI subcommand (scan-invalid-claims) and adds substantial new scanning/recovery logic and tests. Please update the PR title and/or description to reflect the actual scope so reviewers can assess risk and behavior changes appropriately.

Copilot uses AI. Check for mistakes.
@arnaubennassar arnaubennassar changed the title Document remove_ger L2 network config feat: Imporve Remove GER tool Apr 15, 2026
@sonarqubecloud
Copy link
Copy Markdown

@arnaubennassar arnaubennassar merged commit 8bf9084 into develop Apr 16, 2026
24 of 25 checks passed
@arnaubennassar arnaubennassar deleted the feat/fix-removeger-tool-docs branch April 16, 2026 16:38
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.

3 participants