@aztec/txe 0.0.1-commit.3469e52 → 0.0.1-commit.350e0a4d

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.
Files changed (170) hide show
  1. package/dest/AuthRegistry-2RDAZOGB.js +3 -0
  2. package/dest/AuthRegistry-2RDAZOGB.js.map +7 -0
  3. package/dest/ContractClassRegistry-L5F3G33N.js +3 -0
  4. package/dest/ContractClassRegistry-L5F3G33N.js.map +7 -0
  5. package/dest/ContractInstanceRegistry-IJOBAWAC.js +3 -0
  6. package/dest/ContractInstanceRegistry-IJOBAWAC.js.map +7 -0
  7. package/dest/FeeJuice-J3XDQPFS.js +3 -0
  8. package/dest/FeeJuice-J3XDQPFS.js.map +7 -0
  9. package/dest/HandshakeRegistry-QGWZJYVS.js +3 -0
  10. package/dest/HandshakeRegistry-QGWZJYVS.js.map +7 -0
  11. package/dest/MultiCallEntrypoint-WZHPRFJ6.js +3 -0
  12. package/dest/MultiCallEntrypoint-WZHPRFJ6.js.map +7 -0
  13. package/dest/SchnorrAccount-II4XD6MI.js +3 -0
  14. package/dest/SchnorrAccount-II4XD6MI.js.map +7 -0
  15. package/dest/SchnorrInitializerlessAccount-FXIOXUQQ.js +3 -0
  16. package/dest/SchnorrInitializerlessAccount-FXIOXUQQ.js.map +7 -0
  17. package/dest/bin/check_txe_oracle_version.d.ts +2 -0
  18. package/dest/bin/check_txe_oracle_version.d.ts.map +1 -0
  19. package/dest/bin/check_txe_oracle_version.js +61 -0
  20. package/dest/bin/index.js +3 -30
  21. package/dest/bin/index.js.map +7 -0
  22. package/dest/bin/oracle_test_server.d.ts +3 -0
  23. package/dest/bin/oracle_test_server.d.ts.map +1 -0
  24. package/dest/bin/oracle_test_server.js +41 -0
  25. package/dest/chunk-BJVAAXNA.js +3 -0
  26. package/dest/chunk-BJVAAXNA.js.map +7 -0
  27. package/dest/chunk-OMH3BDML.js +304 -0
  28. package/dest/chunk-OMH3BDML.js.map +7 -0
  29. package/dest/chunk-R3ZWQEFL.js +260 -0
  30. package/dest/chunk-R3ZWQEFL.js.map +7 -0
  31. package/dest/constants.d.ts +5 -1
  32. package/dest/constants.d.ts.map +1 -1
  33. package/dest/constants.js +9 -1
  34. package/dest/dispatcher_pool.d.ts +67 -0
  35. package/dest/dispatcher_pool.d.ts.map +1 -0
  36. package/dest/dispatcher_pool.js +286 -0
  37. package/dest/index.d.ts +51 -7
  38. package/dest/index.d.ts.map +1 -1
  39. package/dest/index.js +73 -157
  40. package/dest/metafile.json +38140 -0
  41. package/dest/msgpackr_fr_extension.d.ts +2 -0
  42. package/dest/msgpackr_fr_extension.d.ts.map +1 -0
  43. package/dest/msgpackr_fr_extension.js +21 -0
  44. package/dest/oracle/interfaces.d.ts +61 -30
  45. package/dest/oracle/interfaces.d.ts.map +1 -1
  46. package/dest/oracle/test-resolver/default_fixtures.d.ts +9 -0
  47. package/dest/oracle/test-resolver/default_fixtures.d.ts.map +1 -0
  48. package/dest/oracle/test-resolver/default_fixtures.js +207 -0
  49. package/dest/oracle/test-resolver/index.d.ts +9 -0
  50. package/dest/oracle/test-resolver/index.d.ts.map +1 -0
  51. package/dest/oracle/test-resolver/index.js +32 -0
  52. package/dest/oracle/test-resolver/resolver.d.ts +48 -0
  53. package/dest/oracle/test-resolver/resolver.d.ts.map +1 -0
  54. package/dest/oracle/test-resolver/resolver.js +181 -0
  55. package/dest/oracle/txe_oracle_public_context.d.ts +40 -16
  56. package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
  57. package/dest/oracle/txe_oracle_public_context.js +65 -17
  58. package/dest/oracle/txe_oracle_registry.d.ts +169 -0
  59. package/dest/oracle/txe_oracle_registry.d.ts.map +1 -0
  60. package/dest/oracle/txe_oracle_registry.js +745 -0
  61. package/dest/oracle/txe_oracle_top_level_context.d.ts +55 -29
  62. package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
  63. package/dest/oracle/txe_oracle_top_level_context.js +322 -104
  64. package/dest/oracle/txe_oracle_version.d.ts +17 -0
  65. package/dest/oracle/txe_oracle_version.d.ts.map +1 -0
  66. package/dest/oracle/txe_oracle_version.js +14 -0
  67. package/dest/oracle/txe_private_execution_oracle.d.ts +17 -0
  68. package/dest/oracle/txe_private_execution_oracle.d.ts.map +1 -0
  69. package/dest/oracle/txe_private_execution_oracle.js +15 -0
  70. package/dest/rpc_server.d.ts +14 -0
  71. package/dest/rpc_server.d.ts.map +1 -0
  72. package/dest/rpc_server.js +78 -0
  73. package/dest/rpc_translator.d.ts +112 -222
  74. package/dest/rpc_translator.d.ts.map +1 -1
  75. package/dest/rpc_translator.js +877 -600
  76. package/dest/server.bundle.js +3 -0
  77. package/dest/server.bundle.js.map +7 -0
  78. package/dest/state_machine/archiver.d.ts +7 -6
  79. package/dest/state_machine/archiver.d.ts.map +1 -1
  80. package/dest/state_machine/archiver.js +31 -22
  81. package/dest/state_machine/dummy_p2p_client.d.ts +29 -16
  82. package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
  83. package/dest/state_machine/dummy_p2p_client.js +53 -20
  84. package/dest/state_machine/global_variable_builder.d.ts +10 -6
  85. package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
  86. package/dest/state_machine/global_variable_builder.js +8 -5
  87. package/dest/state_machine/index.d.ts +13 -7
  88. package/dest/state_machine/index.d.ts.map +1 -1
  89. package/dest/state_machine/index.js +75 -21
  90. package/dest/state_machine/mock_epoch_cache.d.ts +21 -4
  91. package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
  92. package/dest/state_machine/mock_epoch_cache.js +35 -3
  93. package/dest/state_machine/synchronizer.d.ts +9 -6
  94. package/dest/state_machine/synchronizer.d.ts.map +1 -1
  95. package/dest/state_machine/synchronizer.js +10 -6
  96. package/dest/txe_session.d.ts +89 -16
  97. package/dest/txe_session.d.ts.map +1 -1
  98. package/dest/txe_session.js +366 -58
  99. package/dest/utils/block_creation.d.ts +6 -6
  100. package/dest/utils/block_creation.d.ts.map +1 -1
  101. package/dest/utils/block_creation.js +9 -7
  102. package/dest/utils/encoding.d.ts +192 -0
  103. package/dest/utils/encoding.d.ts.map +1 -0
  104. package/dest/{util → utils}/encoding.js +7 -2
  105. package/dest/{util → utils}/expected_failure_error.d.ts +1 -1
  106. package/dest/utils/expected_failure_error.d.ts.map +1 -0
  107. package/dest/utils/tx_effect_creation.d.ts +1 -1
  108. package/dest/utils/tx_effect_creation.d.ts.map +1 -1
  109. package/dest/utils/tx_effect_creation.js +0 -1
  110. package/dest/{util → utils}/txe_account_store.d.ts +1 -1
  111. package/dest/utils/txe_account_store.d.ts.map +1 -0
  112. package/dest/utils/txe_artifact_resolver.d.ts +37 -0
  113. package/dest/utils/txe_artifact_resolver.d.ts.map +1 -0
  114. package/dest/utils/txe_artifact_resolver.js +161 -0
  115. package/dest/utils/txe_public_contract_data_source.d.ts +20 -0
  116. package/dest/utils/txe_public_contract_data_source.d.ts.map +1 -0
  117. package/dest/utils/txe_public_contract_data_source.js +51 -0
  118. package/dest/worker.bundle.js +3 -0
  119. package/dest/worker.bundle.js.map +7 -0
  120. package/dest/worker.d.ts +2 -0
  121. package/dest/worker.d.ts.map +1 -0
  122. package/dest/worker.js +92 -0
  123. package/package.json +38 -21
  124. package/src/bin/check_txe_oracle_version.ts +70 -0
  125. package/src/bin/index.ts +11 -2
  126. package/src/bin/oracle_test_server.ts +51 -0
  127. package/src/constants.ts +11 -1
  128. package/src/dispatcher_pool.ts +317 -0
  129. package/src/index.ts +99 -190
  130. package/src/msgpackr_fr_extension.ts +23 -0
  131. package/src/oracle/interfaces.ts +64 -35
  132. package/src/oracle/test-resolver/default_fixtures.ts +282 -0
  133. package/src/oracle/test-resolver/index.ts +44 -0
  134. package/src/oracle/test-resolver/resolver.ts +245 -0
  135. package/src/oracle/txe_oracle_public_context.ts +80 -20
  136. package/src/oracle/txe_oracle_registry.ts +536 -0
  137. package/src/oracle/txe_oracle_top_level_context.ts +430 -168
  138. package/src/oracle/txe_oracle_version.ts +17 -0
  139. package/src/oracle/txe_private_execution_oracle.ts +30 -0
  140. package/src/rpc_server.ts +87 -0
  141. package/src/rpc_translator.ts +1087 -974
  142. package/src/state_machine/archiver.ts +45 -26
  143. package/src/state_machine/dummy_p2p_client.ts +83 -32
  144. package/src/state_machine/global_variable_builder.ts +12 -11
  145. package/src/state_machine/index.ts +105 -40
  146. package/src/state_machine/mock_epoch_cache.ts +45 -4
  147. package/src/state_machine/synchronizer.ts +13 -7
  148. package/src/txe_session.ts +609 -128
  149. package/src/utils/block_creation.ts +10 -7
  150. package/src/{util → utils}/encoding.ts +8 -2
  151. package/src/utils/tx_effect_creation.ts +0 -2
  152. package/src/utils/txe_artifact_resolver.ts +217 -0
  153. package/src/utils/txe_public_contract_data_source.ts +60 -0
  154. package/src/worker.ts +98 -0
  155. package/dest/util/encoding.d.ts +0 -720
  156. package/dest/util/encoding.d.ts.map +0 -1
  157. package/dest/util/expected_failure_error.d.ts.map +0 -1
  158. package/dest/util/txe_account_store.d.ts.map +0 -1
  159. package/dest/util/txe_contract_store.d.ts +0 -12
  160. package/dest/util/txe_contract_store.d.ts.map +0 -1
  161. package/dest/util/txe_contract_store.js +0 -22
  162. package/dest/util/txe_public_contract_data_source.d.ts +0 -21
  163. package/dest/util/txe_public_contract_data_source.d.ts.map +0 -1
  164. package/dest/util/txe_public_contract_data_source.js +0 -67
  165. package/src/util/txe_contract_store.ts +0 -36
  166. package/src/util/txe_public_contract_data_source.ts +0 -86
  167. /package/dest/{util → utils}/expected_failure_error.js +0 -0
  168. /package/dest/{util → utils}/txe_account_store.js +0 -0
  169. /package/src/{util → utils}/expected_failure_error.ts +0 -0
  170. /package/src/{util → utils}/txe_account_store.ts +0 -0
