# Secure Turnstile: Application State Migration Pattern | Cardinal Cryptography

**URL:** <https://forum.aztec.network/t/secure-turnstile-application-state-migration-pattern-cardinal-cryptography/8414>\
**Category:** Aztec\
**Tags:** rfgp\
**Created:** [January 24, 2026, 4:52pm UTC](https://forum.aztec.network/t/secure-turnstile-application-state-migration-pattern-cardinal-cryptography/8414 "2026-01-24T16:52:52Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![AdamGagol](https://dub1.discourse-cdn.com/flex013/user_avatar/forum.aztec.network/adamgagol/32/2835_2.png) [@AdamGagol](https://forum.aztec.network/u/AdamGagol)\
**Post date:** [January 24, 2026, 4:52pm UTC](https://forum.aztec.network/t/secure-turnstile-application-state-migration-pattern-cardinal-cryptography/8414/1 "2026-01-24T16:52:52Z")

</div>

## Summary

This proposal presents a reusable pattern for application-level state migration during Aztec rollup upgrades. Users migrate private state (token balances, NFT ownership, identity attestations) to new rollup instances without per-user L1 transactions.

The mechanism uses Aztec’s existing infrastructure: archive roots published to L1 become the trust anchor for proving historic state on the new rollup. For identity binding, users prove ownership via knowledge of the master nullifier secret key (`nskm`), which persists across rollup instances.

**Prototype scope:** Token migration via both Mode A (routine upgrade) and Mode B (emergency). Mode B is scoped to native (non-bridged) assets; researching and specifying a solution for L1-collateralized assets is part of the work, though some trade-offs are expected.

## About Us

**About Us** We’re the team behind **[Blanksquare](https://blanksquare.io/)**, bringing privacy to EVM via shielded pools and zk-SNARKs. Previously, we were core maintainers of [Aleph Zero](https://alephzero.org), a Substrate-based L1.

**Relevant experience:**

- **ZK Engineering:** Production Halo2 circuits, browser/mobile provers.

- **Aztec/Noir:** 6 weeks hands-on experience (rewriting our shielded pool circuits from Halo2 to Noir for testing).

- **Research:** Published papers on private order books, threshold ECDSA, and compliance (e.g. [https://eprint.iacr.org/2023/1868](https://eprint.iacr.org/2023/1868), [https://eprint.iacr.org/2020/498](https://eprint.iacr.org/2020/498)).

**Grant Execution Team**

- **Damian Straszak** : PhD Computer Science; Cryptography & Development

- **Adam Gągol** : PhD Mathematics; Cryptography & Development

- **Jan Kuczma** : Core Developer; Noir, Solidity

## Architecture Overview

Applications implement two contracts:

1. **Lock Contract (old rollup):** Nullifies user notes, creates `MigrationLockNote`

2. **Claim Contract (new rollup):** Verifies proofs against synced archive root, validates ownership, mints equivalent notes

The L1 portal relays archive roots to the new rollup via Inbox messaging. The L2 root registry stores trusted roots and enforces the turnstile in emergency mode.

**Note:** Archive root relay between rollup instances is not currently standard Aztec infrastructure. This proposal includes deploying an L1 portal contract that reads archive roots from the old rollup contract and relays them to the new rollup’s Inbox.

## Migration Modes

**Critical design principle:** Mode A and Mode B are mutually exclusive. For any given migration, governance activates exactly one mode based on whether the old rollup’s prover is trusted.

- **Mode A (Routine):** Old prover is trusted. Users lock notes on old rollup, then claim on new rollup.

- **Mode B (Emergency):** Old prover cannot be trusted. Users prove note validity at a safe snapshot height H; no pre-locking required. Mode A is disabled to prevent migration of potentially corrupted state.

**Why mutual exclusivity matters:** If a bug is discovered, any state created via the compromised prover is suspect. Allowing Mode A claims during an emergency would let attackers migrate notes created through the exploit.

## Identity Binding

Proving “I own this note” to the new rollup requires a mechanism independent of the old rollup’s execution proofs. If the old prover has bugs, we can’t trust those proofs.

Users prove ownership by demonstrating knowledge of `nskm` (master nullifier secret key) that derives to the note’s `npkm`(master nullifier public key). Since `nskm` is derived from user-controlled seeds independent of any rollup, it persists across rollup instances even as addresses differ.

The `MigrationLockNote` stores the `npkm` in its `owner` field. At claim time, the user proves knowledge of the corresponding `nskm`.

## Mode A: Routine Migration

### Locking (Old Rollup)

User calls `lock_for_migration(note, destination_rollup_id)`:

1. Verify ownership, emit nullifier for original note

2. Create `MigrationLockNote`:

```auto
MigrationLockNote {
    owner: Field, // npkm
    original_note_hash: Field, // poseidon2(original_note.serialize())
    destination_rollup: Field,
    lock_block: Field,
}

```

The lock note is application-agnostic—it stores only the hash of the original note. Application-specific data (amount, asset\_id) is provided as witness during claim and verified against `original_note_hash`.

### Claiming (New Rollup)

User submits a claim transaction with:

1. **Original note:** Witness data, verified against `original_note_hash`

2. **Archive proof:** Merkle path showing block header in synced archive root

3. **Note proof:** Merkle path showing lock note in that block’s note hash tree

4. **Ownership proof:** Proof of `nskm` knowledge

The claim contract:

1. Checks migration mode is A (reverts if emergency mode active)

2. Verifies Merkle proofs against synced archive root

3. Verifies `poseidon2(original_note.serialize()) == lock_note.original_note_hash`

4. Verifies ownership proof

5. Checks `lock_note.destination_rollup == CURRENT_ROLLUP_ID`

6. Emits nullifier `poseidon2(MIGRATION_DOMAIN, original_note_hash, owner)`

7. Mints equivalent note

* * *

## Mode B: Emergency Migration

When the old prover cannot be trusted, governance activates emergency mode by setting `SAFE_SNAPSHOT_HEIGHT = H`and disabling Mode A. Users migrate by proving their original note was valid at H—no pre-locking required.

**Scope:** Mode B applies to native (non-bridged) assets. Handling L1-collateralized assets in emergency mode requires additional L1-side coordination; researching and specifying this solution is part of the deliverables.

### Claiming (New Rollup)

User proves:

1. Original note was **included** in note hash tree at block ≤ H

2. Original note was **not nullified** at block H (IMT non-membership proof)

3. Valid ownership proof (`nskm` knowledge)

Aztec provides history proof primitives (`prove_note_inclusion`, `prove_note_not_nullified`, etc.) for proving against anchor blocks. Our implementation adapts these for cross-rollup verification against a governance-specified snapshot height H, which requires archive nodes to maintain nullifier tree state at that height.

The claim contract verifies these proofs against the archive root at H and mints equivalent notes.

**Why pre-locked notes are rejected:** During emergency mode, even lock notes created before the bug was discovered are suspect—the lock note itself may encode inflated amounts or invalid ownership. Users who locked notes can still migrate by proving their _original_ note was valid at H; the lock note is ignored.

### Nullifier Consistency

Both modes emit the same nullifier: `poseidon2(MIGRATION_DOMAIN, original_note_hash, owner)`. This prevents double-claims across mode transitions (in a very unlikely scenario that they ever happen).

## Archive Root Synchronization

The L1 portal contract reads archive roots from the old rollup contract and relays them to the new rollup’s Inbox. Anyone can call this relay function, making root syncing permissionless in routine mode.

The L2 registry contract stores roots as trusted anchors. In emergency mode, the registry only accepts roots at or before the safe snapshot height. Governance activates emergency mode by calling a restricted function that sets the snapshot height and switches the migration mode.

## Threat Model

| Threat | Mitigation |
| --- | --- |
| Attacker inflation via prover bug | Mode B: prove note validity at pre-bug snapshot height |
| Cross-rollup replay | `destination_rollup` field verified at claim |
| Claim front-running | Ownership proof binds to recipient address |

**Accepted risks:** User error on destination selection (no unlock mechanism); `nskm` theft (standard key-security model); exploits before snapshot height (inherent to any turnstile).

* * *

## Milestones

All milestones below reflect the full Tier 1 scope.

| Milestone | Date | Deliverables |
| --- | --- | --- |
| **M1: Specification & Setup** | Feb 3, 2026 | Type definitions, migration mode enum, Aztec version pinning, dev environment, skeleton contracts |
| **M2: Lock Contract & L1 Infrastructure** | Feb 12, 2026 | Lock contract on old rollup, L1 portal with Inbox relay, L2 root registry with mode enforcement |
| **M3: Mode A Claim** | Feb 20, 2026 | Claim contract with archive + note proof verification, ownership validation, end-to-end Mode A flow with batching support |
| **M4: Mode B Claim** | Feb 27, 2026 | Mode B claim circuits adapting Aztec’s history proof primitives for cross-rollup verification, Mode B claim path for native assets, bridged asset handling specification |
| **M5: Integration & Documentation** | Mar 6, 2026 | Cross-chain integration tests, example token contract with migration hooks, gas and proving time benchmarks, user documentation, deployment guide |

## Funding Request

We offer two tiers depending on grant pool allocation.

### Tier 1: Secure Turnstile: $30,000

The complete architecture with both migration modes and production-ready L1 integration.

**Deliverables:**

- Full Mode A (Lock & Claim) implementation with batching

- Full Mode B (Emergency) implementation adapting Aztec’s history proof primitives for cross-rollup verification

- Bridged asset handling specification for Mode B

- L1 portal and Inbox relay contracts

- L2 root registry with governance-controlled mode switching

- Example token contract with migration hooks

- Gas and proving time benchmarks

- End-to-end cross-chain integration tests

- Technical documentation and user guides

### Tier 2: Migration Foundation: $20,000

Production-ready routine migration path with emergency mode deferred.

**Deliverables:**

- Full Mode A (Lock & Claim) implementation with batching

- L1 portal and Inbox relay contracts

- L2 root registry with mode enforcement

- Mode B design specification (implementation deferred)

- Integration tests for Mode A flow

- Documentation

**Trade-off:** Mode B is fully specified but not implemented. However, even in the event of a proof system bug, Mode B can be implemented post-factum with no harm to migration safety.
