Skip to content

refactor!: rename L1->L2 message content/secret to public_content_hash/private_content - #689

Draft
benesjan wants to merge 1 commit into
mainfrom
jb/rename-l1-to-l2-message-fields
Draft

benesjan wants to merge 1 commit into
mainfrom
jb/rename-l1-to-l2-message-fields

Conversation

@benesjan

@benesjan benesjan commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

Labs side of the L1→L2 message rename agreed in governance discussion #52. The L1 and protocol half lands in aztec-packages as AztecProtocol/aztec-packages#25773, which carries this same diff as labs-patches/0015 so its labs build and tests run against the renamed ABI.

The Inbox data model is unchanged; the names now describe what the fields are:

Concept Old TS Noir
hashed public payload content publicContentHash public_content_hash
L2-side preimage secret privateContent (Fr[]) private_content ([Field; N])
its commitment secretHash privateContentHash private_content_hash
hash helper computeSecretHash / compute_secret_hash computePrivateContentHash compute_private_content_hash
domain separator DOM_SEP__SECRET_HASH DomainSeparator.PRIVATE_CONTENT_HASH DOM_SEP__PRIVATE_CONTENT_HASH

Status and next steps

AztecProtocol/aztec-packages#25773 merged into next on 2026-11-09 (ded2a88). This PR stays a draft until it can build: against the current pin (BB_VERSION=6.0.0-rc.7) it does not compile, because it needs the foundation packages that contain #25773. Those are the renamed InboxAbi/FeeJuicePortalAbi in @aztec-foundation/l1-artifacts, DOM_SEP__PRIVATE_CONTENT_HASH in the protocol types, and the rotated FeeJuice artifact.

  1. Unblock the v7 foundation nightlies. v7.0.0-nightly.20261110 should be the first tag with #25773, but no v7 nightly has reached npm since 7.0.0-nightly.20261031. Every nightly run since Nov 1 fails in publish-npm with ENEEDAUTH on @aztec-foundation/bb.js-api-darwin-arm64, a package added by feat(bb.js): generated bb.js-api package with an in-process wasm transport AztecProtocol/aztec-packages#25433 that has never been published (likely no npm trusted-publisher setup for it yet). Someone with admin rights on the @aztec-foundation npm org has to fix this. The 6.1.0-nightly line still publishes, but it is cut from a branch without #25773.
  2. Bump the foundation pin to the first fully published 7.0.0-nightly from 2026-11-10 or later (labs-aztec-toolchain/bootstrap.sh set-pins <version>). This moves the pin across a major version and pulls in everything on next since 6.0.0-rc.7, so it should land as its own PR unless one is already planned.
  3. Rebase this PR on the bump, take it out of draft and get CI green.
  4. Add the changelog entries. CHANGELOG-DEVELOPERS.md now exists on main, so the Aztec.nr, Aztec.js and CLI breaking changes from the migration note below need entries there before merge.
  5. After merge, in aztec-packages: bump the labs gitlink past this PR and delete labs-patches/0015. apply will likely stop on 0015 because it also edits docs/, which aztec-node main no longer has; delete the patch rather than resolve it, since this PR already carries its code changes.

Breaking changes

  • Aztec.nr: consume_l1_to_l2_message(public_content_hash, private_content, sender, leaf_index), compute_private_content_hash, compute_l1_to_l2_message_{hash,nullifier} params. TXE: send_l1_to_l2_message(public_content_hash, private_content: [Field; N], sender, recipient) and send_l1_to_l2_message_from_private_content_hash; TXE oracle version 10.1 → 11.0. FeeJuice.claim / TokenBridge.claim_* keep their secret params.
  • Aztec.js / stdlib: L1ToL2Message.{publicContentHash,privateContentHash}, computePrivateContentHash(privateContent: Fr[]) (mirrors Noir; computeSecretHash took one field), computeFeeJuiceMessageNullifier / getNonNullifiedL1ToL2MessageWitness take privateContent: Fr[]. generateClaimSecret is removed: use Fr.random() and computePrivateContentHash. L2Claim.claimSecret / claimSecretHash keep their names, but the hash values differ because the domain separator string changed.
  • Bot: crosschain seeds and the inbox bot's persisted messages use the new field names; BotStore.SCHEMA_VERSION 2 → 3, so older stores are discarded on startup.
  • CLI: get-l1-to-l2-message-witness --private-content (was --secret).
  • The PXE protocol oracle aztec_protocol_utl_getL1ToL2MembershipWitness keeps its wire interface (PROTOCOL_ORACLE_INTERFACE_HASH unchanged); only how it is served adapts to the array-taking nullifier helper.

Out of scope: L2→L1 messages (L2ToL1Msg.content etc.) and TransparentNote.secret_hash (app-level; only its hash call changed).

Migration notes

aztec-node main has no developer docs and the aztec-packages docs are on the v6 line, so this note still needs a home in the v7 developer docs. It is the one carried in AztecProtocol/aztec-packages#25773's labs patch (docs/docs-developers/docs/resources/migration_notes.md, section TBD):

Migration note

[L1 contracts, Aztec.nr, Aztec.js, CLI] L1-to-L2 message content and secret renamed to public and private content

The L1-to-L2 message data model is unchanged, but its two application fields have been renamed to describe what they are: content is now the public content hash and secretHash is now the private content hash. The preimage that the consumer reveals on L2 is now called the private content. The private content is application-defined: it can be just a single claim secret, or something richer such as the L2 recipient plus a blinding salt. In the existing fee juice and token bridge flows the value is still a claim secret; it is simply used as the message's private content.

This is a breaking protocol change: the domain separator used to hash the private content was renamed from secret_hash to private_content_hash, so compute_private_content_hash / computePrivateContentHash produce different values than compute_secret_hash / computeSecretHash did. Messages sent with a private content hash computed by the old helper cannot be consumed with the new one; pending (unclaimed) L1-to-L2 messages must be claimed before upgrading or re-sent afterwards.

L1 (Inbox, FeeJuicePortal):

- function sendL2Message(DataStructures.L2Actor memory _recipient, bytes32 _content, bytes32 _secretHash)
+ function sendL2Message(DataStructures.L2Actor memory _recipient, bytes32 _publicContentHash, bytes32 _privateContentHash)
  • DataStructures.L1ToL2Msg.content / .secretHash are now .publicContentHash / .privateContentHash, which also renames these fields in the MessageSent event. Code decoding MessageSent logs by field name (e.g. log.args.message.secretHash) must be updated.
  • Inbox__ContentTooLarge / Inbox__SecretHashTooLarge are now Inbox__PublicContentHashTooLarge / Inbox__PrivateContentHashTooLarge (new selectors).
  • FeeJuicePortal.depositToAztecPublic(_to, _amount, _secretHash) is now depositToAztecPublic(_to, _amount, _privateContentHash) and its DepositToAztecPublic event field is privateContentHash. The reference TokenPortal and UniswapPortal follow the same naming.

Aztec.nr:

- context.consume_l1_to_l2_message(content, [secret], sender, leaf_index);
+ let private_content = [secret];
+ context.consume_l1_to_l2_message(public_content_hash, private_content, sender, leaf_index);
- use aztec::hash::compute_secret_hash;
- let secret_hash = compute_secret_hash([secret]);
+ use aztec::hash::compute_private_content_hash;
+ let private_content = [secret];
+ let private_content_hash = compute_private_content_hash(private_content);
  • compute_l1_to_l2_message_hash(..., content, secret_hash, leaf_index) is now compute_l1_to_l2_message_hash(..., public_content_hash, private_content_hash, leaf_index) and compute_l1_to_l2_message_nullifier(message_hash, secret) is now compute_l1_to_l2_message_nullifier(message_hash, private_content) (only parameter names changed).
  • DOM_SEP__SECRET_HASH is now DOM_SEP__PRIVATE_CONTENT_HASH with a new value.
  • TXE: TestEnvironment::send_l1_to_l2_message(public_content_hash, private_content, sender, recipient) now takes the private content as an array ([secret] where it took secret), and send_l1_to_l2_message_from_secret_hash is now send_l1_to_l2_message_from_private_content_hash.
  • FeeJuice.claim and TokenBridge.claim_public / claim_private are unchanged: they still take their secret parameters, which are used as the private content of the message being consumed.

Aztec.js:

