From a484d3e3559b4664a6f1f03d9e858a87f2927165 Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 11 Mar 2026 05:01:26 +0000 Subject: [PATCH 1/2] fix(pxe): skip oracle version check and add legacy oracle aliases for pinned protocol contracts Protocol contracts (ContractInstanceRegistry, ContractClassRegistry, FeeJuice) shipped with committed bytecode compiled against an older oracle version. Since their bytecode cannot be changed, we skip the oracle version check for these contracts and register legacy oracle name aliases (utilityLog, utilityAssertCompatibleOracleVersion, etc.) so the old oracle names still resolve correctly. Co-Authored-By: Claude Opus 4.6 --- .../src/protocol_contract.ts | 11 +++++++- .../oracle/oracle.ts | 25 ++++++++++++++++++- .../oracle/utility_execution_oracle.ts | 7 ++++++ 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/yarn-project/protocol-contracts/src/protocol_contract.ts b/yarn-project/protocol-contracts/src/protocol_contract.ts index 6544cdab1209..60bb6cc121a6 100644 --- a/yarn-project/protocol-contracts/src/protocol_contract.ts +++ b/yarn-project/protocol-contracts/src/protocol_contract.ts @@ -16,8 +16,17 @@ export interface ProtocolContract { address: AztecAddress; } +/** Returns true if the address is one of the actual protocol contracts (ContractInstanceRegistry, + * ContractClassRegistry or FeeJuice). + * + * TODO(F-416): Drop this function when protocol contracts are redeployed. + */ export function isProtocolContract(address: AztecAddress) { - return Object.values(ProtocolContractAddress).some(a => a.equals(address)); + return ( + address.equals(ProtocolContractAddress.ContractInstanceRegistry) || + address.equals(ProtocolContractAddress.ContractClassRegistry) || + address.equals(ProtocolContractAddress.FeeJuice) + ); } export { type ProtocolContractsProvider } from './provider/protocol_contracts_provider.js'; diff --git a/yarn-project/pxe/src/contract_function_simulator/oracle/oracle.ts b/yarn-project/pxe/src/contract_function_simulator/oracle/oracle.ts index 12d673d745d0..5d17986be4dd 100644 --- a/yarn-project/pxe/src/contract_function_simulator/oracle/oracle.ts +++ b/yarn-project/pxe/src/contract_function_simulator/oracle/oracle.ts @@ -85,13 +85,28 @@ export class Oracle { }); // Build callback object and return it - return oracleNames.reduce((acc, name) => { + const callback = oracleNames.reduce((acc, name) => { const method = this[name as keyof Omit]; acc[name] = method.bind(this); return acc; }, {} as ACIRCallback); + + // Legacy oracle names used by alpha payload protocol contracts (ContractInstanceRegistry, + // ContractClassRegistry, FeeJuice). Their bytecode is committed and cannot be changed. + // TODO(F-416): Remove these aliases on v5 when protocol contracts are redeployed. + const legacyOracles: ACIRCallback = { + utilityLog: this.aztec_utl_log.bind(this), + utilityAssertCompatibleOracleVersion: this.aztec_utl_assertCompatibleOracleVersion.bind(this), + utilityLoadCapsule: this.aztec_utl_loadCapsule.bind(this), + privateStoreInExecutionCache: this.aztec_prv_storeInExecutionCache.bind(this), + privateLoadFromExecutionCache: this.aztec_prv_loadFromExecutionCache.bind(this), + }; + + return { ...callback, ...legacyOracles }; } + // TODO(F-416): This oracle must never change its signature - it is called by the pinned alpha payload protocol + // contracts (ContractInstanceRegistry, ContractClassRegistry, FeeJuice) which cannot be redeployed. // eslint-disable-next-line camelcase aztec_utl_assertCompatibleOracleVersion([version]: ACVMField[]) { this.handlerAsMisc().assertCompatibleOracleVersion(Fr.fromString(version).toNumber()); @@ -104,12 +119,16 @@ export class Oracle { return Promise.resolve([toACVMField(val)]); } + // TODO(F-416): This oracle must never change its signature - it is called by the pinned alpha payload protocol + // contracts (ContractInstanceRegistry, ContractClassRegistry, FeeJuice) which cannot be redeployed. // eslint-disable-next-line camelcase aztec_prv_storeInExecutionCache(values: ACVMField[], [hash]: ACVMField[]): Promise { this.handlerAsPrivate().storeInExecutionCache(values.map(Fr.fromString), Fr.fromString(hash)); return Promise.resolve([]); } + // TODO(F-416): This oracle must never change its signature - it is called by the pinned alpha payload protocol + // contracts (ContractInstanceRegistry, ContractClassRegistry, FeeJuice) which cannot be redeployed. // eslint-disable-next-line camelcase async aztec_prv_loadFromExecutionCache([returnsHash]: ACVMField[]): Promise { const values = await this.handlerAsPrivate().loadFromExecutionCache(Fr.fromString(returnsHash)); @@ -426,6 +445,8 @@ export class Oracle { return Promise.resolve([]); } + // TODO(F-416): This oracle must never change its signature - it is called by the pinned alpha payload protocol + // contracts (ContractInstanceRegistry, ContractClassRegistry, FeeJuice) which cannot be redeployed. // eslint-disable-next-line camelcase async aztec_utl_log( level: ACVMField[], @@ -540,6 +561,8 @@ export class Oracle { return []; } + // TODO(F-416): This oracle must never change its signature - it is called by the pinned alpha payload protocol + // contracts (ContractInstanceRegistry, ContractClassRegistry, FeeJuice) which cannot be redeployed. // eslint-disable-next-line camelcase async aztec_utl_loadCapsule( [contractAddress]: ACVMField[], diff --git a/yarn-project/pxe/src/contract_function_simulator/oracle/utility_execution_oracle.ts b/yarn-project/pxe/src/contract_function_simulator/oracle/utility_execution_oracle.ts index dfb66ce833e3..d3a95241bf13 100644 --- a/yarn-project/pxe/src/contract_function_simulator/oracle/utility_execution_oracle.ts +++ b/yarn-project/pxe/src/contract_function_simulator/oracle/utility_execution_oracle.ts @@ -6,6 +6,7 @@ import { Point } from '@aztec/foundation/curves/grumpkin'; import { LogLevels, type Logger, createLogger } from '@aztec/foundation/log'; import type { MembershipWitness } from '@aztec/foundation/trees'; import type { KeyStore } from '@aztec/key-store'; +import { isProtocolContract } from '@aztec/protocol-contracts'; import type { AuthWitness } from '@aztec/stdlib/auth-witness'; import { AztecAddress } from '@aztec/stdlib/aztec-address'; import { BlockHash } from '@aztec/stdlib/block'; @@ -109,6 +110,12 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra } public assertCompatibleOracleVersion(version: number): void { + // Alpha payload protocol contracts (ContractInstanceRegistry, ContractClassRegistry, FeeJuice) shipped with + // committed bytecode that cannot be changed. Skip the version check for these contracts. + // TODO(F-416): Remove this hack on v5 when protocol contracts are redeployed. + if (isProtocolContract(this.contractAddress)) { + return; + } if (version !== ORACLE_VERSION) { throw new Error(`Incompatible oracle version. Expected version ${ORACLE_VERSION}, got ${version}.`); } From 40eca1800d268d52eaa46045a1cb10f7bf5ec08f Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 11 Mar 2026 05:07:28 +0000 Subject: [PATCH 2/2] fix --- yarn-project/protocol-contracts/src/protocol_contract.ts | 8 ++++++-- .../oracle/utility_execution_oracle.ts | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/yarn-project/protocol-contracts/src/protocol_contract.ts b/yarn-project/protocol-contracts/src/protocol_contract.ts index 60bb6cc121a6..283cd82df733 100644 --- a/yarn-project/protocol-contracts/src/protocol_contract.ts +++ b/yarn-project/protocol-contracts/src/protocol_contract.ts @@ -16,12 +16,16 @@ export interface ProtocolContract { address: AztecAddress; } -/** Returns true if the address is one of the actual protocol contracts (ContractInstanceRegistry, +export function isProtocolContract(address: AztecAddress) { + return Object.values(ProtocolContractAddress).some(a => a.equals(address)); +} + +/** Returns true if the address is one of the ACTUAL protocol contracts (ContractInstanceRegistry, * ContractClassRegistry or FeeJuice). * * TODO(F-416): Drop this function when protocol contracts are redeployed. */ -export function isProtocolContract(address: AztecAddress) { +export function isActualProtocolContract(address: AztecAddress) { return ( address.equals(ProtocolContractAddress.ContractInstanceRegistry) || address.equals(ProtocolContractAddress.ContractClassRegistry) || diff --git a/yarn-project/pxe/src/contract_function_simulator/oracle/utility_execution_oracle.ts b/yarn-project/pxe/src/contract_function_simulator/oracle/utility_execution_oracle.ts index d3a95241bf13..17c8138a0fd9 100644 --- a/yarn-project/pxe/src/contract_function_simulator/oracle/utility_execution_oracle.ts +++ b/yarn-project/pxe/src/contract_function_simulator/oracle/utility_execution_oracle.ts @@ -6,7 +6,7 @@ import { Point } from '@aztec/foundation/curves/grumpkin'; import { LogLevels, type Logger, createLogger } from '@aztec/foundation/log'; import type { MembershipWitness } from '@aztec/foundation/trees'; import type { KeyStore } from '@aztec/key-store'; -import { isProtocolContract } from '@aztec/protocol-contracts'; +import { isActualProtocolContract } from '@aztec/protocol-contracts'; import type { AuthWitness } from '@aztec/stdlib/auth-witness'; import { AztecAddress } from '@aztec/stdlib/aztec-address'; import { BlockHash } from '@aztec/stdlib/block'; @@ -113,7 +113,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra // Alpha payload protocol contracts (ContractInstanceRegistry, ContractClassRegistry, FeeJuice) shipped with // committed bytecode that cannot be changed. Skip the version check for these contracts. // TODO(F-416): Remove this hack on v5 when protocol contracts are redeployed. - if (isProtocolContract(this.contractAddress)) { + if (isActualProtocolContract(this.contractAddress)) { return; } if (version !== ORACLE_VERSION) {