Skip to content

Commit 2ec0175

Browse files
authored
feat: merge-train/fairies-v5 (#24817)
BEGIN_COMMIT_OVERRIDE refactor(pxe): compute oracle interface hash from wire-structural mapping labels (#24752) fix: tagging secrets not being scoped by sender (#24772) chore: clarify scope of packable impl detection (#24820) END_COMMIT_OVERRIDE
2 parents 0d5fc27 + 15c7a1e commit 2ec0175

36 files changed

Lines changed: 696 additions & 992 deletions

noir-projects/aztec-nr/aztec/src/macros/notes.nr

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,12 @@ comptime fn generate_note_properties(s: TypeDefinition) -> Quoted {
186186
let note_type_name = $note_type_name;
187187
let fields_packed_len: u32 = $accumulated_offset;
188188
let note_packed_len: u32 = <$typ as aztec::protocol::traits::Packable>::N;
189+
// We only reject custom Packable layouts whose total packed length differs from the derived
190+
// layout's. A hand-written pack() that keeps the same total length but reorders same-width fields
191+
// is deliberately not caught: the selectors are computed from declared field order and would
192+
// silently point at the wrong packed slot. Detecting it would require knowing whether Packable was
193+
// derived or hand-written, which comptime cannot currently tell us. Custom layouts must define their
194+
// PropertySelectors manually.
189195
std::static_assert(
190196
fields_packed_len == note_packed_len,
191197
f"{note_type_name}'s auto-generated note properties assume the #[derive(Packable)] layout ({fields_packed_len} fields), but its hand-written Packable packs to {note_packed_len}. Derive Packable, or define property selectors manually for the custom layout. See https://docs.aztec.network/errors/15",

noir-projects/aztec-nr/aztec/src/oracle/mod.nr

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,7 @@ use crate::macros::oracle_testing::{generate_oracle_tests, generate_oracle_tests
2222
],
2323
)]
2424
pub mod avm;
25-
#[generate_oracle_tests_excluding(
26-
@[
27-
// TODO: cover once the iv/sym_key BUFFER mapping is expressible as a plain fixed array of bytes, so the
28-
// fixture synthesizer does not need to special-case it.
29-
quote { aes128_decrypt_oracle },
30-
],
31-
)]
25+
#[generate_oracle_tests]
3226
pub mod aes128_decrypt;
3327
#[generate_oracle_tests]
3428
pub mod auth_witness;

noir-projects/aztec-nr/aztec/src/oracle/tx_resolution.nr

Lines changed: 0 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -18,104 +18,3 @@ pub(crate) unconstrained fn get_resolved_txs(requests: EphemeralArray<Field>) ->
1818