@@ -1,11 +1,14 @@
1
- import type { ContractArtifact } from '@aztec/aztec.js/abi';
2
1
  import { CompleteAddress } from '@aztec/aztec.js/addresses';
3
- import type { ContractInstanceWithAddress } from '@aztec/aztec.js/contracts';
4
2
  import { TxHash } from '@aztec/aztec.js/tx';
5
3
  import { BlockNumber } from '@aztec/foundation/branded-types';
6
4
  import type { Fr } from '@aztec/foundation/curves/bn254';
5
+ import type { EthAddress } from '@aztec/foundation/eth-address';
6
+ import type { TaggingSecretStrategy } from '@aztec/pxe/server';
7
+ import type { Option } from '@aztec/pxe/simulator';
7
8
  import type { EventSelector, FunctionSelector } from '@aztec/stdlib/abi';
8
9
  import type { AztecAddress } from '@aztec/stdlib/aztec-address';
10
+ import type { GasSettings } from '@aztec/stdlib/gas';
11
+ import type { PrivateLog } from '@aztec/stdlib/logs';
9
12
  import type { UInt64 } from '@aztec/stdlib/types';
10
13
 
11
14
  // These interfaces complement the ones defined in PXE, and combined with those contain the full list of oracles used by
@@ -24,18 +27,27 @@ import type { UInt64 } from '@aztec/stdlib/types';
24
27
  export interface IAvmExecutionOracle {
25
28
  isAvm: true;
26
29
 
27
- avmOpcodeAddress(): Promise<AztecAddress>;
28
- avmOpcodeSender(): Promise<AztecAddress>;
29
- avmOpcodeBlockNumber(): Promise<BlockNumber>;
30
- avmOpcodeTimestamp(): Promise<bigint>;
31
- avmOpcodeIsStaticCall(): Promise<boolean>;
32
- avmOpcodeChainId(): Promise<Fr>;
33
- avmOpcodeVersion(): Promise<Fr>;
34
- avmOpcodeEmitNullifier(nullifier: Fr): Promise<void>;
35
- avmOpcodeEmitNoteHash(noteHash: Fr): Promise<void>;
36
- avmOpcodeNullifierExists(innerNullifier: Fr, targetAddress: AztecAddress): Promise<boolean>;
37
- avmOpcodeStorageWrite(slot: Fr, value: Fr): Promise<void>;
38
- avmOpcodeStorageRead(slot: Fr): Promise<Fr>;
30
+ address(): Promise<AztecAddress>;
31
+ sender(): Promise<AztecAddress>;
32
+ blockNumber(): Promise<BlockNumber>;
33
+ timestamp(): Promise<bigint>;
34
+ isStaticCall(): Promise<boolean>;
35
+ chainId(): Promise<Fr>;
36
+ version(): Promise<Fr>;
37
+ emitNullifier(nullifier: Fr): Promise<void>;
38
+ emitNoteHash(noteHash: Fr): Promise<void>;
39
+ nullifierExists(siloedNullifier: Fr): Promise<boolean>;
40
+ storageWrite(slot: Fr, value: Fr): Promise<void>;
41
+ storageRead(slot: Fr, contractAddress: AztecAddress): Promise<Fr>;
42
+ getContractInstanceDeployer(address: AztecAddress): Promise<{ member: Fr; exists: boolean }[]>;
43
+ getContractInstanceClassId(address: AztecAddress): Promise<{ member: Fr; exists: boolean }[]>;
44
+ getContractInstanceInitializationHash(address: AztecAddress): Promise<{ member: Fr; exists: boolean }[]>;
45
+ getContractInstanceImmutablesHash(address: AztecAddress): Promise<{ member: Fr; exists: boolean }[]>;
46
+ returndataSize(): Promise<number>;
47
+ returndataCopy(rdOffset: number, copySize: number): Promise<Fr[]>;
48
+ call(l2Gas: number, daGas: number, address: AztecAddress, argsLength: number, args: Fr[]): Promise<void>;
49
+ staticCall(l2Gas: number, daGas: number, address: AztecAddress, argsLength: number, args: Fr[]): Promise<void>;
50
+ successCopy(): Promise<boolean>;
39
51
  }
