Skip to content

feat: preserve stores on schema version or rollup address change#24631

Open
mverzilli wants to merge 25 commits into
merge-train/fairies-v5from
martin/change-store-version-behavior
Open

feat: preserve stores on schema version or rollup address change#24631
mverzilli wants to merge 25 commits into
merge-train/fairies-v5from
martin/change-store-version-behavior

Conversation

@mverzilli

Copy link
Copy Markdown
Contributor

(wip)

Closes F-809

mverzilli added 19 commits July 9, 2026 09:10
Replaces wipe-on-mismatch with store selection keyed on
(l1ChainId, rollupAddress, schemaVersion) for both PXE backends.
…ress first boot

Gate the schema-mismatch throw on a successfully parsed version file so a first
boot with a zero rollup address (storedVersion (0, ZERO) vs (N, ZERO)) resets and
opens instead of throwing forever. Split rollup-address mismatch handling into its
own RollupAddressMismatchPolicy (default 'reset') so the validator HA signer keeps
silent reset-on-rollup-change while schema mismatches stay fail-closed.

For partitioned lmdb-v2 stores, use a sibling '<name>-stores' directory instead of
nesting inside the legacy env dir, so an old binary's rollup-mismatch rm -rf of the
legacy dir cannot destroy per-identity stores; force all three mismatch policies to
'throw' when partitionByIdentity is set.
… layout

Update the database-version README reset conditions, the store-selection design
doc (sibling <name>-stores layout, three throw policies, HA-signer reset default),
and the migration note (ts fence, per-backend on-disk data location).
Comment on lines +14 to +16
Previously, connecting a PXE or embedded wallet to a different or redeployed rollup, or bumping the store schema version, wiped the existing on-disk store in place. That meant master account keys could be destroyed simply by pointing a wallet at a different network. A store now exists per `(l1ChainId, rollupAddress, schemaVersion)` identity, and switching networks (or upgrading) selects the matching store instead of overwriting the previous one.

**Impact**: The first start after upgrading to this version begins with a fresh, empty store; the pre-upgrade data is not deleted. In the browser (sqlite-opfs) the old store stays in OPFS but is not visible to the new `listStores()` utility; on node (lmdb-v2) pre-upgrade data stays at `<dataDirectory>/<name>` while new per-identity stores live under `<dataDirectory>/<name>-stores/`. That covers the server PXE and the CLI wallet; the embedded node wallet previously stored data in cwd-relative, rollup-address-suffixed directories instead (`pxe_data_<rollupAddress>/pxe_data` for the PXE store, `wallet_data_<rollupAddress>/wallet_data` for the wallet store): if you used it before this release, that is where your old data lives. The embedded wallet now defaults its data root to `aztec-wallet-data/`. Browser apps can enumerate and clean up stores for networks no longer in use with the new `listStores()` / `deleteStore()` utilities:

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Suggested change
Previously, connecting a PXE or embedded wallet to a different or redeployed rollup, or bumping the store schema version, wiped the existing on-disk store in place. That meant master account keys could be destroyed simply by pointing a wallet at a different network. A store now exists per `(l1ChainId, rollupAddress, schemaVersion)` identity, and switching networks (or upgrading) selects the matching store instead of overwriting the previous one.
**Impact**: The first start after upgrading to this version begins with a fresh, empty store; the pre-upgrade data is not deleted. In the browser (sqlite-opfs) the old store stays in OPFS but is not visible to the new `listStores()` utility; on node (lmdb-v2) pre-upgrade data stays at `<dataDirectory>/<name>` while new per-identity stores live under `<dataDirectory>/<name>-stores/`. That covers the server PXE and the CLI wallet; the embedded node wallet previously stored data in cwd-relative, rollup-address-suffixed directories instead (`pxe_data_<rollupAddress>/pxe_data` for the PXE store, `wallet_data_<rollupAddress>/wallet_data` for the wallet store): if you used it before this release, that is where your old data lives. The embedded wallet now defaults its data root to `aztec-wallet-data/`. Browser apps can enumerate and clean up stores for networks no longer in use with the new `listStores()` / `deleteStore()` utilities:
Previously, connecting a PXE or embedded wallet to a different or redeployed rollup, or bumping the store schema version, wiped the existing on-disk store in place. That meant master account keys could be destroyed simply by pointing a wallet at a different network. A store now exists per `(l1ChainId, rollupAddress, schemaVersion)` identity, and switching networks (or upgrading) selects the matching store instead of overwriting the previous one.
**Impact**: The first start after upgrading to this version begins with a fresh, empty store; the pre-upgrade data is not deleted. On Node.js environments (lmdb-v2) pre-upgrade data stays at `<dataDirectory>/<name>` while new per-identity stores live under `<dataDirectory>/<name>-stores/`. The embedded Node.js wallet previously stored data in cwd-relative, rollup-address-suffixed directories instead (`pxe_data_<rollupAddress>/pxe_data` for the PXE store, `wallet_data_<rollupAddress>/wallet_data` for the wallet store): if you used it before this release, that is where your old data lives. The embedded wallet now defaults its data root to `aztec-wallet-data/`. Browser apps can enumerate and clean up stores for networks no longer in use with the new `listStores()` / `deleteStore()` utilities:

import { deleteStore, listStores } from '@aztec/kv-store/sqlite-opfs';

const names = await listStores();
await deleteStore(names[0]); // the store must be closed first

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Suggested change
await deleteStore(names[0]); // the store must be closed first
await deleteStore(names[0]);

Comment on lines +51 to +52
* Belt-and-braces invariant check: the identity is part of the physical store name, so the recorded version
* can only disagree if there is a store-naming bug. Refuses to open on mismatch; never clears.

@mverzilli mverzilli Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Suggested change
* Belt-and-braces invariant check: the identity is part of the physical store name, so the recorded version
* can only disagree if there is a store-naming bug. Refuses to open on mismatch; never clears.
* Invariant check: the identity is part of the physical store name, so the recorded version can only
* disagree if there is a store-naming bug. Refuses to open on mismatch.

mverzilli added 6 commits July 9, 2026 16:06
…ng to zero

Opening a persistent sqlite-opfs store (or composing its identity slug) with a
missing l1ChainId, rollupAddress, or schemaVersion silently fell back to the
zero identity, which could route two logically different callers to the same
physical store. Require the full identity and throw instead.

Files: yarn-project/kv-store/src/store_identity.ts,
yarn-project/kv-store/src/store_identity.test.ts,
yarn-project/kv-store/src/sqlite-opfs/index.ts,
yarn-project/kv-store/src/sqlite-opfs/create_store.test.ts
IdentityStoreConfig previously allowed l1ChainId and rollupAddress to be
omitted, in which case the identity-partitioned store fell back to the zero
identity. Make both fields required so callers can no longer open a PXE data
store without a complete identity.

Files: yarn-project/pxe/src/entrypoints/server/store.ts,
yarn-project/pxe/src/entrypoints/server/utils.ts,
yarn-project/pxe/src/entrypoints/server/store.test.ts
…tity

The embedded wallet's wallet_data store held account secrets and aliases,
which are not tied to any particular network, yet it was keyed by
(l1ChainId, rollupAddress, schemaVersion) like the PXE data store. That meant
switching networks silently swapped in a different (empty) wallet store.
Key wallet_data by schema version alone (wallet_data_v1) so it stays the same
store across networks.

Files: yarn-project/wallets/src/embedded/wallet_db.ts,
yarn-project/wallets/src/embedded/entrypoints/node.ts,
yarn-project/wallets/src/embedded/entrypoints/browser.ts
…note

Files: docs/docs-developers/docs/resources/migration_notes.md
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