1919
#[oracle(aztec_utl_getResolvedTxs)]
2020
unconstrained fn get_resolved_txs_oracle(requests: EphemeralArray<Field>) -> EphemeralArray<Option<ResolvedTx>> {}
21-
22-
mod test {
23-
use crate::oracle::tx_resolution::ResolvedTx;
24-
use crate::protocol::traits::Deserialize;
25-
26-
#[test]
27-
unconstrained fn resolved_tx_serialization_matches_typescript() {
28-
// Setup test data
29-
let tx_hash = 123;
30-
let unique_note_hashes = BoundedVec::from_array([4, 5]);
31-
let first_nullifier = 6;
32-
let block_number: u32 = 7;
33-
let block_hash = 8;
34-
35-
// Create a ResolvedTx instance
36-
let resolved_tx = ResolvedTx {
37-
tx_hash,
38-
unique_note_hashes_in_tx: unique_note_hashes,
39-
first_nullifier_in_tx: first_nullifier,
40-
block_number,
41-
block_hash,
42-
};
43-
44-
// Expected output generated from TypeScript's `ResolvedTx.toFields()`
45-
let serialized_resolved_tx_from_typescript = [
46-
0x000000000000000000000000000000000000000000000000000000000000007b,
47-
0x0000000000000000000000000000000000000000000000000000000000000004,
48-
0x0000000000000000000000000000000000000000000000000000000000000005,
49-
0x0000000000000000000000000000000000000000000000000000000000000000,
50-
0x0000000000000000000000000000000000000000000000000000000000000000,
51-
0x0000000000000000000000000000000000000000000000000000000000000000,
52-
0x0000000000000000000000000000000000000000000000000000000000000000,
53-
0x0000000000000000000000000000000000000000000000000000000000000000,
54-
0x0000000000000000000000000000000000000000000000000000000000000000,
55-
0x0000000000000000000000000000000000000000000000000000000000000000,
56-
0x0000000000000000000000000000000000000000000000000000000000000000,
57-
0x0000000000000000000000000000000000000000000000000000000000000000,
58-
0x0000000000000000000000000000000000000000000000000000000000000000,
59-
0x0000000000000000000000000000000000000000000000000000000000000000,
60-
0x0000000000000000000000000000000000000000000000000000000000000000,
61-
0x0000000000000000000000000000000000000000000000000000000000000000,
62-
0x0000000000000000000000000000000000000000000000000000000000000000,
63-
0x0000000000000000000000000000000000000000000000000000000000000000,
64-
0x0000000000000000000000000000000000000000000000000000000000000000,
65-
0x0000000000000000000000000000000000000000000000000000000000000000,
66-
0x0000000000000000000000000000000000000000000000000000000000000000,
67-
0x0000000000000000000000000000000000000000000000000000000000000000,
68-
0x0000000000000000000000000000000000000000000000000000000000000000,
69-
0x0000000000000000000000000000000000000000000000000000000000000000,
70-
0x0000000000000000000000000000000000000000000000000000000000000000,
71-
0x0000000000000000000000000000000000000000000000000000000000000000,
72-
0x0000000000000000000000000000000000000000000000000000000000000000,
73-
0x0000000000000000000000000000000000000000000000000000000000000000,
74-
0x0000000000000000000000000000000000000000000000000000000000000000,
75-
0x0000000000000000000000000000000000000000000000000000000000000000,
76-
0x0000000000000000000000000000000000000000000000000000000000000000,
77-
0x0000000000000000000000000000000000000000000000000000000000000000,
78-
0x0000000000000000000000000000000000000000000000000000000000000000,
79-
0x0000000000000000000000000000000000000000000000000000000000000000,
80-
0x0000000000000000000000000000000000000000000000000000000000000000,
81-
0x0000000000000000000000000000000000000000000000000000000000000000,
82-
0x0000000000000000000000000000000000000000000000000000000000000000,
83-
0x0000000000000000000000000000000000000000000000000000000000000000,
84-
0x0000000000000000000000000000000000000000000000000000000000000000,
85-
0x0000000000000000000000000000000000000000000000000000000000000000,
86-
0x0000000000000000000000000000000000000000000000000000000000000000,
87-
0x0000000000000000000000000000000000000000000000000000000000000000,
88-
0x0000000000000000000000000000000000000000000000000000000000000000,
89-
0x0000000000000000000000000000000000000000000000000000000000000000,
90-
0x0000000000000000000000000000000000000000000000000000000000000000,
91-
0x0000000000000000000000000000000000000000000000000000000000000000,
92-
0x0000000000000000000000000000000000000000000000000000000000000000,
93-
0x0000000000000000000000000000000000000000000000000000000000000000,
94-
0x0000000000000000000000000000000000000000000000000000000000000000,
95-
0x0000000000000000000000000000000000000000000000000000000000000000,
96-
0x0000000000000000000000000000000000000000000000000000000000000000,
97-
0x0000000000000000000000000000000000000000000000000000000000000000,
98-
0x0000000000000000000000000000000000000000000000000000000000000000,
99-
0x0000000000000000000000000000000000000000000000000000000000000000,
100-
0x0000000000000000000000000000000000000000000000000000000000000000,
101-
0x0000000000000000000000000000000000000000000000000000000000000000,
102-
0x0000000000000000000000000000000000000000000000000000000000000000,
103-
0x0000000000000000000000000000000000000000000000000000000000000000,
104-
0x0000000000000000000000000000000000000000000000000000000000000000,
105-
0x0000000000000000000000000000000000000000000000000000000000000000,
106-
0x0000000000000000000000000000000000000000000000000000000000000000,
107-
0x0000000000000000000000000000000000000000000000000000000000000000,
108-
0x0000000000000000000000000000000000000000000000000000000000000000,
109-
0x0000000000000000000000000000000000000000000000000000000000000000,
110-
0x0000000000000000000000000000000000000000000000000000000000000000,
111-
0x0000000000000000000000000000000000000000000000000000000000000002,
112-
0x0000000000000000000000000000000000000000000000000000000000000006,
113-
0x0000000000000000000000000000000000000000000000000000000000000007,
114-
0x0000000000000000000000000000000000000000000000000000000000000008,
115-
];
116-
117-
let deserialized = ResolvedTx::deserialize(serialized_resolved_tx_from_typescript);
118-
119-
assert_eq(deserialized, resolved_tx);
120-
}
121-
}

yarn-project/cli-wallet/src/utils/wallet.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,10 @@ export class CLIWallet extends BaseWallet {
145145
increasedFee: InteractionFeeOptions,
146146
): Promise<TxProvingResult> {
147147
const cancellationTxRequest = await this.createCancellationTxExecutionRequest(from, txNonce, increasedFee);
148-
return await this.pxe.proveTx(cancellationTxRequest, { scopes: this.scopesFrom(from), senderForTags: from });
148+
return await this.pxe.proveTx(cancellationTxRequest, {
149+
scopes: this.scopesFrom(from, [], undefined),
150+
senderForTags: from,
151+
});
149152
}
150153

151154
override async getAccountFromAddress(address: AztecAddress) {
@@ -311,7 +314,7 @@ export class CLIWallet extends BaseWallet {
311314
opts: SimulateViaEntrypointOptions,
312315
): Promise<TxSimulationResultWithAppOffset> {
313316
const { from, feeOptions, additionalScopes, sendMessagesAs } = opts;
314-
const scopes = this.scopesFrom(from, additionalScopes);
317+
const scopes = this.scopesFrom(from, additionalScopes ?? [], sendMessagesAs);
315318
const feeExecutionPayload = await feeOptions.walletFeePaymentMethod?.getExecutionPayload();
316319
const finalExecutionPayload = feeExecutionPayload
317320
? mergeExecutionPayloads([feeExecutionPayload, executionPayload])

yarn-project/end-to-end/src/test-wallet/test_wallet.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ export class TestWallet extends BaseWallet {
318318
opts: SimulateViaEntrypointOptions,
319319
): Promise<TxSimulationResultWithAppOffset> {
320320
const { from, feeOptions, additionalScopes, skipTxValidation, skipFeeEnforcement, sendMessagesAs } = opts;
321-
const scopes = this.scopesFrom(from, additionalScopes);
321+
const scopes = this.scopesFrom(from, additionalScopes ?? [], sendMessagesAs);
322322
const skipKernels = this.simulationMode !== 'full';
323323
const useOverride = this.simulationMode === 'kernelless-override';
324324

@@ -384,7 +384,7 @@ export class TestWallet extends BaseWallet {
384384
});
385385
const txRequest = await this.createTxExecutionRequestFromPayloadAndFee(exec, opts.from, fee);
386386
const txProvingResult = await this.pxe.proveTx(txRequest, {
387-
scopes: this.scopesFrom(opts.from, opts.additionalScopes),
387+
scopes: this.scopesFrom(opts.from, opts.additionalScopes ?? [], opts.sendMessagesAs),
388388
senderForTags: this.senderForTagsFrom(opts.from, opts.sendMessagesAs),
389389
});
390390
return new ProvenTx(

yarn-project/pxe/src/bin/check_oracle_version.ts

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,24 @@ import { keccak256String } from '@aztec/foundation/crypto/keccak';
33
import { dirname, join } from 'path';
44
import { fileURLToPath } from 'url';
55

6+
import { ORACLE_REGISTRY } from '../contract_function_simulator/index.js';
67
import { ORACLE_INTERFACE_HASH, ORACLE_VERSION_MAJOR } from '../oracle_version.js';
78
import { getOracleRegistrySignature, readNumericGlobal } from './oracle_version_helpers.js';
89

910
/**
1011
* Verifies that the Oracle interface matches the expected interface hash.
1112
*
1213
* The Oracle interface needs to be versioned to ensure compatibility between Aztec.nr and PXE. This function computes
13-
* a hash of the `ORACLE_REGISTRY` declaration (where each oracle's parameter names, parameter types, and return type
14+
* a hash of `ORACLE_REGISTRY` (where each oracle's parameter names, parameter types, and return type
1415
* live) and compares it against a known hash. If they don't match, it means the interface has changed and the oracle
1516
* version needs to be bumped:
1617
* - If the change is backward-breaking (e.g. removing/renaming an oracle, or changing its params/return), bump
1718
* ORACLE_VERSION_MAJOR.
1819
* - If the change is an oracle addition (non-breaking), bump ORACLE_VERSION_MINOR.
1920
*/
2021
function assertOracleInterfaceMatches(): void {
21-
// The script runs from dest/bin/ after compilation, so we go up to the package root then into src/ to find
22-
// the source file.
23-
const currentDir = dirname(fileURLToPath(import.meta.url));
24-
const packageRoot = dirname(dirname(currentDir)); // Go up from bin/ to pxe/
25-
const registrySourcePath = join(packageRoot, 'src/contract_function_simulator/oracle/oracle_registry.ts');
26-
27-
const oracleInterfaceSignature = getOracleRegistrySignature(registrySourcePath, 'ORACLE_REGISTRY');
28-
2922
// We use keccak256 here just because we already have it in the dependencies.
30-
const oracleInterfaceHash = keccak256String(oracleInterfaceSignature);
23+
const oracleInterfaceHash = keccak256String(getOracleRegistrySignature(ORACLE_REGISTRY));
3124
if (oracleInterfaceHash !== ORACLE_INTERFACE_HASH) {
3225
throw new Error(
3326
`The Oracle interface has changed. Update ORACLE_INTERFACE_HASH to ${oracleInterfaceHash} in pxe/src/oracle_version.ts and bump the oracle version (ORACLE_VERSION_MAJOR for breaking changes, ORACLE_VERSION_MINOR for oracle additions).`,

yarn-project/pxe/src/bin/index.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1 @@
1-
export {
2-
getOracleInterfaceSignature,
3-
getOracleRegistrySignature,
4-
readNumericGlobal,
5-
} from './oracle_version_helpers.js';
1+
export { getOracleRegistrySignature, readNumericGlobal } from './oracle_version_helpers.js';

yarn-project/pxe/src/bin/oracle_version_helpers.test.ts

Lines changed: 29 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
/* eslint-disable camelcase */
12
import { mkdtempSync, rmSync, writeFileSync } from 'fs';
23
import { tmpdir } from 'os';
34
import { join } from 'path';
45

6+
import { ARRAY, AZTEC_ADDRESS, BOOL, FIELD, OPTION, U32, makeEntry } from '../contract_function_simulator/index.js';
7+
import { TX_HASH } from '../contract_function_simulator/oracle/oracle_type_mappings.js';
58
import { getOracleRegistrySignature, readNumericGlobal } from './oracle_version_helpers.js';
69

710
describe('readNumericGlobal', () => {
@@ -51,17 +54,7 @@ describe('readNumericGlobal', () => {
5154
});
5255

5356
describe('getOracleRegistrySignature', () => {
54-
let dir: string;
55-
56-
beforeAll(() => {
57-
dir = mkdtempSync(join(tmpdir(), 'oracle-registry-'));
58-
});
59-
60-
afterAll(() => {
61-
rmSync(dir, { recursive: true, force: true });
62-
});
63-
64-
const SAMPLE_REGISTRY = `export const ORACLE_REGISTRY = {
57+
const SAMPLE_REGISTRY = {
6558
aztec_utl_foo: makeEntry({
6659
params: [
6760
{ name: 'a', type: U32 },
@@ -72,54 +65,42 @@ describe('getOracleRegistrySignature', () => {
7265
aztec_utl_bar: makeEntry({ returnType: FIELD }),
7366
aztec_prv_baz: makeEntry({ params: [{ name: 'x', type: FIELD }] }),
7467
aztec_prv_qux: makeEntry(),
75-
} satisfies Record<string, OracleRegistryEntry>;
76-
`;
68+
};
7769

7870
it('builds a sorted signature of names, ordered typed params, and return types', () => {
79-
const path = writeFixture(dir, 'registry.ts', SAMPLE_REGISTRY);
80-
expect(getOracleRegistrySignature(path, 'ORACLE_REGISTRY')).toBe(
81-
'aztec_prv_baz(x: FIELD): void\n' +
71+
expect(getOracleRegistrySignature(SAMPLE_REGISTRY)).toBe(
72+
'aztec_prv_baz(x: field): void\n' +
8273
'aztec_prv_qux(): void\n' +
83-
'aztec_utl_bar(): FIELD\n' +
84-
'aztec_utl_foo(a: U32, b: OPTION(AZTEC_ADDRESS)): BOOL',
74+
'aztec_utl_bar(): field\n' +
75+
'aztec_utl_foo(a: u32, b: option(aztec-address)): bool',
8576
);
8677
});
8778

8879
it('changes when a parameter type changes (the gap the Oracle-class hash missed)', () => {
89-
const before = writeFixture(dir, 'before.ts', SAMPLE_REGISTRY);
90-
const after = writeFixture(dir, 'after.ts', SAMPLE_REGISTRY.replace('type: OPTION(AZTEC_ADDRESS)', 'type: FIELD'));
91-
expect(getOracleRegistrySignature(after, 'ORACLE_REGISTRY')).not.toBe(
92-
getOracleRegistrySignature(before, 'ORACLE_REGISTRY'),
93-
);
80+
const after = {
81+
...SAMPLE_REGISTRY,
82+
aztec_utl_foo: makeEntry({
83+
params: [
84+
{ name: 'a', type: U32 },
85+
{ name: 'b', type: FIELD },
86+
],
87+
returnType: BOOL,
88+
}),
89+
};
90+
expect(getOracleRegistrySignature(after)).not.toBe(getOracleRegistrySignature(SAMPLE_REGISTRY));
9491
});
9592

96-
it('is insensitive to formatting of the type expressions', () => {
97-
const reformatted = writeFixture(
98-
dir,
99-
'reformatted.ts',
100-
SAMPLE_REGISTRY.replace('OPTION(AZTEC_ADDRESS)', 'OPTION(\n AZTEC_ADDRESS\n )'),
101-
);
102-
const original = writeFixture(dir, 'original.ts', SAMPLE_REGISTRY);
103-
expect(getOracleRegistrySignature(reformatted, 'ORACLE_REGISTRY')).toBe(
104-
getOracleRegistrySignature(original, 'ORACLE_REGISTRY'),
105-
);
106-
});
107-
108-
it('throws on spread members, which are not yet supported', () => {
109-
const path = writeFixture(
110-
dir,
111-
'spread.ts',
112-
`export const ORACLE_REGISTRY = {
113-
...BASE_REGISTRY,
114-
aztec_utl_foo: makeEntry({ returnType: FIELD }),
115-
} satisfies Record<string, OracleRegistryEntry>;\n`,
116-
);
117-
expect(() => getOracleRegistrySignature(path, 'ORACLE_REGISTRY')).toThrow(/Spread elements are not supported/);
93+
it('does not change when a mapping is swapped for a wire-equivalent one', () => {
94+
const withField = { aztec_utl_foo: makeEntry({ params: [{ name: 'a', type: FIELD }] }) };
95+
const withTxHash = { aztec_utl_foo: makeEntry({ params: [{ name: 'a', type: TX_HASH }] }) };
96+
expect(getOracleRegistrySignature(withTxHash)).toBe(getOracleRegistrySignature(withField));
11897
});
11998

120-
it('throws when the registry is absent', () => {
121-
const path = writeFixture(dir, 'absent.ts', `export const SOMETHING_ELSE = {};\n`);
122-
expect(() => getOracleRegistrySignature(path, 'ORACLE_REGISTRY')).toThrow(/Could not find oracle registry/);
99+
it('captures nested composite kinds in the signature', () => {
100+
const registry = {
101+
aztec_utl_foo: makeEntry({ params: [{ name: 'a', type: OPTION(ARRAY(FIELD)) }], returnType: AZTEC_ADDRESS }),
102+
};
103+
expect(getOracleRegistrySignature(registry)).toBe('aztec_utl_foo(a: option(array(field))): aztec-address');
123104
});
124105
});
125106

0 commit comments

Comments
 (0)