@aztec/txe 0.0.1-commit.03f7ef2 → 0.0.1-commit.04d373f
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/ContractClassRegistry-KKNT527R.js +3 -0
- package/dest/ContractClassRegistry-KKNT527R.js.map +7 -0
- package/dest/ContractInstanceRegistry-GSKBNL3Q.js +3 -0
- package/dest/ContractInstanceRegistry-GSKBNL3Q.js.map +7 -0
- package/dest/FeeJuice-GUJ5O6GB.js +3 -0
- package/dest/FeeJuice-GUJ5O6GB.js.map +7 -0
- package/dest/MultiCallEntrypoint-ZQPCKVKL.js +3 -0
- package/dest/MultiCallEntrypoint-ZQPCKVKL.js.map +7 -0
- package/dest/SchnorrAccount-QIXE5DXA.js +3 -0
- package/dest/SchnorrAccount-QIXE5DXA.js.map +7 -0
- package/dest/bin/check_txe_oracle_version.d.ts +2 -0
- package/dest/bin/check_txe_oracle_version.d.ts.map +1 -0
- package/dest/bin/check_txe_oracle_version.js +32 -0
- package/dest/bin/index.js +3 -30
- package/dest/bin/index.js.map +7 -0
- package/dest/chunk-BJVAAXNA.js +3 -0
- package/dest/chunk-BJVAAXNA.js.map +7 -0
- package/dest/chunk-DF6RMOC6.js +304 -0
- package/dest/chunk-DF6RMOC6.js.map +7 -0
- package/dest/chunk-PPJTNNUG.js +265 -0
- package/dest/chunk-PPJTNNUG.js.map +7 -0
- package/dest/constants.d.ts +5 -0
- package/dest/constants.d.ts.map +1 -0
- package/dest/constants.js +7 -0
- package/dest/dispatcher_pool.d.ts +67 -0
- package/dest/dispatcher_pool.d.ts.map +1 -0
- package/dest/dispatcher_pool.js +284 -0
- package/dest/index.d.ts +188 -7
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +148 -75
- package/dest/metafile.json +38147 -0
- package/dest/msgpackr_fr_extension.d.ts +2 -0
- package/dest/msgpackr_fr_extension.d.ts.map +1 -0
- package/dest/msgpackr_fr_extension.js +21 -0
- package/dest/oracle/interfaces.d.ts +40 -28
- package/dest/oracle/interfaces.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_public_context.d.ts +18 -13
- package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_public_context.js +31 -16
- package/dest/oracle/txe_oracle_top_level_context.d.ts +49 -31
- package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_top_level_context.js +265 -119
- package/dest/oracle/txe_private_execution_oracle.d.ts +17 -0
- package/dest/oracle/txe_private_execution_oracle.d.ts.map +1 -0
- package/dest/oracle/txe_private_execution_oracle.js +15 -0
- package/dest/rpc_server.d.ts +14 -0
- package/dest/rpc_server.d.ts.map +1 -0
- package/dest/rpc_server.js +78 -0
- package/dest/rpc_translator.d.ts +144 -82
- package/dest/rpc_translator.d.ts.map +1 -1
- package/dest/rpc_translator.js +599 -238
- package/dest/server.bundle.js +3 -0
- package/dest/server.bundle.js.map +7 -0
- package/dest/state_machine/archiver.d.ts +20 -67
- package/dest/state_machine/archiver.d.ts.map +1 -1
- package/dest/state_machine/archiver.js +65 -182
- package/dest/state_machine/dummy_p2p_client.d.ts +28 -17
- package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
- package/dest/state_machine/dummy_p2p_client.js +51 -24
- package/dest/state_machine/global_variable_builder.d.ts +9 -4
- package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
- package/dest/state_machine/global_variable_builder.js +10 -4
- package/dest/state_machine/index.d.ts +11 -7
- package/dest/state_machine/index.d.ts.map +1 -1
- package/dest/state_machine/index.js +57 -16
- package/dest/state_machine/mock_epoch_cache.d.ts +26 -8
- package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
- package/dest/state_machine/mock_epoch_cache.js +49 -9
- package/dest/state_machine/synchronizer.d.ts +6 -6
- package/dest/state_machine/synchronizer.d.ts.map +1 -1
- package/dest/state_machine/synchronizer.js +4 -4
- package/dest/txe_oracle_version.d.ts +17 -0
- package/dest/txe_oracle_version.d.ts.map +1 -0
- package/dest/txe_oracle_version.js +14 -0
- package/dest/txe_session.d.ts +83 -19
- package/dest/txe_session.d.ts.map +1 -1
- package/dest/txe_session.js +291 -66
- package/dest/utils/block_creation.d.ts +4 -4
- package/dest/utils/block_creation.d.ts.map +1 -1
- package/dest/utils/block_creation.js +18 -5
- package/dest/utils/encoding.d.ts +191 -0
- package/dest/utils/encoding.d.ts.map +1 -0
- package/dest/{util → utils}/encoding.js +7 -2
- package/dest/{util → utils}/expected_failure_error.d.ts +1 -1
- package/dest/utils/expected_failure_error.d.ts.map +1 -0
- package/dest/utils/tx_effect_creation.d.ts +2 -3
- package/dest/utils/tx_effect_creation.d.ts.map +1 -1
- package/dest/utils/tx_effect_creation.js +3 -6
- package/dest/utils/txe_account_store.d.ts +10 -0
- package/dest/utils/txe_account_store.d.ts.map +1 -0
- package/dest/{util/txe_account_data_provider.js → utils/txe_account_store.js} +1 -1
- package/dest/utils/txe_public_contract_data_source.d.ts +20 -0
- package/dest/utils/txe_public_contract_data_source.d.ts.map +1 -0
- package/dest/utils/txe_public_contract_data_source.js +48 -0
- package/dest/worker.bundle.js +3 -0
- package/dest/worker.bundle.js.map +7 -0
- package/dest/worker.d.ts +2 -0
- package/dest/worker.d.ts.map +1 -0
- package/dest/worker.js +92 -0
- package/package.json +38 -22
- package/src/bin/check_txe_oracle_version.ts +37 -0
- package/src/bin/index.ts +11 -2
- package/src/constants.ts +9 -0
- package/src/dispatcher_pool.ts +316 -0
- package/src/index.ts +166 -80
- package/src/msgpackr_fr_extension.ts +23 -0
- package/src/oracle/interfaces.ts +48 -34
- package/src/oracle/txe_oracle_public_context.ts +46 -18
- package/src/oracle/txe_oracle_top_level_context.ts +322 -169
- package/src/oracle/txe_private_execution_oracle.ts +30 -0
- package/src/rpc_server.ts +87 -0
- package/src/rpc_translator.ts +687 -326
- package/src/state_machine/archiver.ts +69 -220
- package/src/state_machine/dummy_p2p_client.ts +80 -37
- package/src/state_machine/global_variable_builder.ts +19 -4
- package/src/state_machine/index.ts +73 -16
- package/src/state_machine/mock_epoch_cache.ts +61 -14
- package/src/state_machine/synchronizer.ts +6 -6
- package/src/txe_oracle_version.ts +17 -0
- package/src/txe_session.ts +439 -132
- package/src/utils/block_creation.ts +19 -16
- package/src/{util → utils}/encoding.ts +8 -2
- package/src/utils/tx_effect_creation.ts +3 -11
- package/src/{util/txe_account_data_provider.ts → utils/txe_account_store.ts} +1 -1
- package/src/utils/txe_public_contract_data_source.ts +58 -0
- package/src/worker.ts +98 -0
- package/dest/util/encoding.d.ts +0 -720
- package/dest/util/encoding.d.ts.map +0 -1
- package/dest/util/expected_failure_error.d.ts.map +0 -1
- package/dest/util/txe_account_data_provider.d.ts +0 -10
- package/dest/util/txe_account_data_provider.d.ts.map +0 -1
- package/dest/util/txe_contract_data_provider.d.ts +0 -12
- package/dest/util/txe_contract_data_provider.d.ts.map +0 -1
- package/dest/util/txe_contract_data_provider.js +0 -22
- package/dest/util/txe_public_contract_data_source.d.ts +0 -21
- package/dest/util/txe_public_contract_data_source.d.ts.map +0 -1
- package/dest/util/txe_public_contract_data_source.js +0 -67
- package/src/util/txe_contract_data_provider.ts +0 -36
- package/src/util/txe_public_contract_data_source.ts +0 -86
- /package/dest/{util → utils}/expected_failure_error.js +0 -0
- /package/src/{util → utils}/expected_failure_error.ts +0 -0
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS,
|
|
3
|
-
|
|
4
|
-
DEFAULT_L2_GAS_LIMIT,
|
|
5
|
-
DEFAULT_TEARDOWN_DA_GAS_LIMIT,
|
|
6
|
-
DEFAULT_TEARDOWN_L2_GAS_LIMIT,
|
|
3
|
+
MAX_PRIVATE_LOGS_PER_TX,
|
|
7
4
|
NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
|
|
8
5
|
} from '@aztec/constants';
|
|
9
6
|
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
@@ -13,13 +10,18 @@ import { LogLevels, type Logger, applyStringFormatting, createLogger } from '@az
|
|
|
13
10
|
import { TestDateProvider } from '@aztec/foundation/timer';
|
|
14
11
|
import type { KeyStore } from '@aztec/key-store';
|
|
15
12
|
import {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
13
|
+
AddressStore,
|
|
14
|
+
CapsuleService,
|
|
15
|
+
CapsuleStore,
|
|
16
|
+
type ContractStore,
|
|
17
|
+
type ExecutionHooks,
|
|
18
|
+
NoteStore,
|
|
19
|
+
ORACLE_VERSION_MAJOR,
|
|
20
|
+
PrivateEventStore,
|
|
21
|
+
RecipientTaggingStore,
|
|
22
|
+
SenderAddressBookStore,
|
|
23
|
+
SenderTaggingStore,
|
|
24
|
+
composeHooks,
|
|
23
25
|
enrichPublicSimulationError,
|
|
24
26
|
} from '@aztec/pxe/server';
|
|
25
27
|
import {
|
|
@@ -48,7 +50,7 @@ import {
|
|
|
48
50
|
PublicContractsDB,
|
|
49
51
|
PublicProcessor,
|
|
50
52
|
} from '@aztec/simulator/server';
|
|
51
|
-
import { type ContractArtifact, EventSelector, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
|
|
53
|
+
import { type ContractArtifact, EventSelector, FunctionCall, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
|
|
52
54
|
import { AuthWitness } from '@aztec/stdlib/auth-witness';
|
|
53
55
|
import { PublicSimulatorConfig } from '@aztec/stdlib/avm';
|
|
54
56
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
@@ -61,6 +63,7 @@ import {
|
|
|
61
63
|
PrivateToPublicAccumulatedData,
|
|
62
64
|
PublicCallRequest,
|
|
63
65
|
} from '@aztec/stdlib/kernel';
|
|
66
|
+
import { hashPublicKey } from '@aztec/stdlib/keys';
|
|
64
67
|
import { ChonkProof } from '@aztec/stdlib/proofs';
|
|
65
68
|
import { makeGlobalVariables } from '@aztec/stdlib/testing';
|
|
66
69
|
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
@@ -77,14 +80,13 @@ import {
|
|
|
77
80
|
collectNested,
|
|
78
81
|
} from '@aztec/stdlib/tx';
|
|
79
82
|
import type { UInt64 } from '@aztec/stdlib/types';
|
|
80
|
-
import { ForkCheckpoint } from '@aztec/world-state';
|
|
83
|
+
import { ForkCheckpoint } from '@aztec/world-state/native';
|
|
81
84
|
|
|
85
|
+
import { DEFAULT_ADDRESS } from '../constants.js';
|
|
82
86
|
import type { TXEStateMachine } from '../state_machine/index.js';
|
|
83
|
-
import { DEFAULT_ADDRESS } from '../txe_session.js';
|
|
84
|
-
import type { TXEAccountDataProvider } from '../util/txe_account_data_provider.js';
|
|
85
|
-
import type { TXEContractDataProvider } from '../util/txe_contract_data_provider.js';
|
|
86
|
-
import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_source.js';
|
|
87
87
|
import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from '../utils/block_creation.js';
|
|
88
|
+
import type { TXEAccountStore } from '../utils/txe_account_store.js';
|
|
89
|
+
import { TXEPublicContractDataSource } from '../utils/txe_public_contract_data_source.js';
|
|
88
90
|
import type { ITxeExecutionOracle } from './interfaces.js';
|
|
89
91
|
|
|
90
92
|
export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracle {
|
|
@@ -95,15 +97,16 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
95
97
|
|
|
96
98
|
constructor(
|
|
97
99
|
private stateMachine: TXEStateMachine,
|
|
98
|
-
private
|
|
99
|
-
private
|
|
100
|
+
private contractStore: ContractStore,
|
|
101
|
+
private noteStore: NoteStore,
|
|
100
102
|
private keyStore: KeyStore,
|
|
101
|
-
private
|
|
102
|
-
private
|
|
103
|
-
private
|
|
104
|
-
private
|
|
105
|
-
private
|
|
106
|
-
private
|
|
103
|
+
private addressStore: AddressStore,
|
|
104
|
+
private accountStore: TXEAccountStore,
|
|
105
|
+
private senderTaggingStore: SenderTaggingStore,
|
|
106
|
+
private recipientTaggingStore: RecipientTaggingStore,
|
|
107
|
+
private senderAddressBookStore: SenderAddressBookStore,
|
|
108
|
+
private capsuleStore: CapsuleStore,
|
|
109
|
+
private privateEventStore: PrivateEventStore,
|
|
107
110
|
private nextBlockTimestamp: bigint,
|
|
108
111
|
private version: Fr,
|
|
109
112
|
private chainId: Fr,
|
|
@@ -113,48 +116,62 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
113
116
|
this.logger.debug('Entering Top Level Context');
|
|
114
117
|
}
|
|
115
118
|
|
|
116
|
-
|
|
117
|
-
|
|
119
|
+
private contractOracleVersion: { major: number; minor: number } | undefined;
|
|
120
|
+
|
|
121
|
+
assertCompatibleOracleVersion(major: number, minor: number): void {
|
|
122
|
+
if (major !== ORACLE_VERSION_MAJOR) {
|
|
123
|
+
const hint =
|
|
124
|
+
major > ORACLE_VERSION_MAJOR
|
|
125
|
+
? 'The contract was compiled with a newer version of Aztec.nr than this aztec cli version supports. Upgrade your aztec cli version to a compatible version.'
|
|
126
|
+
: 'The contract was compiled with an older version of Aztec.nr than this aztec cli version supports. Recompile the contract with a compatible version of Aztec.nr.';
|
|
118
127
|
throw new Error(
|
|
119
|
-
`Incompatible
|
|
128
|
+
`Incompatible aztec cli version: ${hint} See https://docs.aztec.network/errors/8 (expected oracle major version ${ORACLE_VERSION_MAJOR}, got ${major})`,
|
|
120
129
|
);
|
|
121
130
|
}
|
|
131
|
+
this.contractOracleVersion = { major, minor };
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Prefixed with "nonOracleFunction" as it is not used as an oracle handler.
|
|
135
|
+
nonOracleFunctionGetContractOracleVersion(): { major: number; minor: number } | undefined {
|
|
136
|
+
return this.contractOracleVersion;
|
|
122
137
|
}
|
|
123
138
|
|
|
124
139
|
// This is typically only invoked in private contexts, but it is convenient to also have it in top-level for testing
|
|
125
140
|
// setup.
|
|
126
|
-
|
|
141
|
+
getRandomField(): Fr {
|
|
127
142
|
return Fr.random();
|
|
128
143
|
}
|
|
129
144
|
|
|
130
145
|
// We instruct users to debug contracts via this oracle, so it makes sense that they'd expect it to also work in tests
|
|
131
|
-
|
|
146
|
+
log(level: number, message: string, fields: Fr[]): Promise<void> {
|
|
132
147
|
if (!LogLevels[level]) {
|
|
133
|
-
throw new Error(`Invalid
|
|
148
|
+
throw new Error(`Invalid log level: ${level}`);
|
|
134
149
|
}
|
|
135
150
|
const levelName = LogLevels[level];
|
|
136
151
|
|
|
137
152
|
this.logger[levelName](`${applyStringFormatting(message, fields)}`, { module: `${this.logger.module}:debug_log` });
|
|
153
|
+
return Promise.resolve();
|
|
138
154
|
}
|
|
139
155
|
|
|
140
|
-
|
|
156
|
+
getDefaultAddress(): AztecAddress {
|
|
141
157
|
return DEFAULT_ADDRESS;
|
|
142
158
|
}
|
|
143
159
|
|
|
144
|
-
async
|
|
160
|
+
async getNextBlockNumber(): Promise<BlockNumber> {
|
|
145
161
|
return BlockNumber((await this.getLastBlockNumber()) + 1);
|
|
146
162
|
}
|
|
147
163
|
|
|
148
|
-
|
|
164
|
+
getNextBlockTimestamp(): Promise<bigint> {
|
|
149
165
|
return Promise.resolve(this.nextBlockTimestamp);
|
|
150
166
|
}
|
|
151
167
|
|
|
152
|
-
async
|
|
153
|
-
return (await this.stateMachine.node.
|
|
168
|
+
async getLastBlockTimestamp() {
|
|
169
|
+
return (await this.stateMachine.node.getBlockData('latest'))!.header.globalVariables.timestamp;
|
|
154
170
|
}
|
|
155
171
|
|
|
156
|
-
async
|
|
157
|
-
const
|
|
172
|
+
async getLastTxEffects() {
|
|
173
|
+
const latestBlockNumber = await this.stateMachine.archiver.getBlockNumber();
|
|
174
|
+
const block = await this.stateMachine.archiver.getBlock({ number: latestBlockNumber });
|
|
158
175
|
|
|
159
176
|
if (block!.body.txEffects.length != 1) {
|
|
160
177
|
// Note that calls like env.mine() will result in blocks with no transactions, hitting this
|
|
@@ -163,12 +180,41 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
163
180
|
|
|
164
181
|
const txEffects = block!.body.txEffects[0];
|
|
165
182
|
|
|
166
|
-
|
|
183
|
+
const privateLogs = txEffects.privateLogs;
|
|
184
|
+
if (privateLogs.length > MAX_PRIVATE_LOGS_PER_TX) {
|
|
185
|
+
throw new Error(`${privateLogs.length} private logs exceed max ${MAX_PRIVATE_LOGS_PER_TX}`);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return {
|
|
189
|
+
txHash: txEffects.txHash,
|
|
190
|
+
noteHashes: txEffects.noteHashes,
|
|
191
|
+
nullifiers: txEffects.nullifiers,
|
|
192
|
+
privateLogs,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
async syncContractNonOracleMethod(contractAddress: AztecAddress, scope: AztecAddress, jobId: string) {
|
|
197
|
+
if (contractAddress.equals(DEFAULT_ADDRESS)) {
|
|
198
|
+
this.logger.debug(`Skipping sync in getPrivateEvents because the events correspond to the default address.`);
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
203
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(
|
|
204
|
+
contractAddress,
|
|
205
|
+
null,
|
|
206
|
+
async (call, execScopes) => {
|
|
207
|
+
await this.executeUtilityCall(call, execScopes, jobId);
|
|
208
|
+
},
|
|
209
|
+
blockHeader,
|
|
210
|
+
jobId,
|
|
211
|
+
[scope],
|
|
212
|
+
);
|
|
167
213
|
}
|
|
168
214
|
|
|
169
|
-
async
|
|
215
|
+
async getPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress) {
|
|
170
216
|
return (
|
|
171
|
-
await this.
|
|
217
|
+
await this.privateEventStore.getPrivateEvents(selector, {
|
|
172
218
|
contractAddress,
|
|
173
219
|
scopes: [scope],
|
|
174
220
|
fromBlock: 0,
|
|
@@ -177,7 +223,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
177
223
|
).map(e => e.packedEvent);
|
|
178
224
|
}
|
|
179
225
|
|
|
180
|
-
async
|
|
226
|
+
async advanceBlocksBy(blocks: number) {
|
|
181
227
|
this.logger.debug(`time traveling ${blocks} blocks`);
|
|
182
228
|
|
|
183
229
|
for (let i = 0; i < blocks; i++) {
|
|
@@ -185,70 +231,79 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
185
231
|
}
|
|
186
232
|
}
|
|
187
233
|
|
|
188
|
-
|
|
234
|
+
advanceTimestampBy(duration: UInt64) {
|
|
189
235
|
this.logger.debug(`time traveling ${duration} seconds`);
|
|
190
236
|
this.nextBlockTimestamp += duration;
|
|
191
237
|
}
|
|
192
238
|
|
|
193
|
-
|
|
239
|
+
private deploymentNullifier(address: AztecAddress): Promise<Fr> {
|
|
240
|
+
return siloNullifier(AztecAddress.fromNumber(CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS), address.toField());
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
async deploy(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
|
|
194
244
|
// Emit deployment nullifier
|
|
195
245
|
await this.mineBlock({
|
|
196
|
-
nullifiers: [
|
|
197
|
-
await siloNullifier(
|
|
198
|
-
AztecAddress.fromNumber(CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS),
|
|
199
|
-
instance.address.toField(),
|
|
200
|
-
),
|
|
201
|
-
],
|
|
246
|
+
nullifiers: [await this.deploymentNullifier(instance.address)],
|
|
202
247
|
});
|
|
203
248
|
|
|
204
249
|
if (!secret.equals(Fr.ZERO)) {
|
|
205
|
-
await this.
|
|
250
|
+
await this.addAccount(artifact, instance, secret);
|
|
206
251
|
} else {
|
|
207
|
-
await this.
|
|
208
|
-
await this.
|
|
252
|
+
await this.contractStore.addContractInstance(instance);
|
|
253
|
+
await this.contractStore.addContractArtifact(artifact);
|
|
209
254
|
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
210
255
|
}
|
|
211
256
|
}
|
|
212
257
|
|
|
213
|
-
|
|
258
|
+
/**
|
|
259
|
+
* Mines a single block containing only the deployment nullifiers for the contracts at the given addresses.
|
|
260
|
+
*/
|
|
261
|
+
async mineDeploymentNullifiers(addresses: AztecAddress[]) {
|
|
262
|
+
await this.mineBlock({
|
|
263
|
+
nullifiers: await Promise.all(addresses.map(address => this.deploymentNullifier(address))),
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
async addAccount(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
|
|
214
268
|
const partialAddress = await computePartialAddress(instance);
|
|
215
269
|
|
|
216
270
|
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
217
|
-
await this.
|
|
218
|
-
await this.
|
|
271
|
+
await this.contractStore.addContractInstance(instance);
|
|
272
|
+
await this.contractStore.addContractArtifact(artifact);
|
|
219
273
|
|
|
220
274
|
const completeAddress = await this.keyStore.addAccount(secret, partialAddress);
|
|
221
|
-
await this.
|
|
222
|
-
await this.
|
|
275
|
+
await this.accountStore.setAccount(completeAddress.address, completeAddress);
|
|
276
|
+
await this.addressStore.addCompleteAddress(completeAddress);
|
|
223
277
|
this.logger.debug(`Created account ${completeAddress.address}`);
|
|
224
278
|
|
|
225
279
|
return completeAddress;
|
|
226
280
|
}
|
|
227
281
|
|
|
228
|
-
async
|
|
282
|
+
async createAccount(secret: Fr) {
|
|
229
283
|
// This is a foot gun !
|
|
230
284
|
const completeAddress = await this.keyStore.addAccount(secret, secret);
|
|
231
|
-
await this.
|
|
232
|
-
await this.
|
|
285
|
+
await this.accountStore.setAccount(completeAddress.address, completeAddress);
|
|
286
|
+
await this.addressStore.addCompleteAddress(completeAddress);
|
|
233
287
|
this.logger.debug(`Created account ${completeAddress.address}`);
|
|
234
288
|
|
|
235
289
|
return completeAddress;
|
|
236
290
|
}
|
|
237
291
|
|
|
238
|
-
async
|
|
239
|
-
const account = await this.
|
|
240
|
-
const
|
|
292
|
+
async addAuthWitness(address: AztecAddress, messageHash: Fr) {
|
|
293
|
+
const account = await this.accountStore.getAccount(address);
|
|
294
|
+
const ivpkMHash = await hashPublicKey(account.publicKeys.ivpkM);
|
|
295
|
+
const privateKey = await this.keyStore.getMasterSecretKey(ivpkMHash);
|
|
241
296
|
|
|
242
297
|
const schnorr = new Schnorr();
|
|
243
|
-
const signature = await schnorr.constructSignature(messageHash
|
|
298
|
+
const signature = await schnorr.constructSignature(messageHash, privateKey);
|
|
244
299
|
|
|
245
|
-
const authWitness = new AuthWitness(messageHash,
|
|
300
|
+
const authWitness = new AuthWitness(messageHash, signature.toLimbFields());
|
|
246
301
|
|
|
247
302
|
this.authwits.set(authWitness.requestHash.toString(), authWitness);
|
|
248
303
|
}
|
|
249
304
|
|
|
250
305
|
async mineBlock(options: { nullifiers?: Fr[] } = {}) {
|
|
251
|
-
const blockNumber = await this.
|
|
306
|
+
const blockNumber = await this.getNextBlockNumber();
|
|
252
307
|
|
|
253
308
|
const txEffect = TxEffect.empty();
|
|
254
309
|
txEffect.nullifiers = [getSingleTxBlockRequestHash(blockNumber), ...(options.nullifiers ?? [])];
|
|
@@ -272,19 +327,23 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
272
327
|
await this.stateMachine.handleL2Block(block);
|
|
273
328
|
}
|
|
274
329
|
|
|
275
|
-
async
|
|
276
|
-
from: AztecAddress,
|
|
330
|
+
async privateCallNewFlow(
|
|
331
|
+
from: AztecAddress | undefined,
|
|
277
332
|
targetContractAddress: AztecAddress = AztecAddress.zero(),
|
|
278
333
|
functionSelector: FunctionSelector = FunctionSelector.empty(),
|
|
279
334
|
args: Fr[],
|
|
280
335
|
argsHash: Fr = Fr.zero(),
|
|
281
336
|
isStaticCall: boolean = false,
|
|
337
|
+
additionalScopes: AztecAddress[] = [],
|
|
338
|
+
jobId: string,
|
|
339
|
+
authorizedUtilityCallTargets: AztecAddress[],
|
|
340
|
+
gasSettings: GasSettings,
|
|
282
341
|
) {
|
|
283
342
|
this.logger.verbose(
|
|
284
|
-
`Executing external function ${await this.
|
|
343
|
+
`Executing external function ${await this.contractStore.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
|
|
285
344
|
);
|
|
286
345
|
|
|
287
|
-
const artifact = await this.
|
|
346
|
+
const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
288
347
|
if (!artifact) {
|
|
289
348
|
const message = functionSelector.equals(await FunctionSelector.fromSignature('verify_private_authwit(Field)'))
|
|
290
349
|
? 'Found no account contract artifact for a private authwit check - use `create_contract_account` instead of `create_light_account` for authwit support.'
|
|
@@ -292,60 +351,80 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
292
351
|
throw new Error(message);
|
|
293
352
|
}
|
|
294
353
|
|
|
295
|
-
const
|
|
354
|
+
const scopes = from === undefined ? additionalScopes : [from, ...additionalScopes];
|
|
296
355
|
|
|
297
|
-
|
|
356
|
+
// Sync notes before executing private function to discover notes from previous transactions
|
|
357
|
+
const utilityExecutor = async (call: FunctionCall, execScopes: AztecAddress[]) => {
|
|
358
|
+
await this.executeUtilityCall(call, execScopes, jobId);
|
|
359
|
+
};
|
|
298
360
|
|
|
299
|
-
const
|
|
361
|
+
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
362
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(
|
|
363
|
+
targetContractAddress,
|
|
364
|
+
functionSelector,
|
|
365
|
+
utilityExecutor,
|
|
366
|
+
blockHeader,
|
|
367
|
+
jobId,
|
|
368
|
+
scopes,
|
|
369
|
+
);
|
|
300
370
|
|
|
301
|
-
const
|
|
371
|
+
const blockNumber = await this.getNextBlockNumber();
|
|
302
372
|
|
|
303
|
-
const
|
|
373
|
+
const msgSender = from ?? AztecAddress.NULL_MSG_SENDER;
|
|
374
|
+
const callContext = new CallContext(msgSender, targetContractAddress, functionSelector, isStaticCall);
|
|
304
375
|
|
|
305
376
|
const txContext = new TxContext(this.chainId, this.version, gasSettings);
|
|
306
377
|
|
|
307
|
-
const blockHeader = await this.stateMachine.anchorBlockDataProvider.getBlockHeader();
|
|
308
|
-
|
|
309
378
|
const protocolNullifier = await computeProtocolNullifier(getSingleTxBlockRequestHash(blockNumber));
|
|
310
379
|
const noteCache = new ExecutionNoteCache(protocolNullifier);
|
|
380
|
+
// In production, the account contract sets the min revertible counter before calling the app function.
|
|
381
|
+
// Since TXE bypasses the account contract, we simulate this by setting minRevertibleSideEffectCounter to 1,
|
|
382
|
+
// marking all side effects as revertible.
|
|
383
|
+
const minRevertibleSideEffectCounter = 1;
|
|
384
|
+
await noteCache.setMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter);
|
|
311
385
|
const taggingIndexCache = new ExecutionTaggingIndexCache();
|
|
312
386
|
|
|
313
387
|
const simulator = new WASMSimulator();
|
|
314
388
|
|
|
315
|
-
const privateExecutionOracle = new PrivateExecutionOracle(
|
|
389
|
+
const privateExecutionOracle = new PrivateExecutionOracle({
|
|
316
390
|
argsHash,
|
|
317
391
|
txContext,
|
|
318
392
|
callContext,
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
[],
|
|
325
|
-
HashedValuesCache.create([new HashedValues(args, argsHash)]),
|
|
393
|
+
anchorBlockHeader: blockHeader,
|
|
394
|
+
utilityExecutor,
|
|
395
|
+
authWitnesses: Array.from(this.authwits.values()),
|
|
396
|
+
capsules: [],
|
|
397
|
+
executionCache: HashedValuesCache.create([new HashedValues(args, argsHash)]),
|
|
326
398
|
noteCache,
|
|
327
399
|
taggingIndexCache,
|
|
328
|
-
this.
|
|
329
|
-
this.
|
|
330
|
-
this.keyStore,
|
|
331
|
-
this.
|
|
332
|
-
this.stateMachine.node,
|
|
333
|
-
this.
|
|
334
|
-
this.
|
|
335
|
-
this.
|
|
336
|
-
this.
|
|
337
|
-
this.
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
from,
|
|
400
|
+
contractStore: this.contractStore,
|
|
401
|
+
noteStore: this.noteStore,
|
|
402
|
+
keyStore: this.keyStore,
|
|
403
|
+
addressStore: this.addressStore,
|
|
404
|
+
aztecNode: this.stateMachine.node,
|
|
405
|
+
senderTaggingStore: this.senderTaggingStore,
|
|
406
|
+
recipientTaggingStore: this.recipientTaggingStore,
|
|
407
|
+
senderAddressBookStore: this.senderAddressBookStore,
|
|
408
|
+
capsuleService: new CapsuleService(this.capsuleStore, scopes),
|
|
409
|
+
privateEventStore: this.privateEventStore,
|
|
410
|
+
contractSyncService: this.stateMachine.contractSyncService,
|
|
411
|
+
jobId,
|
|
412
|
+
totalPublicCalldataCount: 0,
|
|
413
|
+
sideEffectCounter: minRevertibleSideEffectCounter,
|
|
414
|
+
scopes,
|
|
415
|
+
// In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
|
|
416
|
+
// contract would perform, including setting senderForTags.
|
|
417
|
+
senderForTags: from,
|
|
347
418
|
simulator,
|
|
348
|
-
|
|
419
|
+
messageContextService: this.stateMachine.messageContextService,
|
|
420
|
+
l2TipsStore: this.stateMachine.l2TipsProvider,
|
|
421
|
+
hooks: composeHooks({
|
|
422
|
+
authorizeUtilityCall: this.buildAuthorizeUtilityCallHook(
|
|
423
|
+
isStaticCall ? 'private view' : 'private',
|
|
424
|
+
authorizedUtilityCallTargets,
|
|
425
|
+
),
|
|
426
|
+
}),
|
|
427
|
+
});
|
|
349
428
|
|
|
350
429
|
// Note: This is a slight modification of simulator.run without any of the checks. Maybe we should modify simulator.run with a boolean value to skip checks.
|
|
351
430
|
let result: PrivateExecutionResult;
|
|
@@ -367,24 +446,27 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
367
446
|
);
|
|
368
447
|
const publicFunctionsCalldata = await Promise.all(
|
|
369
448
|
publicCallRequests.map(async r => {
|
|
370
|
-
const calldata = await privateExecutionOracle.
|
|
449
|
+
const calldata = await privateExecutionOracle.getHashPreimage(r.calldataHash);
|
|
371
450
|
return new HashedValues(calldata, r.calldataHash);
|
|
372
451
|
}),
|
|
373
452
|
);
|
|
374
453
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
result = new PrivateExecutionResult(executionResult, Fr.ZERO, publicFunctionsCalldata);
|
|
454
|
+
noteCache.finish();
|
|
455
|
+
const nonceGenerator = noteCache.getNonceGenerator();
|
|
456
|
+
result = new PrivateExecutionResult(executionResult, nonceGenerator, publicFunctionsCalldata);
|
|
379
457
|
} catch (err) {
|
|
380
458
|
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during private execution'));
|
|
381
459
|
}
|
|
382
460
|
|
|
383
|
-
// According to the protocol rules,
|
|
384
|
-
//
|
|
385
|
-
//
|
|
386
|
-
const
|
|
387
|
-
|
|
461
|
+
// According to the protocol rules, there must be at least one nullifier in the tx. The first nullifier is used as
|
|
462
|
+
// the nonce generator for the note hashes.
|
|
463
|
+
// We pass the non-zero minRevertibleSideEffectCounter to make sure the side effects are split correctly.
|
|
464
|
+
const { publicInputs } = await generateSimulatedProvingResult(
|
|
465
|
+
result,
|
|
466
|
+
(addr, sel) => this.contractStore.getDebugFunctionName(addr, sel),
|
|
467
|
+
this.stateMachine.node,
|
|
468
|
+
minRevertibleSideEffectCounter,
|
|
469
|
+
);
|
|
388
470
|
|
|
389
471
|
const globals = makeGlobalVariables();
|
|
390
472
|
globals.blockNumber = blockNumber;
|
|
@@ -395,7 +477,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
395
477
|
|
|
396
478
|
const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
|
|
397
479
|
|
|
398
|
-
const
|
|
480
|
+
const bindings = this.logger.getBindings();
|
|
481
|
+
const contractsDB = new PublicContractsDB(
|
|
482
|
+
new TXEPublicContractDataSource(blockNumber, this.contractStore),
|
|
483
|
+
bindings,
|
|
484
|
+
);
|
|
399
485
|
const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
|
|
400
486
|
const config = PublicSimulatorConfig.from({
|
|
401
487
|
skipFeeEnforcement: true,
|
|
@@ -408,8 +494,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
408
494
|
globals,
|
|
409
495
|
guardedMerkleTrees,
|
|
410
496
|
contractsDB,
|
|
411
|
-
new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config),
|
|
497
|
+
new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings),
|
|
412
498
|
new TestDateProvider(),
|
|
499
|
+
undefined,
|
|
500
|
+
createLogger('simulator:public-processor', bindings),
|
|
413
501
|
);
|
|
414
502
|
|
|
415
503
|
const tx = await Tx.create({
|
|
@@ -434,7 +522,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
434
522
|
} else if (!processedTx.revertCode.isOK()) {
|
|
435
523
|
if (processedTx.revertReason) {
|
|
436
524
|
try {
|
|
437
|
-
await enrichPublicSimulationError(processedTx.revertReason, this.
|
|
525
|
+
await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.logger);
|
|
438
526
|
// eslint-disable-next-line no-empty
|
|
439
527
|
} catch {}
|
|
440
528
|
throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
|
|
@@ -443,11 +531,17 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
443
531
|
}
|
|
444
532
|
}
|
|
445
533
|
|
|
534
|
+
// Walk the nested private-call tree and collect every offchain effect the transaction emitted.
|
|
535
|
+
// PXE stores these on each `PrivateCallExecutionResult` and they never reach TXE via the
|
|
536
|
+
// `aztec_utl_emitOffchainEffect` foreign-call path (that path only fires at the top-level), so
|
|
537
|
+
// we pull them out here and the RPC wrapper will hand them to `TXESession` for buffering.
|
|
538
|
+
const offchainEffects = collectNested([executionResult], r => r.offchainEffects.map(e => e.data));
|
|
539
|
+
|
|
446
540
|
if (isStaticCall) {
|
|
447
541
|
await checkpoint!.revert();
|
|
448
542
|
|
|
449
543
|
await forkedWorldTrees.close();
|
|
450
|
-
return executionResult.returnValues ?? [];
|
|
544
|
+
return { returnValues: executionResult.returnValues ?? [], offchainEffects };
|
|
451
545
|
}
|
|
452
546
|
|
|
453
547
|
const txEffect = TxEffect.empty();
|
|
@@ -469,30 +563,25 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
469
563
|
|
|
470
564
|
await forkedWorldTrees.close();
|
|
471
565
|
|
|
472
|
-
return executionResult.returnValues ?? [];
|
|
566
|
+
return { returnValues: executionResult.returnValues ?? [], offchainEffects };
|
|
473
567
|
}
|
|
474
568
|
|
|
475
|
-
async
|
|
476
|
-
from: AztecAddress,
|
|
569
|
+
async publicCallNewFlow(
|
|
570
|
+
from: AztecAddress | undefined,
|
|
477
571
|
targetContractAddress: AztecAddress,
|
|
478
572
|
calldata: Fr[],
|
|
479
573
|
isStaticCall: boolean,
|
|
574
|
+
gasSettings: GasSettings,
|
|
480
575
|
) {
|
|
481
576
|
this.logger.verbose(
|
|
482
|
-
`Executing public function ${await this.
|
|
577
|
+
`Executing public function ${await this.contractStore.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`,
|
|
483
578
|
);
|
|
484
579
|
|
|
485
|
-
const blockNumber = await this.
|
|
486
|
-
|
|
487
|
-
const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
|
|
488
|
-
|
|
489
|
-
const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
|
|
490
|
-
|
|
491
|
-
const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
|
|
580
|
+
const blockNumber = await this.getNextBlockNumber();
|
|
492
581
|
|
|
493
582
|
const txContext = new TxContext(this.chainId, this.version, gasSettings);
|
|
494
583
|
|
|
495
|
-
const anchorBlockHeader = await this.stateMachine.
|
|
584
|
+
const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
496
585
|
|
|
497
586
|
const calldataHash = await computeCalldataHash(calldata);
|
|
498
587
|
const calldataHashedValues = new HashedValues(calldata, calldataHash);
|
|
@@ -506,7 +595,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
506
595
|
|
|
507
596
|
const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
|
|
508
597
|
|
|
509
|
-
const
|
|
598
|
+
const bindings2 = this.logger.getBindings();
|
|
599
|
+
const contractsDB = new PublicContractsDB(
|
|
600
|
+
new TXEPublicContractDataSource(blockNumber, this.contractStore),
|
|
601
|
+
bindings2,
|
|
602
|
+
);
|
|
510
603
|
const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
|
|
511
604
|
const config = PublicSimulatorConfig.from({
|
|
512
605
|
skipFeeEnforcement: true,
|
|
@@ -515,8 +608,16 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
515
608
|
collectStatistics: false,
|
|
516
609
|
collectCallMetadata: true,
|
|
517
610
|
});
|
|
518
|
-
const simulator = new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config);
|
|
519
|
-
const processor = new PublicProcessor(
|
|
611
|
+
const simulator = new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings2);
|
|
612
|
+
const processor = new PublicProcessor(
|
|
613
|
+
globals,
|
|
614
|
+
guardedMerkleTrees,
|
|
615
|
+
contractsDB,
|
|
616
|
+
simulator,
|
|
617
|
+
new TestDateProvider(),
|
|
618
|
+
undefined,
|
|
619
|
+
createLogger('simulator:public-processor', bindings2),
|
|
620
|
+
);
|
|
520
621
|
|
|
521
622
|
// We're simulating a scenario in which private execution immediately enqueues a public call and halts. The private
|
|
522
623
|
// kernel init would in this case inject a nullifier with the transaction request hash as a non-revertible
|
|
@@ -529,7 +630,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
529
630
|
// may require producing reverts.
|
|
530
631
|
const revertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
|
|
531
632
|
revertibleAccumulatedData.publicCallRequests[0] = new PublicCallRequest(
|
|
532
|
-
from,
|
|
633
|
+
from ?? AztecAddress.NULL_MSG_SENDER,
|
|
533
634
|
targetContractAddress,
|
|
534
635
|
isStaticCall,
|
|
535
636
|
calldataHash,
|
|
@@ -547,7 +648,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
547
648
|
constantData,
|
|
548
649
|
/*gasUsed=*/ new Gas(0, 0),
|
|
549
650
|
/*feePayer=*/ AztecAddress.zero(),
|
|
550
|
-
/*
|
|
651
|
+
/*expirationTimestamp=*/ 0n,
|
|
551
652
|
inputsForPublic,
|
|
552
653
|
undefined,
|
|
553
654
|
);
|
|
@@ -574,7 +675,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
574
675
|
} else if (!processedTx.revertCode.isOK()) {
|
|
575
676
|
if (processedTx.revertReason) {
|
|
576
677
|
try {
|
|
577
|
-
await enrichPublicSimulationError(processedTx.revertReason, this.
|
|
678
|
+
await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.logger);
|
|
578
679
|
// eslint-disable-next-line no-empty
|
|
579
680
|
} catch {}
|
|
580
681
|
throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
|
|
@@ -615,26 +716,52 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
615
716
|
return returnValues ?? [];
|
|
616
717
|
}
|
|
617
718
|
|
|
618
|
-
async
|
|
719
|
+
async executeUtilityFunction(
|
|
619
720
|
targetContractAddress: AztecAddress,
|
|
620
721
|
functionSelector: FunctionSelector,
|
|
621
722
|
args: Fr[],
|
|
723
|
+
jobId: string,
|
|
724
|
+
authorizedUtilityCallTargets: AztecAddress[],
|
|
622
725
|
) {
|
|
623
|
-
const artifact = await this.
|
|
726
|
+
const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
624
727
|
if (!artifact) {
|
|
625
728
|
throw new Error(`Cannot call ${functionSelector} as there is no artifact found at ${targetContractAddress}.`);
|
|
626
729
|
}
|
|
627
730
|
|
|
628
|
-
|
|
731
|
+
// Sync notes before executing utility function to discover notes from previous transactions
|
|
732
|
+
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
733
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(
|
|
734
|
+
targetContractAddress,
|
|
735
|
+
functionSelector,
|
|
736
|
+
async (call, execScopes) => {
|
|
737
|
+
await this.executeUtilityCall(call, execScopes, jobId);
|
|
738
|
+
},
|
|
739
|
+
blockHeader,
|
|
740
|
+
jobId,
|
|
741
|
+
await this.keyStore.getAccounts(),
|
|
742
|
+
);
|
|
743
|
+
|
|
744
|
+
const call = FunctionCall.from({
|
|
629
745
|
name: artifact.name,
|
|
630
|
-
selector: functionSelector,
|
|
631
746
|
to: targetContractAddress,
|
|
632
|
-
|
|
747
|
+
selector: functionSelector,
|
|
748
|
+
type: FunctionType.UTILITY,
|
|
749
|
+
hideMsgSender: false,
|
|
750
|
+
isStatic: false,
|
|
751
|
+
args,
|
|
752
|
+
returnTypes: [],
|
|
753
|
+
});
|
|
633
754
|
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
755
|
+
return this.executeUtilityCall(call, await this.keyStore.getAccounts(), jobId, authorizedUtilityCallTargets);
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
private async executeUtilityCall(
|
|
759
|
+
call: FunctionCall,
|
|
760
|
+
scopes: AztecAddress[],
|
|
761
|
+
jobId: string,
|
|
762
|
+
authorizedUtilityCallTargets: AztecAddress[] = [],
|
|
763
|
+
): Promise<Fr[]> {
|
|
764
|
+
const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
|
|
638
765
|
if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
|
|
639
766
|
throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
|
|
640
767
|
}
|
|
@@ -645,25 +772,38 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
645
772
|
});
|
|
646
773
|
|
|
647
774
|
try {
|
|
648
|
-
const anchorBlockHeader = await this.stateMachine.
|
|
649
|
-
const
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
775
|
+
const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
776
|
+
const simulator = new WASMSimulator();
|
|
777
|
+
const utilityExecutor = async (syncCall: FunctionCall, execScopes: AztecAddress[]) => {
|
|
778
|
+
await this.executeUtilityCall(syncCall, execScopes, jobId);
|
|
779
|
+
};
|
|
780
|
+
const oracle = new UtilityExecutionOracle({
|
|
781
|
+
contractAddress: call.to,
|
|
782
|
+
authWitnesses: [],
|
|
783
|
+
capsules: [],
|
|
653
784
|
anchorBlockHeader,
|
|
654
|
-
this.
|
|
655
|
-
this.
|
|
656
|
-
this.keyStore,
|
|
657
|
-
this.
|
|
658
|
-
this.stateMachine.node,
|
|
659
|
-
this.
|
|
660
|
-
this.
|
|
661
|
-
this.
|
|
662
|
-
this.
|
|
663
|
-
this.
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
785
|
+
contractStore: this.contractStore,
|
|
786
|
+
noteStore: this.noteStore,
|
|
787
|
+
keyStore: this.keyStore,
|
|
788
|
+
addressStore: this.addressStore,
|
|
789
|
+
aztecNode: this.stateMachine.node,
|
|
790
|
+
recipientTaggingStore: this.recipientTaggingStore,
|
|
791
|
+
senderAddressBookStore: this.senderAddressBookStore,
|
|
792
|
+
capsuleService: new CapsuleService(this.capsuleStore, scopes),
|
|
793
|
+
privateEventStore: this.privateEventStore,
|
|
794
|
+
messageContextService: this.stateMachine.messageContextService,
|
|
795
|
+
contractSyncService: this.stateMachine.contractSyncService,
|
|
796
|
+
l2TipsStore: this.stateMachine.l2TipsProvider,
|
|
797
|
+
jobId,
|
|
798
|
+
scopes,
|
|
799
|
+
simulator,
|
|
800
|
+
hooks: composeHooks({
|
|
801
|
+
authorizeUtilityCall: this.buildAuthorizeUtilityCallHook('utility', authorizedUtilityCallTargets),
|
|
802
|
+
}),
|
|
803
|
+
utilityExecutor,
|
|
804
|
+
});
|
|
805
|
+
const acirExecutionResult = await simulator
|
|
806
|
+
.executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
|
|
667
807
|
.catch((err: Error) => {
|
|
668
808
|
err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
|
|
669
809
|
throw new ExecutionError(
|
|
@@ -677,10 +817,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
677
817
|
);
|
|
678
818
|
});
|
|
679
819
|
|
|
680
|
-
this.logger.verbose(`Utility
|
|
820
|
+
this.logger.verbose(`Utility execution for ${call.to}.${call.selector} completed`);
|
|
681
821
|
return witnessMapToFields(acirExecutionResult.returnWitness);
|
|
682
822
|
} catch (err) {
|
|
683
|
-
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility
|
|
823
|
+
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility execution'));
|
|
684
824
|
}
|
|
685
825
|
}
|
|
686
826
|
|
|
@@ -690,7 +830,20 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
690
830
|
}
|
|
691
831
|
|
|
692
832
|
private async getLastBlockNumber(): Promise<BlockNumber> {
|
|
693
|
-
const
|
|
694
|
-
return
|
|
833
|
+
const block = await this.stateMachine.node.getBlock('latest');
|
|
834
|
+
return block ? block.header.globalVariables.blockNumber : BlockNumber.ZERO;
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
private buildAuthorizeUtilityCallHook(
|
|
838
|
+
callerContext: 'private' | 'private view' | 'utility',
|
|
839
|
+
authorizedTargets: AztecAddress[],
|
|
840
|
+
): ExecutionHooks['authorizeUtilityCall'] | undefined {
|
|
841
|
+
if (authorizedTargets.length === 0) {
|
|
842
|
+
return undefined;
|
|
843
|
+
}
|
|
844
|
+
return req =>
|
|
845
|
+
Promise.resolve({
|
|
846
|
+
authorized: req.callerContext === callerContext && authorizedTargets.some(t => t.equals(req.target)),
|
|
847
|
+
});
|
|
695
848
|
}
|
|
696
849
|
}
|