Skip to content

Feature: App-specific block snapshot verification in Mode B - #56

Merged
JanKuczma merged 3 commits into
mainfrom
feature/mode-b-at-block
Mar 22, 2026
Merged

Feature: App-specific block snapshot verification in Mode B#56
JanKuczma merged 3 commits into
mainfrom
feature/mode-b-at-block

Conversation

@JanKuczma

@JanKuczma JanKuczma commented Mar 22, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

Release Notes

  • Refactor

    • Renamed migration verification APIs for improved clarity: verify_migration_mode_a/bverify_migration_at_block/at_snapshot
    • Updated Mode B migration finalization to use finish_at_snapshot() and finish_at_block() methods with explicit block-based verification option
  • Documentation

    • Updated architecture, integration guides, and specifications to reflect renamed APIs and clarify snapshot-based versus explicit block-number verification flows

@coderabbitai

coderabbitai Bot commented Mar 22, 2026

Copy link
Copy Markdown

Walkthrough

This pull request introduces a systematic renaming of the migration verification API in MigrationArchiveRegistry, changing verify_migration_mode_a/verify_migration_mode_b to verify_migration_at_block/verify_migration_at_snapshot. Mode B migration builders are refactored to provide two finalization paths: snapshot-based and explicit block-number-based, with corresponding updates across documentation, Noir contracts, TypeScript wrappers, and test applications.

Changes

Cohort / File(s) Summary
Documentation API References
docs/architecture.md, docs/security.md, docs/spec/mode-a-spec.md, docs/spec/mode-b-spec.md
Updated references to renamed verification functions; clarified function usage patterns in Mode A/B documentation.
Specification Updates
docs/integration-guide.md, docs/spec/migration-spec.md
Updated Mode B builder examples to use finish_at_snapshot() and added documentation for alternative finish_at_block() flow; comprehensive spec updates for renamed verification entrypoints and builder methods.
Migration Archive Registry
noir/contracts/migration-archive-registry/src/main.nr, ts/aztec-state-migration/noir-contracts/MigrationArchiveRegistry.ts
Renamed internal private functions and TypeScript method wrappers from mode-specific naming to block/snapshot-based naming.
Mode A Migration Builder
noir/aztec-state-migration/src/mode_a/builder.nr
Updated verification call to use verify_migration_at_block.
Mode B Migration Builder
noir/aztec-state-migration/src/mode_b/builder.nr
Significant API refactoring: replaced finish() with finish_at_snapshot() and finish_at_block(block_number) methods; split internal completion logic; moved signature verification handling.
Test Contract Updates
noir/test-contracts/example-app/v2/src/main.nr, noir/test-contracts/minimal-benchmark/src/main.nr, noir/test-contracts/nft-migration-app/v2/src/main.nr, noir/test-contracts/token-migration-app/v2/src/main.nr
Updated Mode B finalization calls from finish() to finish_at_snapshot(); added new storage field and methods to example-app for block-number-based migrations.
E2E Test Enhancement
e2e-tests/migration-mode-b.test.ts
Expanded test to exercise both snapshot-based and block-based Mode B migration paths; added test step for migrate_mode_b_at_block flow with block number setup and validation.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant App as Test App<br/>(v2)
    participant MigrationBuilder as MigrationModeB<br/>Builder
    participant Registry as MigrationArchiveRegistry
    
    rect rgba(0, 100, 200, 0.5)
    Note over User,Registry: Snapshot-Based Mode B Migration
    User->>App: migrate_mode_b_at_snapshot(proof_data)
    App->>MigrationBuilder: builder.finish_at_snapshot(recipient, signature)
    MigrationBuilder->>MigrationBuilder: _verify_signature(recipient, signature)
    MigrationBuilder->>MigrationBuilder: _finish_at_snapshot()
    MigrationBuilder->>Registry: verify_migration_at_snapshot(block_hash)
    Registry-->>MigrationBuilder: verification passed
    MigrationBuilder-->>App: migration complete
    end
    
    rect rgba(200, 100, 0, 0.5)
    Note over User,Registry: Block-Number-Based Mode B Migration
    User->>App: migrate_mode_b_at_block(proof_data, block_header)
    App->>MigrationBuilder: builder.finish_at_block(recipient, signature, block_number)
    MigrationBuilder->>MigrationBuilder: _verify_signature(recipient, signature)
    MigrationBuilder->>MigrationBuilder: _finish_at_block(block_number)
    MigrationBuilder->>Registry: verify_migration_at_block(block_number, block_hash)
    Registry-->>MigrationBuilder: verification passed
    MigrationBuilder-->>App: migration complete
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Suggested reviewers

  • DamianStraszak

Poem

🐰 A curious hop through migrations grand,
Block-based paths now clearly planned,
Snapshot or block—take your pick,
The registry's renamed trick,
APIs blooming, tests now click!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 38.89% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Feature: App-specific block snapshot verification in Mode B' directly reflects the main changes: renaming verification functions to support app-specific block verification in Mode B alongside snapshot-based verification.

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

✨ 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 feature/mode-b-at-block

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

Tip

You can disable sequence diagrams in the walkthrough.

Disable the reviews.sequence_diagrams setting to disable sequence diagrams in the walkthrough.

@DamianStraszak DamianStraszak 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.

Very nice generalization. Looks solid.

/// Claim a Mode B (app specific block number) migration on the new rollup.
///
/// Verifies note inclusion and non-nullification at the specified block number via
/// `migrate_notes_mode_b` and mints the equivalent tokens to the caller.

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.

This comment is copied from the other function, but still, it's a bit too specific. Instead of "mints tokens" should be "creates note".

Base automatically changed from bump-aztec-version to main March 22, 2026 19:31

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
docs/architecture.md (1)

19-27: ⚠️ Potential issue | 🟡 Minor

Update the topology diagram to the new Mode B app entrypoints.

This section renames the registry verification methods, but the same diagram still shows the app exposing migrate_mode_b(). After this PR, the externally visible Mode B paths are migrate_mode_b_at_snapshot() / migrate_mode_b_at_block(), so the topology view is still stale.

