Skip to content

feat(pxe): recipient-side interactive handshake registration#24514

Open
nchamo wants to merge 1 commit into
merge-train/fairies-v5from
nchamo/f-660-featpxe-recipient-side-registration-and-discovery-of
Open

feat(pxe): recipient-side interactive handshake registration#24514
nchamo wants to merge 1 commit into
merge-train/fairies-v5from
nchamo/f-660-featpxe-recipient-side-registration-and-discovery-of

Conversation

@nchamo

@nchamo nchamo commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Motivation

An interactive handshake emits no announcement log. The recipient learns the ephemeral key while authorizing it, but PXE had no way to use that knowledge: handshake discovery only scans announcements, so messages sent under an interactive handshake could never be found. The registry's interactive_handshake entrypoint landed in #24473.

The change

  • New handshake variant on TaggingSecretSource. It takes the ephemeral key's x-coordinate (the value the recipient signs, y is positive by protocol construction). PXE reconstructs the point and derives the shared secret internally, so only the resolved secret is kept.
  • The shared-secrets store now records each secret's kind, and scanning derives the tag streams from it: arbitrary secrets keep the directional stream, handshake secrets are scanned under the bare app-siloed streams of both delivery modes.
  • Listing and removal use the registered form: RegisteredTaggingSecretSource carries the resolved secret for handshake entries, and removal matches kind + secret.
  • The store's value format changed, so PXE_DATA_SCHEMA_VERSION is bumped.

Since there is no announcement to re-scan, re-registration is the recovery path on a fresh PXE. The end-to-end interactive flow (signing + wallet helpers) lands with F-787.

Fixes F-660

@nchamo nchamo self-assigned this Jul 3, 2026
@nchamo nchamo added ci-draft Run CI on draft PRs. ci-no-fail-fast Sets NO_FAIL_FAST in the CI so the run is not aborted on the first failure labels Jul 3, 2026
export type RegisteredTaggingSecretSource =
| Exclude<TaggingSecretSource, { kind: 'handshake' }>
/** A handshake's resolved shared secret, derived at registration from the handshake's ephemeral key. */
| { kind: 'handshake'; recipient: AztecAddress; secret: Point };

@nchamo nchamo Jul 3, 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.

See that handshake secrets are not symmetrical. When they are added, they are a ephPk. But then we derive the secret and store that.

So when we list secrets via getTaggingSecretSources, we return the already derived secret. And if you want to remove the secret via removeTaggingSecretSource, you specify the derived secret too. I thought that would be the best way to do that because if someone forgot the ephPk, they wouldn't be able to unregister the secret

for await (const existing of this.#sharedSecretsByRecipient.getValuesAsync(recipient.toString())) {
if (existing === secretStr) {
if (existing.secret === secretStr) {
if (existing.kind !== kind) {

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.

Like the error message says. If you try to register the same secret twice, but with a different type, we'll fail. I'm not sure if this is the best way to handle this scenario, but overwriting felt off. And silently ignoring the secret didn't seem like a good solution either

@nchamo nchamo marked this pull request as ready for review July 3, 2026 20:25
@nchamo nchamo requested a review from vezenovm July 3, 2026 20:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci-draft Run CI on draft PRs. ci-no-fail-fast Sets NO_FAIL_FAST in the CI so the run is not aborted on the first failure

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant