@aztec/txe 5.0.0-rc.1 → 5.0.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/AuthRegistry-URXCCPYF.js +3 -0
- package/dest/AuthRegistry-URXCCPYF.js.map +7 -0
- package/dest/{ContractClassRegistry-EHVIHGEK.js → ContractClassRegistry-5RDBM6TC.js} +1 -1
- package/dest/{ContractClassRegistry-EHVIHGEK.js.map → ContractClassRegistry-5RDBM6TC.js.map} +2 -2
- package/dest/{ContractInstanceRegistry-DWZDXHRG.js → ContractInstanceRegistry-GCR4G4D7.js} +1 -1
- package/dest/{ContractInstanceRegistry-DWZDXHRG.js.map → ContractInstanceRegistry-GCR4G4D7.js.map} +1 -1
- package/dest/{FeeJuice-MI32ZO7B.js → FeeJuice-O3KOSZO5.js} +1 -1
- package/dest/{FeeJuice-MI32ZO7B.js.map → FeeJuice-O3KOSZO5.js.map} +1 -1
- package/dest/HandshakeRegistry-TXSMHMNY.js +3 -0
- package/dest/HandshakeRegistry-TXSMHMNY.js.map +7 -0
- package/dest/MultiCallEntrypoint-P4FSRXAD.js +3 -0
- package/dest/MultiCallEntrypoint-P4FSRXAD.js.map +7 -0
- package/dest/SchnorrAccount-AQZX7ROU.js +3 -0
- package/dest/SchnorrAccount-AQZX7ROU.js.map +7 -0
- package/dest/SchnorrInitializerlessAccount-KMX2H3J6.js +3 -0
- package/dest/SchnorrInitializerlessAccount-KMX2H3J6.js.map +7 -0
- package/dest/bin/index.js +1 -1
- package/dest/bin/oracle_test_server.js +2 -2
- package/dest/{chunk-UPW55EJX.js → chunk-I6DL4FT2.js} +2 -2
- package/dest/chunk-IAO54JS2.js +266 -0
- package/dest/{chunk-5U25VAFR.js.map → chunk-IAO54JS2.js.map} +4 -4
- package/dest/constants.d.ts +1 -1
- package/dest/constants.d.ts.map +1 -1
- package/dest/constants.js +1 -1
- package/dest/metafile.json +7241 -6706
- package/dest/oracle/interfaces.d.ts +10 -5
- package/dest/oracle/interfaces.d.ts.map +1 -1
- package/dest/oracle/test-resolver/default_fixtures.d.ts +9 -0
- package/dest/oracle/test-resolver/default_fixtures.d.ts.map +1 -0
- package/dest/oracle/test-resolver/default_fixtures.js +164 -0
- package/dest/oracle/test-resolver/index.d.ts +1 -1
- package/dest/oracle/test-resolver/index.d.ts.map +1 -1
- package/dest/oracle/test-resolver/index.js +1 -2
- package/dest/oracle/test-resolver/resolver.d.ts +22 -8
- package/dest/oracle/test-resolver/resolver.d.ts.map +1 -1
- package/dest/oracle/test-resolver/resolver.js +62 -32
- package/dest/oracle/txe_oracle_public_context.d.ts +4 -4
- package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_registry.d.ts +156 -3
- package/dest/oracle/txe_oracle_registry.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_registry.js +179 -26
- package/dest/oracle/txe_oracle_top_level_context.d.ts +20 -8
- package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_top_level_context.js +72 -30
- package/dest/oracle/txe_oracle_version.d.ts +2 -2
- package/dest/oracle/txe_oracle_version.js +2 -2
- package/dest/rpc_translator.d.ts +10 -2
- package/dest/rpc_translator.d.ts.map +1 -1
- package/dest/rpc_translator.js +69 -5
- package/dest/server.bundle.js +1 -1
- package/dest/state_machine/archiver.d.ts +1 -1
- package/dest/state_machine/archiver.d.ts.map +1 -1
- package/dest/state_machine/archiver.js +1 -2
- package/dest/state_machine/dummy_p2p_client.d.ts +3 -2
- package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
- package/dest/state_machine/dummy_p2p_client.js +3 -0
- package/dest/state_machine/global_variable_builder.d.ts +3 -4
- package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
- package/dest/state_machine/global_variable_builder.js +0 -3
- package/dest/state_machine/index.d.ts +6 -5
- package/dest/state_machine/index.d.ts.map +1 -1
- package/dest/state_machine/index.js +35 -10
- package/dest/state_machine/synchronizer.d.ts +3 -2
- package/dest/state_machine/synchronizer.d.ts.map +1 -1
- package/dest/state_machine/synchronizer.js +3 -2
- package/dest/txe_session.d.ts +8 -6
- package/dest/txe_session.d.ts.map +1 -1
- package/dest/txe_session.js +53 -27
- package/dest/utils/block_creation.d.ts +2 -2
- package/dest/utils/block_creation.d.ts.map +1 -1
- package/dest/utils/block_creation.js +2 -2
- package/dest/worker.bundle.js +1 -1
- package/package.json +17 -17
- package/src/bin/oracle_test_server.ts +2 -2
- package/src/constants.ts +1 -1
- package/src/oracle/interfaces.ts +9 -3
- package/src/oracle/test-resolver/default_fixtures.ts +226 -0
- package/src/oracle/test-resolver/index.ts +1 -2
- package/src/oracle/test-resolver/resolver.ts +74 -41
- package/src/oracle/txe_oracle_public_context.ts +3 -3
- package/src/oracle/txe_oracle_registry.ts +106 -13
- package/src/oracle/txe_oracle_top_level_context.ts +76 -30
- package/src/oracle/txe_oracle_version.ts +2 -2
- package/src/rpc_translator.ts +93 -5
- package/src/state_machine/archiver.ts +0 -1
- package/src/state_machine/dummy_p2p_client.ts +5 -0
- package/src/state_machine/global_variable_builder.ts +2 -16
- package/src/state_machine/index.ts +31 -29
- package/src/state_machine/synchronizer.ts +3 -2
- package/src/txe_session.ts +62 -23
- package/src/utils/block_creation.ts +2 -1
- package/dest/AuthRegistry-CPGFQR26.js +0 -3
- package/dest/AuthRegistry-CPGFQR26.js.map +0 -7
- package/dest/HandshakeRegistry-3KSP3ITH.js +0 -3
- package/dest/HandshakeRegistry-3KSP3ITH.js.map +0 -7
- package/dest/MultiCallEntrypoint-IU7HYFYE.js +0 -3
- package/dest/MultiCallEntrypoint-IU7HYFYE.js.map +0 -7
- package/dest/SchnorrAccount-6TUE7JX4.js +0 -3
- package/dest/SchnorrAccount-6TUE7JX4.js.map +0 -7
- package/dest/SchnorrInitializerlessAccount-S3DU2DJK.js +0 -3
- package/dest/SchnorrInitializerlessAccount-S3DU2DJK.js.map +0 -7
- package/dest/chunk-5U25VAFR.js +0 -265
- package/dest/oracle/test-resolver/fixtures.d.ts +0 -43
- package/dest/oracle/test-resolver/fixtures.d.ts.map +0 -1
- package/dest/oracle/test-resolver/fixtures.js +0 -39
- package/src/oracle/test-resolver/fixtures.ts +0 -84
- /package/dest/{chunk-UPW55EJX.js.map → chunk-I6DL4FT2.js.map} +0 -0
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
/* eslint-disable camelcase */
|
|
2
2
|
import type { Logger } from '@aztec/foundation/log';
|
|
3
3
|
import { createLogger } from '@aztec/foundation/log';
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
4
|
+
import { withoutHexPrefix } from '@aztec/foundation/string';
|
|
5
|
+
import { BOUNDED_VEC, BYTE, BoundedVec, Option, type OracleRegistryEntry, makeEntry } from '@aztec/pxe/simulator';
|
|
6
6
|
|
|
7
7
|
import type { ForeignCallArgs, ForeignCallResult } from '../../utils/encoding.js';
|
|
8
|
-
import
|
|
8
|
+
import { toInputSlots } from '../txe_oracle_registry.js';
|
|
9
|
+
import { synthesizeDefaultFixtures } from './default_fixtures.js';
|
|
9
10
|
|
|
10
|
-
/** Name of the meta-oracle that Noir tests call to
|
|
11
|
+
/** Name of the meta-oracle that Noir tests call to announce the next call's scenario by name. */
|
|
11
12
|
const SET_SCENARIO_ORACLE = 'aztec_oracle_test_set_scenario';
|
|
13
|
+
export const SET_SCENARIO_ENTRY = makeEntry({ params: [{ name: 'name', type: BOUNDED_VEC(BYTE) }] });
|
|
12
14
|
|
|
13
15
|
export type OracleTestCallInput = {
|
|
14
16
|
session_id: number;
|
|
@@ -19,12 +21,22 @@ export type OracleTestCallInput = {
|
|
|
19
21
|
};
|
|
20
22
|
|
|
21
23
|
/**
|
|
22
|
-
*
|
|
24
|
+
* One test case for an oracle: the expected deserialized `inputs`, the `output` to serialize back to Noir, and the
|
|
25
|
+
* `scenario` name (`some`/`none`) the matching Noir test announces. Single-scenario oracles leave `scenario` undefined
|
|
26
|
+
* and are selected automatically.
|
|
27
|
+
*/
|
|
28
|
+
export interface OracleTestScenario {
|
|
29
|
+
scenario?: string;
|
|
30
|
+
inputs: Record<string, unknown>;
|
|
31
|
+
output: unknown;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Oracle resolver for serialization tests. Selects a fixture scenario, verifies that the received inputs match, and
|
|
23
36
|
* returns the corresponding fixture output.
|
|
24
37
|
*
|
|
25
|
-
* For oracles with a single
|
|
26
|
-
*
|
|
27
|
-
* real oracle.
|
|
38
|
+
* For oracles with a single scenario, it is selected automatically. For oracles with multiple scenarios, the Noir test
|
|
39
|
+
* announces the scenario by name via the `aztec_oracle_test_set_scenario` meta-oracle before calling the real oracle.
|
|
28
40
|
*/
|
|
29
41
|
export class OracleTestResolver {
|
|
30
42
|
private readonly calledOracles = new Set<string>();
|
|
@@ -33,12 +45,20 @@ export class OracleTestResolver {
|
|
|
33
45
|
|
|
34
46
|
constructor(
|
|
35
47
|
private readonly registry: Record<string, OracleRegistryEntry>,
|
|
36
|
-
private readonly fixtures:
|
|
48
|
+
private readonly fixtures: Record<string, OracleTestScenario[]>,
|
|
37
49
|
logger?: Logger,
|
|
38
50
|
) {
|
|
39
51
|
this.logger = logger ?? createLogger('txe:test-resolver');
|
|
40
52
|
}
|
|
41
53
|
|
|
54
|
+
/**
|
|
55
|
+
* Builds a resolver whose fixtures are the default scenarios synthesized from the registry's type mappings. The
|
|
56
|
+
* matching Noir serialization tests are auto-generated by `#[auto_serialization_test]` from the same convention.
|
|
57
|
+
*/
|
|
58
|
+
static fromRegistry(registry: Record<string, OracleRegistryEntry>, logger?: Logger): OracleTestResolver {
|
|
59
|
+
return new OracleTestResolver(registry, synthesizeDefaultFixtures(registry), logger);
|
|
60
|
+
}
|
|
61
|
+
|
|
42
62
|
// eslint-disable-next-line require-await
|
|
43
63
|
async resolve_foreign_call(callData: OracleTestCallInput): Promise<ForeignCallResult> {
|
|
44
64
|
const oracleName = callData.function;
|
|
@@ -48,8 +68,6 @@ export class OracleTestResolver {
|
|
|
48
68
|
return this.#handleSetScenario(callData);
|
|
49
69
|
}
|
|
50
70
|
|
|
51
|
-
this.calledOracles.add(oracleName);
|
|
52
|
-
|
|
53
71
|
if (!(oracleName in this.registry)) {
|
|
54
72
|
throw new Error(`Oracle '${oracleName}' not found in registry`);
|
|
55
73
|
}
|
|
@@ -62,6 +80,7 @@ export class OracleTestResolver {
|
|
|
62
80
|
|
|
63
81
|
const match = this.#selectScenario(callData.session_id, oracleName, scenarios);
|
|
64
82
|
this.#verifyInputs(callData.inputs, entry, match, oracleName);
|
|
83
|
+
this.calledOracles.add(oracleName);
|
|
65
84
|
|
|
66
85
|
this.logger.debug('Verified scenario for oracle', { oracleName });
|
|
67
86
|
|
|
@@ -81,62 +100,57 @@ export class OracleTestResolver {
|
|
|
81
100
|
return Object.keys(this.registry).filter(name => !(name in this.fixtures));
|
|
82
101
|
}
|
|
83
102
|
|
|
103
|
+
/**
|
|
104
|
+
* Records the scenario name for the session's next oracle call. A test announces once per multi-scenario position
|
|
105
|
+
* (param or return), so successive announcements accumulate joined with `+`, matching the names the fixture
|
|
106
|
+
* synthesizer builds (e.g. `some+some`).
|
|
107
|
+
*/
|
|
84
108
|
#handleSetScenario(callData: { session_id: number; inputs: ForeignCallArgs }): ForeignCallResult {
|
|
85
|
-
const
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
.map(code => String.fromCharCode(code))
|
|
89
|
-
.join('');
|
|
109
|
+
const name = decodeScenarioName(callData.inputs);
|
|
110
|
+
const existing = this.pendingScenario.get(callData.session_id);
|
|
111
|
+
const scenario = existing !== undefined ? `${existing}+${name}` : name;
|
|
90
112
|
|
|
91
|
-
this.logger.debug('Setting scenario for next oracle call', { sessionId: callData.session_id,
|
|
92
|
-
this.pendingScenario.set(callData.session_id,
|
|
113
|
+
this.logger.debug('Setting scenario for next oracle call', { sessionId: callData.session_id, scenario });
|
|
114
|
+
this.pendingScenario.set(callData.session_id, scenario);
|
|
93
115
|
|
|
94
116
|
return { values: [] };
|
|
95
117
|
}
|
|
96
118
|
|
|
97
|
-
/** Selects
|
|
119
|
+
/** Selects the fixture by the announced scenario name (for multi-scenario oracles) or returns the single fixture. */
|
|
98
120
|
#selectScenario(sessionId: number, oracleName: string, fixtures: OracleTestScenario[]): OracleTestScenario {
|
|
99
|
-
const
|
|
121
|
+
const announced = this.pendingScenario.get(sessionId);
|
|
100
122
|
|
|
101
|
-
if (
|
|
123
|
+
if (announced !== undefined) {
|
|
102
124
|
this.pendingScenario.delete(sessionId);
|
|
103
|
-
const
|
|
104
|
-
if (
|
|
105
|
-
const available = fixtures.map(s => s.scenario).join(', ');
|
|
106
|
-
throw new Error(`No scenario
|
|
125
|
+
const match = fixtures.find(s => s.scenario === announced);
|
|
126
|
+
if (!match) {
|
|
127
|
+
const available = fixtures.map(s => s.scenario ?? '<default>').join(', ');
|
|
128
|
+
throw new Error(`No scenario '${announced}' for oracle '${oracleName}'. Available: ${available}`);
|
|
107
129
|
}
|
|
108
|
-
|
|
109
|
-
throw new Error(`Duplicate scenario name '${selectedName}' for oracle '${oracleName}'`);
|
|
110
|
-
}
|
|
111
|
-
return matches[0];
|
|
130
|
+
return match;
|
|
112
131
|
}
|
|
113
132
|
|
|
114
133
|
if (fixtures.length === 1) {
|
|
115
134
|
return fixtures[0];
|
|
116
135
|
}
|
|
117
136
|
|
|
118
|
-
throw new Error(
|
|
119
|
-
`Oracle '${oracleName}' has ${fixtures.length} fixture scenarios. ` +
|
|
120
|
-
`Use #[oracle_test("scenario_name")] to select one.`,
|
|
121
|
-
);
|
|
137
|
+
throw new Error(`Oracle '${oracleName}' has ${fixtures.length} scenarios but none was announced before the call.`);
|
|
122
138
|
}
|
|
123
139
|
|
|
124
140
|
/** Deserializes actual inputs and verifies they match the scenario's expected inputs. */
|
|
125
141
|
#verifyInputs(
|
|
126
142
|
rawInputs: ForeignCallArgs,
|
|
127
143
|
entry: OracleRegistryEntry,
|
|
128
|
-
|
|
144
|
+
fixture: OracleTestScenario,
|
|
129
145
|
oracleName: string,
|
|
130
146
|
): void {
|
|
131
|
-
const expectedInputs =
|
|
147
|
+
const expectedInputs = fixture.inputs;
|
|
132
148
|
if (Object.keys(expectedInputs).length === 0) {
|
|
133
149
|
return;
|
|
134
150
|
}
|
|
135
151
|
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
);
|
|
139
|
-
const named = entry.deserializeParams(normalized);
|
|
152
|
+
const scenarioLabel = fixture.scenario ? ` (scenario '${fixture.scenario}')` : '';
|
|
153
|
+
const named = entry.deserializeParams(toInputSlots(rawInputs));
|
|
140
154
|
|
|
141
155
|
for (const param of named) {
|
|
142
156
|
if (!(param.name in expectedInputs)) {
|
|
@@ -146,20 +160,39 @@ export class OracleTestResolver {
|
|
|
146
160
|
);
|
|
147
161
|
}
|
|
148
162
|
if (!valuesEqual(param.value, expectedInputs[param.name])) {
|
|
149
|
-
const scenarioLabel = scenario.scenario ? ` (scenario '${scenario.scenario}')` : '';
|
|
150
163
|
throw new Error(
|
|
151
164
|
`Input mismatch for oracle '${oracleName}'${scenarioLabel}: ` +
|
|
152
165
|
`param '${param.name}' expected ${String(expectedInputs[param.name])} ` +
|
|
153
|
-
`but got ${String(param.value)}`,
|
|
166
|
+
`but got ${String(param.value)}. ${versionBumpHint(oracleName)}`,
|
|
154
167
|
);
|
|
155
168
|
}
|
|
156
169
|
}
|
|
157
170
|
}
|
|
158
171
|
}
|
|
159
172
|
|
|
173
|
+
/**
|
|
174
|
+
* Decodes the scenario name announced by `set_oracle_test_scenario`, whose argument is a `BoundedVec<u8, N>`
|
|
175
|
+
*/
|
|
176
|
+
function decodeScenarioName(inputs: ForeignCallArgs): string {
|
|
177
|
+
const [{ value }] = SET_SCENARIO_ENTRY.deserializeParams(toInputSlots(inputs));
|
|
178
|
+
return String.fromCharCode(...value.data);
|
|
179
|
+
}
|
|
180
|
+
|
|
160
181
|
function valuesEqual(actual: unknown, expected: unknown): boolean {
|
|
182
|
+
if (actual instanceof Option && expected instanceof Option) {
|
|
183
|
+
return actual.equals(expected, valuesEqual);
|
|
184
|
+
}
|
|
185
|
+
if (actual instanceof BoundedVec && expected instanceof BoundedVec) {
|
|
186
|
+
return actual.equals(expected, valuesEqual);
|
|
187
|
+
}
|
|
161
188
|
if (Array.isArray(actual) && Array.isArray(expected)) {
|
|
162
189
|
return actual.length === expected.length && actual.every((v, i) => valuesEqual(v, expected[i]));
|
|
163
190
|
}
|
|
164
191
|
return String(actual) === String(expected);
|
|
165
192
|
}
|
|
193
|
+
|
|
194
|
+
function versionBumpHint(oracle: string): string {
|
|
195
|
+
return oracle.startsWith('aztec_txe_') || oracle.startsWith('aztec_avm_')
|
|
196
|
+
? 'If you changed this oracle, consider bumping the TXE oracle version in yarn-project/txe/src/oracle/txe_oracle_version.ts.'
|
|
197
|
+
: 'If you changed this oracle, consider bumping the PXE oracle version in yarn-project/pxe/src/oracle_version.ts.';
|
|
198
|
+
}
|
|
@@ -164,19 +164,19 @@ export class TXEOraclePublicContext implements IAvmExecutionOracle {
|
|
|
164
164
|
);
|
|
165
165
|
}
|
|
166
166
|
|
|
167
|
-
call(_l2Gas: number, _daGas: number, _address: AztecAddress, _argsLength: number, _args: Fr[]): Promise<
|
|
167
|
+
call(_l2Gas: number, _daGas: number, _address: AztecAddress, _argsLength: number, _args: Fr[]): Promise<void> {
|
|
168
168
|
throw new Error(
|
|
169
169
|
'Contract calls are forbidden inside a `TestEnvironment::public_context`, use `public_call` instead',
|
|
170
170
|
);
|
|
171
171
|
}
|
|
172
172
|
|
|
173
|
-
staticCall(_l2Gas: number, _daGas: number, _address: AztecAddress, _argsLength: number, _args: Fr[]): Promise<
|
|
173
|
+
staticCall(_l2Gas: number, _daGas: number, _address: AztecAddress, _argsLength: number, _args: Fr[]): Promise<void> {
|
|
174
174
|
throw new Error(
|
|
175
175
|
'Contract calls are forbidden inside a `TestEnvironment::public_context`, use `public_call` instead',
|
|
176
176
|
);
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
-
successCopy(): Promise<
|
|
179
|
+
successCopy(): Promise<boolean> {
|
|
180
180
|
throw new Error(
|
|
181
181
|
'Contract calls are forbidden inside a `TestEnvironment::public_context`, use `public_call` instead',
|
|
182
182
|
);
|
|
@@ -4,16 +4,20 @@ import {
|
|
|
4
4
|
MAX_NOTE_HASHES_PER_TX,
|
|
5
5
|
MAX_NULLIFIERS_PER_TX,
|
|
6
6
|
MAX_PRIVATE_LOGS_PER_TX,
|
|
7
|
+
PRIVATE_CONTEXT_INPUTS_LENGTH,
|
|
7
8
|
PRIVATE_LOG_SIZE_IN_FIELDS,
|
|
8
9
|
} from '@aztec/constants';
|
|
9
10
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
11
|
+
import { Point } from '@aztec/foundation/curves/grumpkin';
|
|
10
12
|
import { withHexPrefix, withoutHexPrefix } from '@aztec/foundation/string';
|
|
13
|
+
import type { TaggingSecretStrategy } from '@aztec/pxe/server';
|
|
11
14
|
import {
|
|
12
15
|
ARRAY,
|
|
13
16
|
AZTEC_ADDRESS,
|
|
14
17
|
BIGINT,
|
|
15
18
|
BLOCK_NUMBER,
|
|
16
19
|
BOOL,
|
|
20
|
+
ETH_ADDRESS,
|
|
17
21
|
FIELD,
|
|
18
22
|
FUNCTION_SELECTOR,
|
|
19
23
|
type InputSlot,
|
|
@@ -23,6 +27,7 @@ import {
|
|
|
23
27
|
type OracleRegistryEntry,
|
|
24
28
|
type ParamTypes,
|
|
25
29
|
STR,
|
|
30
|
+
type SlotShape,
|
|
26
31
|
type TypeMapping,
|
|
27
32
|
U32,
|
|
28
33
|
makeEntry,
|
|
@@ -42,20 +47,68 @@ import {
|
|
|
42
47
|
} from '../constants.js';
|
|
43
48
|
import type { ForeignCallArgs, ForeignCallResult } from '../utils/encoding.js';
|
|
44
49
|
|
|
50
|
+
// Spreading `ORACLE_REGISTRY` re-materializes its entries into `TXE_ORACLE_REGISTRY`'s inferred type, which names the
|
|
51
|
+
// protocol types below. Re-exporting them gives tsc a portable path to each instead of falling back to a deep
|
|
52
|
+
// node_modules path that breaks .d.ts portability (TS2742).
|
|
53
|
+
export type { ContractClassLogData, EmbeddedCurvePoint, TxEffectData } from '@aztec/pxe/simulator';
|
|
54
|
+
export type { BlockHash } from '@aztec/stdlib/block';
|
|
55
|
+
export type { MembershipWitness } from '@aztec/foundation/trees';
|
|
56
|
+
export type { NullifierMembershipWitness, PublicDataWitness } from '@aztec/stdlib/trees';
|
|
57
|
+
|
|
45
58
|
const GAS_SETTINGS: TypeMapping<GasSettings> = {
|
|
46
|
-
serialization: { fn: v => v.toFields() },
|
|
47
59
|
deserialization: {
|
|
48
60
|
fn: ([reader]) => GasSettings.fromFields(reader.readFieldArray(GAS_SETTINGS_LENGTH)),
|
|
49
|
-
slots: 1,
|
|
50
61
|
},
|
|
62
|
+
shape: [{ len: GAS_SETTINGS_LENGTH }],
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
// Tagging secret strategy discriminants. Must match the Noir test helper `TaggingSecretStrategy` in
|
|
66
|
+
// aztec-nr `test/helpers/tagging_secret_strategy.nr`. This is a test-only oracle (only `set_tagging_secret_strategy`
|
|
67
|
+
// reads it), so the mapping lives here on the TXE side rather than in the production oracle type mappings.
|
|
68
|
+
const STRATEGY_NON_INTERACTIVE_HANDSHAKE = 1;
|
|
69
|
+
const STRATEGY_ARBITRARY_SECRET = 2;
|
|
70
|
+
const STRATEGY_ADDRESS_DERIVED = 3;
|
|
71
|
+
|
|
72
|
+
const TAGGING_SECRET_STRATEGY: TypeMapping<TaggingSecretStrategy> = {
|
|
73
|
+
serialization: {
|
|
74
|
+
fn: strategy => {
|
|
75
|
+
switch (strategy.type) {
|
|
76
|
+
case 'non-interactive-handshake':
|
|
77
|
+
return [new Fr(STRATEGY_NON_INTERACTIVE_HANDSHAKE), Fr.ZERO, Fr.ZERO];
|
|
78
|
+
case 'address-derived':
|
|
79
|
+
return [new Fr(STRATEGY_ADDRESS_DERIVED), Fr.ZERO, Fr.ZERO];
|
|
80
|
+
case 'arbitrary-secret':
|
|
81
|
+
return [new Fr(STRATEGY_ARBITRARY_SECRET), strategy.secret.x, strategy.secret.y];
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
deserialization: {
|
|
86
|
+
fn: ([kindReader, xReader, yReader]) => {
|
|
87
|
+
const kind = kindReader.readField().toNumber();
|
|
88
|
+
const [x, y] = [xReader.readField(), yReader.readField()];
|
|
89
|
+
switch (kind) {
|
|
90
|
+
case STRATEGY_NON_INTERACTIVE_HANDSHAKE:
|
|
91
|
+
return { type: 'non-interactive-handshake' };
|
|
92
|
+
case STRATEGY_ADDRESS_DERIVED:
|
|
93
|
+
return { type: 'address-derived' };
|
|
94
|
+
case STRATEGY_ARBITRARY_SECRET:
|
|
95
|
+
return { type: 'arbitrary-secret', secret: Point.fromFields([x, y]) };
|
|
96
|
+
default:
|
|
97
|
+
throw new Error(`Unrecognized tagging secret strategy kind: ${kind}`);
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
shape: ['scalar', 'scalar', 'scalar'],
|
|
51
102
|
};
|
|
52
103
|
|
|
53
104
|
const PRIVATE_CONTEXT_INPUTS: TypeMapping<PrivateContextInputs> = {
|
|
54
105
|
serialization: { fn: v => v.toFields() },
|
|
106
|
+
shape: Array<SlotShape>(PRIVATE_CONTEXT_INPUTS_LENGTH).fill('scalar'),
|
|
55
107
|
};
|
|
56
108
|
|
|
57
109
|
const COMPLETE_ADDRESS: TypeMapping<CompleteAddress> = {
|
|
58
110
|
serialization: { fn: v => [v.address.toField(), ...v.publicKeys.toFields()] },
|
|
111
|
+
shape: Array<SlotShape>(8).fill('scalar'), // address + 7 public-key fields
|
|
59
112
|
};
|
|
60
113
|
|
|
61
114
|
const TXE_TX_EFFECTS: TypeMapping<{
|
|
@@ -91,6 +144,17 @@ const TXE_TX_EFFECTS: TypeMapping<{
|
|
|
91
144
|
] as (Fr | Fr[])[];
|
|
92
145
|
},
|
|
93
146
|
},
|
|
147
|
+
// txHash, padded note hashes + count, padded nullifiers + count, flattened private-log storage + lengths + count.
|
|
148
|
+
shape: [
|
|
149
|
+
'scalar',
|
|
150
|
+
{ len: MAX_NOTE_HASHES_PER_TX },
|
|
151
|
+
'scalar',
|
|
152
|
+
{ len: MAX_NULLIFIERS_PER_TX },
|
|
153
|
+
'scalar',
|
|
154
|
+
{ len: MAX_PRIVATE_LOGS_PER_TX * PRIVATE_LOG_SIZE_IN_FIELDS },
|
|
155
|
+
{ len: MAX_PRIVATE_LOGS_PER_TX },
|
|
156
|
+
'scalar',
|
|
157
|
+
],
|
|
94
158
|
};
|
|
95
159
|
|
|
96
160
|
const TXE_OFFCHAIN_EFFECTS: TypeMapping<{ effects: Fr[][] }> = {
|
|
@@ -109,6 +173,12 @@ const TXE_OFFCHAIN_EFFECTS: TypeMapping<{ effects: Fr[][] }> = {
|
|
|
109
173
|
return [rawArrayStorage, effectLengths, new Fr(effects.length)] as (Fr | Fr[])[];
|
|
110
174
|
},
|
|
111
175
|
},
|
|
176
|
+
// Flattened effect storage, per-effect lengths, then the effect count.
|
|
177
|
+
shape: [
|
|
178
|
+
{ len: MAX_OFFCHAIN_EFFECTS_PER_TXE_QUERY * MAX_OFFCHAIN_EFFECT_LEN },
|
|
179
|
+
{ len: MAX_OFFCHAIN_EFFECTS_PER_TXE_QUERY },
|
|
180
|
+
'scalar',
|
|
181
|
+
],
|
|
112
182
|
};
|
|
113
183
|
|
|
114
184
|
const TXE_CALL_CONTEXT: TypeMapping<{ txHash: Fr; anchorBlockTimestamp: bigint }> = {
|
|
@@ -118,15 +188,18 @@ const TXE_CALL_CONTEXT: TypeMapping<{ txHash: Fr; anchorBlockTimestamp: bigint }
|
|
|
118
188
|
return [new Fr(isSome), txHash, new Fr(anchorBlockTimestamp)];
|
|
119
189
|
},
|
|
120
190
|
},
|
|
191
|
+
shape: ['scalar', 'scalar', 'scalar'], // discriminant, txHash, anchor block timestamp
|
|
121
192
|
};
|
|
122
193
|
|
|
123
194
|
const CONTRACT_INSTANCE_MEMBER: TypeMapping<{ member: Fr; exists: boolean }> = {
|
|
124
195
|
serialization: { fn: ({ member, exists }) => [member, new Fr(exists)] },
|
|
196
|
+
shape: ['scalar', 'scalar'],
|
|
125
197
|
};
|
|
126
198
|
|
|
127
199
|
const EVENT_SELECTOR: TypeMapping<EventSelector> = {
|
|
128
200
|
serialization: { fn: v => [v.toField()] },
|
|
129
|
-
deserialization: { fn: ([reader]) => EventSelector.fromField(reader.readField())
|
|
201
|
+
deserialization: { fn: ([reader]) => EventSelector.fromField(reader.readField()) },
|
|
202
|
+
shape: ['scalar'],
|
|
130
203
|
};
|
|
131
204
|
|
|
132
205
|
const TXE_PRIVATE_EVENTS: TypeMapping<Fr[][]> = {
|
|
@@ -144,9 +217,15 @@ const TXE_PRIVATE_EVENTS: TypeMapping<Fr[][]> = {
|
|
|
144
217
|
return [rawArrayStorage, eventLengths, new Fr(events.length)] as (Fr | Fr[])[];
|
|
145
218
|
},
|
|
146
219
|
},
|
|
220
|
+
// Flattened event storage, per-event lengths, then the event count.
|
|
221
|
+
shape: [
|
|
222
|
+
{ len: MAX_PRIVATE_EVENTS_PER_TXE_QUERY * MAX_PRIVATE_EVENT_LEN },
|
|
223
|
+
{ len: MAX_PRIVATE_EVENTS_PER_TXE_QUERY },
|
|
224
|
+
'scalar',
|
|
225
|
+
],
|
|
147
226
|
};
|
|
148
227
|
|
|
149
|
-
export const TXE_ORACLE_REGISTRY
|
|
228
|
+
export const TXE_ORACLE_REGISTRY = {
|
|
150
229
|
...ORACLE_REGISTRY,
|
|
151
230
|
|
|
152
231
|
aztec_txe_assertCompatibleOracleVersion: makeEntry({
|
|
@@ -219,6 +298,20 @@ export const TXE_ORACLE_REGISTRY: Record<string, OracleRegistryEntry> = {
|
|
|
219
298
|
],
|
|
220
299
|
}),
|
|
221
300
|
|
|
301
|
+
aztec_txe_sendL1ToL2Message: makeEntry({
|
|
302
|
+
params: [
|
|
303
|
+
{ name: 'content', type: FIELD },
|
|
304
|
+
{ name: 'secretHash', type: FIELD },
|
|
305
|
+
{ name: 'sender', type: ETH_ADDRESS },
|
|
306
|
+
{ name: 'recipient', type: AZTEC_ADDRESS },
|
|
307
|
+
],
|
|
308
|
+
returnType: FIELD,
|
|
309
|
+
}),
|
|
310
|
+
|
|
311
|
+
aztec_txe_setTaggingSecretStrategy: makeEntry({
|
|
312
|
+
params: [{ name: 'strategy', type: OPTION(TAGGING_SECRET_STRATEGY) }],
|
|
313
|
+
}),
|
|
314
|
+
|
|
222
315
|
aztec_txe_getLastBlockTimestamp: makeEntry({
|
|
223
316
|
returnType: BIGINT,
|
|
224
317
|
}),
|
|
@@ -253,6 +346,7 @@ export const TXE_ORACLE_REGISTRY: Record<string, OracleRegistryEntry> = {
|
|
|
253
346
|
|
|
254
347
|
aztec_txe_executeUtilityFunction: makeEntry({
|
|
255
348
|
params: [
|
|
349
|
+
{ name: 'from', type: OPTION(AZTEC_ADDRESS) },
|
|
256
350
|
{ name: 'targetContractAddress', type: AZTEC_ADDRESS },
|
|
257
351
|
{ name: 'functionSelector', type: FUNCTION_SELECTOR },
|
|
258
352
|
{ name: 'args', type: ARRAY(FIELD) },
|
|
@@ -336,7 +430,6 @@ export const TXE_ORACLE_REGISTRY: Record<string, OracleRegistryEntry> = {
|
|
|
336
430
|
{ name: 'argsLength', type: U32 },
|
|
337
431
|
{ name: 'args', type: ARRAY(FIELD) },
|
|
338
432
|
],
|
|
339
|
-
returnType: ARRAY(FIELD),
|
|
340
433
|
}),
|
|
341
434
|
|
|
342
435
|
aztec_avm_staticCall: makeEntry({
|
|
@@ -347,10 +440,9 @@ export const TXE_ORACLE_REGISTRY: Record<string, OracleRegistryEntry> = {
|
|
|
347
440
|
{ name: 'argsLength', type: U32 },
|
|
348
441
|
{ name: 'args', type: ARRAY(FIELD) },
|
|
349
442
|
],
|
|
350
|
-
returnType: ARRAY(FIELD),
|
|
351
443
|
}),
|
|
352
444
|
|
|
353
|
-
aztec_avm_successCopy: makeEntry({ returnType:
|
|
445
|
+
aztec_avm_successCopy: makeEntry({ returnType: BOOL }),
|
|
354
446
|
|
|
355
447
|
aztec_avm_getContractInstanceDeployer: makeEntry({
|
|
356
448
|
params: [{ name: 'address', type: AZTEC_ADDRESS }],
|
|
@@ -368,7 +460,12 @@ export const TXE_ORACLE_REGISTRY: Record<string, OracleRegistryEntry> = {
|
|
|
368
460
|
params: [{ name: 'address', type: AZTEC_ADDRESS }],
|
|
369
461
|
returnType: CONTRACT_INSTANCE_MEMBER,
|
|
370
462
|
}),
|
|
371
|
-
}
|
|
463
|
+
} satisfies Record<string, OracleRegistryEntry>;
|
|
464
|
+
|
|
465
|
+
export function toInputSlots(inputs: ForeignCallArgs): InputSlot[] {
|
|
466
|
+
// TXE foreign calls use bare hex strings, but Fr.fromString requires a 0x prefix to parse as hex.
|
|
467
|
+
return inputs.map(v => (Array.isArray(v) ? (v as string[]).map(withHexPrefix) : [withHexPrefix(v as string)]));
|
|
468
|
+
}
|
|
372
469
|
|
|
373
470
|
/**
|
|
374
471
|
* Deserializes oracle inputs, calls the handler with typed params, serializes the result, and wraps
|
|
@@ -387,11 +484,7 @@ export async function callTxeHandler<K extends keyof typeof TXE_ORACLE_REGISTRY>
|
|
|
387
484
|
) => MaybePromise<Parameters<(typeof TXE_ORACLE_REGISTRY)[K]['serializeReturn']>[0]>;
|
|
388
485
|
}): Promise<ForeignCallResult> {
|
|
389
486
|
const entry = TXE_ORACLE_REGISTRY[oracle] as OracleRegistryEntry;
|
|
390
|
-
|
|
391
|
-
const normalized: InputSlot[] = inputs.map(v =>
|
|
392
|
-
Array.isArray(v) ? (v as string[]).map(withHexPrefix) : [withHexPrefix(v as string)],
|
|
393
|
-
);
|
|
394
|
-
const named = entry.deserializeParams(normalized);
|
|
487
|
+
const named = entry.deserializeParams(toInputSlots(inputs));
|
|
395
488
|
const positional = named.map((p: { value: unknown }) => p.value);
|
|
396
489
|
const result = await handler(positional as any);
|
|
397
490
|
const outputSlots = entry.serializeReturn(result);
|