@aztec/pxe 5.0.0-rc.2 → 5.0.0
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/block_synchronizer/block_synchronizer.d.ts +5 -3
- package/dest/block_synchronizer/block_synchronizer.d.ts.map +1 -1
- package/dest/block_synchronizer/block_synchronizer.js +7 -1
- package/dest/contract/contract_class_service.d.ts +31 -0
- package/dest/contract/contract_class_service.d.ts.map +1 -0
- package/dest/contract/contract_class_service.js +68 -0
- package/dest/{contract_sync → contract}/contract_sync_service.d.ts +7 -6
- package/dest/contract/contract_sync_service.d.ts.map +1 -0
- package/dest/{contract_sync → contract}/contract_sync_service.js +10 -30
- package/dest/contract/helpers.d.ts +7 -0
- package/dest/contract/helpers.d.ts.map +1 -0
- package/dest/contract/helpers.js +20 -0
- package/dest/contract_function_simulator/anchored_contract_data.d.ts +36 -0
- package/dest/contract_function_simulator/anchored_contract_data.d.ts.map +1 -0
- package/dest/contract_function_simulator/anchored_contract_data.js +54 -0
- package/dest/contract_function_simulator/aztec_node_read_cache.d.ts +39 -0
- package/dest/contract_function_simulator/aztec_node_read_cache.d.ts.map +1 -0
- package/dest/contract_function_simulator/aztec_node_read_cache.js +60 -0
- package/dest/contract_function_simulator/contract_function_simulator.d.ts +9 -3
- package/dest/contract_function_simulator/contract_function_simulator.d.ts.map +1 -1
- package/dest/contract_function_simulator/contract_function_simulator.js +31 -14
- package/dest/contract_function_simulator/execution_note_cache.d.ts +3 -9
- package/dest/contract_function_simulator/execution_note_cache.d.ts.map +1 -1
- package/dest/contract_function_simulator/execution_note_cache.js +8 -28
- package/dest/contract_function_simulator/index.d.ts +4 -2
- package/dest/contract_function_simulator/index.d.ts.map +1 -1
- package/dest/contract_function_simulator/index.js +2 -1
- package/dest/contract_function_simulator/noir-structs/fact.d.ts +5 -5
- package/dest/contract_function_simulator/noir-structs/fact.d.ts.map +1 -1
- package/dest/contract_function_simulator/noir-structs/fact.js +2 -2
- package/dest/contract_function_simulator/noir-structs/fact_collection.d.ts +3 -3
- package/dest/contract_function_simulator/noir-structs/fact_collection.d.ts.map +1 -1
- package/dest/contract_function_simulator/noir-structs/fact_collection.js +3 -1
- package/dest/contract_function_simulator/noir-structs/log_retrieval_response.d.ts +7 -1
- package/dest/contract_function_simulator/noir-structs/log_retrieval_response.d.ts.map +1 -1
- package/dest/contract_function_simulator/noir-structs/pending_tagged_log.d.ts +11 -0
- package/dest/contract_function_simulator/noir-structs/pending_tagged_log.d.ts.map +1 -0
- package/dest/contract_function_simulator/noir-structs/pending_tagged_log.js +4 -0
- package/dest/contract_function_simulator/noir-structs/provided_secret.d.ts +2 -2
- package/dest/contract_function_simulator/noir-structs/provided_secret.d.ts.map +1 -1
- package/dest/contract_function_simulator/noir-structs/provided_secret.js +1 -1
- package/dest/contract_function_simulator/noir-structs/resolved_tagging_strategy.d.ts +8 -1
- package/dest/contract_function_simulator/noir-structs/resolved_tagging_strategy.d.ts.map +1 -1
- package/dest/contract_function_simulator/noir-structs/resolved_tagging_strategy.js +17 -0
- package/dest/contract_function_simulator/oracle/acir_callback.d.ts +7 -2
- package/dest/contract_function_simulator/oracle/acir_callback.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/acir_callback.js +55 -11
- package/dest/contract_function_simulator/oracle/legacy_oracle_registry.d.ts +39 -0
- package/dest/contract_function_simulator/oracle/legacy_oracle_registry.d.ts.map +1 -0
- package/dest/contract_function_simulator/oracle/legacy_oracle_registry.js +107 -0
- package/dest/contract_function_simulator/oracle/oracle_registry.d.ts +10 -7
- package/dest/contract_function_simulator/oracle/oracle_registry.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/oracle_registry.js +41 -10
- package/dest/contract_function_simulator/oracle/oracle_type_mappings.d.ts +48 -9
- package/dest/contract_function_simulator/oracle/oracle_type_mappings.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/oracle_type_mappings.js +51 -30
- package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts +10 -2
- package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/private_execution_oracle.js +73 -32
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts +20 -16
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.js +68 -47
- package/dest/debug/pxe_debug_utils.d.ts +2 -2
- package/dest/debug/pxe_debug_utils.d.ts.map +1 -1
- package/dest/entrypoints/client/bundle/utils.js +2 -2
- package/dest/entrypoints/client/lazy/utils.js +2 -2
- package/dest/entrypoints/server/index.d.ts +5 -2
- package/dest/entrypoints/server/index.d.ts.map +1 -1
- package/dest/entrypoints/server/index.js +3 -1
- package/dest/error_enriching.d.ts +5 -3
- package/dest/error_enriching.d.ts.map +1 -1
- package/dest/error_enriching.js +12 -10
- package/dest/hooks/execution_hooks.d.ts +15 -4
- package/dest/hooks/execution_hooks.d.ts.map +1 -1
- package/dest/hooks/index.d.ts +3 -2
- package/dest/hooks/index.d.ts.map +1 -1
- package/dest/hooks/index.js +1 -0
- package/dest/hooks/resolve_custom_request.d.ts +23 -0
- package/dest/hooks/resolve_custom_request.d.ts.map +1 -0
- package/dest/hooks/resolve_custom_request.js +3 -0
- package/dest/hooks/resolve_tagging_secret_strategy.d.ts +10 -1
- package/dest/hooks/resolve_tagging_secret_strategy.d.ts.map +1 -1
- package/dest/hooks/resolve_tagging_secret_strategy.js +3 -3
- package/dest/logs/log_service.d.ts +3 -2
- package/dest/logs/log_service.d.ts.map +1 -1
- package/dest/logs/log_service.js +33 -16
- package/dest/oracle_version.d.ts +2 -2
- package/dest/oracle_version.js +2 -2
- package/dest/private_kernel/hints/private_kernel_reset_private_inputs_builder.d.ts +1 -1
- package/dest/private_kernel/hints/private_kernel_reset_private_inputs_builder.d.ts.map +1 -1
- package/dest/private_kernel/hints/private_kernel_reset_private_inputs_builder.js +6 -2
- package/dest/private_kernel/private_kernel_execution_prover.d.ts +1 -1
- package/dest/private_kernel/private_kernel_execution_prover.d.ts.map +1 -1
- package/dest/private_kernel/private_kernel_execution_prover.js +17 -36
- package/dest/private_kernel/private_kernel_oracle.d.ts +4 -2
- package/dest/private_kernel/private_kernel_oracle.d.ts.map +1 -1
- package/dest/private_kernel/private_kernel_oracle.js +17 -5
- package/dest/pxe.d.ts +81 -46
- package/dest/pxe.d.ts.map +1 -1
- package/dest/pxe.js +135 -104
- package/dest/storage/backwards_compatibility_tests/schema_tests.d.ts +1 -1
- package/dest/storage/backwards_compatibility_tests/schema_tests.d.ts.map +1 -1
- package/dest/storage/backwards_compatibility_tests/schema_tests.js +31 -7
- package/dest/storage/contract_store/contract_store.d.ts +27 -24
- package/dest/storage/contract_store/contract_store.d.ts.map +1 -1
- package/dest/storage/contract_store/contract_store.js +63 -74
- package/dest/storage/fact_store/fact_service.d.ts +6 -4
- package/dest/storage/fact_store/fact_service.d.ts.map +1 -1
- package/dest/storage/fact_store/fact_service.js +19 -4
- package/dest/storage/fact_store/fact_store.d.ts +1 -1
- package/dest/storage/fact_store/fact_store.js +1 -1
- package/dest/storage/fact_store/index.d.ts +2 -1
- package/dest/storage/fact_store/index.d.ts.map +1 -1
- package/dest/storage/fact_store/index.js +1 -0
- package/dest/storage/fact_store/origin_state.d.ts +57 -0
- package/dest/storage/fact_store/origin_state.d.ts.map +1 -0
- package/dest/storage/fact_store/origin_state.js +53 -0
- package/dest/storage/metadata.d.ts +2 -2
- package/dest/storage/metadata.d.ts.map +1 -1
- package/dest/storage/metadata.js +1 -1
- package/dest/storage/tagging_store/tagging_secret_sources_store.d.ts +17 -6
- package/dest/storage/tagging_store/tagging_secret_sources_store.d.ts.map +1 -1
- package/dest/storage/tagging_store/tagging_secret_sources_store.js +24 -11
- package/dest/tagging/constants.d.ts +2 -2
- package/dest/tagging/constants.d.ts.map +1 -1
- package/dest/tagging/constants.js +18 -9
- package/package.json +17 -17
- package/src/block_synchronizer/block_synchronizer.ts +9 -1
- package/src/contract/contract_class_service.ts +83 -0
- package/src/{contract_sync → contract}/contract_sync_service.ts +18 -37
- package/src/contract/helpers.ts +35 -0
- package/src/contract_function_simulator/anchored_contract_data.ts +74 -0
- package/src/contract_function_simulator/aztec_node_read_cache.ts +89 -0
- package/src/contract_function_simulator/contract_function_simulator.ts +56 -14
- package/src/contract_function_simulator/execution_note_cache.ts +7 -28
- package/src/contract_function_simulator/index.ts +7 -1
- package/src/contract_function_simulator/noir-structs/fact.ts +4 -4
- package/src/contract_function_simulator/noir-structs/fact_collection.ts +9 -4
- package/src/contract_function_simulator/noir-structs/log_retrieval_response.ts +6 -0
- package/src/contract_function_simulator/noir-structs/pending_tagged_log.ts +12 -0
- package/src/contract_function_simulator/noir-structs/provided_secret.ts +1 -1
- package/src/contract_function_simulator/noir-structs/resolved_tagging_strategy.ts +21 -0
- package/src/contract_function_simulator/oracle/acir_callback.ts +58 -12
- package/src/contract_function_simulator/oracle/legacy_oracle_registry.ts +147 -0
- package/src/contract_function_simulator/oracle/oracle_registry.ts +32 -7
- package/src/contract_function_simulator/oracle/oracle_type_mappings.ts +49 -32
- package/src/contract_function_simulator/oracle/private_execution_oracle.ts +92 -41
- package/src/contract_function_simulator/oracle/utility_execution_oracle.ts +104 -59
- package/src/debug/pxe_debug_utils.ts +1 -1
- package/src/entrypoints/client/bundle/utils.ts +2 -2
- package/src/entrypoints/client/lazy/utils.ts +2 -2
- package/src/entrypoints/server/index.ts +5 -1
- package/src/error_enriching.ts +26 -10
- package/src/hooks/execution_hooks.ts +14 -3
- package/src/hooks/index.ts +2 -0
- package/src/hooks/resolve_custom_request.ts +24 -0
- package/src/hooks/resolve_tagging_secret_strategy.ts +14 -0
- package/src/logs/log_service.ts +31 -11
- package/src/oracle_version.ts +2 -2
- package/src/private_kernel/hints/private_kernel_reset_private_inputs_builder.ts +11 -1
- package/src/private_kernel/private_kernel_execution_prover.ts +22 -52
- package/src/private_kernel/private_kernel_oracle.ts +23 -4
- package/src/pxe.ts +209 -143
- package/src/storage/backwards_compatibility_tests/__snapshots__/AddressStore.json +6 -6
- package/src/storage/backwards_compatibility_tests/__snapshots__/ContractStore.json +1 -1
- package/src/storage/backwards_compatibility_tests/__snapshots__/KeyStore.json +12 -12
- package/src/storage/backwards_compatibility_tests/__snapshots__/RecipientTaggingStore.json +11 -3
- package/src/storage/backwards_compatibility_tests/__snapshots__/SenderTaggingStore.json +12 -4
- package/src/storage/backwards_compatibility_tests/__snapshots__/TaggingSecretSourcesStore.json +3 -3
- package/src/storage/backwards_compatibility_tests/__snapshots__/opened_stores.json +1 -1
- package/src/storage/backwards_compatibility_tests/schema_tests.ts +38 -4
- package/src/storage/contract_store/contract_store.ts +85 -92
- package/src/storage/fact_store/fact_service.ts +29 -5
- package/src/storage/fact_store/fact_store.ts +1 -1
- package/src/storage/fact_store/index.ts +10 -0
- package/src/storage/fact_store/origin_state.ts +75 -0
- package/src/storage/metadata.ts +1 -1
- package/src/storage/tagging_store/tagging_secret_sources_store.ts +36 -15
- package/src/tagging/constants.ts +19 -9
- package/dest/contract_function_simulator/proxied_contract_data_source.d.ts +0 -6
- package/dest/contract_function_simulator/proxied_contract_data_source.d.ts.map +0 -1
- package/dest/contract_function_simulator/proxied_contract_data_source.js +0 -51
- package/dest/contract_sync/contract_sync_service.d.ts.map +0 -1
- package/dest/contract_sync/helpers.d.ts +0 -28
- package/dest/contract_sync/helpers.d.ts.map +0 -1
- package/dest/contract_sync/helpers.js +0 -48
- package/src/contract_function_simulator/proxied_contract_data_source.ts +0 -60
- package/src/contract_sync/helpers.ts +0 -79
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
2
|
+
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
3
|
+
import type { BlockHash, BlockParameter } from '@aztec/stdlib/block';
|
|
4
|
+
import type { AztecNode } from '@aztec/stdlib/interfaces/server';
|
|
5
|
+
import type { TxHash } from '@aztec/stdlib/tx';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Per-execution cache for immutable Aztec node reads.
|
|
9
|
+
*/
|
|
10
|
+
export class AztecNodeReadCache {
|
|
11
|
+
private readonly cache = new Map<string, Promise<unknown>>();
|
|
12
|
+
|
|
13
|
+
constructor(private readonly aztecNode: AztecNode) {}
|
|
14
|
+
|
|
15
|
+
/** Fetches a block without reissuing the same node request. */
|
|
16
|
+
public getBlock(block: BlockParameter) {
|
|
17
|
+
return this.#cachedRead(`block:${this.#keyPart(block)}`, () => this.aztecNode.getBlock(block));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Fetches a transaction receipt with its effect attached. */
|
|
21
|
+
public getTxReceiptWithEffect(txHash: TxHash) {
|
|
22
|
+
return this.#cachedRead(`tx-receipt-with-effect:${txHash.toString()}`, () =>
|
|
23
|
+
this.aztecNode.getTxReceipt(txHash, { includeTxEffect: true } as const),
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Fetches an archive-tree witness for a block hash. */
|
|
28
|
+
public getBlockHashMembershipWitness(referenceBlock: BlockParameter, blockHash: BlockHash) {
|
|
29
|
+
return this.#cachedRead(
|
|
30
|
+
`block-hash-membership-witness:${this.#keyPart(referenceBlock)}:${blockHash.toString()}`,
|
|
31
|
+
() => this.aztecNode.getBlockHashMembershipWitness(referenceBlock, blockHash),
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Fetches a public-data-tree witness for a leaf slot. */
|
|
36
|
+
public getPublicDataWitness(referenceBlock: BlockParameter, leafSlot: Fr) {
|
|
37
|
+
return this.#cachedRead(`public-data-witness:${this.#keyPart(referenceBlock)}:${leafSlot.toString()}`, () =>
|
|
38
|
+
this.aztecNode.getPublicDataWitness(referenceBlock, leafSlot),
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Fetches public storage for a single slot. */
|
|
43
|
+
public getPublicStorageAt(referenceBlock: BlockParameter, contractAddress: AztecAddress, storageSlot: Fr) {
|
|
44
|
+
return this.#cachedRead(
|
|
45
|
+
`public-storage:${this.#keyPart(referenceBlock)}:${contractAddress.toString()}:${storageSlot.toString()}`,
|
|
46
|
+
() => this.aztecNode.getPublicStorageAt(referenceBlock, contractAddress, storageSlot),
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Fetches a contiguous public storage range, reusing cached reads for overlapping slots. */
|
|
51
|
+
public getPublicStorageRange(
|
|
52
|
+
referenceBlock: BlockParameter,
|
|
53
|
+
contractAddress: AztecAddress,
|
|
54
|
+
startStorageSlot: Fr,
|
|
55
|
+
numberOfElements: number,
|
|
56
|
+
) {
|
|
57
|
+
const slots = Array(numberOfElements)
|
|
58
|
+
.fill(0)
|
|
59
|
+
.map((_, i) => new Fr(startStorageSlot.value + BigInt(i)));
|
|
60
|
+
|
|
61
|
+
return Promise.all(slots.map(storageSlot => this.getPublicStorageAt(referenceBlock, contractAddress, storageSlot)));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
#cachedRead<T>(key: string, fetch: () => Promise<T>): Promise<T> {
|
|
65
|
+
const cached = this.cache.get(key);
|
|
66
|
+
if (cached) {
|
|
67
|
+
return cached as Promise<T>;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const promise = fetch();
|
|
71
|
+
promise.catch(() => this.cache.delete(key));
|
|
72
|
+
this.cache.set(key, promise);
|
|
73
|
+
return promise;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
#keyPart(value: unknown): string {
|
|
77
|
+
if (['string', 'number', 'bigint', 'boolean'].includes(typeof value)) {
|
|
78
|
+
return String(value);
|
|
79
|
+
}
|
|
80
|
+
if (value && typeof value === 'object') {
|
|
81
|
+
const toString = (value as { toString?: () => string }).toString;
|
|
82
|
+
if (toString && toString !== Object.prototype.toString) {
|
|
83
|
+
return toString.call(value);
|
|
84
|
+
}
|
|
85
|
+
return JSON.stringify(value, (_key, nested) => (typeof nested === 'bigint' ? nested.toString() : nested));
|
|
86
|
+
}
|
|
87
|
+
return String(value);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
MAX_PRIVATE_LOGS_PER_TX,
|
|
20
20
|
MAX_TX_LIFETIME,
|
|
21
21
|
PRIVATE_TX_L2_GAS_OVERHEAD,
|
|
22
|
+
PUBLIC_DATA_WRITE_LENGTH,
|
|
22
23
|
PUBLIC_TX_L2_GAS_OVERHEAD,
|
|
23
24
|
TX_DA_GAS_OVERHEAD,
|
|
24
25
|
} from '@aztec/constants';
|
|
@@ -80,6 +81,7 @@ import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
|
80
81
|
import {
|
|
81
82
|
BlockHeader,
|
|
82
83
|
CallContext,
|
|
84
|
+
type ContractOverrides,
|
|
83
85
|
HashedValues,
|
|
84
86
|
type OffchainEffect,
|
|
85
87
|
PrivateExecutionResult,
|
|
@@ -90,7 +92,8 @@ import {
|
|
|
90
92
|
getFinalMinRevertibleSideEffectCounter,
|
|
91
93
|
} from '@aztec/stdlib/tx';
|
|
92
94
|
|
|
93
|
-
import type {
|
|
95
|
+
import type { ContractClassService } from '../contract/contract_class_service.js';
|
|
96
|
+
import type { ContractSyncService } from '../contract/contract_sync_service.js';
|
|
94
97
|
import type { ExecutionHooks } from '../hooks/index.js';
|
|
95
98
|
import type { TxResolverService } from '../messages/tx_resolver_service.js';
|
|
96
99
|
import type { AddressStore } from '../storage/address_store/address_store.js';
|
|
@@ -104,6 +107,7 @@ import type { PrivateEventStore } from '../storage/private_event_store/private_e
|
|
|
104
107
|
import type { RecipientTaggingStore } from '../storage/tagging_store/recipient_tagging_store.js';
|
|
105
108
|
import type { SenderTaggingStore } from '../storage/tagging_store/sender_tagging_store.js';
|
|
106
109
|
import type { TaggingSecretSourcesStore } from '../storage/tagging_store/tagging_secret_sources_store.js';
|
|
110
|
+
import { AnchoredContractData } from './anchored_contract_data.js';
|
|
107
111
|
import type { BenchmarkedNode } from './benchmarked_node.js';
|
|
108
112
|
import { ExecutionNoteCache } from './execution_note_cache.js';
|
|
109
113
|
import { ExecutionTaggingIndexCache } from './execution_tagging_index_cache.js';
|
|
@@ -131,6 +135,9 @@ export type ContractSimulatorRunOpts = {
|
|
|
131
135
|
/** Args for ContractFunctionSimulator constructor. */
|
|
132
136
|
export type ContractFunctionSimulatorArgs = {
|
|
133
137
|
contractStore: ContractStore;
|
|
138
|
+
contractClassService: ContractClassService;
|
|
139
|
+
/** Per-simulation contract overrides. */
|
|
140
|
+
overrides?: ContractOverrides;
|
|
134
141
|
noteStore: NoteStore;
|
|
135
142
|
keyStore: KeyStore;
|
|
136
143
|
addressStore: AddressStore;
|
|
@@ -154,6 +161,8 @@ export type ContractFunctionSimulatorArgs = {
|
|
|
154
161
|
export class ContractFunctionSimulator {
|
|
155
162
|
private readonly log: Logger;
|
|
156
163
|
private readonly contractStore: ContractStore;
|
|
164
|
+
private readonly contractClassService: ContractClassService;
|
|
165
|
+
private readonly overrides: ContractOverrides | undefined;
|
|
157
166
|
private readonly noteStore: NoteStore;
|
|
158
167
|
private readonly keyStore: KeyStore;
|
|
159
168
|
private readonly addressStore: AddressStore;
|
|
@@ -172,6 +181,8 @@ export class ContractFunctionSimulator {
|
|
|
172
181
|
|
|
173
182
|
constructor(args: ContractFunctionSimulatorArgs) {
|
|
174
183
|
this.contractStore = args.contractStore;
|
|
184
|
+
this.contractClassService = args.contractClassService;
|
|
185
|
+
this.overrides = args.overrides;
|
|
175
186
|
this.noteStore = args.noteStore;
|
|
176
187
|
this.keyStore = args.keyStore;
|
|
177
188
|
this.addressStore = args.addressStore;
|
|
@@ -208,10 +219,23 @@ export class ContractFunctionSimulator {
|
|
|
208
219
|
|
|
209
220
|
const contractAddress = request.origin;
|
|
210
221
|
|
|
211
|
-
const
|
|
222
|
+
const anchoredContractData = new AnchoredContractData(
|
|
223
|
+
this.contractStore,
|
|
224
|
+
this.contractClassService,
|
|
225
|
+
anchorBlockHeader,
|
|
226
|
+
this.overrides,
|
|
227
|
+
);
|
|
228
|
+
|
|
229
|
+
const entryPointArtifact = await anchoredContractData.getFunctionArtifactWithDebugMetadata(
|
|
212
230
|
contractAddress,
|
|
213
231
|
request.functionSelector,
|
|
214
232
|
);
|
|
233
|
+
if (!entryPointArtifact) {
|
|
234
|
+
throw new Error(
|
|
235
|
+
`Cannot run function ${request.functionSelector} on ${contractAddress}: the contract is not registered. ` +
|
|
236
|
+
`Register it via wallet.registerContract(...).`,
|
|
237
|
+
);
|
|
238
|
+
}
|
|
215
239
|
|
|
216
240
|
if (entryPointArtifact.functionType !== FunctionType.PRIVATE) {
|
|
217
241
|
throw new Error(`Cannot run ${entryPointArtifact.functionType} function as private`);
|
|
@@ -239,6 +263,7 @@ export class ContractFunctionSimulator {
|
|
|
239
263
|
const privateExecutionOracle = new PrivateExecutionOracle({
|
|
240
264
|
argsHash: request.firstCallArgsHash,
|
|
241
265
|
txContext: request.txContext,
|
|
266
|
+
txRequestSalt: request.salt,
|
|
242
267
|
callContext,
|
|
243
268
|
anchorBlockHeader,
|
|
244
269
|
utilityExecutor: async (call, execScopes) => {
|
|
@@ -249,7 +274,7 @@ export class ContractFunctionSimulator {
|
|
|
249
274
|
executionCache: HashedValuesCache.create(request.argsOfCalls),
|
|
250
275
|
noteCache,
|
|
251
276
|
taggingIndexCache,
|
|
252
|
-
|
|
277
|
+
anchoredContractData,
|
|
253
278
|
noteStore: this.noteStore,
|
|
254
279
|
keyStore: this.keyStore,
|
|
255
280
|
addressStore: this.addressStore,
|
|
@@ -289,8 +314,7 @@ export class ContractFunctionSimulator {
|
|
|
289
314
|
);
|
|
290
315
|
const simulatorTeardownTimer = new Timer();
|
|
291
316
|
|
|
292
|
-
noteCache.
|
|
293
|
-
const firstNullifierHint = noteCache.getNonceGenerator();
|
|
317
|
+
const firstNullifier = noteCache.getNonceGenerator();
|
|
294
318
|
|
|
295
319
|
const publicCallRequests = collectNested([executionResult], r =>
|
|
296
320
|
r.publicInputs.publicCallRequests
|
|
@@ -313,9 +337,9 @@ export class ContractFunctionSimulator {
|
|
|
313
337
|
}
|
|
314
338
|
|
|
315
339
|
// Not to be confused with a PrivateCallExecutionResult. This is a superset
|
|
316
|
-
// of the PrivateCallExecutionResult, containing also
|
|
340
|
+
// of the PrivateCallExecutionResult, containing also firstNullifier
|
|
317
341
|
// and publicFunctionsCalldata.
|
|
318
|
-
return new PrivateExecutionResult(executionResult,
|
|
342
|
+
return new PrivateExecutionResult(executionResult, firstNullifier, publicFunctionsCalldata);
|
|
319
343
|
} catch (err) {
|
|
320
344
|
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during private execution'));
|
|
321
345
|
}
|
|
@@ -333,7 +357,20 @@ export class ContractFunctionSimulator {
|
|
|
333
357
|
scopes: AztecAddress[],
|
|
334
358
|
jobId: string,
|
|
335
359
|
): Promise<{ result: Fr[]; offchainEffects: OffchainEffect[] }> {
|
|
336
|
-
const
|
|
360
|
+
const anchoredContractData = new AnchoredContractData(
|
|
361
|
+
this.contractStore,
|
|
362
|
+
this.contractClassService,
|
|
363
|
+
anchorBlockHeader,
|
|
364
|
+
this.overrides,
|
|
365
|
+
);
|
|
366
|
+
|
|
367
|
+
const entryPointArtifact = await anchoredContractData.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
|
|
368
|
+
if (!entryPointArtifact) {
|
|
369
|
+
throw new Error(
|
|
370
|
+
`Cannot run function ${call.selector} on ${call.to}: the contract is not registered. ` +
|
|
371
|
+
`Register it via wallet.registerContract(...).`,
|
|
372
|
+
);
|
|
373
|
+
}
|
|
337
374
|
|
|
338
375
|
if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
|
|
339
376
|
throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
|
|
@@ -353,7 +390,7 @@ export class ContractFunctionSimulator {
|
|
|
353
390
|
authWitnesses: authwits,
|
|
354
391
|
capsules: [],
|
|
355
392
|
anchorBlockHeader,
|
|
356
|
-
|
|
393
|
+
anchoredContractData,
|
|
357
394
|
noteStore: this.noteStore,
|
|
358
395
|
keyStore: this.keyStore,
|
|
359
396
|
addressStore: this.addressStore,
|
|
@@ -618,12 +655,12 @@ export async function generateSimulatedProvingResult(
|
|
|
618
655
|
siloedNullifiers,
|
|
619
656
|
minRevertibleSideEffectCounter,
|
|
620
657
|
);
|
|
658
|
+
// The protocol nullifier is the nonce generator and the tx's first nullifier. It is injected by the
|
|
659
|
+
// init kernel (at counter 1, index 0) rather than emitted by any private call, so it is absent from
|
|
660
|
+
// the executed nullifiers above. Mirror the kernel here by prepending it as the first non-revertible
|
|
661
|
+
// nullifier.
|
|
621
662
|
const nonceGenerator = privateExecutionResult.firstNullifier;
|
|
622
|
-
|
|
623
|
-
nonRevertibleNullifiers.push(nonceGenerator);
|
|
624
|
-
} else if (!nonRevertibleNullifiers[0].equals(nonceGenerator)) {
|
|
625
|
-
throw new Error('The first non revertible nullifier should be equal to the nonce generator. This is a bug!');
|
|
626
|
-
}
|
|
663
|
+
nonRevertibleNullifiers.unshift(nonceGenerator);
|
|
627
664
|
|
|
628
665
|
if (isPrivateOnlyTx) {
|
|
629
666
|
// We must make the note hashes unique by using the
|
|
@@ -886,6 +923,11 @@ function meterGasUsed(data: PrivateToRollupAccumulatedData | PrivateToPublicAccu
|
|
|
886
923
|
);
|
|
887
924
|
meteredL2Gas += numContractClassLogs * L2_GAS_PER_CONTRACT_CLASS_LOG;
|
|
888
925
|
|
|
926
|
+
if (isPrivateOnlyTx) {
|
|
927
|
+
// The public data write that the private tx base rollup always performs to update the fee payer's balance.
|
|
928
|
+
meteredDAFields += PUBLIC_DATA_WRITE_LENGTH;
|
|
929
|
+
}
|
|
930
|
+
|
|
889
931
|
const meteredDAGas = meteredDAFields * DA_GAS_PER_FIELD;
|
|
890
932
|
|
|
891
933
|
if ((data as PrivateToPublicAccumulatedData).publicCallRequests) {
|
|
@@ -43,12 +43,6 @@ export class ExecutionNoteCache {
|
|
|
43
43
|
|
|
44
44
|
private inRevertiblePhase = false;
|
|
45
45
|
|
|
46
|
-
/**
|
|
47
|
-
* Whether the protocol nullifier was used for nonce generation.
|
|
48
|
-
* We don't need to use the protocol nullifier if a non-revertible nullifier is emitted.
|
|
49
|
-
*/
|
|
50
|
-
private usedProtocolNullifierForNonces: boolean | undefined;
|
|
51
|
-
|
|
52
46
|
constructor(private readonly protocolNullifier: Fr) {}
|
|
53
47
|
|
|
54
48
|
/**
|
|
@@ -64,12 +58,9 @@ export class ExecutionNoteCache {
|
|
|
64
58
|
this.inRevertiblePhase = true;
|
|
65
59
|
this.minRevertibleSideEffectCounter = minRevertibleSideEffectCounter;
|
|
66
60
|
|
|
67
|
-
|
|
68
|
-
//
|
|
69
|
-
|
|
70
|
-
// we don't want to use them as the nonce generator.
|
|
71
|
-
this.usedProtocolNullifierForNonces = nullifiers.length === 0;
|
|
72
|
-
const nonceGenerator = this.usedProtocolNullifierForNonces ? this.protocolNullifier : new Fr(nullifiers[0]);
|
|
61
|
+
// The protocol nullifier is always the tx's first nullifier (injected by the kernel init), so it is the
|
|
62
|
+
// nonce generator for every note hash.
|
|
63
|
+
const nonceGenerator = this.protocolNullifier;
|
|
73
64
|
|
|
74
65
|
// The existing pending notes are all non-revertible.
|
|
75
66
|
// They cannot be squashed by nullifiers emitted after minRevertibleSideEffectCounter is set.
|
|
@@ -102,14 +93,6 @@ export class ExecutionNoteCache {
|
|
|
102
93
|
return sideEffectCounter >= this.minRevertibleSideEffectCounter;
|
|
103
94
|
}
|
|
104
95
|
|
|
105
|
-
public finish() {
|
|
106
|
-
// If we never entered the revertible phase, and there are no nullifiers emitted, we need to use the protocol
|
|
107
|
-
// nullifier as the nonce generator.
|
|
108
|
-
if (!this.inRevertiblePhase) {
|
|
109
|
-
this.usedProtocolNullifierForNonces = this.getEmittedNullifiers().length === 0;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
96
|
/**
|
|
114
97
|
* Add a new note to cache.
|
|
115
98
|
* @param note - New note created during execution.
|
|
@@ -223,19 +206,15 @@ export class ExecutionNoteCache {
|
|
|
223
206
|
}
|
|
224
207
|
|
|
225
208
|
/**
|
|
226
|
-
* @returns All nullifiers
|
|
227
|
-
*
|
|
209
|
+
* @returns All nullifiers of the transaction: the protocol nullifier (the kernel-injected first nullifier),
|
|
210
|
+
* followed by those emitted by private calls.
|
|
228
211
|
*/
|
|
229
212
|
getAllNullifiers(): Fr[] {
|
|
230
|
-
|
|
231
|
-
throw new Error('usedProtocolNullifierForNonces is not set yet. Call finish() to complete the transaction.');
|
|
232
|
-
}
|
|
233
|
-
const allNullifiers = this.getEmittedNullifiers();
|
|
234
|
-
return [...(this.usedProtocolNullifierForNonces ? [this.protocolNullifier] : []), ...allNullifiers];
|
|
213
|
+
return [this.protocolNullifier, ...this.getEmittedNullifiers()];
|
|
235
214
|
}
|
|
236
215
|
|
|
237
216
|
getNonceGenerator(): Fr {
|
|
238
|
-
return this.
|
|
217
|
+
return this.protocolNullifier;
|
|
239
218
|
}
|
|
240
219
|
|
|
241
220
|
#recordNullifier(contractAddress: AztecAddress, siloedNullifier: bigint) {
|
|
@@ -21,23 +21,27 @@ export {
|
|
|
21
21
|
ETH_ADDRESS,
|
|
22
22
|
EVENT_VALIDATION_REQUEST,
|
|
23
23
|
FIELD,
|
|
24
|
+
FIXED_ARRAY,
|
|
24
25
|
FUNCTION_SELECTOR,
|
|
25
26
|
LOG_RETRIEVAL_REQUEST,
|
|
26
27
|
LOG_RETRIEVAL_RESPONSE,
|
|
27
28
|
MEMBERSHIP_WITNESS,
|
|
28
|
-
MESSAGE_CONTEXT,
|
|
29
29
|
NOTE_SELECTOR,
|
|
30
30
|
NOTE_VALIDATION_REQUEST,
|
|
31
31
|
OPTION,
|
|
32
32
|
PENDING_TAGGED_LOG,
|
|
33
33
|
POINT,
|
|
34
34
|
PROVIDED_SECRET,
|
|
35
|
+
SLOT_NUMBER,
|
|
35
36
|
STR,
|
|
37
|
+
STRUCT,
|
|
36
38
|
U32,
|
|
39
|
+
tryFieldWidth,
|
|
37
40
|
type InputSlot,
|
|
38
41
|
type MaybePromise,
|
|
39
42
|
type OutputSlot,
|
|
40
43
|
type SlotShape,
|
|
44
|
+
type StructField,
|
|
41
45
|
type TypeMapping,
|
|
42
46
|
} from './oracle/oracle_type_mappings.js';
|
|
43
47
|
export { ExecutionNoteCache } from './execution_note_cache.js';
|
|
@@ -53,6 +57,7 @@ export { TxResolverService } from '../messages/tx_resolver_service.js';
|
|
|
53
57
|
export { UtilityExecutionOracle } from './oracle/utility_execution_oracle.js';
|
|
54
58
|
export { PrivateExecutionOracle } from './oracle/private_execution_oracle.js';
|
|
55
59
|
export { buildACIRCallback, UnavailableOracleError } from './oracle/acir_callback.js';
|
|
60
|
+
export { LEGACY_ORACLE_REGISTRY } from './oracle/legacy_oracle_registry.js';
|
|
56
61
|
export { executePrivateFunction, extractPrivateCircuitPublicInputs } from './oracle/private_execution.js';
|
|
57
62
|
export { generateSimulatedProvingResult } from './contract_function_simulator.js';
|
|
58
63
|
export { packAsHintedNote } from './oracle/note_packing_utils.js';
|
|
@@ -66,6 +71,7 @@ export { EventValidationRequest } from './noir-structs/event_validation_request.
|
|
|
66
71
|
export type { LogRetrievalRequest } from './noir-structs/log_retrieval_request.js';
|
|
67
72
|
export type { LogRetrievalResponse } from './noir-structs/log_retrieval_response.js';
|
|
68
73
|
export { NoteValidationRequest } from './noir-structs/note_validation_request.js';
|
|
74
|
+
export type { PendingTaggedLog } from './noir-structs/pending_tagged_log.js';
|
|
69
75
|
export type { TxEffectData } from './noir-structs/tx_effect_data.js';
|
|
70
76
|
export type { ProvidedSecret } from './noir-structs/provided_secret.js';
|
|
71
77
|
export { ResolvedTx } from './noir-structs/resolved_tx.js';
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import type { Fr } from '@aztec/foundation/curves/bn254';
|
|
2
2
|
|
|
3
|
+
import type { RetractableFactOrigin } from '../../storage/fact_store/index.js';
|
|
3
4
|
import type { EphemeralArray } from './ephemeral_array.js';
|
|
4
5
|
import type { Option } from './option.js';
|
|
5
|
-
import type { OriginBlock } from './origin_block.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* A single fact returned within a fact collection by the fact store oracles.
|
|
9
9
|
*
|
|
10
|
-
* A TS version of the `Fact` struct in `facts/mod.nr`. `originBlock` is `Some` for a retractable fact (
|
|
11
|
-
*
|
|
10
|
+
* A TS version of the `Fact` struct in `facts/mod.nr`. `originBlock` is `Some` for a retractable fact (carrying its
|
|
11
|
+
* origin block's current chain state) and `None` for a non-retractable one.
|
|
12
12
|
*/
|
|
13
|
-
export type Fact = { factTypeId: Fr; payload: EphemeralArray<Fr>; originBlock: Option<
|
|
13
|
+
export type Fact = { factTypeId: Fr; payload: EphemeralArray<Fr>; originBlock: Option<RetractableFactOrigin> };
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
2
2
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
3
3
|
|
|
4
|
-
import type {
|
|
4
|
+
import type { FactWithOriginState, RetractableFactOrigin } from '../../storage/fact_store/index.js';
|
|
5
|
+
import { OriginBlockState } from '../../storage/fact_store/index.js';
|
|
5
6
|
import type { EphemeralArrayService } from '../ephemeral_array_service.js';
|
|
6
7
|
import { EphemeralArray } from './ephemeral_array.js';
|
|
7
8
|
import type { Fact } from './fact.js';
|
|
@@ -27,7 +28,7 @@ export function toNoirFactCollection(
|
|
|
27
28
|
scope: AztecAddress,
|
|
28
29
|
factCollectionTypeId: Fr,
|
|
29
30
|
factCollectionId: Fr,
|
|
30
|
-
facts:
|
|
31
|
+
facts: FactWithOriginState[],
|
|
31
32
|
): FactCollection {
|
|
32
33
|
return {
|
|
33
34
|
contractAddress,
|
|
@@ -37,12 +38,16 @@ export function toNoirFactCollection(
|
|
|
37
38
|
facts: EphemeralArray.fromValues(
|
|
38
39
|
service,
|
|
39
40
|
facts.map(
|
|
40
|
-
(fact:
|
|
41
|
+
(fact: FactWithOriginState): Fact => ({
|
|
41
42
|
factTypeId: fact.factTypeId,
|
|
42
43
|
payload: EphemeralArray.fromValues(service, fact.payload),
|
|
43
44
|
originBlock: fact.originBlock
|
|
44
45
|
? Option.some(fact.originBlock)
|
|
45
|
-
: Option.none<
|
|
46
|
+
: Option.none<RetractableFactOrigin>({
|
|
47
|
+
blockNumber: 0,
|
|
48
|
+
blockHash: Fr.ZERO,
|
|
49
|
+
blockState: OriginBlockState.Pending,
|
|
50
|
+
}),
|
|
46
51
|
}),
|
|
47
52
|
),
|
|
48
53
|
),
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import type { BlockNumber } from '@aztec/foundation/branded-types';
|
|
1
2
|
import type { Fr } from '@aztec/foundation/curves/bn254';
|
|
3
|
+
import type { BlockHash } from '@aztec/stdlib/block';
|
|
2
4
|
import type { TxHash } from '@aztec/stdlib/tx';
|
|
5
|
+
import type { UInt64 } from '@aztec/stdlib/types';
|
|
3
6
|
|
|
4
7
|
/**
|
|
5
8
|
* Intermediate struct used to perform batch log retrieval by PXE. The `utilityBulkRetrieveLogs` oracle stores values of this
|
|
@@ -10,4 +13,7 @@ export type LogRetrievalResponse = {
|
|
|
10
13
|
txHash: TxHash;
|
|
11
14
|
uniqueNoteHashesInTx: Fr[];
|
|
12
15
|
firstNullifierInTx: Fr;
|
|
16
|
+
blockNumber: BlockNumber;
|
|
17
|
+
blockTimestamp: UInt64;
|
|
18
|
+
blockHash: BlockHash;
|
|
13
19
|
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Fr } from '@aztec/foundation/curves/bn254';
|
|
2
|
+
|
|
3
|
+
import type { ResolvedTx } from './resolved_tx.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Represents a pending tagged log as it is stored in the pending tagged log array to which the fetchTaggedLogs oracle
|
|
7
|
+
* inserts found private logs. A TS version of `pending_tagged_log.nr`.
|
|
8
|
+
*/
|
|
9
|
+
export type PendingTaggedLog = {
|
|
10
|
+
log: Fr[];
|
|
11
|
+
context: ResolvedTx;
|
|
12
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Fr } from '@aztec/foundation/curves/bn254';
|
|
2
2
|
import type { AppTaggingSecretKind } from '@aztec/stdlib/logs';
|
|
3
3
|
|
|
4
|
-
/** A tagging secret an app supplies explicitly to `
|
|
4
|
+
/** A tagging secret an app supplies explicitly to `getPendingTaggedLogsV2` when PXE cannot derive it internally. */
|
|
5
5
|
export type ProvidedSecret = { secret: Fr; mode: AppTaggingSecretKind };
|
|
@@ -3,6 +3,7 @@ import { Fr } from '@aztec/foundation/curves/bn254';
|
|
|
3
3
|
// Keep in sync with aztec::messages::delivery::ResolvedTaggingStrategy
|
|
4
4
|
const NON_INTERACTIVE_HANDSHAKE = 1;
|
|
5
5
|
const UNCONSTRAINED_SECRET = 2;
|
|
6
|
+
const INTERACTIVE_HANDSHAKE = 3;
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* The tagging secret PXE hands to the contract after applying the wallet's {@link TaggingSecretStrategy} choice
|
|
@@ -13,6 +14,14 @@ export type ResolvedTaggingStrategy =
|
|
|
13
14
|
/** A non-interactive handshake: the recipient re-derives the secret from the onchain handshake registry. */
|
|
14
15
|
type: 'non-interactive-handshake';
|
|
15
16
|
}
|
|
17
|
+
| {
|
|
18
|
+
/**
|
|
19
|
+
* An interactive handshake: the registry obtains the recipient's signed authorization through the custom
|
|
20
|
+
* request oracle, and the recipient learns the secret while signing. Nothing announcing the handshake is
|
|
21
|
+
* published onchain.
|
|
22
|
+
*/
|
|
23
|
+
type: 'interactive-handshake';
|
|
24
|
+
}
|
|
16
25
|
| {
|
|
17
26
|
/**
|
|
18
27
|
* An app-siloed, recipient-directional secret, ready to use. Only sound for unconstrained delivery.
|
|
@@ -29,6 +38,8 @@ export function resolvedTaggingStrategyToFields(resolved: ResolvedTaggingStrateg
|
|
|
29
38
|
return [new Fr(NON_INTERACTIVE_HANDSHAKE), Fr.ZERO];
|
|
30
39
|
case 'unconstrained-secret':
|
|
31
40
|
return [new Fr(UNCONSTRAINED_SECRET), resolved.secret];
|
|
41
|
+
case 'interactive-handshake':
|
|
42
|
+
return [new Fr(INTERACTIVE_HANDSHAKE), Fr.ZERO];
|
|
32
43
|
}
|
|
33
44
|
}
|
|
34
45
|
|
|
@@ -36,10 +47,20 @@ export function resolvedTaggingStrategyToFields(resolved: ResolvedTaggingStrateg
|
|
|
36
47
|
export function resolvedTaggingStrategyFromFields(kind: number, secret: Fr): ResolvedTaggingStrategy {
|
|
37
48
|
switch (kind) {
|
|
38
49
|
case NON_INTERACTIVE_HANDSHAKE:
|
|
50
|
+
assertAbsentSecret(kind, secret);
|
|
39
51
|
return { type: 'non-interactive-handshake' };
|
|
52
|
+
case INTERACTIVE_HANDSHAKE:
|
|
53
|
+
assertAbsentSecret(kind, secret);
|
|
54
|
+
return { type: 'interactive-handshake' };
|
|
40
55
|
case UNCONSTRAINED_SECRET:
|
|
41
56
|
return { type: 'unconstrained-secret', secret };
|
|
42
57
|
default:
|
|
43
58
|
throw new Error(`Unrecognized resolved tagging strategy kind: ${kind}`);
|
|
44
59
|
}
|
|
45
60
|
}
|
|
61
|
+
|
|
62
|
+
function assertAbsentSecret(kind: number, secret: Fr): void {
|
|
63
|
+
if (!secret.isZero()) {
|
|
64
|
+
throw new Error(`Resolved tagging strategy ${kind} must not include a secret`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -2,7 +2,8 @@ import type { ACIRCallback, ACVMField } from '@aztec/simulator/client';
|
|
|
2
2
|
|
|
3
3
|
import { ORACLE_VERSION_MAJOR, ORACLE_VERSION_MINOR } from '../../oracle_version.js';
|
|
4
4
|
import type { IMiscOracle, IPrivateExecutionOracle, IUtilityExecutionOracle } from './interfaces.js';
|
|
5
|
-
import {
|
|
5
|
+
import { LEGACY_ORACLE_REGISTRY, type LegacyOracleEntry } from './legacy_oracle_registry.js';
|
|
6
|
+
import { type NamedValue, ORACLE_REGISTRY, type OracleRegistryEntry, makeEntry } from './oracle_registry.js';
|
|
6
7
|
|
|
7
8
|
export class UnavailableOracleError extends Error {
|
|
8
9
|
constructor(oracleName: string) {
|
|
@@ -17,26 +18,71 @@ export class UnavailableOracleError extends Error {
|
|
|
17
18
|
* `aztec_{scope}_{methodName}` convention to resolve the handler, and calling the method directly. Unknown oracle
|
|
18
19
|
* names produce enhanced error messages based on the contract's oracle version.
|
|
19
20
|
*/
|
|
20
|
-
export function buildACIRCallback(
|
|
21
|
+
export function buildACIRCallback(
|
|
22
|
+
handler: OracleHandler,
|
|
23
|
+
registries: {
|
|
24
|
+
real?: Record<string, OracleRegistryEntry>;
|
|
25
|
+
legacy?: Record<string, LegacyOracleEntry>;
|
|
26
|
+
} = {},
|
|
27
|
+
): ACIRCallback {
|
|
28
|
+
const { real = ORACLE_REGISTRY, legacy: legacyRegistry = LEGACY_ORACLE_REGISTRY } = registries;
|
|
21
29
|
const target = {} as ACIRCallback;
|
|
22
|
-
for (const [oracleKey, entry] of Object.entries(
|
|
23
|
-
const
|
|
24
|
-
if (!match) {
|
|
25
|
-
throw new Error(`Oracle "${oracleKey}" does not follow the aztec_{scope}_{method} convention`);
|
|
26
|
-
}
|
|
27
|
-
const [, scope, methodName] = match;
|
|
30
|
+
for (const [oracleKey, entry] of Object.entries(real)) {
|
|
31
|
+
const { scope, methodName } = parseOracleName(oracleKey, 'Oracle');
|
|
28
32
|
target[oracleKey] = async (...inputs: ACVMField[][]) => {
|
|
29
33
|
assertHandlerSupportsScope(handler, scope);
|
|
30
34
|
const named = entry.deserializeParams(inputs);
|
|
31
|
-
const positional = named.map(p => p.value);
|
|
35
|
+
const positional = named.map((p: NamedValue) => p.value);
|
|
32
36
|
const result = await (handler as any)[methodName](...positional);
|
|
33
37
|
return entry.serializeReturn(result);
|
|
34
38
|
};
|
|
35
39
|
}
|
|
36
40
|
|
|
37
|
-
|
|
41
|
+
// Legacy oracle names: served for contracts compiled against a retired oracle version. Each reuses the current
|
|
42
|
+
// handler of its `modernOracle` and reshapes the wire (params and/or return) back to what the old bytecode expects.
|
|
43
|
+
for (const [legacyKey, legacy] of Object.entries(legacyRegistry)) {
|
|
44
|
+
const { scope } = parseOracleName(legacyKey, 'Legacy oracle');
|
|
45
|
+
if (legacyKey in target) {
|
|
46
|
+
throw new Error(`Legacy oracle "${legacyKey}" collides with a live oracle of the same name in the registry`);
|
|
47
|
+
}
|
|
48
|
+
const modernEntry = real[legacy.modernOracle];
|
|
49
|
+
const { methodName } = parseOracleName(legacy.modernOracle, 'Oracle');
|
|
50
|
+
// Override only the side whose wire changed; inherit the other from the modern entry.
|
|
51
|
+
const paramOverride = legacy.params;
|
|
52
|
+
const paramSource = paramOverride ? makeEntry({ params: [...paramOverride.legacyType] }) : modernEntry;
|
|
53
|
+
const returnOverride = legacy.returnType;
|
|
54
|
+
const returnSource = returnOverride ? makeEntry({ returnType: returnOverride.legacyType }) : modernEntry;
|
|
55
|
+
target[legacyKey] = async (...inputs: ACVMField[][]) => {
|
|
56
|
+
assertHandlerSupportsScope(handler, scope);
|
|
57
|
+
const legacyArgs = paramSource.deserializeParams(inputs).map(p => p.value);
|
|
58
|
+
const positional = paramOverride ? await paramOverride.mapping(legacyArgs) : legacyArgs;
|
|
59
|
+
const result = await (handler as any)[methodName](...positional);
|
|
60
|
+
return returnSource.serializeReturn(returnOverride ? returnOverride.mapping(result) : result);
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return new Proxy(target, makeUnknownOracleTrap(handler));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Parses an `aztec_{scope}_{method}` oracle name into its parts, throwing if it doesn't follow the convention. */
|
|
68
|
+
function parseOracleName(key: string, label: string): { scope: string; methodName: string } {
|
|
69
|
+
const match = key.match(/^aztec_(\w+?)_(.+)$/);
|
|
70
|
+
if (!match) {
|
|
71
|
+
throw new Error(`${label} "${key}" does not follow the aztec_{scope}_{method} convention`);
|
|
72
|
+
}
|
|
73
|
+
return { scope: match[1], methodName: match[2] };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Proxy trap for the callback table: a known oracle name passes through; an unknown one throws a diagnostic keyed on
|
|
78
|
+
* the contract's oracle version (version unknown, contract newer than this environment, or a same-version mismatch).
|
|
79
|
+
*/
|
|
80
|
+
function makeUnknownOracleTrap(handler: OracleHandler): ProxyHandler<ACIRCallback> {
|
|
81
|
+
return {
|
|
38
82
|
get(obj, prop: string) {
|
|
39
|
-
|
|
83
|
+
// Own-property check only: `in` would match inherited `Object.prototype` keys (e.g. `constructor`, `toString`)
|
|
84
|
+
// and return the built-in instead of falling through to the unknown-oracle diagnostic below.
|
|
85
|
+
if (Object.hasOwn(obj, prop)) {
|
|
40
86
|
return (obj as Record<string, unknown>)[prop];
|
|
41
87
|
}
|
|
42
88
|
|
|
@@ -76,7 +122,7 @@ export function buildACIRCallback(handler: OracleHandler): ACIRCallback {
|
|
|
76
122
|
}
|
|
77
123
|
};
|
|
78
124
|
},
|
|
79
|
-
}
|
|
125
|
+
};
|
|
80
126
|
}
|
|
81
127
|
|
|
82
128
|
type OracleHandler = IMiscOracle & (IUtilityExecutionOracle | IPrivateExecutionOracle);
|