Skip to content

fix(pxe): backward-compatible deserialization of validation requests#20957

Draft
nchamo wants to merge 3 commits intomerge-train/fairiesfrom
fix/backward-compat-pxe-deserialization
Draft

fix(pxe): backward-compatible deserialization of validation requests#20957
nchamo wants to merge 3 commits intomerge-train/fairiesfrom
fix/backward-compat-pxe-deserialization

Conversation

@nchamo
Copy link
Contributor

@nchamo nchamo commented Feb 27, 2026

Summary

In #20840, we introduced a change to reflect the actual max length used for messages and notes, we were not calculating it correctly beforehand. The main issue is that aztec-nr used those notes/events max lengths as the max size for BoundedVec when communicating with PXE. And, on PXE's side, we also used that value to deserialize the BoundedVec.

But when we updated those values, old contracts were no longer compatible with the new version of PXE and new contracts were no longer compatible with the old version of PXE.

I can think of quick two ways to prevent this from happening again:

  1. Pass the actual size of BoundedVec as a parameter, from aztec-nr to PXE, so that it knows how to deserialize it
  2. Infer the actual size based on the known structure of the requests

This PR is a small implementation of option (2). It:

  • Automatically detects the size of BoundedVec based on the known structure of the requests
  • Validates that the actual length (and not the BoundedVec size) doesn't exceed a maximum allowed by PXE, while continuing to support BoundedVecs with higher size
  • Add a test that fails when we try to lower the supported max length by PXE (since this would be a breaking change)

Fixes #14617
Fixes F-375

@nchamo nchamo self-assigned this Feb 27, 2026
@nchamo nchamo added the ci-draft Run CI on draft PRs. label Feb 27, 2026
import { MAX_NOTE_PACKED_LEN } from './note_validation_request.js';

const MAX_PUBLIC_LOG_LEN_FOR_NOTE_COMPLETION = MAX_NOTE_PACKED_LEN;
const MAX_LOG_CONTENT_LEN = Math.max(MAX_PUBLIC_LOG_LEN_FOR_NOTE_COMPLETION, PRIVATE_LOG_CIPHERTEXT_LEN);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I believe it didn't make sense to have this. MAX_NOTE_PACKED_LEN is calculated in aztec-nr from PRIVATE_LOG_CIPHERTEXT_LEN, and it should always be lower for it. But please correct me if I'm wrong

if (eventLen > MAX_EVENT_CONTENT_LEN) {
throw new Error(`Event content length ${eventLen} exceeds MAX_EVENT_CONTENT_LEN ${MAX_EVENT_CONTENT_LEN}.`);
}
if (eventLen > arraySize) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This shouldn't happen, but it doesn't hurt to check

// Event content is serialized as a BoundedVec: `storage[capacity] ++ len`. The storage capacity may differ across
// aztec-nr versions (e.g. old contracts used 11, current ones use 10), so we infer it dynamically from the total field
// count. This constant is only used to validate the *content length* (the BoundedVec `.len()`), not the storage size.
const MAX_EVENT_CONTENT_LEN = 10;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added this so we can still validate something from PXE's side but we can remove it if we want to fully trust what we receive

@nchamo nchamo requested a review from nventuro February 27, 2026 19:24
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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant