From 6878e1df4af16815908aa9385e95b6676b449c65 Mon Sep 17 00:00:00 2001 From: IlyasRidhuan Date: Mon, 27 Apr 2026 09:33:14 +0000 Subject: [PATCH 1/8] AZIP-8: Public Key hash to mitigate Harvest-Now-X-Later risks --- AZIPs/azip-8.md | 133 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 AZIPs/azip-8.md diff --git a/AZIPs/azip-8.md b/AZIPs/azip-8.md new file mode 100644 index 0000000..f39516e --- /dev/null +++ b/AZIPs/azip-8.md @@ -0,0 +1,133 @@ +# AZIP-8: Public Key hash to mitigate Harvest-Now-X-Later risks + +## Preamble + +| `azip` | `title` | `description` | `author` | `discussions-to` | `status` | `category` | `created` | +|-----|-|-|-|-|-|-|-| +| 8 | Public Key hash to mitigate Harvest-Now-X-Later risks | Contract instances contain public key hash instead of public key points | Ilyas Ridhuan (@IlyasRidhuan) | - | Draft | Core | 2026-04-27 | + + +## Abstract + +Public keys in Aztec are points on the Grumpkin curve; these public keys are included as part of contract instances that are shared amongst participants. To mitigate the risk of Harvest-Now-Decrypt/Link-Later attacks, this AZIP proposes the migration to storing the public key hash of each +public key in the contract instance rather than the points themselves. + +Note this does NOT apply to the Incoming Viewing Key (ivk) which needs to remain as a point to satisfy the current encrypt-to-address scheme. + +## Impacted Stakeholders + +### App Developers +Noir contract authors who consume `get_public_keys(account)` see a struct reshape from `Point` to `Field` (a pre-computed hash), and the field-name convention changes from `masterNullifierPublicKey.hash()` to `npk_hash`. Existing contracts that consumed `npk_m`, `ovpk_m`, or `spk_m` as curve points will not compile and must be redesigned (no such consumers exist in current aztec-nr). + +### Infrastructure Providers (Indexers, P2P Nodes, Block Explorers) +Off-chain decoders of the `ContractInstancePublished` event must update to the new payload shape (15 → 12 fields). + +### Wallets +The `PublicKeys` struct changes from four `Point` fields to one `Point` (`IncomingViewingPublicKey`) plus three `Fr` hashes. + +## Motivation + +A contract instance in Aztec contains the set of public keys used for sensitive operations such as encrypting, signing, and nullifying. These keys are currently stored in the instance as elliptic points on the Grumpkin curve. +These instances need to be shared amongst participants in order for all parties to be able to validate the correctness of the instance they are interacting with (via address derivation). + +A nefarious party may choose to collect (harvest) all on-chain information in the hopes that, if a quantum computer becomes available, they will be able to break the discrete log security of these points. By recovering the secret keys of these points, +they would be able to decrypt, link, and spend a user's notes, resulting in a total loss of funds and privacy. + +## Specification + +> The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174 + +### Overview of Different Keys + +| `key name` | `key-pair (secret / public)` | `Description` | +|------------|------------------------------|----------------| +| Nullifier Hiding Key | nhk / nhpk | Used to create nullifiers (e.g. when spending notes) | +| Incoming Viewing Key | ivsk / ivpk | Used to decrypt incoming ciphertexts. Used in encrypt-to-address | +| Outgoing Viewing Key | ovsk / ovpk | Used to encrypt outgoing logs. Used for record-keeping | +| Tagging Key | tsk / tpk | Used for tagging and note discovery | + + +### Change to Hashing Scheme for a Public Key +The protocol MUST compute the `public_key_hash` using a domain-separated Poseidon2 hash with a serialised point but MUST NOT include the infinity flag. The infinity flag is always false for the public keys. + +```noir +// Previous scheme +public_key_hash = Poseidon2::hash(point.x, point.y, point.is_inf) + +// Updated scheme +// where DOM_SEP__PUBLIC_KEY_HASH = poseidon2_hash_bytes(b"az_dom_sep__public_key_hash") +public_key_hash = Poseidon2::hash([DOM_SEP__PUBLIC_KEY_HASH, point.x, point.y]) +``` + +### Changes to Contract Instances and Event Payload + +The protocol-circuits `PublicKeys` struct SHALL be: + +```noir +pub struct PublicKeys { + pub npk_hash: Field, + pub ivpk: IvpkM, + pub ovpk_hash: Field, + pub tpk_hash: Field, +} +``` + + +The event payload MUST change from 15 fields to 12 fields: + +```noir +[ MAGIC, address, version, salt, class_id, init_hash, + npk_hash, // 2 fields → 1 field + ivpk.x, ivpk.y, // unchanged + ovpk_hash, // 2 fields → 1 field + tpk_hash, // 2 fields → 1 field + deployer ] +``` + +`ContractInstancePublished.version` and `SerializableContractInstance.VERSION` MUST be bumped from 1 to 2. + +### Change to Public Keys Hash Value in Address Derivation + +`public_keys_hash` MUST compute one hash for `ivpk` in-circuit and combine the four hashes using `DOM_SEP__PUBLIC_KEYS_HASH`. It MUST NOT recompute the hashes for `npk`, `ovpk`, or `tpk` as these values are only available to their owner. + +```noir +public_keys_hash = Poseidon2::hash([ + DOM_SEP__PUBLIC_KEYS_HASH, + npk_hash, + Poseidon2::hash([DOM_SEP__PUBLIC_KEY_HASH, ivpk.x, ivpk.y]), + ovpk_hash, + tpk_hash ]); + +``` + +### Performance Impact +While an additional layer of public key hashing is required, this does not need to happen in circuit. Overall, the number of poseidon2 permutation rounds decreases by 2 as the public keys hash is comprised of 5 elements now instead of 13. We need to perform an extra poseidon2 hash to compute the ivpk_hash in the circuit. + + +## Rationale +Harvest-Now-X-Later is a genuine concern across blockchains and it is prudent to proactively prepare for a post-quantum future. By keeping the public keys on the client device, we can minimise the risk that a harvest adversary is able to retroactively link a user's on-chain behavior. + +While we accept that the ivsk is susceptible given that the public key needs to remain in point form, it is the combination of keys (e.g. ivsk + nhk) that would result in a loss of funds or a complete breakdown of privacy. + +| Key | Impact if compromised | Risk Mitigated By this Proposal | +|------|-----------------------|---------------------------------| +| nhk | Partial Privacy breach, spend-graph linkability.
No funds loss unless the signing key is also compromised. | Yes | +| ivsk | Partial Privacy breach, read access to user account.
Access to all incoming private logs.
Access to all balances and app state.
Able to recover all note plaintexts to build a spend witness.
No funds loss unless the signing key is compromised; private-funds loss additionally requires access to the nhk. | No | +| ovsk | Partial Privacy breach, decrypts any of the user's own bookkeeping logs of sent notes.
Able to see which contracts the user called, amounts transferred, and recipient addresses for the user's own txs.
No funds loss. | Yes | +| tsk | Partial Privacy breach, metadata linkability (metadata only).
Accelerates filtering of private logs sent to the user.
No funds loss. | Yes | + + +## Backwards Compatibility +This proposal is NOT backward compatible and represents a breaking change to the protocol. + +1. **Address invalidation.** Every existing contract address and account address is derived using `public_keys_hash`. A change to the hashing scheme entails regeneration of addresses. +2. **PXE database invalidation.** Existing PXE databases carrying `{n,iv,ov,t}pk_hash` entries computed under the old scheme are invalid. +3. **`ContractInstancePublished` event consumers.** Indexers and P2P decoders that parse the v1 payload (15 fields) MUST be updated to the v2 payload (12 fields). + +## Security Considerations +### On-chain validation of non-ivpk +The nhpk, ovpk, and tpk are no longer checked in circuit to be on curve or to not be the point at infinity (for example, during `publish_for_public_execution`). This becomes a trust assumption for the user's PXE to guarantee, as generating off-curve keys (for example, an nhpk) would result in unspendable notes. + +## Copyright Waiver: +Copyright and related rights waived via [CC0](https://github.com/AztecProtocol/governance/blob/main/LICENSE). + From 7875d31eebaca2682395cbb3e6efa1b7a0847f94 Mon Sep 17 00:00:00 2001 From: Ilyas Ridhuan Date: Tue, 28 Apr 2026 13:45:29 +0100 Subject: [PATCH 2/8] Apply suggestions from code review Co-authored-by: Michael Connor --- AZIPs/azip-8.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/AZIPs/azip-8.md b/AZIPs/azip-8.md index f39516e..cc588d6 100644 --- a/AZIPs/azip-8.md +++ b/AZIPs/azip-8.md @@ -4,7 +4,7 @@ | `azip` | `title` | `description` | `author` | `discussions-to` | `status` | `category` | `created` | |-----|-|-|-|-|-|-|-| -| 8 | Public Key hash to mitigate Harvest-Now-X-Later risks | Contract instances contain public key hash instead of public key points | Ilyas Ridhuan (@IlyasRidhuan) | - | Draft | Core | 2026-04-27 | +| 8 | Public Key hash to mitigate Harvest-Now-X-Later risks | Contract instances contain public key hash instead of public key points | Ilyas Ridhuan (@IlyasRidhuan), Mike Connor (@iAmMichaelConnor) | - | Draft | Core | 2026-04-27 | ## Abstract @@ -101,7 +101,7 @@ public_keys_hash = Poseidon2::hash([ ``` ### Performance Impact -While an additional layer of public key hashing is required, this does not need to happen in circuit. Overall, the number of poseidon2 permutation rounds decreases by 2 as the public keys hash is comprised of 5 elements now instead of 13. We need to perform an extra poseidon2 hash to compute the ivpk_hash in the circuit. +While an additional layer of public key hashing is required, this does not need to happen in circuit. Overall, the number of poseidon2 permutation rounds to derive an address decreases by 2 as the public keys hash is comprised of 5 elements now instead of 13. We need to perform an extra poseidon2 hash to compute the ivpk_hash in the circuit. ## Rationale @@ -111,14 +111,14 @@ While we accept that the ivsk is susceptible given that the public key needs to | Key | Impact if compromised | Risk Mitigated By this Proposal | |------|-----------------------|---------------------------------| -| nhk | Partial Privacy breach, spend-graph linkability.
No funds loss unless the signing key is also compromised. | Yes | -| ivsk | Partial Privacy breach, read access to user account.
Access to all incoming private logs.
Access to all balances and app state.
Able to recover all note plaintexts to build a spend witness.
No funds loss unless the signing key is compromised; private-funds loss additionally requires access to the nhk. | No | +| nhk | Partial Privacy breach, spend-graph linkability.
No funds loss unless the abstract tx authorization mechanism of the user's account contract is also compromised. | Yes | +| ivsk | Partial Privacy breach, read access to all messages that were encrypted to the user in a very specific way: via non-interactive secret sharing over a public bulletin board (such as via Aztec's private logs). That is, by broadcasting an ephemeral public key as a means to non-interactively establish a shared secret with the user (a.k.a. ephemeral-static ECDH).
Note: not all private messages on Aztec are submitted in this way: offchain logs can be used instead; and other, non-leaky secret-sharing schemes are programmable by users.
For apps which _do_ assemble logs in the way described formerly, an attacker who learns the user's ivsk and the ephemeral public key can:
Access the incoming private logs.
Access the balances and app state that were conveyed through those messages.
Recover note plaintexts to build a spend witness.
No funds loss unless the user's abstract tx authorization key is also compromised; private-funds loss additionally requires access to the nhk. | No | | ovsk | Partial Privacy breach, decrypts any of the user's own bookkeeping logs of sent notes.
Able to see which contracts the user called, amounts transferred, and recipient addresses for the user's own txs.
No funds loss. | Yes | -| tsk | Partial Privacy breach, metadata linkability (metadata only).
Accelerates filtering of private logs sent to the user.
No funds loss. | Yes | +| tsk | This key is currently unused.
No funds loss. | Yes | ## Backwards Compatibility -This proposal is NOT backward compatible and represents a breaking change to the protocol. +This proposal is NOT backward compatible and represents a breaking change to the protocol. This AZIP MUST therefore be shipped as part of a new Aztec rollup version. 1. **Address invalidation.** Every existing contract address and account address is derived using `public_keys_hash`. A change to the hashing scheme entails regeneration of addresses. 2. **PXE database invalidation.** Existing PXE databases carrying `{n,iv,ov,t}pk_hash` entries computed under the old scheme are invalid. From a48d90eda200df58562b85f93eab6f29cbeb10c9 Mon Sep 17 00:00:00 2001 From: IlyasRidhuan Date: Tue, 28 Apr 2026 13:23:28 +0000 Subject: [PATCH 3/8] updates --- AZIPs/azip-8.md | 103 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 97 insertions(+), 6 deletions(-) diff --git a/AZIPs/azip-8.md b/AZIPs/azip-8.md index cc588d6..26aa6a6 100644 --- a/AZIPs/azip-8.md +++ b/AZIPs/azip-8.md @@ -12,12 +12,13 @@ Public keys in Aztec are points on the Grumpkin curve; these public keys are included as part of contract instances that are shared amongst participants. To mitigate the risk of Harvest-Now-Decrypt/Link-Later attacks, this AZIP proposes the migration to storing the public key hash of each public key in the contract instance rather than the points themselves. -Note this does NOT apply to the Incoming Viewing Key (ivk) which needs to remain as a point to satisfy the current encrypt-to-address scheme. +Note this does NOT apply to the Incoming Viewing Public Key (ivpk) which needs to remain as a point to satisfy the current encrypt-to-address scheme. ## Impacted Stakeholders ### App Developers -Noir contract authors who consume `get_public_keys(account)` see a struct reshape from `Point` to `Field` (a pre-computed hash), and the field-name convention changes from `masterNullifierPublicKey.hash()` to `npk_hash`. Existing contracts that consumed `npk_m`, `ovpk_m`, or `spk_m` as curve points will not compile and must be redesigned (no such consumers exist in current aztec-nr). +Noir contract authors who consume `get_public_keys(account)` see a struct reshape from `Point` to `Field` (a pre-computed hash), and the field-name convention changes from `masterNullifierPublicKey.hash()` to `npk_hash`. Existing contracts that consumed `npk_m`, `ovpk_m`, or `spk_m` as curve points will not compile and must be redesigned. +Apps MUST NOT see `npk_m` or `ovpk_m`; the Key Validation Request oracle and aztec-nr APIs enforce this at the interface level. ### Infrastructure Providers (Indexers, P2P Nodes, Block Explorers) Off-chain decoders of the `ContractInstancePublished` event must update to the new payload shape (15 → 12 fields). @@ -48,12 +49,9 @@ they would be able to decrypt, link, and spend a user's notes, resulting in a to ### Change to Hashing Scheme for a Public Key -The protocol MUST compute the `public_key_hash` using a domain-separated Poseidon2 hash with a serialised point but MUST NOT include the infinity flag. The infinity flag is always false for the public keys. +The protocol MUST compute the `public_key_hash` using a domain-separated Poseidon2 hash over the serialised point. ```noir -// Previous scheme -public_key_hash = Poseidon2::hash(point.x, point.y, point.is_inf) - // Updated scheme // where DOM_SEP__PUBLIC_KEY_HASH = poseidon2_hash_bytes(b"az_dom_sep__public_key_hash") public_key_hash = Poseidon2::hash([DOM_SEP__PUBLIC_KEY_HASH, point.x, point.y]) @@ -100,6 +98,95 @@ public_keys_hash = Poseidon2::hash([ ``` +The full address derivation under this proposal is shown below. Yellow highlights mark the new pre-hashed values; the off-circuit subgraph captures the work shifted out of the circuit by this AZIP. + +```mermaid +flowchart TD + %% --- salted initialisation hash --- + DSS["DOM_SEP__INIT_HASH"] + SALT["salt"] + INIT["initialisation_hash"] + DEP["deployer_address"] + H2(("Poseidon2")) + SIH["salted_initialisation_hash"] + DSS --> H2 + SALT --> H2 + INIT --> H2 + DEP --> H2 + H2 --> SIH + + %% --- partial address --- + DSPA["DOM_SEP__PARTIAL_ADDR"] + CID["contract_class_id"] + H3(("Poseidon2")) + PA["partial_address"] + DSPA --> H3 + CID --> H3 + SIH --> H3 + H3 --> PA + + %% --- public keys hash, split across PXE and circuit --- + subgraph offcircuit["Off-circuit (PXE) — NEW"] + NPK["npk point"] + OVPK["ovpk point"] + TPK["tpk point"] + NPKH["npk_hash"]:::new + OVPKH["ovpk_hash"]:::new + TPKH["tpk_hash"]:::new + NPK -. poseidon2 .-> NPKH + OVPK -. poseidon2 .-> OVPKH + TPK -. poseidon2 .-> TPKH + end + + subgraph incircuit["In-circuit"] + IVPK["ivpk point"] + IVPKH["ivpk_hash"]:::new + PKH["public_keys_hash"] + IVPK -->|poseidon2| IVPKH + NPKH --> PKH + IVPKH --> PKH + OVPKH --> PKH + TPKH --> PKH + end + + %% --- pre address --- + DSCA["DOM_SEP__CONTRACT_ADDR_V1"] + H5(("Poseidon2")) + PRE["pre_addr"] + DSCA --> H5 + PKH --> H5 + PA --> H5 + H5 --> PRE + + %% --- address point and address --- + EC["pre_addr · G + ivpk"] + AP["address_point"] + ADDR["address (x-coordinate)"] + PRE --> EC + IVPK -. reused .-> EC + EC --> AP + AP --> ADDR + + classDef new fill:#fff4cd,stroke:#d4a017,stroke-width:2px,color:#000 + linkStyle 9,10,11,12 stroke:#d4a017,stroke-width:2px + linkStyle 13,14,15,16 stroke:#d4a017,stroke-width:1.5px +``` + +### Key Validation Requests + +The Key Validation Request (KVR) interface MUST change. Today an app receives `{ sk_app, Pk_m, app_address }`; under this proposal it becomes `{ sk_app, hashed_pk_m, app_address }`. Apps MUST NOT receive `Pk_m`. This entails: +- aztec-nr interface and constraint changes for any contract issuing a KVR. +- Kernel circuit changes to validate the new request shape. + +### aztec-nr Oracle Interface + +The oracle for retrieving public keys MUST return hashed public keys rather than points, and the oracle name SHOULD change accordingly. Oracle interfaces are part of the protocol surface: alternative smart contract frameworks may need to execute aztec-nr contracts (and vice versa) in future. + +### AVM and Kernel Changes + +- AVM opcodes and logic that touch public keys MUST be updated to operate over hashes rather than points. +- Kernel circuits MUST be updated to validate the contract address of the function being processed against the new `public_keys_hash` derivation, and to handle the new KVR shape. + ### Performance Impact While an additional layer of public key hashing is required, this does not need to happen in circuit. Overall, the number of poseidon2 permutation rounds to derive an address decreases by 2 as the public keys hash is comprised of 5 elements now instead of 13. We need to perform an extra poseidon2 hash to compute the ivpk_hash in the circuit. @@ -109,6 +196,10 @@ Harvest-Now-X-Later is a genuine concern across blockchains and it is prudent to While we accept that the ivsk is susceptible given that the public key needs to remain in point form, it is the combination of keys (e.g. ivsk + nhk) that would result in a loss of funds or a complete breakdown of privacy. +Two keys remain effectively unprotectable by this proposal: +- **`ivpk_m`** must be visible to any app circuit that derives an address, since address derivation encodes `ivpk_m` into its constraint system. Leakage is practically unavoidable. +- **The signing public key** (the to-be-repurposed `tpk` slot) is exposed whenever the user signs something for a counterparty, since verification requires it. + | Key | Impact if compromised | Risk Mitigated By this Proposal | |------|-----------------------|---------------------------------| | nhk | Partial Privacy breach, spend-graph linkability.
No funds loss unless the abstract tx authorization mechanism of the user's account contract is also compromised. | Yes | From 226300e38c40b0a9398f2747b54b6f19f0b5a129 Mon Sep 17 00:00:00 2001 From: Ilyas Ridhuan Date: Wed, 29 Apr 2026 15:29:42 +0100 Subject: [PATCH 4/8] Apply suggestions from code review Co-authored-by: ciaranightingale <52419674+ciaranightingale@users.noreply.github.com> --- AZIPs/azip-8.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AZIPs/azip-8.md b/AZIPs/azip-8.md index 26aa6a6..4b23710 100644 --- a/AZIPs/azip-8.md +++ b/AZIPs/azip-8.md @@ -44,8 +44,8 @@ they would be able to decrypt, link, and spend a user's notes, resulting in a to |------------|------------------------------|----------------| | Nullifier Hiding Key | nhk / nhpk | Used to create nullifiers (e.g. when spending notes) | | Incoming Viewing Key | ivsk / ivpk | Used to decrypt incoming ciphertexts. Used in encrypt-to-address | -| Outgoing Viewing Key | ovsk / ovpk | Used to encrypt outgoing logs. Used for record-keeping | -| Tagging Key | tsk / tpk | Used for tagging and note discovery | +| Outgoing Viewing Key | ovsk / ovpk | For encrypting outgoing logs. Used for record-keeping (not currently used) | +| Tagging Key | tsk / tpk | For tagging and note discovery (not currently used) | ### Change to Hashing Scheme for a Public Key From aa08e16f780c859c2efb6a47c919397616ac74dd Mon Sep 17 00:00:00 2001 From: Ilyas Ridhuan Date: Wed, 29 Apr 2026 16:09:21 +0100 Subject: [PATCH 5/8] Update AZIPs/azip-8.md Co-authored-by: ciaranightingale <52419674+ciaranightingale@users.noreply.github.com> --- AZIPs/azip-8.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AZIPs/azip-8.md b/AZIPs/azip-8.md index 4b23710..8b85781 100644 --- a/AZIPs/azip-8.md +++ b/AZIPs/azip-8.md @@ -4,7 +4,7 @@ | `azip` | `title` | `description` | `author` | `discussions-to` | `status` | `category` | `created` | |-----|-|-|-|-|-|-|-| -| 8 | Public Key hash to mitigate Harvest-Now-X-Later risks | Contract instances contain public key hash instead of public key points | Ilyas Ridhuan (@IlyasRidhuan), Mike Connor (@iAmMichaelConnor) | - | Draft | Core | 2026-04-27 | +| 8 | Public Key hash to mitigate Harvest-Now-X-Later risks | Contract instances contain public key hash instead of public key points | Ilyas Ridhuan (@IlyasRidhuan), Mike Connor (@iAmMichaelConnor), Ciara Nightingale (@ciaranightingale) | - | Draft | Core | 2026-04-27 | ## Abstract From 6a9ce08a7b9458326102fcac99e61d48593bd001 Mon Sep 17 00:00:00 2001 From: IlyasRidhuan Date: Thu, 30 Apr 2026 13:36:38 +0000 Subject: [PATCH 6/8] address comments --- AZIPs/azip-8.md | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/AZIPs/azip-8.md b/AZIPs/azip-8.md index 8b85781..5d75f25 100644 --- a/AZIPs/azip-8.md +++ b/AZIPs/azip-8.md @@ -17,7 +17,7 @@ Note this does NOT apply to the Incoming Viewing Public Key (ivpk) which needs t ## Impacted Stakeholders ### App Developers -Noir contract authors who consume `get_public_keys(account)` see a struct reshape from `Point` to `Field` (a pre-computed hash), and the field-name convention changes from `masterNullifierPublicKey.hash()` to `npk_hash`. Existing contracts that consumed `npk_m`, `ovpk_m`, or `spk_m` as curve points will not compile and must be redesigned. +Noir contract authors who consume `get_public_keys(account)` see a struct reshape from `Point` to `Field` (a pre-computed hash), and the field-name convention changes from `masterNullifierPublicKey.hash()` to `npk_m_hash`. Existing contracts that consumed `npk_m`, `ovpk_m`, or `spk_m` as curve points will not compile and must be redesigned. Apps MUST NOT see `npk_m` or `ovpk_m`; the Key Validation Request oracle and aztec-nr APIs enforce this at the interface level. ### Infrastructure Providers (Indexers, P2P Nodes, Block Explorers) @@ -53,8 +53,8 @@ The protocol MUST compute the `public_key_hash` using a domain-separated Poseido ```noir // Updated scheme -// where DOM_SEP__PUBLIC_KEY_HASH = poseidon2_hash_bytes(b"az_dom_sep__public_key_hash") -public_key_hash = Poseidon2::hash([DOM_SEP__PUBLIC_KEY_HASH, point.x, point.y]) +// where DOM_SEP__SINGLE_PUBLIC_KEY_HASH = poseidon2_hash_bytes(b"az_dom_sep__single_public_key_hash") +public_key_hash = Poseidon2::hash([DOM_SEP__SINGLE_PUBLIC_KEY_HASH, point.x, point.y]) ``` ### Changes to Contract Instances and Event Payload @@ -63,10 +63,10 @@ The protocol-circuits `PublicKeys` struct SHALL be: ```noir pub struct PublicKeys { - pub npk_hash: Field, - pub ivpk: IvpkM, - pub ovpk_hash: Field, - pub tpk_hash: Field, + pub npk_m_hash: Field, + pub ivpk_m: IvpkM, + pub ovpk_m_hash: Field, + pub tpk_m_hash: Field, } ``` @@ -75,10 +75,10 @@ The event payload MUST change from 15 fields to 12 fields: ```noir [ MAGIC, address, version, salt, class_id, init_hash, - npk_hash, // 2 fields → 1 field - ivpk.x, ivpk.y, // unchanged - ovpk_hash, // 2 fields → 1 field - tpk_hash, // 2 fields → 1 field + npk_m_hash, // 2 fields → 1 field + ivpk_m.x, ivpk_m.y, // unchanged + ovpk_m_hash, // 2 fields → 1 field + tpk_m_hash, // 2 fields → 1 field deployer ] ``` @@ -91,10 +91,10 @@ The event payload MUST change from 15 fields to 12 fields: ```noir public_keys_hash = Poseidon2::hash([ DOM_SEP__PUBLIC_KEYS_HASH, - npk_hash, - Poseidon2::hash([DOM_SEP__PUBLIC_KEY_HASH, ivpk.x, ivpk.y]), - ovpk_hash, - tpk_hash ]); + npk_m_hash, + Poseidon2::hash([DOM_SEP__SINGLE_PUBLIC_KEY_HASH, ivpk_m.x, ivpk_m.y]), + ovpk_m_hash, + tpk_m_hash ]); ``` @@ -130,9 +130,9 @@ flowchart TD NPK["npk point"] OVPK["ovpk point"] TPK["tpk point"] - NPKH["npk_hash"]:::new - OVPKH["ovpk_hash"]:::new - TPKH["tpk_hash"]:::new + NPKH["npk_m_hash"]:::new + OVPKH["ovpk_m_hash"]:::new + TPKH["tpk_m_hash"]:::new NPK -. poseidon2 .-> NPKH OVPK -. poseidon2 .-> OVPKH TPK -. poseidon2 .-> TPKH From 5890a99381075c88b2752ec6fcf6c61780cba173 Mon Sep 17 00:00:00 2001 From: IlyasRidhuan Date: Thu, 30 Apr 2026 13:37:23 +0000 Subject: [PATCH 7/8] one more change --- AZIPs/azip-8.md | 1 + 1 file changed, 1 insertion(+) diff --git a/AZIPs/azip-8.md b/AZIPs/azip-8.md index 5d75f25..82255fc 100644 --- a/AZIPs/azip-8.md +++ b/AZIPs/azip-8.md @@ -15,6 +15,7 @@ public key in the contract instance rather than the points themselves. Note this does NOT apply to the Incoming Viewing Public Key (ivpk) which needs to remain as a point to satisfy the current encrypt-to-address scheme. ## Impacted Stakeholders +This AZIP changes contract address derivation, so every stakeholder that consumes, displays, or persists an Aztec address is affected on the next version of Aztec that adopts it. See [Backwards Compatibility](#backwards-compatibility) for the underlying change. ### App Developers Noir contract authors who consume `get_public_keys(account)` see a struct reshape from `Point` to `Field` (a pre-computed hash), and the field-name convention changes from `masterNullifierPublicKey.hash()` to `npk_m_hash`. Existing contracts that consumed `npk_m`, `ovpk_m`, or `spk_m` as curve points will not compile and must be redesigned. From dbe7e8115e9592cc02990c6cfa1b7fcfb6398a07 Mon Sep 17 00:00:00 2001 From: Koen Date: Thu, 14 May 2026 11:40:07 +0400 Subject: [PATCH 8/8] chore: move status to accepted --- AZIPs/azip-8.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AZIPs/azip-8.md b/AZIPs/azip-8.md index 82255fc..0c570f7 100644 --- a/AZIPs/azip-8.md +++ b/AZIPs/azip-8.md @@ -4,7 +4,7 @@ | `azip` | `title` | `description` | `author` | `discussions-to` | `status` | `category` | `created` | |-----|-|-|-|-|-|-|-| -| 8 | Public Key hash to mitigate Harvest-Now-X-Later risks | Contract instances contain public key hash instead of public key points | Ilyas Ridhuan (@IlyasRidhuan), Mike Connor (@iAmMichaelConnor), Ciara Nightingale (@ciaranightingale) | - | Draft | Core | 2026-04-27 | +| 8 | Public Key hash to mitigate Harvest-Now-X-Later risks | Contract instances contain public key hash instead of public key points | Ilyas Ridhuan (@IlyasRidhuan), Mike Connor (@iAmMichaelConnor), Ciara Nightingale (@ciaranightingale) | - | Accepted | Core | 2026-04-27 | ## Abstract