40
52
 
41
53
  /**
@@ -44,43 +56,60 @@ export interface IAvmExecutionOracle {
44
56
  export interface ITxeExecutionOracle {
45
57
  isTxe: true;
46
58
 
47
- txeGetDefaultAddress(): AztecAddress;
48
- txeGetNextBlockNumber(): Promise<BlockNumber>;
49
- txeGetNextBlockTimestamp(): Promise<UInt64>;
50
- txeAdvanceBlocksBy(blocks: number): Promise<void>;
51
- txeAdvanceTimestampBy(duration: UInt64): void;
52
- txeDeploy(artifact: ContractArtifact, instance: ContractInstanceWithAddress, foreignSecret: Fr): Promise<void>;
53
- txeCreateAccount(secret: Fr): Promise<CompleteAddress>;
54
- txeAddAccount(
55
- artifact: ContractArtifact,
56
- instance: ContractInstanceWithAddress,
59
+ getDefaultAddress(): AztecAddress;
60
+ getNextBlockNumber(): Promise<BlockNumber>;
61
+ getNextBlockTimestamp(): Promise<UInt64>;
62
+ advanceBlocksBy(blocks: number): Promise<void>;
63
+ advanceTimestampBy(duration: UInt64): void;
64
+ deploy(
65
+ contractPath: string,
66
+ initializer: string,
67
+ args: Fr[],
57
68
  secret: Fr,
58
- ): Promise<CompleteAddress>;
59
- txeAddAuthWitness(address: AztecAddress, messageHash: Fr): Promise<void>;
60
- txeGetLastBlockTimestamp(): Promise<bigint>;
61
- txeGetLastTxEffects(): Promise<{
69
+ salt: Fr,
70
+ deployer: AztecAddress,
71
+ ): Promise<Fr[]>;
72
+ createAccount(secret: Fr): Promise<CompleteAddress>;
73
+ addAccount(secret: Fr): Promise<CompleteAddress>;
74
+ addAuthWitness(address: AztecAddress, messageHash: Fr): Promise<void>;
75
+ sendL1ToL2Message(content: Fr, secretHash: Fr, sender: EthAddress, recipient: AztecAddress): Promise<Fr>;
76
+ setTaggingSecretStrategy(strategy: Option<TaggingSecretStrategy>): void;
77
+ getLastBlockTimestamp(): Promise<bigint>;
78
+ getLastTxEffects(): Promise<{
62
79
  txHash: TxHash;
63
80
  noteHashes: Fr[];
64
81
  nullifiers: Fr[];
82
+ privateLogs: PrivateLog[];
65
83
  }>;
66
- txeGetPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress): Promise<Fr[][]>;
67
- txePrivateCallNewFlow(
68
- from: AztecAddress,
84
+ getPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress): Promise<Fr[][]>;
85
+ privateCallNewFlow(
86
+ from: AztecAddress | undefined,
69
87
  targetContractAddress: AztecAddress,
70
88
  functionSelector: FunctionSelector,
71
89
  args: Fr[],
72
90
  argsHash: Fr,
73
91
  isStaticCall: boolean,
74
- ): Promise<Fr[]>;
75
- txeSimulateUtilityFunction(
92
+ additionalScopes: AztecAddress[],
93
+ jobId: string,
94
+ authorizedUtilityCallTargets: AztecAddress[],
95
+ gasSettings: GasSettings,
96
+ ): Promise<{ returnValues: Fr[]; offchainEffects: Fr[][] }>;
97
+ executeUtilityFunction(
98
+ from: AztecAddress | undefined,
76
99
  targetContractAddress: AztecAddress,
77
100
  functionSelector: FunctionSelector,
78
101
  args: Fr[],
102
+ jobId: string,
103
+ authorizedUtilityCallTargets: AztecAddress[],
79
104
  ): Promise<Fr[]>;
80
- txePublicCallNewFlow(
81
- from: AztecAddress,
105
+ publicCallNewFlow(
106
+ from: AztecAddress | undefined,
82
107
  targetContractAddress: AztecAddress,
83
108
  calldata: Fr[],
84
109
  isStaticCall: boolean,
110
+ gasSettings: GasSettings,
85
111
  ): Promise<Fr[]>;
112
+ // TODO(F-335): Drop this from here as it's not a real oracle handler - it's only called from
113
+ // RPCTranslator::txeGetPrivateEvents and never from Noir.
114
+ syncContractNonOracleMethod(contractAddress: AztecAddress, scope: AztecAddress, jobId: string): Promise<void>;
86
115
  }
@@ -0,0 +1,282 @@
1
+ import { AztecAddress } from '@aztec/aztec.js/addresses';
2
+ import { BlockNumber, SlotNumber } from '@aztec/foundation/branded-types';
3
+ import { Fr } from '@aztec/foundation/curves/bn254';
4
+ import { EthAddress } from '@aztec/foundation/eth-address';
5
+ import {
6
+ AZTEC_ADDRESS,
7
+ BIGINT,
8
+ BLOCK_HASH,
9
+ BLOCK_NUMBER,
10
+ BOOL,
11
+ BYTE,
12
+ BoundedVec,
13
+ DELIVERY_MODE,
14
+ ETH_ADDRESS,
15
+ FIELD,
16
+ FUNCTION_SELECTOR,
17
+ NOTE_SELECTOR,
18
+ Option,
19
+ type OracleRegistryEntry,
20
+ SLOT_NUMBER,
21
+ type StructField,
22
+ type TypeMapping,
23
+ U32,
24
+ tryFieldWidth,
25
+ } from '@aztec/pxe/simulator';
26
+ import { FunctionSelector, NoteSelector } from '@aztec/stdlib/abi';
27
+ import { BlockHash } from '@aztec/stdlib/block';
28
+ import { AppTaggingSecretKind } from '@aztec/stdlib/logs';
29
+
30
+ import type { OracleTestScenario } from './resolver.js';
31
+
32
+ /**
33
+ * Synthesizes fixture scenarios for every oracle in the registry whose parameters and return are built from scalars,
34
+ * arrays/bounded vecs of them, `Option`s of them, or `STRUCT`s over them. The matching Noir serialization tests are
35
+ * auto-generated by `#[generate_oracle_tests]` from the same seed/scenario convention.
36
+ */
37
+ export function synthesizeDefaultFixtures(
38
+ registry: Record<string, OracleRegistryEntry>,
39
+ ): Record<string, OracleTestScenario[]> {
40
+ const synthesized: Record<string, OracleTestScenario[]> = {};
41
+
42
+ for (const [name, entry] of Object.entries(registry)) {
43
+ const scenarios = synthesizeScenarios(entry);
44
+ if (scenarios !== undefined) {
45
+ synthesized[name] = scenarios;
46
+ }
47
+ }
48
+
49
+ return synthesized;
50
+ }
51
+
52
+ /**
53
+ * The test-value implementations, one per oracle type, mirroring the Noir synthesizer tables (`scalars` and
54
+ * `synthesizers` in `noir-projects/aztec-nr/.../macros/oracle_testing.nr`) exactly.
55
+ */
56
+ const TEST_VALUE_IMPLS: TestValueImpl[] = [
57
+ scalar(FIELD, seed => new Fr(seed)),
58
+ scalar(U32, seed => seed),
59
+ scalar(BLOCK_NUMBER, seed => BlockNumber(seed)),
60
+ scalar(BIGINT, seed => BigInt(seed)),
61
+ scalar(BYTE, seed => seed),
62
+ scalar(BOOL, seed => seed % 2 !== 0),
63
+ scalar(AZTEC_ADDRESS, seed => AztecAddress.fromNumberUnsafe(seed)),
64
+ scalar(ETH_ADDRESS, seed => EthAddress.fromField(new Fr(seed))),
65
+ scalar(FUNCTION_SELECTOR, seed => FunctionSelector.fromField(new Fr(seed))),
66
+ scalar(NOTE_SELECTOR, seed => NoteSelector.fromField(new Fr(seed))),
67
+ scalar(BLOCK_HASH, seed => new BlockHash(new Fr(seed))),
68
+ scalar(SLOT_NUMBER, seed => SlotNumber(seed)),
69
+ // Only two delivery modes are valid for tagging, so the seed alternates between them, matching the Noir impl.
70
+ scalar(DELIVERY_MODE, seed =>
71
+ seed % 2 === 0 ? AppTaggingSecretKind.UNCONSTRAINED : AppTaggingSecretKind.CONSTRAINED,
72
+ ),
73
+ composite(isOption, (type, seed) => [
74
+ named(Option.some(firstValue(type.inner, seed)), 'some'),
75
+ named(Option.none(firstValue(type.inner, seed)), 'none'),
76
+ ]),
77
+ composite(isArray, (type, seed) => [unnamed(collectionData(type.inner, seed, DEFAULT_ARRAY_LENGTH))]),
78
+ composite(isBoundedVec, (type, seed) => [
79
+ unnamed(
80
+ BoundedVec.from({
81
+ data: collectionData(type.inner, seed, DEFAULT_ARRAY_LENGTH),
82
+ maxLength: BOUNDED_VEC_MAX_LENGTH,
83
+ }),
84
+ ),
85
+ ]),
86
+ composite(isStruct, (type, seed) => [unnamed(structValue(type, seed))]),
87
+ // A fixed-length array uses its real (signature) length, unlike the generic-length ARRAY which is pinned to
88
+ // DEFAULT_ARRAY_LENGTH.
89
+ composite(isFixedArray, (type, seed) => [unnamed(collectionData(type.inner, seed, type.length))]),
90
+ // Same for a fixed-capacity bounded vec: real capacity, DEFAULT_ARRAY_LENGTH elements (its value type is a plain
91
+ // element array, unlike the two-slot BOUNDED_VEC), clamped to the capacity so small vecs stay valid.
92
+ composite(isFixedBoundedVec, (type, seed) => [
93
+ unnamed(collectionData(type.inner, seed, Math.min(DEFAULT_ARRAY_LENGTH, type.maxLength))),
94
+ ]),
95
+ ];
96
+
97
+ /**
98
+ * The base every seed is offset by, applied once where a parameter's position becomes its seed, so generated values
99
+ * stay clear of 0. Must match `SEED_BASE` in the Noir `oracle_testing.nr`.
100
+ */
101
+ const SEED_BASE = 10;
102
+
103
+ /** Elements per synthesized array and bounded vec. Must match `TEST_COLLECTION_LEN` in the Noir `oracle_testing.nr`. */
104
+ const DEFAULT_ARRAY_LENGTH = 3;
105
+
106
+ /**
107
+ * Capacity of synthesized bounded vecs, deliberately larger than the data length so padding is exercised. Must match
108
+ * `TEST_BOUNDED_VEC_CAP` in the Noir `oracle_testing.nr`.
109
+ */
110
+ const BOUNDED_VEC_MAX_LENGTH = 5;
111
+
112
+ /**
113
+ * One canonical test case for a type: the `value` to put on the wire (or expect back), and the `name` of the
114
+ * serialization shape it exercises (unset for single-scenario types). Mirrors the Noir `Scenario<T>`.
115
+ */
116
+ interface Scenario {
117
+ value: unknown;
118
+ name?: string;
119
+ }
120
+
121
+ function unnamed(value: unknown): Scenario {
122
+ return { value };
123
+ }
124
+ function named(value: unknown, name: string): Scenario {
125
+ return { value, name };
126
+ }
127
+
128
+ /**
129
+ * One type's test-value implementation, mirroring a Noir `TestValueSynthesizer` entry: `match` selects the type and
130
+ * `scenarios` yields its [`Scenario`]s for `seed`, one per serialization shape, like the Noir entry's `scenarios`
131
+ * function.
132
+ */
133
+ interface TestValueImpl {
134
+ match: (type: TypeMapping<any>) => boolean;
135
+ scenarios: (type: TypeMapping<any>, seed: number) => Scenario[];
136
+ }
137
+
138
+ /** A scalar impl: matches the singleton `type` by identity and yields a single unnamed scenario. */
139
+ function scalar(type: TypeMapping<any>, value: (seed: number) => unknown): TestValueImpl {
140
+ return { match: t => t === type, scenarios: (_type, seed) => [unnamed(value(seed))] };
141
+ }
142
+
143
+ /** A composite impl: selected by the `kind` type guard, recursing through its element/inner mapping. */
144
+ function composite<K extends CompositeMapping>(
145
+ guard: (type: TypeMapping<any>) => type is K,
146
+ scenarios: (type: K, seed: number) => Scenario[],
147
+ ): TestValueImpl {
148
+ return { match: guard, scenarios: (type, seed) => scenarios(type as K, seed) };
149
+ }
150
+
151
+ /** Synthesized element values for a collection. */
152
+ function collectionData(element: TypeMapping<any>, seed: number, length: number): unknown[] {
153
+ return Array.from({ length }, (_, i) => firstValue(element, seed + i));
154
+ }
155
+
156
+ /**
157
+ * The synthesized prop bag for a struct: each field's first scenario, seeded at the field's flat wire offset so the
158
+ * values depend on the wire layout rather than on how each side groups its fields. Mirrors the Noir reflected impls.
159
+ */
160
+ function structValue(type: StructMapping, seed: number): Record<string, unknown> {
161
+ const value: Record<string, unknown> = {};
162
+ let offset = 0;
163
+ for (const field of type.fields) {
164
+ value[field.name] = firstValue(field.type, seed + offset);
165
+ const width = tryFieldWidth(field.type.shape);
166
+ if (width === undefined) {
167
+ // A variable-width field has no flat offset to seed the next field at, so only this oracle is unsynthesizable.
168
+ throw new UnsynthesizableTypeError(field.type, `struct field '${field.name}' has a variable-width shape`);
169
+ }
170
+ offset += width;
171
+ }
172
+ return value;
173
+ }
174
+
175
+ /**
176
+ * The [`Scenario`]s for `type` at `seed`, one per serialization *shape*, mirroring the Noir `scenarios_for`
177
+ * dispatcher. Throws if the type has no matching impl.
178
+ */
179
+ function scenariosForType(type: TypeMapping<any>, seed: number): Scenario[] {
180
+ const impl = TEST_VALUE_IMPLS.find(i => i.match(type));
181
+ if (!impl) {
182
+ throw new UnsynthesizableTypeError(type);
183
+ }
184
+ return impl.scenarios(type, seed);
185
+ }
186
+
187
+ /** The first (representative) test value of `type`, used for collection elements and `Option` inners. */
188
+ function firstValue(type: TypeMapping<any>, seed: number): unknown {
189
+ return scenariosForType(type, seed)[0].value;
190
+ }
191
+
192
+ class UnsynthesizableTypeError extends Error {
193
+ constructor(type: TypeMapping<any>, detail?: string) {
194
+ super(detail ?? `No test-value impl for type: ${JSON.stringify(Object.keys(type))}`);
195
+ this.name = 'UnsynthesizableTypeError';
196
+ }
197
+ }
198
+
199
+ /**
200
+ * Synthesizes the scenarios for one oracle by zipping every position's [`Scenario`] list to one case per test (a
201
+ * shorter list wraps around via mod), mirroring the Noir macro. Returns `undefined` if any param or return type is
202
+ * unsynthesizable (ephemeral arrays, structs with a variable-width field).
203
+ */
204
+ function synthesizeScenarios(entry: OracleRegistryEntry): OracleTestScenario[] | undefined {
205
+ try {
206
+ return synthesizeScenariosOrThrow(entry);
207
+ } catch (e) {
208
+ if (e instanceof UnsynthesizableTypeError) {
209
+ return undefined;
210
+ }
211
+ throw e;
212
+ }
213
+ }
214
+
215
+ function synthesizeScenariosOrThrow(entry: OracleRegistryEntry): OracleTestScenario[] {
216
+ const params = entry.params.map((param, index) => ({
217
+ name: param.name,
218
+ scenarios: scenariosForType(param.type, SEED_BASE + index),
219
+ }));
220
+ // The return's seed is the slot right after the last parameter, so its value is distinct from every parameter.
221
+ const returnScenarios =
222
+ entry.returnType === undefined ? undefined : scenariosForType(entry.returnType, SEED_BASE + entry.params.length);
223
+
224
+ // Positions with more than one scenario drive the test count; their names are zipped together (joined with `+`) per
225
+ // test, matching the announcements the Noir tests emit and the resolver joins.
226
+ const positions = [...params.map(p => p.scenarios), ...(returnScenarios !== undefined ? [returnScenarios] : [])];
227
+ const namedPositions = positions.filter(s => s.length > 1);
228
+ const testCount = Math.max(1, ...positions.map(s => s.length));
229
+
230
+ const scenarios: OracleTestScenario[] = [];
231
+ for (let index = 0; index < testCount; index++) {
232
+ const inputs: Record<string, unknown> = {};
233
+ for (const { name, scenarios: cases } of params) {
234
+ inputs[name] = cases[index % cases.length].value;
235
+ }
236
+ const output = returnScenarios === undefined ? undefined : returnScenarios[index % returnScenarios.length].value;
237
+ const scenario =
238
+ namedPositions.length === 0
239
+ ? undefined
240
+ : namedPositions.map(cases => cases[index % cases.length].name!).join('+');
241
+ scenarios.push({ scenario, inputs, output });
242
+ }
243
+ return scenarios;
244
+ }
245
+
246
+ /**
247
+ * The composite `TypeMapping`s (`ARRAY`/`BOUNDED_VEC`/`OPTION`/`STRUCT`/`FIXED_ARRAY`/`FIXED_BOUNDED_VEC`),
248
+ * discriminated by `kind`. The combinators attach `kind` plus the inner mapping(s) at construction; the registry
249
+ * erases params to the base `TypeMapping`, so the guards below recover the structure for recursion.
250
+ */
251
+ type ArrayMapping = TypeMapping & { kind: 'array'; inner: TypeMapping };
252
+ type BoundedVecMapping = TypeMapping & { kind: 'bounded-vec'; inner: TypeMapping };
253
+ type OptionMapping = TypeMapping & { kind: 'option'; inner: TypeMapping };
254
+ type StructMapping = TypeMapping & { kind: 'struct'; fields: readonly StructField[] };
255
+ type FixedArrayMapping = TypeMapping & { kind: 'fixed-array'; inner: TypeMapping; length: number };
256
+ type FixedBoundedVecMapping = TypeMapping & { kind: 'fixed-bounded-vec'; inner: TypeMapping; maxLength: number };
257
+ type CompositeMapping =
258
+ | ArrayMapping
259
+ | BoundedVecMapping
260
+ | OptionMapping
261
+ | StructMapping
262
+ | FixedArrayMapping
263
+ | FixedBoundedVecMapping;
264
+
265
+ function isArray(type: TypeMapping<any>): type is ArrayMapping {
266
+ return 'kind' in type && type.kind === 'array';
267
+ }
268
+ function isBoundedVec(type: TypeMapping<any>): type is BoundedVecMapping {
269
+ return 'kind' in type && type.kind === 'bounded-vec';
270
+ }
271
+ function isOption(type: TypeMapping<any>): type is OptionMapping {
272
+ return 'kind' in type && type.kind === 'option';
273
+ }
274
+ function isStruct(type: TypeMapping<any>): type is StructMapping {
275
+ return 'kind' in type && type.kind === 'struct';
276
+ }
277
+ function isFixedArray(type: TypeMapping<any>): type is FixedArrayMapping {
278
+ return 'kind' in type && type.kind === 'fixed-array';
279
+ }
280
+ function isFixedBoundedVec(type: TypeMapping<any>): type is FixedBoundedVecMapping {
281
+ return 'kind' in type && type.kind === 'fixed-bounded-vec';
282
+ }
@@ -0,0 +1,44 @@
1
+ /* eslint-disable camelcase */
2
+ import { createSafeJsonRpcServer } from '@aztec/foundation/json-rpc/server';
3
+ import type { Logger } from '@aztec/foundation/log';
4
+ import type { ApiSchemaFor } from '@aztec/foundation/schemas';
5
+ import { zodFor } from '@aztec/stdlib/schemas';
6
+
7
+ import { z } from 'zod';
8
+
9
+ import { ForeignCallArgsSchema, type ForeignCallResult, ForeignCallResultSchema } from '../../utils/encoding.js';
10
+ import { TXE_ORACLE_REGISTRY } from '../txe_oracle_registry.js';
11
+ import { type OracleTestCallInput, OracleTestResolver } from './resolver.js';
12
+
13
+ const OracleTestCallInputSchema = zodFor<OracleTestCallInput>()(
14
+ z.object({
15
+ session_id: z.number().nonnegative(),
16
+ function: z.string(),
17
+ root_path: z.string(),
18
+ package_name: z.string(),
19
+ inputs: ForeignCallArgsSchema,
20
+ }),
21
+ );
22
+
23
+ /** Narrowed interface exposing only the RPC method. */
24
+ interface OracleTestRpcHandler {
25
+ resolve_foreign_call(callData: OracleTestCallInput): Promise<ForeignCallResult>;
26
+ }
27
+
28
+ const OracleTestRpcHandlerSchema: ApiSchemaFor<OracleTestRpcHandler> = {
29
+ resolve_foreign_call: z.function({
30
+ input: z.tuple([OracleTestCallInputSchema]),
31
+ output: ForeignCallResultSchema,
32
+ }),
33
+ };
34
+
35
+ /** Creates an RPC server backed by the oracle test resolver. */
36
+ export function createOracleTestRpcServer(logger: Logger) {
37
+ const resolver = OracleTestResolver.fromRegistry(TXE_ORACLE_REGISTRY, logger);
38
+ const server = createSafeJsonRpcServer<OracleTestRpcHandler>(resolver, OracleTestRpcHandlerSchema, {
39
+ http200OnError: true,
40
+ });
41
+ return { server, resolver };
42
+ }
43
+
44
+ export { OracleTestResolver } from './resolver.js';