Skip to content

feat(txe): add oracle roundtrip test framework#23537

Draft
nchamo wants to merge 2 commits into
nchamo/txe-deploy-normalizefrom
nchamo/oracle-roundtrip-tests
Draft

feat(txe): add oracle roundtrip test framework#23537
nchamo wants to merge 2 commits into
nchamo/txe-deploy-normalizefrom
nchamo/oracle-roundtrip-tests

Conversation

@nchamo
Copy link
Copy Markdown
Contributor

@nchamo nchamo commented May 24, 2026

Why we are doing this

Oracle calls between Noir and TypeScript cross a serialization boundary — values are serialized in Noir, sent over JSON-RPC as hex strings, and deserialized back in TS. There was no automated way to verify that the TS oracle registry's type definitions (params and return types) correctly round-trip through this boundary. A mismatch silently produces wrong values at runtime. Some oracles had tests named "serialization should match typescript", but those were hard to maintain and impossible to actually verify across the Noir/TS boundary.

Our fix

Introduces an #[oracle_test] Noir macro and a lightweight TS test resolver that together verify serialization correctness for each oracle in the registry.

Noir side: #[oracle_test] generates __oracle_test__-prefixed test functions that call the real oracle with known inputs and assert on the output. For oracles with multiple scenarios (e.g. Option returning some/none), #[oracle_test("scenario_name")] selects a named fixture via a meta-oracle call before invoking the real oracle.

TS side: OracleTestResolver receives the oracle call, selects the matching fixture scenario, deserializes the incoming hex inputs using the registry's param definitions, and verifies they match the expected values from the fixture. It then serializes the fixture output through the registry's return type and sends it back. Noir asserts the received values match the expected output, closing the loop.

Notes

  • CI integration: bootstrap.sh starts the resolver server on a separate port, runs all __oracle_test__ tests against it, and filters them out of the regular TXE test run
  • PR includes two initial oracle tests (avm_storage_read, get_sender_for_tags with some/none scenarios) and 9 unit tests for the resolver
  • Moves txe_oracle_registry.ts and txe_oracle_version.ts into oracle/ subdirectory and replaces hand-rolled hex prefix helpers with withHexPrefix/withoutHexPrefix from foundation

@nchamo nchamo added the ci-draft Run CI on draft PRs. label May 24, 2026
@nchamo nchamo self-assigned this May 24, 2026
@@ -383,16 +384,16 @@ export async function callTxeHandler<K extends keyof typeof TXE_ORACLE_REGISTRY>
}): Promise<ForeignCallResult> {
const entry = TXE_ORACLE_REGISTRY[oracle] as OracleRegistryEntry;
// TXE foreign calls use bare hex strings, but Fr.fromString requires a 0x prefix to parse as hex.
const prefixHex = (s: string) => (s.startsWith('0x') ? s : `0x${s}`);
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.

Figured out there was already a function for this

@AztecBot
Copy link
Copy Markdown
Collaborator

Flakey Tests

🤖 says: This CI run detected 1 tests that failed, but were tolerated due to a .test_patterns.yml entry.

\033FLAKED\033 (8;;http://ci.aztec-labs.com/dee35eee3b42e92d�dee35eee3b42e92d8;;�):  yarn-project/end-to-end/scripts/run_test.sh simple src/e2e_p2p/broadcasted_invalid_block_proposal_slash.test.ts (294s) (code: 0) group:e2e-p2p-epoch-flakes

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.

2 participants