Based on learnings: Applies to **/*.nr : Update docs/spec/mode-a-spec.md, docs/spec/mode-b-spec.md, and/or docs/architecture.md when contract interfaces change (public functions, events, externally visible behavior).

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

In `@docs/architecture.md` around lines 19 - 27, The topology diagram in
docs/architecture.md is stale: it still shows the app exposing migrate_mode_b()
while the contract now exposes migrate_mode_b_at_snapshot() and
migrate_mode_b_at_block(); update the diagram and any labels referencing
migrate_mode_b() to the new entrypoints migrate_mode_b_at_snapshot() and
migrate_mode_b_at_block(), and similarly ensure MigrationKeyRegistry references
the renamed verification methods (verify_migration_at_snapshot(),
verify_migration_at_block()) and that docs/spec/mode-a-spec.md and
docs/spec/mode-b-spec.md are updated to match these public function names so the
diagrams and text reflect the new external contract interfaces.
e2e-tests/migration-mode-b.test.ts (2)

198-203: ⚠️ Potential issue | 🟡 Minor

Assert that a second active note exists before indexing it.

The setup only rejects the zero-note case, but Line 283 assumes balanceNotesActive[1] exists. If the app or wallet collapses balances into a single active note, this test fails before it exercises the new at-block path.

Suggested guard
-  if (balanceNotesActive.length === 0) {
-    throw new Error("No active balance notes found");
+  if (balanceNotesActive.length < 2) {
+    throw new Error(
+      "Expected at least two active balance notes to cover snapshot and at-block migration paths",
+    );
   }

Also applies to: 283-289

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

In `@e2e-tests/migration-mode-b.test.ts` around lines 198 - 203, The test
currently only checks balanceNotesActive.length !== 0 but later accesses
balanceNotesActive[1]; update the guard to assert that balanceNotesActive has at
least two active notes (e.g., if (balanceNotesActive.length < 2) throw new
Error("Expected at least two active balance notes for indexing at-block path")),
or alternatively create/ensure a second active note before using
balanceNotesActive[1]; adjust the code paths around the indexing that reference
balanceNotesActive[1] so they only run when balanceNotesActive.length >= 2
(symbols: balanceNotesActive, balanceNote and the subsequent indexing logic that
uses balanceNotesActive[1]).

143-156: ⚠️ Potential issue | 🟠 Major

Use a different registered block for the at-block scenario.

Step 10.1 reuses the same provenBlockNumber that was already stored as the global snapshot height. With both paths anchored to the same header/hash, this still passes if migrate_mode_b_at_block accidentally routes through snapshot verification. Register another block and rebuild the second proof/header against that block so this test actually distinguishes the new behavior.

Also applies to: 279-321

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

In `@e2e-tests/migration-mode-b.test.ts` around lines 143 - 156, The test
currently reuses provenBlockNumber and archiveProof/archive_sibling_path when
calling newArchiveRegistry.methods.set_snapshot_height(...) and later for the
at-block scenario, which masks incorrect routing through snapshot verification;
instead register a second block (create a new block number variable, a new
header and proof) and use that new block/header/proof for the
migrate_mode_b_at_block scenario so the two paths are anchored to different
headers/hashes; update the calls around set_snapshot_height/get_snapshot_height
and the at-block test (also change the duplicated logic in the later section
around lines 279-321) to build and pass the distinct proof/header to the
at-block invocation.
noir/test-contracts/example-app/v2/src/main.nr (1)

193-236: ⚠️ Potential issue | 🟠 Major

Update specs/architecture docs for the new Mode B interface.

This file adds/renames externally visible contract functions (migrate_mode_b_at_snapshot, migrate_mode_b_at_block, set_migration_block_number). Please update the relevant docs in this PR.

As per coding guidelines, "Update docs/spec/mode-a-spec.md, docs/spec/mode-b-spec.md, and/or docs/architecture.md when contract interfaces change (public functions, events, externally visible behavior)."

Also applies to: 385-388

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

In `@noir/test-contracts/example-app/v2/src/main.nr` around lines 193 - 236, The
PR introduces/renames externally visible contract functions
(migrate_mode_b_at_snapshot, migrate_mode_b_at_block,
set_migration_block_number) but the specs/architecture docs were not updated;
update docs/spec/mode-a-spec.md, docs/spec/mode-b-spec.md, and
docs/architecture.md to reflect the new Mode B interface: add/modify entries for
these functions (signatures, visibility [external/private], purpose, parameters,
side-effects like minting to balances and proof verification via
MigrationModeB::finish_at_snapshot/finish_at_block), note the storage slot
requirement (balances_expected_storage_slot from
STORAGE_LAYOUT_ExampleMigrationAppV1), and any changes to externally visible
behavior or migration flow so the docs and contract interface remain in sync.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@noir/test-contracts/example-app/v2/src/main.nr`:
- Line 56: The field migration_block_number is currently caller-writable via
set_migration_block_number which allows anyone to hijack Mode B-at-block
verification; change the storage to a restricted variable and add an ownership
check in the setter: make migration_block_number private/mutable (or use an
Ownable/owner field already present) and update set_migration_block_number to
require Context::caller (or the contract owner identifier used in this codebase)
matches the authorized owner before setting; apply the same restriction to the
other setter(s) referenced around lines ~385-388 and ensure callers cannot
bypass the check.

---

Outside diff comments:
In `@docs/architecture.md`:
- Around line 19-27: The topology diagram in docs/architecture.md is stale: it
still shows the app exposing migrate_mode_b() while the contract now exposes
migrate_mode_b_at_snapshot() and migrate_mode_b_at_block(); update the diagram
and any labels referencing migrate_mode_b() to the new entrypoints
migrate_mode_b_at_snapshot() and migrate_mode_b_at_block(), and similarly ensure
MigrationKeyRegistry references the renamed verification methods
(verify_migration_at_snapshot(), verify_migration_at_block()) and that
docs/spec/mode-a-spec.md and docs/spec/mode-b-spec.md are updated to match these
public function names so the diagrams and text reflect the new external contract
interfaces.

In `@e2e-tests/migration-mode-b.test.ts`:
- Around line 198-203: The test currently only checks balanceNotesActive.length
!== 0 but later accesses balanceNotesActive[1]; update the guard to assert that
balanceNotesActive has at least two active notes (e.g., if
(balanceNotesActive.length < 2) throw new Error("Expected at least two active
balance notes for indexing at-block path")), or alternatively create/ensure a
second active note before using balanceNotesActive[1]; adjust the code paths
around the indexing that reference balanceNotesActive[1] so they only run when
balanceNotesActive.length >= 2 (symbols: balanceNotesActive, balanceNote and the
subsequent indexing logic that uses balanceNotesActive[1]).
- Around line 143-156: The test currently reuses provenBlockNumber and
archiveProof/archive_sibling_path when calling
newArchiveRegistry.methods.set_snapshot_height(...) and later for the at-block
scenario, which masks incorrect routing through snapshot verification; instead
register a second block (create a new block number variable, a new header and
proof) and use that new block/header/proof for the migrate_mode_b_at_block
scenario so the two paths are anchored to different headers/hashes; update the
calls around set_snapshot_height/get_snapshot_height and the at-block test (also
change the duplicated logic in the later section around lines 279-321) to build
and pass the distinct proof/header to the at-block invocation.

In `@noir/test-contracts/example-app/v2/src/main.nr`:
- Around line 193-236: The PR introduces/renames externally visible contract
functions (migrate_mode_b_at_snapshot, migrate_mode_b_at_block,
set_migration_block_number) but the specs/architecture docs were not updated;
update docs/spec/mode-a-spec.md, docs/spec/mode-b-spec.md, and
docs/architecture.md to reflect the new Mode B interface: add/modify entries for
these functions (signatures, visibility [external/private], purpose, parameters,
side-effects like minting to balances and proof verification via
MigrationModeB::finish_at_snapshot/finish_at_block), note the storage slot
requirement (balances_expected_storage_slot from
STORAGE_LAYOUT_ExampleMigrationAppV1), and any changes to externally visible
behavior or migration flow so the docs and contract interface remain in sync.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 23577703-94e3-4614-b6b0-70d869ff61f1

📥 Commits

Reviewing files that changed from the base of the PR and between 3e4125f and 384141a.

⛔ Files ignored due to path filters (2)
  • solidity/soldeer.lock is excluded by !**/*.lock
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (50)
  • .devcontainer/development/Dockerfile
  • .devcontainer/mac-arm/Dockerfile
  • .devcontainer/testing/Dockerfile
  • .github/workflows/ci.yml
  • .github/workflows/publish.yml
  • .mcp.json
  • CLAUDE.md
  • README.md
  • docs/architecture.md
  • docs/integration-guide.md
  • docs/security.md
  • docs/spec/migration-spec.md
  • docs/spec/mode-a-spec.md
  • docs/spec/mode-b-spec.md
  • e2e-tests/migration-key-registry.test.ts
  • e2e-tests/migration-mode-a.test.ts
  • e2e-tests/migration-mode-b.test.ts
  • e2e-tests/migration-public-mode-b.test.ts
  • e2e-tests/nft-migration-mode-a.test.ts
  • e2e-tests/nft-migration-mode-b.test.ts
  • e2e-tests/package.json
  • e2e-tests/test-utils.ts
  • e2e-tests/token-migration-mode-a.test.ts
  • e2e-tests/token-migration-mode-b.test.ts
  • e2e-tests/token-migration-public-mode-b.test.ts
  • noir/aztec-state-migration/Nargo.toml
  • noir/aztec-state-migration/src/mode_a/builder.nr
  • noir/aztec-state-migration/src/mode_b/builder.nr
  • noir/contracts/migration-archive-registry/Nargo.toml
  • noir/contracts/migration-archive-registry/src/main.nr
  • noir/contracts/migration-key-registry/Nargo.toml
  • noir/test-contracts/example-app/v1/Nargo.toml
  • noir/test-contracts/example-app/v2/Nargo.toml
  • noir/test-contracts/example-app/v2/src/main.nr
  • noir/test-contracts/minimal-benchmark/Nargo.toml
  • noir/test-contracts/minimal-benchmark/src/main.nr
  • noir/test-contracts/nft-migration-app/v1/Nargo.toml
  • noir/test-contracts/nft-migration-app/v2/Nargo.toml
  • noir/test-contracts/nft-migration-app/v2/src/main.nr
  • noir/test-contracts/token-migration-app/v1/Nargo.toml
  • noir/test-contracts/token-migration-app/v2/Nargo.toml
  • noir/test-contracts/token-migration-app/v2/src/main.nr
  • noir/tests/Nargo.toml
  • solidity/contracts/Poseidon2Deploy.sol
  • solidity/contracts/RegisterNewRollupVersionPayload.sol
  • solidity/foundry.toml
  • solidity/remappings.txt
  • ts/aztec-state-migration/noir-contracts/MigrationArchiveRegistry.ts
  • ts/aztec-state-migration/package.json
  • ts/aztec-state-migration/proofs.ts
💤 Files with no reviewable changes (1)
  • solidity/contracts/RegisterNewRollupVersionPayload.sol

Comment thread noir/test-contracts/example-app/v2/src/main.nr
@JanKuczma
JanKuczma force-pushed the feature/mode-b-at-block branch from 384141a to 7e21692 Compare March 22, 2026 19:47

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 the current code and only fix it if needed.

Inline comments:
In `@docs/spec/migration-spec.md`:
- Around line 276-279: Update the Mode B builder example and surrounding text to
mention the new block-number alternative: note that in addition to
.finish_at_snapshot(recipient, signature) callers can use
.finish_at_block(recipient, signature, block_number) to verify against a
specific block height; reference the builder and Mode B in the wording and add a
short clarifying sentence that .finish_at_block takes an extra block_number
parameter and performs the same migration-signature check at that block.

In `@e2e-tests/migration-mode-b.test.ts`:
- Line 283: The test assumes a second active note but only checked for
zero-length earlier; before using balanceNotesActive[1] (assigned to
balanceNote2) add a guard or assertion that balanceNotesActive.length >= 2, or
change the logic to handle the single-note case (e.g., use balanceNotesActive[0]
or branch accordingly). Locate the access to balanceNotesActive and the
assignment to balanceNote2 and either assert/expect length >= 2 or conditionally
select the correct index so the test cannot throw an out-of-bounds error.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: baace820-6cc3-4639-83d1-a1698cfd441c