- import { computeSecretHash } from '@aztec-labs/aztec.js/crypto';
- const secretHash = await computeSecretHash(secret);
+ import { computePrivateContentHash } from '@aztec-labs/aztec.js/crypto';
+ const privateContent = [secret];
+ const privateContentHash = await computePrivateContentHash(privateContent);
  • computePrivateContentHash takes the whole private content as an array of fields (mirroring Noir's compute_private_content_hash), where computeSecretHash took a single field.
  • L1ToL2Message.content / .secretHash (@aztec-labs/stdlib/messaging) are now .publicContentHash / .privateContentHash; computeFeeJuiceMessageNullifier(messageHash, privateContent) and getNonNullifiedL1ToL2MessageWitness(..., privateContent, ...) renamed their parameter and now take the private content as an array of fields (privateContent: Fr[]).
  • generateClaimSecret has been removed: generate the claim secret with Fr.random() and hash it with computePrivateContentHash from @aztec-labs/aztec.js/crypto. L2Claim.claimSecret / claimSecretHash keep their names; the hash is now computed with computePrivateContentHash, so the values differ from previous versions (see the domain separator note above).

CLI:

  • aztec get-l1-to-l2-message-witness --secret is now --private-content.
  • The aztec-wallet claimSecret=... payment argument and the claimSecret output key of aztec-wallet bridge-fee-juice / aztec bridge-erc20 are unchanged (the hash values differ because of the domain separator change).

Testing

Run in aztec-packages against the foundation tree with this diff applied as patch 0015 (see AztecProtocol/aztec-packages#25773 for the full list): labs yarn-project build, typecheck, prettier and oracle-version checks; unit tests in stdlib, bot, txe, pxe, ethereum, archiver, cli, cli-wallet and aztec.js (85 suites); aztec-nr TXE tests (all chunks) and noir-contracts tests; e2e single-node/cross-chain/l1_to_l2.test.ts. Rebased onto main at feca567 (2026-11-09). The conflicts were main's additive TXE oracle bump to 10.1 (this PR now goes to 11.0, with TXE_ORACLE_INTERFACE_HASH recomputed from the merged registry), the retryUntil rewrite in bridge_fee_juice.ts and the Timer change in streaming_inbox.test.ts. main has no other new uses of the old names.

benesjan added a commit to AztecProtocol/aztec-packages that referenced this pull request Nov 9, 2026
…h/private_content (#25773)

Implements the rename agreed in [governance discussion
#52](AztecProtocol/governance#52 (comment)).

This is a pure rename fixing stale terminology (Aztec.nr also uses the
new terminology).

| Concept | Old | Solidity / TS | Noir |
|---|---|---|---|
| hashed public payload | `content` | `publicContentHash` |
`public_content_hash` |
| L2-side preimage | `secret` | `privateContent` (`Fr[]`) |
`private_content` (`[Field; N]`) |
| its commitment | `secretHash` | `privateContentHash` |
`private_content_hash` |
| hash helper | `computeSecretHash` / `compute_secret_hash` |
`computePrivateContentHash` | `compute_private_content_hash` |
| domain separator | `DOM_SEP__SECRET_HASH` (`"secret_hash"`) |
`DomainSeparator.PRIVATE_CONTENT_HASH` | `DOM_SEP__PRIVATE_CONTENT_HASH`
(`"private_content_hash"`) |

## How this is split

L1 and Noir protocol changes live here; everything in aztec-node goes
upstream.

- **This PR (foundation):** `l1-contracts` (Inbox, FeeJuicePortal,
interfaces, errors, test portals and tests), `noir-projects/fnd` (the
domain separator in `constants.nr` and its test, the `aztec_sublib` copy
of the L1→L2 helpers, `FeeJuice`), the regenerated genesis constants,
and the labs side carried as
`labs-patches/0015-refactor-rename-L1-L2-message-content-secret-to-publ.patch`
so this tree's labs build and tests run against the renamed ABI and
separator.
- **aztec-node:** the same labs diff, rebased on aztec-node `main`, is
aztec-labs-eng/aztec-node#689. It can only go green once aztec-node's
foundation pin (`BB_VERSION` in `labs-aztec-toolchain/bootstrap.sh`)
moves to a foundation release that includes this PR. When it merges and
this repo bumps the labs gitlink past it, patch 0015 drops out of the
series.

## Breaking changes

- **Protocol**: the domain separator *string* was renamed, so the
private content hash value changes. Pending L1→L2 messages whose hash
was computed with the old helper cannot be consumed with the new one.
`FeeJuice` hashes with it, so its class id rotates and the genesis
constants move (regenerated with
`noir-projects/fnd/scripts/regenerate_genesis_constants.sh --fixtures`;
nothing hand-edited).
- **L1**: `Inbox.sendL2Message(_recipient, _publicContentHash,
_privateContentHash)`, `L1ToL2Msg` struct / `MessageSent` event fields,
`Inbox__PublicContentHashTooLarge` / `Inbox__PrivateContentHashTooLarge`
(new selectors), `FeeJuicePortal.depositToAztecPublic(...,
_privateContentHash)` and its event, reference `TokenPortal` /
`UniswapPortal`.
- **Aztec.nr** (aztec-node):
`consume_l1_to_l2_message(public_content_hash, private_content, sender,
leaf_index)`, `compute_private_content_hash`,
`compute_l1_to_l2_message_{hash,nullifier}` params, TXE
`send_l1_to_l2_message(public_content_hash, private_content: [Field; N],
...)` / `send_l1_to_l2_message_from_private_content_hash` (TXE oracle
version bumped). The `aztec_sublib` copy here follows the same names.
`FeeJuice.claim` / `TokenBridge.claim_*` keep their `secret` params
(used as the message's private content).
- **Aztec.js / stdlib** (aztec-node):
`L1ToL2Message.{publicContentHash,privateContentHash}`,
`computePrivateContentHash(privateContent: Fr[])` (mirrors Noir;
`computeSecretHash` took a single field),
`computeFeeJuiceMessageNullifier` /
`getNonNullifiedL1ToL2MessageWitness` take `privateContent: Fr[]`.
`generateClaimSecret` removed — use `Fr.random()` +
`computePrivateContentHash`. `L2Claim.claimSecret` / `claimSecretHash`
keep their names.
- **Bot** (aztec-node): crosschain seeds and the inbox bot's persisted
messages use the new field names; `BotStore.SCHEMA_VERSION` 2 → 3, so
older stores are discarded on startup.
- **CLI** (aztec-node): `get-l1-to-l2-message-witness
--private-content`.

Out of scope: L2→L1 messages (`L2ToL1Msg.content` etc.),
`TransparentNote.secret_hash` (app-level; only its
`compute_private_content_hash` call updated), versioned docs, and this
repo's `docs/` (pinned to aztec-node's v6 line, which does not carry the
rename).

## Expected failures

- `labs/yarn-project/aztec/src/{mainnet,testnet}_compatibility.test.ts`
pin what the live networks were deployed with; the `FeeJuice` class id
rotation breaks them until the corresponding governance upgrade. They
only run on release branches and were deliberately not touched.
…h/private_content

Labs side of the rename agreed in governance discussion #52. The Inbox data
model is unchanged; the fields are named for what they are: `content` is the
public content hash and `secret`/`secretHash` are the private content and its
hash.

- Aztec.nr: `consume_l1_to_l2_message(public_content_hash, private_content,
  sender, leaf_index)`, `compute_private_content_hash`,
  `DOM_SEP__PRIVATE_CONTENT_HASH`, TXE `send_l1_to_l2_message` (now takes the
  private content as an array) / `send_l1_to_l2_message_from_private_content_hash`.
  TXE oracle version bumped.
- Aztec.js / stdlib: `L1ToL2Message.{publicContentHash,privateContentHash}`,
  `computePrivateContentHash(privateContent: Fr[])`, `generateClaimSecret`
  removed.
- Bot: crosschain seeds and inbox bot records renamed; store schema bumped so
  older stores are discarded.
- CLI: `get-l1-to-l2-message-witness --private-content`.
- Contracts and e2e tests updated to the renamed L1 `Inbox` /
  `FeeJuicePortal` ABI.
@benesjan
benesjan force-pushed the jb/rename-l1-to-l2-message-fields branch from fc60994 to 01db83d Compare November 9, 2026 15:11

This branch has not been deployed

No deployments
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