From baba31a278699e05fb3bb360645eeda78c64ba91 Mon Sep 17 00:00:00 2001 From: Nico Chamo Date: Tue, 7 Jul 2026 16:34:03 -0300 Subject: [PATCH 1/3] feat(e2e): interactive handshake e2e with in-process responder --- .../interactive_handshake_responder.ts | 126 ++++++++++++++++++ .../src/automine/delivery/onchain.test.ts | 58 +++++++- .../delivery/onchain_delivery_harness.ts | 56 +++++++- .../src/handshake-registry/constants.ts | 10 ++ .../src/handshake-registry/index.ts | 1 + 5 files changed, 243 insertions(+), 8 deletions(-) create mode 100644 yarn-project/end-to-end/src/automine/delivery/interactive_handshake_responder.ts diff --git a/yarn-project/end-to-end/src/automine/delivery/interactive_handshake_responder.ts b/yarn-project/end-to-end/src/automine/delivery/interactive_handshake_responder.ts new file mode 100644 index 000000000000..954723a14b39 --- /dev/null +++ b/yarn-project/end-to-end/src/automine/delivery/interactive_handshake_responder.ts @@ -0,0 +1,126 @@ +import { AztecAddress, type CompleteAddress } from '@aztec/aztec.js/addresses'; +import { DomainSeparator } from '@aztec/constants'; +import { poseidon2HashWithSeparator } from '@aztec/foundation/crypto/poseidon'; +import { Schnorr, type SchnorrSignature } from '@aztec/foundation/crypto/schnorr'; +import { Fq, Fr } from '@aztec/foundation/curves/bn254'; +import type { GrumpkinScalar } from '@aztec/foundation/curves/grumpkin'; +import { + INTERACTIVE_HANDSHAKE_REQUEST_KIND, + STANDARD_HANDSHAKE_REGISTRY_ADDRESS, +} from '@aztec/standard-contracts/handshake-registry/constants'; +import { type PublicKeys, derivePublicKeyFromSecretKey } from '@aztec/stdlib/keys'; + +import type { CustomRequest } from './onchain_delivery_harness.js'; + +/** + * The decoded payload of the registry's interactive-handshake signature request. Note it never carries the sender, + * so the recipient authorizes the handshake without learning who initiated it. + */ +export type InteractiveHandshakeRequest = { + /** The account whose authorization is being requested. */ + recipient: AztecAddress; + chainId: Fr; + version: Fr; + /** The x-coordinate of the handshake's ephemeral public key (its y-coordinate is positive by construction). */ + ephPkX: Fr; +}; + +/** + * The recipient's signed authorization for an interactive handshake. Mirrors the registry contract's + * `RecipientSignature` struct field for field. + */ +export type RecipientSignature = { + /** The recipient's master public keys, bound in-circuit to the recipient's address via `partialAddress`. */ + publicKeys: PublicKeys; + partialAddress: Fr; + /** The x-coordinate of the recipient's master message-signing public key. */ + mspkX: Fr; + /** Whether that key's y-coordinate is positive, so the circuit can reconstruct the point from `mspkX`. */ + mspkYIsPositive: boolean; + /** The schnorr signature over the handshake message. */ + signature: SchnorrSignature; +}; + +/** + * Parses and validates the registry's interactive-handshake signature request. + * + * @throws If the request kind is not {@link INTERACTIVE_HANDSHAKE_REQUEST_KIND}, the issuing contract is not the + * standard HandshakeRegistry, or the payload does not have the expected shape. + */ +export function parseInteractiveHandshakeRequest(request: CustomRequest): InteractiveHandshakeRequest { + if (!request.kind.equals(INTERACTIVE_HANDSHAKE_REQUEST_KIND)) { + throw new Error(`Not an interactive-handshake signature request: unexpected kind ${request.kind}`); + } + if (!request.contractAddress.equals(STANDARD_HANDSHAKE_REGISTRY_ADDRESS)) { + throw new Error( + `Interactive-handshake signature request issued by ${request.contractAddress}, expected the standard HandshakeRegistry at ${STANDARD_HANDSHAKE_REGISTRY_ADDRESS}`, + ); + } + if (request.payload.length !== 4) { + throw new Error(`Interactive-handshake signature request payload has ${request.payload.length} fields, expected 4`); + } + + const [recipient, chainId, version, ephPkX] = request.payload; + return { recipient: new AztecAddress(recipient), chainId, version, ephPkX }; +} + +/** + * Produces the recipient's signed authorization for an interactive handshake, signing with the master + * message-signing secret key. + */ +export async function signInteractiveHandshake( + request: InteractiveHandshakeRequest, + completeAddress: CompleteAddress, + masterMessageSigningSecretKey: GrumpkinScalar, +): Promise { + const mspk = await derivePublicKeyFromSecretKey(masterMessageSigningSecretKey); + const [mspkX, mspkYIsPositive] = mspk.toXAndSign(); + + const message = await computeInteractiveHandshakeSignatureMessage({ + chainId: request.chainId, + version: request.version, + registry: STANDARD_HANDSHAKE_REGISTRY_ADDRESS, + ephPkX: request.ephPkX, + }); + const signature = await new Schnorr().constructSignature(message, masterMessageSigningSecretKey); + + return { + publicKeys: completeAddress.publicKeys, + partialAddress: completeAddress.partialAddress, + mspkX, + mspkYIsPositive, + signature, + }; +} + +/** Serializes a {@link RecipientSignature} to the field layout the registry's in-circuit deserialization expects. */ +export function recipientSignatureToFields(recipientSignature: RecipientSignature): Fr[] { + const s = Fq.fromBuffer(recipientSignature.signature.s); + const e = Fq.fromBuffer(recipientSignature.signature.e); + return [ + ...recipientSignature.publicKeys.toFields(), + recipientSignature.partialAddress, + recipientSignature.mspkX, + new Fr(recipientSignature.mspkYIsPositive), + s.lo, + s.hi, + e.lo, + e.hi, + ]; +} + +/** + * The message an interactive-handshake authorization signs: the handshake's ephemeral key and chain context under + * `DomainSeparator.INTERACTIVE_HANDSHAKE_SIGNATURE`, exactly as the registry recomputes it in-circuit. + */ +function computeInteractiveHandshakeSignatureMessage(args: { + chainId: Fr; + version: Fr; + registry: AztecAddress; + ephPkX: Fr; +}): Promise { + return poseidon2HashWithSeparator( + [args.chainId, args.version, args.registry, args.ephPkX], + DomainSeparator.INTERACTIVE_HANDSHAKE_SIGNATURE, + ); +} diff --git a/yarn-project/end-to-end/src/automine/delivery/onchain.test.ts b/yarn-project/end-to-end/src/automine/delivery/onchain.test.ts index cdab97abcf31..dbda404ddab1 100644 --- a/yarn-project/end-to-end/src/automine/delivery/onchain.test.ts +++ b/yarn-project/end-to-end/src/automine/delivery/onchain.test.ts @@ -1,6 +1,15 @@ +import type { InitialAccountData } from '@aztec/accounts/testing'; +import type { CompleteAddress } from '@aztec/aztec.js/addresses'; import { Point } from '@aztec/foundation/curves/grumpkin'; +import { deriveKeys } from '@aztec/stdlib/keys'; -import { buildMessageDeliveryTest } from './onchain_delivery_harness.js'; +import type { TestWallet } from '../../test-wallet/test_wallet.js'; +import { + parseInteractiveHandshakeRequest, + recipientSignatureToFields, + signInteractiveHandshake, +} from './interactive_handshake_responder.js'; +import { type CustomRequestHook, buildMessageDeliveryTest } from './onchain_delivery_harness.js'; describe('onchain delivery', () => { let arbitrarySecret: Point; @@ -34,8 +43,8 @@ describe('onchain delivery', () => { }, }); - // With the recipient registering the sender, - // the recipient PXE reconstructs the address-derived tag and discovers the delivery. + // With the recipient registering the sender, the recipient PXE reconstructs the address-derived tag + // and discovers the delivery. buildMessageDeliveryTest({ strategy: 'address-derived', mode: 'unconstrained', @@ -44,4 +53,47 @@ describe('onchain delivery', () => { await recipientWallet.registerSender(senderAddress); }, }); + + buildMessageDeliveryTest({ + strategy: 'interactive handshake', + mode: 'constrained', + senderHook: () => Promise.resolve({ type: 'interactive-handshake' }), + customRequestResponder: interactiveHandshakeResponder, + }); + + buildMessageDeliveryTest({ + strategy: 'interactive handshake', + mode: 'unconstrained', + senderHook: () => Promise.resolve({ type: 'interactive-handshake' }), + customRequestResponder: interactiveHandshakeResponder, + }); + + // Serves the registry's interactive-handshake signature request for the recipient: registers the handshake on the + // recipient PXE, then answers with the signed response. + function interactiveHandshakeResponder( + recipientWallet: TestWallet, + recipientAccount: InitialAccountData, + recipientCompleteAddress: CompleteAddress, + ): CustomRequestHook { + return async request => { + const parsed = parseInteractiveHandshakeRequest(request); + + // Register before signing. + await recipientWallet.registerTaggingSecretSource({ + kind: 'handshake', + recipient: parsed.recipient, + ephPk: parsed.ephPkX, + }); + + // The master message-signing secret key is deliberately never held by PXE or the key store; the wallet + // derives it client-side from the account secret. + const { masterMessageSigningSecretKey } = await deriveKeys(recipientAccount.secret); + const recipientSignature = await signInteractiveHandshake( + parsed, + recipientCompleteAddress, + masterMessageSigningSecretKey, + ); + return recipientSignatureToFields(recipientSignature); + }; + } }); diff --git a/yarn-project/end-to-end/src/automine/delivery/onchain_delivery_harness.ts b/yarn-project/end-to-end/src/automine/delivery/onchain_delivery_harness.ts index d10ae9196aea..e996350c93f0 100644 --- a/yarn-project/end-to-end/src/automine/delivery/onchain_delivery_harness.ts +++ b/yarn-project/end-to-end/src/automine/delivery/onchain_delivery_harness.ts @@ -1,8 +1,9 @@ import { type InitialAccountData, generateSchnorrAccounts } from '@aztec/accounts/testing'; import type { FieldLike } from '@aztec/aztec.js/abi'; import { NO_FROM } from '@aztec/aztec.js/account'; -import type { AztecAddress } from '@aztec/aztec.js/addresses'; +import type { AztecAddress, CompleteAddress } from '@aztec/aztec.js/addresses'; import type { AztecNode } from '@aztec/aztec.js/node'; +import type { AccountManager } from '@aztec/aztec.js/wallet'; import { BlockNumber } from '@aztec/foundation/branded-types'; import { type DeliveryEvent, OnchainDeliveryTestContract } from '@aztec/noir-test-contracts.js/OnchainDeliveryTest'; import type { PXECreationOptions } from '@aztec/pxe/server'; @@ -18,6 +19,19 @@ import { TestWallet } from '../../test-wallet/test_wallet.js'; // rather than importing the hook type, which `@aztec/pxe/server` does not re-export. export type SenderHook = NonNullable['resolveTaggingSecretStrategy']>; +// The wallet hook resolving a contract's custom request (e.g. the registry's interactive-handshake signature +// request), derived from the exported PXE options for the same reason as `SenderHook`. +export type CustomRequestHook = NonNullable['resolveCustomRequest']>; +export type CustomRequest = Parameters[0]; + +// Builds the hook serving custom requests issued during the sender's simulations. Installed on the sender PXE at +// creation but built only once the recipient exists, since serving typically needs the recipient's wallet and keys. +export type CustomRequestResponder = ( + recipient: TestWallet, + recipientAccount: InitialAccountData, + recipientCompleteAddress: CompleteAddress, +) => CustomRequestHook; + export type Mode = 'constrained' | 'unconstrained'; // A single mode applies to both the event and note sends; `{ events, notes }` sends each in its own mode, which @@ -47,12 +61,15 @@ export function buildMessageDeliveryTest(opts: { recipientAddress: AztecAddress, sender: AztecAddress, ) => Promise; + // Serves the custom requests issued during the sender's simulations (e.g. the registry's interactive-handshake + // signature request). + customRequestResponder?: CustomRequestResponder; // Extra `it()`s to register in this cell's suite, e.g. assertions against state a custom `senderHook` recorded. // Called inside the same `describe`, after the two baseline assertions below, so it shares their `beforeAll` // instead of depending on Jest's cross-`describe` execution order. additionalTests?: () => void; }) { - const { strategy, mode, senderHook, recipientRegistration, additionalTests } = opts; + const { strategy, mode, senderHook, recipientRegistration, customRequestResponder, additionalTests } = opts; const description = `${strategy} x ${formatMode(mode)}`; describe(description, () => { @@ -84,11 +101,14 @@ export function buildMessageDeliveryTest(opts: { ? contractSender.methods.emit_note(recipient, value) : contractSender.methods.emit_note_unconstrained(recipient, value); + let additionallyFundedAccounts: InitialAccountData[]; + let recipientAccount: AccountManager | undefined; + let customRequestCount = 0; + beforeAll(async () => { // The sender PXE holds the sender and carries this cell's tagging-secret-strategy hook. The recipient is funded // at genesis here but created and deployed on the isolated recipient PXE below, so it carries no sender state // from other cells. - let additionallyFundedAccounts: InitialAccountData[]; ({ aztecNode, additionallyFundedAccounts, @@ -98,7 +118,27 @@ export function buildMessageDeliveryTest(opts: { } = await setup(1, { ...AUTOMINE_E2E_OPTS, additionallyFundedAccounts: await generateSchnorrAccounts(1, 'schnorr'), - pxeCreationOptions: { hooks: { resolveTaggingSecretStrategy: senderHook } }, + pxeCreationOptions: { + hooks: { + resolveTaggingSecretStrategy: senderHook, + resolveCustomRequest: async (request: CustomRequest) => { + if (!customRequestResponder) { + throw new Error('A custom request arrived but this test cell has no customRequestResponder configured'); + } + const account = recipientAccount; + if (!account) { + throw new Error('A custom request arrived before the recipient wallet was created'); + } + customRequestCount++; + const respond = customRequestResponder( + walletRecipient, + additionallyFundedAccounts[0], + await account.getCompleteAddress(), + ); + return respond(request); + }, + }, + }, })); ({ wallet: walletRecipient, teardown: teardownRecipient } = await setupPXEAndGetWallet( @@ -108,7 +148,7 @@ export function buildMessageDeliveryTest(opts: { undefined, 'pxe-recipient', )); - const recipientAccount = await walletRecipient.createSchnorrAccount( + recipientAccount = await walletRecipient.createSchnorrAccount( additionallyFundedAccounts[0].secret, additionallyFundedAccounts[0].salt, additionallyFundedAccounts[0].signingKey, @@ -172,6 +212,12 @@ export function buildMessageDeliveryTest(opts: { expect(readNotes).toEqual(noteValues); }); + if (customRequestResponder) { + it('the custom request hook fires exactly once, on the send that bootstraps the tagging secret', () => { + expect(customRequestCount).toBe(1); + }); + } + additionalTests?.(); }); } diff --git a/yarn-project/standard-contracts/src/handshake-registry/constants.ts b/yarn-project/standard-contracts/src/handshake-registry/constants.ts index 48b4cd153728..42f905f9751e 100644 --- a/yarn-project/standard-contracts/src/handshake-registry/constants.ts +++ b/yarn-project/standard-contracts/src/handshake-registry/constants.ts @@ -1,6 +1,8 @@ // Lightweight metadata leaf export for browser bundles: importing from // `@aztec/standard-contracts/handshake-registry/constants` avoids dragging in the // `HandshakeRegistry.json` static import. +import { sha256ToField } from '@aztec/foundation/crypto/sha256'; +import type { Fr } from '@aztec/foundation/curves/bn254'; import type { AztecAddress } from '@aztec/stdlib/aztec-address'; import { StandardContractAddress, StandardContractClassId, StandardContractSalt } from '../standard_contract_data.js'; @@ -8,3 +10,11 @@ import { StandardContractAddress, StandardContractClassId, StandardContractSalt export const STANDARD_HANDSHAKE_REGISTRY_ADDRESS: AztecAddress = StandardContractAddress.HandshakeRegistry; export const STANDARD_HANDSHAKE_REGISTRY_CLASS_ID = StandardContractClassId.HandshakeRegistry; export const STANDARD_HANDSHAKE_REGISTRY_SALT = StandardContractSalt.HandshakeRegistry; + +/** + * Request kind under which the HandshakeRegistry asks for a recipient's interactive-handshake signature through the + * `resolveCustomRequest` hook. Mirrors `INTERACTIVE_HANDSHAKE_REQUEST_KIND` in the registry contract. + */ +export const INTERACTIVE_HANDSHAKE_REQUEST_KIND: Fr = sha256ToField([ + Buffer.from('HANDSHAKE_REGISTRY::INTERACTIVE_HANDSHAKE_REQUEST'), +]); diff --git a/yarn-project/standard-contracts/src/handshake-registry/index.ts b/yarn-project/standard-contracts/src/handshake-registry/index.ts index f10e7186a45f..2cc367647d2e 100644 --- a/yarn-project/standard-contracts/src/handshake-registry/index.ts +++ b/yarn-project/standard-contracts/src/handshake-registry/index.ts @@ -6,6 +6,7 @@ import { makeStandardContract } from '../make_standard_contract.js'; import type { StandardContract } from '../standard_contract.js'; export { + INTERACTIVE_HANDSHAKE_REQUEST_KIND, STANDARD_HANDSHAKE_REGISTRY_ADDRESS, STANDARD_HANDSHAKE_REGISTRY_CLASS_ID, STANDARD_HANDSHAKE_REGISTRY_SALT, From 5222bcaf1823ab2425c1ec917e709d929fb59a8b Mon Sep 17 00:00:00 2001 From: Nico Chamo Date: Wed, 8 Jul 2026 09:43:48 -0300 Subject: [PATCH 2/3] refactor(e2e): import PXE hook types instead of deriving them --- .../interactive_handshake_responder.ts | 3 +-- .../src/automine/delivery/onchain.test.ts | 5 +++-- .../delivery/onchain_delivery_harness.ts | 20 +++++-------------- 3 files changed, 9 insertions(+), 19 deletions(-) diff --git a/yarn-project/end-to-end/src/automine/delivery/interactive_handshake_responder.ts b/yarn-project/end-to-end/src/automine/delivery/interactive_handshake_responder.ts index 954723a14b39..e46d0fa2b4d5 100644 --- a/yarn-project/end-to-end/src/automine/delivery/interactive_handshake_responder.ts +++ b/yarn-project/end-to-end/src/automine/delivery/interactive_handshake_responder.ts @@ -4,14 +4,13 @@ import { poseidon2HashWithSeparator } from '@aztec/foundation/crypto/poseidon'; import { Schnorr, type SchnorrSignature } from '@aztec/foundation/crypto/schnorr'; import { Fq, Fr } from '@aztec/foundation/curves/bn254'; import type { GrumpkinScalar } from '@aztec/foundation/curves/grumpkin'; +import type { CustomRequest } from '@aztec/pxe/config'; import { INTERACTIVE_HANDSHAKE_REQUEST_KIND, STANDARD_HANDSHAKE_REGISTRY_ADDRESS, } from '@aztec/standard-contracts/handshake-registry/constants'; import { type PublicKeys, derivePublicKeyFromSecretKey } from '@aztec/stdlib/keys'; -import type { CustomRequest } from './onchain_delivery_harness.js'; - /** * The decoded payload of the registry's interactive-handshake signature request. Note it never carries the sender, * so the recipient authorizes the handshake without learning who initiated it. diff --git a/yarn-project/end-to-end/src/automine/delivery/onchain.test.ts b/yarn-project/end-to-end/src/automine/delivery/onchain.test.ts index dbda404ddab1..0e0dfaeb5039 100644 --- a/yarn-project/end-to-end/src/automine/delivery/onchain.test.ts +++ b/yarn-project/end-to-end/src/automine/delivery/onchain.test.ts @@ -1,6 +1,7 @@ import type { InitialAccountData } from '@aztec/accounts/testing'; import type { CompleteAddress } from '@aztec/aztec.js/addresses'; import { Point } from '@aztec/foundation/curves/grumpkin'; +import type { ResolveCustomRequest } from '@aztec/pxe/config'; import { deriveKeys } from '@aztec/stdlib/keys'; import type { TestWallet } from '../../test-wallet/test_wallet.js'; @@ -9,7 +10,7 @@ import { recipientSignatureToFields, signInteractiveHandshake, } from './interactive_handshake_responder.js'; -import { type CustomRequestHook, buildMessageDeliveryTest } from './onchain_delivery_harness.js'; +import { buildMessageDeliveryTest } from './onchain_delivery_harness.js'; describe('onchain delivery', () => { let arbitrarySecret: Point; @@ -74,7 +75,7 @@ describe('onchain delivery', () => { recipientWallet: TestWallet, recipientAccount: InitialAccountData, recipientCompleteAddress: CompleteAddress, - ): CustomRequestHook { + ): ResolveCustomRequest { return async request => { const parsed = parseInteractiveHandshakeRequest(request); diff --git a/yarn-project/end-to-end/src/automine/delivery/onchain_delivery_harness.ts b/yarn-project/end-to-end/src/automine/delivery/onchain_delivery_harness.ts index e996350c93f0..6e00fca5969e 100644 --- a/yarn-project/end-to-end/src/automine/delivery/onchain_delivery_harness.ts +++ b/yarn-project/end-to-end/src/automine/delivery/onchain_delivery_harness.ts @@ -6,7 +6,7 @@ import type { AztecNode } from '@aztec/aztec.js/node'; import type { AccountManager } from '@aztec/aztec.js/wallet'; import { BlockNumber } from '@aztec/foundation/branded-types'; import { type DeliveryEvent, OnchainDeliveryTestContract } from '@aztec/noir-test-contracts.js/OnchainDeliveryTest'; -import type { PXECreationOptions } from '@aztec/pxe/server'; +import type { CustomRequest, ResolveCustomRequest, ResolveTaggingSecretStrategy } from '@aztec/pxe/config'; import type { AztecNodeDebug } from '@aztec/stdlib/interfaces/client'; import { jest } from '@jest/globals'; @@ -15,22 +15,13 @@ import { AUTOMINE_E2E_OPTS } from '../../fixtures/fixtures.js'; import { ensureHandshakeRegistryPublished, setup, setupPXEAndGetWallet } from '../../fixtures/setup.js'; import { TestWallet } from '../../test-wallet/test_wallet.js'; -// The wallet hook that selects a message's tagging-secret source. Derived from the exported PXE options -// rather than importing the hook type, which `@aztec/pxe/server` does not re-export. -export type SenderHook = NonNullable['resolveTaggingSecretStrategy']>; - -// The wallet hook resolving a contract's custom request (e.g. the registry's interactive-handshake signature -// request), derived from the exported PXE options for the same reason as `SenderHook`. -export type CustomRequestHook = NonNullable['resolveCustomRequest']>; -export type CustomRequest = Parameters[0]; - // Builds the hook serving custom requests issued during the sender's simulations. Installed on the sender PXE at // creation but built only once the recipient exists, since serving typically needs the recipient's wallet and keys. export type CustomRequestResponder = ( recipient: TestWallet, recipientAccount: InitialAccountData, recipientCompleteAddress: CompleteAddress, -) => CustomRequestHook; +) => ResolveCustomRequest; export type Mode = 'constrained' | 'unconstrained'; @@ -54,7 +45,7 @@ export function buildMessageDeliveryTest(opts: { strategy: string; mode: DeliveryMode; // Required: every cell states its source explicitly rather than leaning on the PXE default (covered by unit tests). - senderHook: SenderHook; + senderHook: ResolveTaggingSecretStrategy; // Recipient-side setup the source requires (e.g. registering a raw arbitrary secret); runs once after deployment. recipientRegistration?: ( recipient: TestWallet, @@ -125,15 +116,14 @@ export function buildMessageDeliveryTest(opts: { if (!customRequestResponder) { throw new Error('A custom request arrived but this test cell has no customRequestResponder configured'); } - const account = recipientAccount; - if (!account) { + if (!recipientAccount) { throw new Error('A custom request arrived before the recipient wallet was created'); } customRequestCount++; const respond = customRequestResponder( walletRecipient, additionallyFundedAccounts[0], - await account.getCompleteAddress(), + await recipientAccount.getCompleteAddress(), ); return respond(request); }, From 5336e8e93aee6dbeb8215c8e698fb1915c855f01 Mon Sep 17 00:00:00 2001 From: Nico Chamo Date: Wed, 8 Jul 2026 13:46:28 -0300 Subject: [PATCH 3/3] docs(standard-contracts): TODO to source request kind from artifact --- .../standard-contracts/src/handshake-registry/constants.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/yarn-project/standard-contracts/src/handshake-registry/constants.ts b/yarn-project/standard-contracts/src/handshake-registry/constants.ts index 42f905f9751e..0573b2b125d5 100644 --- a/yarn-project/standard-contracts/src/handshake-registry/constants.ts +++ b/yarn-project/standard-contracts/src/handshake-registry/constants.ts @@ -15,6 +15,9 @@ export const STANDARD_HANDSHAKE_REGISTRY_SALT = StandardContractSalt.HandshakeRe * Request kind under which the HandshakeRegistry asks for a recipient's interactive-handshake signature through the * `resolveCustomRequest` hook. Mirrors `INTERACTIVE_HANDSHAKE_REQUEST_KIND` in the registry contract. */ +// TODO: remove this mirrored constant and read the value from the HandshakeRegistry artifact once the contract +// global can be `#[abi]`-exported. Fixed upstream but not yet released: +// https://github.com/noir-lang/noir/pull/12714 and https://github.com/noir-lang/noir/issues/12620. export const INTERACTIVE_HANDSHAKE_REQUEST_KIND: Fr = sha256ToField([ Buffer.from('HANDSHAKE_REGISTRY::INTERACTIVE_HANDSHAKE_REQUEST'), ]);