📥 Commits

Reviewing files that changed from the base of the PR and between 384141a and 7e21692.

📒 Files selected for processing (15)
  • docs/architecture.md
  • docs/integration-guide.md
  • docs/security.md
  • docs/spec/migration-spec.md
  • docs/spec/mode-a-spec.md
  • docs/spec/mode-b-spec.md
  • e2e-tests/migration-mode-b.test.ts
  • noir/aztec-state-migration/src/mode_a/builder.nr
  • noir/aztec-state-migration/src/mode_b/builder.nr
  • noir/contracts/migration-archive-registry/src/main.nr
  • noir/test-contracts/example-app/v2/src/main.nr
  • noir/test-contracts/minimal-benchmark/src/main.nr
  • noir/test-contracts/nft-migration-app/v2/src/main.nr
  • noir/test-contracts/token-migration-app/v2/src/main.nr
  • ts/aztec-state-migration/noir-contracts/MigrationArchiveRegistry.ts

Comment thread docs/spec/migration-spec.md
Comment thread e2e-tests/migration-mode-b.test.ts
@JanKuczma
JanKuczma merged commit 4afcdc2 into main Mar 22, 2026
3 checks passed
@JanKuczma
JanKuczma deleted the feature/mode-b-at-block branch March 22, 2026 20:09
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.

2 participants