@aztec/txe 0.0.1-commit.6d3c34e → 0.0.1-commit.7035c9bd6
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/constants.d.ts +1 -2
- package/dest/constants.d.ts.map +1 -1
- package/dest/constants.js +0 -1
- package/dest/index.d.ts +1 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +88 -54
- package/dest/oracle/interfaces.d.ts +29 -28
- package/dest/oracle/interfaces.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_public_context.d.ts +13 -13
- package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_public_context.js +16 -16
- package/dest/oracle/txe_oracle_top_level_context.d.ts +23 -22
- package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_top_level_context.js +144 -62
- package/dest/rpc_translator.d.ts +92 -81
- package/dest/rpc_translator.d.ts.map +1 -1
- package/dest/rpc_translator.js +323 -176
- package/dest/state_machine/archiver.d.ts +20 -69
- package/dest/state_machine/archiver.d.ts.map +1 -1
- package/dest/state_machine/archiver.js +34 -178
- package/dest/state_machine/dummy_p2p_client.d.ts +16 -12
- package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
- package/dest/state_machine/dummy_p2p_client.js +28 -16
- package/dest/state_machine/index.d.ts +7 -5
- package/dest/state_machine/index.d.ts.map +1 -1
- package/dest/state_machine/index.js +39 -12
- package/dest/state_machine/mock_epoch_cache.d.ts +24 -8
- package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
- package/dest/state_machine/mock_epoch_cache.js +43 -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 +3 -3
- package/dest/txe_session.d.ts +12 -6
- package/dest/txe_session.d.ts.map +1 -1
- package/dest/txe_session.js +112 -28
- package/dest/util/encoding.d.ts +17 -17
- package/dest/util/txe_public_contract_data_source.d.ts +2 -3
- package/dest/util/txe_public_contract_data_source.d.ts.map +1 -1
- package/dest/util/txe_public_contract_data_source.js +5 -22
- 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 -4
- 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/package.json +16 -16
- package/src/constants.ts +0 -1
- package/src/index.ts +89 -52
- package/src/oracle/interfaces.ts +32 -31
- package/src/oracle/txe_oracle_public_context.ts +16 -18
- package/src/oracle/txe_oracle_top_level_context.ts +178 -111
- package/src/rpc_translator.ts +360 -202
- package/src/state_machine/archiver.ts +37 -234
- package/src/state_machine/dummy_p2p_client.ts +40 -22
- package/src/state_machine/index.ts +53 -11
- package/src/state_machine/mock_epoch_cache.ts +53 -14
- package/src/state_machine/synchronizer.ts +5 -5
- package/src/txe_session.ts +129 -88
- package/src/util/txe_public_contract_data_source.ts +10 -36
- package/src/utils/block_creation.ts +19 -16
- package/src/utils/tx_effect_creation.ts +3 -11
- package/dest/util/txe_contract_store.d.ts +0 -12
- package/dest/util/txe_contract_store.d.ts.map +0 -1
- package/dest/util/txe_contract_store.js +0 -22
- package/src/util/txe_contract_store.ts +0 -36
|
@@ -21,7 +21,7 @@ import { makeGlobalVariables } from '@aztec/stdlib/testing';
|
|
|
21
21
|
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
22
22
|
import { CallContext, HashedValues, PrivateExecutionResult, Tx, TxConstantData, TxContext, TxEffect, TxHash, collectNested } from '@aztec/stdlib/tx';
|
|
23
23
|
import { ForkCheckpoint } from '@aztec/world-state';
|
|
24
|
-
import { DEFAULT_ADDRESS
|
|
24
|
+
import { DEFAULT_ADDRESS } from '../constants.js';
|
|
25
25
|
import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_source.js';
|
|
26
26
|
import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from '../utils/block_creation.js';
|
|
27
27
|
export class TXEOracleTopLevelContext {
|
|
@@ -40,10 +40,11 @@ export class TXEOracleTopLevelContext {
|
|
|
40
40
|
version;
|
|
41
41
|
chainId;
|
|
42
42
|
authwits;
|
|
43
|
+
contractSyncService;
|
|
43
44
|
isMisc;
|
|
44
45
|
isTxe;
|
|
45
46
|
logger;
|
|
46
|
-
constructor(stateMachine, contractStore, noteStore, keyStore, addressStore, accountStore, senderTaggingStore, recipientTaggingStore, senderAddressBookStore, capsuleStore, privateEventStore, nextBlockTimestamp, version, chainId, authwits){
|
|
47
|
+
constructor(stateMachine, contractStore, noteStore, keyStore, addressStore, accountStore, senderTaggingStore, recipientTaggingStore, senderAddressBookStore, capsuleStore, privateEventStore, nextBlockTimestamp, version, chainId, authwits, contractSyncService){
|
|
47
48
|
this.stateMachine = stateMachine;
|
|
48
49
|
this.contractStore = contractStore;
|
|
49
50
|
this.noteStore = noteStore;
|
|
@@ -59,45 +60,48 @@ export class TXEOracleTopLevelContext {
|
|
|
59
60
|
this.version = version;
|
|
60
61
|
this.chainId = chainId;
|
|
61
62
|
this.authwits = authwits;
|
|
63
|
+
this.contractSyncService = contractSyncService;
|
|
62
64
|
this.isMisc = true;
|
|
63
65
|
this.isTxe = true;
|
|
64
66
|
this.logger = createLogger('txe:top_level_context');
|
|
65
67
|
this.logger.debug('Entering Top Level Context');
|
|
66
68
|
}
|
|
67
|
-
|
|
69
|
+
assertCompatibleOracleVersion(version) {
|
|
68
70
|
if (version !== ORACLE_VERSION) {
|
|
69
71
|
throw new Error(`Incompatible oracle version. TXE is using version '${ORACLE_VERSION}', but got a request for '${version}'.`);
|
|
70
72
|
}
|
|
71
73
|
}
|
|
72
74
|
// This is typically only invoked in private contexts, but it is convenient to also have it in top-level for testing
|
|
73
75
|
// setup.
|
|
74
|
-
|
|
76
|
+
getRandomField() {
|
|
75
77
|
return Fr.random();
|
|
76
78
|
}
|
|
77
79
|
// We instruct users to debug contracts via this oracle, so it makes sense that they'd expect it to also work in tests
|
|
78
|
-
|
|
80
|
+
log(level, message, fields) {
|
|
79
81
|
if (!LogLevels[level]) {
|
|
80
|
-
throw new Error(`Invalid
|
|
82
|
+
throw new Error(`Invalid log level: ${level}`);
|
|
81
83
|
}
|
|
82
84
|
const levelName = LogLevels[level];
|
|
83
85
|
this.logger[levelName](`${applyStringFormatting(message, fields)}`, {
|
|
84
86
|
module: `${this.logger.module}:debug_log`
|
|
85
87
|
});
|
|
88
|
+
return Promise.resolve();
|
|
86
89
|
}
|
|
87
|
-
|
|
90
|
+
getDefaultAddress() {
|
|
88
91
|
return DEFAULT_ADDRESS;
|
|
89
92
|
}
|
|
90
|
-
async
|
|
93
|
+
async getNextBlockNumber() {
|
|
91
94
|
return BlockNumber(await this.getLastBlockNumber() + 1);
|
|
92
95
|
}
|
|
93
|
-
|
|
96
|
+
getNextBlockTimestamp() {
|
|
94
97
|
return Promise.resolve(this.nextBlockTimestamp);
|
|
95
98
|
}
|
|
96
|
-
async
|
|
99
|
+
async getLastBlockTimestamp() {
|
|
97
100
|
return (await this.stateMachine.node.getBlockHeader('latest')).globalVariables.timestamp;
|
|
98
101
|
}
|
|
99
|
-
async
|
|
100
|
-
const
|
|
102
|
+
async getLastTxEffects() {
|
|
103
|
+
const latestBlockNumber = await this.stateMachine.archiver.getBlockNumber();
|
|
104
|
+
const block = await this.stateMachine.archiver.getBlock(latestBlockNumber);
|
|
101
105
|
if (block.body.txEffects.length != 1) {
|
|
102
106
|
// Note that calls like env.mine() will result in blocks with no transactions, hitting this
|
|
103
107
|
throw new Error(`Expected a single transaction in the last block, found ${block.body.txEffects.length}`);
|
|
@@ -109,7 +113,19 @@ export class TXEOracleTopLevelContext {
|
|
|
109
113
|
nullifiers: txEffects.nullifiers
|
|
110
114
|
};
|
|
111
115
|
}
|
|
112
|
-
async
|
|
116
|
+
async syncContractNonOracleMethod(contractAddress, scope, jobId) {
|
|
117
|
+
if (contractAddress.equals(DEFAULT_ADDRESS)) {
|
|
118
|
+
this.logger.debug(`Skipping sync in getPrivateEvents because the events correspond to the default address.`);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
122
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(contractAddress, null, async (call, execScopes)=>{
|
|
123
|
+
await this.executeUtilityCall(call, execScopes, jobId);
|
|
124
|
+
}, blockHeader, jobId, [
|
|
125
|
+
scope
|
|
126
|
+
]);
|
|
127
|
+
}
|
|
128
|
+
async getPrivateEvents(selector, contractAddress, scope) {
|
|
113
129
|
return (await this.privateEventStore.getPrivateEvents(selector, {
|
|
114
130
|
contractAddress,
|
|
115
131
|
scopes: [
|
|
@@ -119,17 +135,17 @@ export class TXEOracleTopLevelContext {
|
|
|
119
135
|
toBlock: await this.getLastBlockNumber() + 1
|
|
120
136
|
})).map((e)=>e.packedEvent);
|
|
121
137
|
}
|
|
122
|
-
async
|
|
138
|
+
async advanceBlocksBy(blocks) {
|
|
123
139
|
this.logger.debug(`time traveling ${blocks} blocks`);
|
|
124
140
|
for(let i = 0; i < blocks; i++){
|
|
125
141
|
await this.mineBlock();
|
|
126
142
|
}
|
|
127
143
|
}
|
|
128
|
-
|
|
144
|
+
advanceTimestampBy(duration) {
|
|
129
145
|
this.logger.debug(`time traveling ${duration} seconds`);
|
|
130
146
|
this.nextBlockTimestamp += duration;
|
|
131
147
|
}
|
|
132
|
-
async
|
|
148
|
+
async deploy(artifact, instance, secret) {
|
|
133
149
|
// Emit deployment nullifier
|
|
134
150
|
await this.mineBlock({
|
|
135
151
|
nullifiers: [
|
|
@@ -137,25 +153,25 @@ export class TXEOracleTopLevelContext {
|
|
|
137
153
|
]
|
|
138
154
|
});
|
|
139
155
|
if (!secret.equals(Fr.ZERO)) {
|
|
140
|
-
await this.
|
|
156
|
+
await this.addAccount(artifact, instance, secret);
|
|
141
157
|
} else {
|
|
142
158
|
await this.contractStore.addContractInstance(instance);
|
|
143
|
-
await this.contractStore.addContractArtifact(
|
|
159
|
+
await this.contractStore.addContractArtifact(artifact);
|
|
144
160
|
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
145
161
|
}
|
|
146
162
|
}
|
|
147
|
-
async
|
|
163
|
+
async addAccount(artifact, instance, secret) {
|
|
148
164
|
const partialAddress = await computePartialAddress(instance);
|
|
149
165
|
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
150
166
|
await this.contractStore.addContractInstance(instance);
|
|
151
|
-
await this.contractStore.addContractArtifact(
|
|
167
|
+
await this.contractStore.addContractArtifact(artifact);
|
|
152
168
|
const completeAddress = await this.keyStore.addAccount(secret, partialAddress);
|
|
153
169
|
await this.accountStore.setAccount(completeAddress.address, completeAddress);
|
|
154
170
|
await this.addressStore.addCompleteAddress(completeAddress);
|
|
155
171
|
this.logger.debug(`Created account ${completeAddress.address}`);
|
|
156
172
|
return completeAddress;
|
|
157
173
|
}
|
|
158
|
-
async
|
|
174
|
+
async createAccount(secret) {
|
|
159
175
|
// This is a foot gun !
|
|
160
176
|
const completeAddress = await this.keyStore.addAccount(secret, secret);
|
|
161
177
|
await this.accountStore.setAccount(completeAddress.address, completeAddress);
|
|
@@ -163,7 +179,7 @@ export class TXEOracleTopLevelContext {
|
|
|
163
179
|
this.logger.debug(`Created account ${completeAddress.address}`);
|
|
164
180
|
return completeAddress;
|
|
165
181
|
}
|
|
166
|
-
async
|
|
182
|
+
async addAuthWitness(address, messageHash) {
|
|
167
183
|
const account = await this.accountStore.getAccount(address);
|
|
168
184
|
const privateKey = await this.keyStore.getMasterSecretKey(account.publicKeys.masterIncomingViewingPublicKey);
|
|
169
185
|
const schnorr = new Schnorr();
|
|
@@ -174,7 +190,7 @@ export class TXEOracleTopLevelContext {
|
|
|
174
190
|
this.authwits.set(authWitness.requestHash.toString(), authWitness);
|
|
175
191
|
}
|
|
176
192
|
async mineBlock(options = {}) {
|
|
177
|
-
const blockNumber = await this.
|
|
193
|
+
const blockNumber = await this.getNextBlockNumber();
|
|
178
194
|
const txEffect = TxEffect.empty();
|
|
179
195
|
txEffect.nullifiers = [
|
|
180
196
|
getSingleTxBlockRequestHash(blockNumber),
|
|
@@ -196,35 +212,73 @@ export class TXEOracleTopLevelContext {
|
|
|
196
212
|
this.logger.info(`Created block ${blockNumber} with timestamp ${block.header.globalVariables.timestamp}`);
|
|
197
213
|
await this.stateMachine.handleL2Block(block);
|
|
198
214
|
}
|
|
199
|
-
async
|
|
215
|
+
async privateCallNewFlow(from, targetContractAddress = AztecAddress.zero(), functionSelector = FunctionSelector.empty(), args, argsHash = Fr.zero(), isStaticCall = false, jobId) {
|
|
200
216
|
this.logger.verbose(`Executing external function ${await this.contractStore.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`);
|
|
201
217
|
const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
202
218
|
if (!artifact) {
|
|
203
219
|
const message = functionSelector.equals(await FunctionSelector.fromSignature('verify_private_authwit(Field)')) ? 'Found no account contract artifact for a private authwit check - use `create_contract_account` instead of `create_light_account` for authwit support.' : 'Function Artifact does not exist';
|
|
204
220
|
throw new Error(message);
|
|
205
221
|
}
|
|
222
|
+
// When `from` is the zero address (e.g. when deploying a new account contract), we return an
|
|
223
|
+
// empty scope list which acts as deny-all: no notes are visible and no keys are accessible.
|
|
224
|
+
const effectiveScopes = from.isZero() ? [] : [
|
|
225
|
+
from
|
|
226
|
+
];
|
|
206
227
|
// Sync notes before executing private function to discover notes from previous transactions
|
|
207
|
-
const utilityExecutor = async (call)=>{
|
|
208
|
-
await this.executeUtilityCall(call);
|
|
228
|
+
const utilityExecutor = async (call, execScopes)=>{
|
|
229
|
+
await this.executeUtilityCall(call, execScopes, jobId);
|
|
209
230
|
};
|
|
210
|
-
await this.
|
|
211
|
-
|
|
231
|
+
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
232
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(targetContractAddress, functionSelector, utilityExecutor, blockHeader, jobId, effectiveScopes);
|
|
233
|
+
const blockNumber = await this.getNextBlockNumber();
|
|
212
234
|
const callContext = new CallContext(from, targetContractAddress, functionSelector, isStaticCall);
|
|
213
235
|
const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
|
|
214
236
|
const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
|
|
215
237
|
const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
|
|
216
238
|
const txContext = new TxContext(this.chainId, this.version, gasSettings);
|
|
217
|
-
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
218
239
|
const protocolNullifier = await computeProtocolNullifier(getSingleTxBlockRequestHash(blockNumber));
|
|
219
240
|
const noteCache = new ExecutionNoteCache(protocolNullifier);
|
|
241
|
+
// In production, the account contract sets the min revertible counter before calling the app function.
|
|
242
|
+
// Since TXE bypasses the account contract, we simulate this by setting minRevertibleSideEffectCounter to 1,
|
|
243
|
+
// marking all side effects as revertible.
|
|
244
|
+
const minRevertibleSideEffectCounter = 1;
|
|
245
|
+
await noteCache.setMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter);
|
|
220
246
|
const taggingIndexCache = new ExecutionTaggingIndexCache();
|
|
221
247
|
const simulator = new WASMSimulator();
|
|
222
|
-
const privateExecutionOracle = new PrivateExecutionOracle(
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
248
|
+
const privateExecutionOracle = new PrivateExecutionOracle({
|
|
249
|
+
argsHash,
|
|
250
|
+
txContext,
|
|
251
|
+
callContext,
|
|
252
|
+
anchorBlockHeader: blockHeader,
|
|
253
|
+
utilityExecutor,
|
|
254
|
+
authWitnesses: Array.from(this.authwits.values()),
|
|
255
|
+
capsules: [],
|
|
256
|
+
executionCache: HashedValuesCache.create([
|
|
257
|
+
new HashedValues(args, argsHash)
|
|
258
|
+
]),
|
|
259
|
+
noteCache,
|
|
260
|
+
taggingIndexCache,
|
|
261
|
+
contractStore: this.contractStore,
|
|
262
|
+
noteStore: this.noteStore,
|
|
263
|
+
keyStore: this.keyStore,
|
|
264
|
+
addressStore: this.addressStore,
|
|
265
|
+
aztecNode: this.stateMachine.node,
|
|
266
|
+
senderTaggingStore: this.senderTaggingStore,
|
|
267
|
+
recipientTaggingStore: this.recipientTaggingStore,
|
|
268
|
+
senderAddressBookStore: this.senderAddressBookStore,
|
|
269
|
+
capsuleStore: this.capsuleStore,
|
|
270
|
+
privateEventStore: this.privateEventStore,
|
|
271
|
+
contractSyncService: this.stateMachine.contractSyncService,
|
|
272
|
+
jobId,
|
|
273
|
+
totalPublicCalldataCount: 0,
|
|
274
|
+
sideEffectCounter: minRevertibleSideEffectCounter,
|
|
275
|
+
scopes: effectiveScopes,
|
|
276
|
+
// In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
|
|
277
|
+
// contract would perform, including setting senderForTags.
|
|
278
|
+
senderForTags: from,
|
|
279
|
+
simulator,
|
|
280
|
+
messageContextService: this.stateMachine.messageContextService
|
|
281
|
+
});
|
|
228
282
|
// 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.
|
|
229
283
|
let result;
|
|
230
284
|
let executionResult;
|
|
@@ -236,21 +290,19 @@ export class TXEOracleTopLevelContext {
|
|
|
236
290
|
r.publicInputs.publicTeardownCallRequest
|
|
237
291
|
]));
|
|
238
292
|
const publicFunctionsCalldata = await Promise.all(publicCallRequests.map(async (r)=>{
|
|
239
|
-
const calldata = await privateExecutionOracle.
|
|
293
|
+
const calldata = await privateExecutionOracle.loadFromExecutionCache(r.calldataHash);
|
|
240
294
|
return new HashedValues(calldata, r.calldataHash);
|
|
241
295
|
}));
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
result = new PrivateExecutionResult(executionResult, Fr.ZERO, publicFunctionsCalldata);
|
|
296
|
+
noteCache.finish();
|
|
297
|
+
const nonceGenerator = noteCache.getNonceGenerator();
|
|
298
|
+
result = new PrivateExecutionResult(executionResult, nonceGenerator, publicFunctionsCalldata);
|
|
246
299
|
} catch (err) {
|
|
247
300
|
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during private execution'));
|
|
248
301
|
}
|
|
249
|
-
// According to the protocol rules,
|
|
250
|
-
//
|
|
251
|
-
//
|
|
252
|
-
const
|
|
253
|
-
const { publicInputs } = await generateSimulatedProvingResult(result, nonceGenerator, this.contractStore);
|
|
302
|
+
// According to the protocol rules, there must be at least one nullifier in the tx. The first nullifier is used as
|
|
303
|
+
// the nonce generator for the note hashes.
|
|
304
|
+
// We pass the non-zero minRevertibleSideEffectCounter to make sure the side effects are split correctly.
|
|
305
|
+
const { publicInputs } = await generateSimulatedProvingResult(result, (addr, sel)=>this.contractStore.getDebugFunctionName(addr, sel), this.stateMachine.node, minRevertibleSideEffectCounter);
|
|
254
306
|
const globals = makeGlobalVariables();
|
|
255
307
|
globals.blockNumber = blockNumber;
|
|
256
308
|
globals.timestamp = this.nextBlockTimestamp;
|
|
@@ -258,7 +310,8 @@ export class TXEOracleTopLevelContext {
|
|
|
258
310
|
globals.version = this.version;
|
|
259
311
|
globals.gasFees = GasFees.empty();
|
|
260
312
|
const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
|
|
261
|
-
const
|
|
313
|
+
const bindings = this.logger.getBindings();
|
|
314
|
+
const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(blockNumber, this.contractStore), bindings);
|
|
262
315
|
const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
|
|
263
316
|
const config = PublicSimulatorConfig.from({
|
|
264
317
|
skipFeeEnforcement: true,
|
|
@@ -267,7 +320,7 @@ export class TXEOracleTopLevelContext {
|
|
|
267
320
|
collectStatistics: false,
|
|
268
321
|
collectCallMetadata: true
|
|
269
322
|
});
|
|
270
|
-
const processor = new PublicProcessor(globals, guardedMerkleTrees, contractsDB, new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config), new TestDateProvider());
|
|
323
|
+
const processor = new PublicProcessor(globals, guardedMerkleTrees, contractsDB, new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings), new TestDateProvider(), undefined, createLogger('simulator:public-processor', bindings));
|
|
271
324
|
const tx = await Tx.create({
|
|
272
325
|
data: publicInputs,
|
|
273
326
|
chonkProof: ChonkProof.empty(),
|
|
@@ -317,9 +370,9 @@ export class TXEOracleTopLevelContext {
|
|
|
317
370
|
await forkedWorldTrees.close();
|
|
318
371
|
return executionResult.returnValues ?? [];
|
|
319
372
|
}
|
|
320
|
-
async
|
|
373
|
+
async publicCallNewFlow(from, targetContractAddress, calldata, isStaticCall) {
|
|
321
374
|
this.logger.verbose(`Executing public function ${await this.contractStore.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`);
|
|
322
|
-
const blockNumber = await this.
|
|
375
|
+
const blockNumber = await this.getNextBlockNumber();
|
|
323
376
|
const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
|
|
324
377
|
const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
|
|
325
378
|
const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
|
|
@@ -334,7 +387,8 @@ export class TXEOracleTopLevelContext {
|
|
|
334
387
|
globals.version = this.version;
|
|
335
388
|
globals.gasFees = GasFees.empty();
|
|
336
389
|
const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
|
|
337
|
-
const
|
|
390
|
+
const bindings2 = this.logger.getBindings();
|
|
391
|
+
const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(blockNumber, this.contractStore), bindings2);
|
|
338
392
|
const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
|
|
339
393
|
const config = PublicSimulatorConfig.from({
|
|
340
394
|
skipFeeEnforcement: true,
|
|
@@ -343,8 +397,8 @@ export class TXEOracleTopLevelContext {
|
|
|
343
397
|
collectStatistics: false,
|
|
344
398
|
collectCallMetadata: true
|
|
345
399
|
});
|
|
346
|
-
const simulator = new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config);
|
|
347
|
-
const processor = new PublicProcessor(globals, guardedMerkleTrees, contractsDB, simulator, new TestDateProvider());
|
|
400
|
+
const simulator = new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings2);
|
|
401
|
+
const processor = new PublicProcessor(globals, guardedMerkleTrees, contractsDB, simulator, new TestDateProvider(), undefined, createLogger('simulator:public-processor', bindings2));
|
|
348
402
|
// We're simulating a scenario in which private execution immediately enqueues a public call and halts. The private
|
|
349
403
|
// kernel init would in this case inject a nullifier with the transaction request hash as a non-revertible
|
|
350
404
|
// side-effect, which the AVM then expects to exist in order to use it as the nonce generator when siloing notes as
|
|
@@ -357,7 +411,7 @@ export class TXEOracleTopLevelContext {
|
|
|
357
411
|
revertibleAccumulatedData.publicCallRequests[0] = new PublicCallRequest(from, targetContractAddress, isStaticCall, calldataHash);
|
|
358
412
|
const inputsForPublic = new PartialPrivateTailPublicInputsForPublic(nonRevertibleAccumulatedData, revertibleAccumulatedData, PublicCallRequest.empty());
|
|
359
413
|
const constantData = new TxConstantData(anchorBlockHeader, txContext, Fr.zero(), Fr.zero());
|
|
360
|
-
const txData = new PrivateKernelTailCircuitPublicInputs(constantData, /*gasUsed=*/ new Gas(0, 0), /*feePayer=*/ AztecAddress.zero(), /*
|
|
414
|
+
const txData = new PrivateKernelTailCircuitPublicInputs(constantData, /*gasUsed=*/ new Gas(0, 0), /*feePayer=*/ AztecAddress.zero(), /*expirationTimestamp=*/ 0n, inputsForPublic, undefined);
|
|
361
415
|
const tx = await Tx.create({
|
|
362
416
|
data: txData,
|
|
363
417
|
chonkProof: ChonkProof.empty(),
|
|
@@ -410,19 +464,29 @@ export class TXEOracleTopLevelContext {
|
|
|
410
464
|
await forkedWorldTrees.close();
|
|
411
465
|
return returnValues ?? [];
|
|
412
466
|
}
|
|
413
|
-
async
|
|
467
|
+
async executeUtilityFunction(targetContractAddress, functionSelector, args, jobId) {
|
|
414
468
|
const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
415
469
|
if (!artifact) {
|
|
416
470
|
throw new Error(`Cannot call ${functionSelector} as there is no artifact found at ${targetContractAddress}.`);
|
|
417
471
|
}
|
|
418
472
|
// Sync notes before executing utility function to discover notes from previous transactions
|
|
419
|
-
await this.
|
|
420
|
-
|
|
473
|
+
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
474
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(targetContractAddress, functionSelector, async (call, execScopes)=>{
|
|
475
|
+
await this.executeUtilityCall(call, execScopes, jobId);
|
|
476
|
+
}, blockHeader, jobId, 'ALL_SCOPES');
|
|
477
|
+
const call = FunctionCall.from({
|
|
478
|
+
name: artifact.name,
|
|
479
|
+
to: targetContractAddress,
|
|
480
|
+
selector: functionSelector,
|
|
481
|
+
type: FunctionType.UTILITY,
|
|
482
|
+
hideMsgSender: false,
|
|
483
|
+
isStatic: false,
|
|
484
|
+
args,
|
|
485
|
+
returnTypes: []
|
|
421
486
|
});
|
|
422
|
-
|
|
423
|
-
return this.executeUtilityCall(call);
|
|
487
|
+
return this.executeUtilityCall(call, 'ALL_SCOPES', jobId);
|
|
424
488
|
}
|
|
425
|
-
async executeUtilityCall(call) {
|
|
489
|
+
async executeUtilityCall(call, scopes, jobId) {
|
|
426
490
|
const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
|
|
427
491
|
if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
|
|
428
492
|
throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
|
|
@@ -433,7 +497,25 @@ export class TXEOracleTopLevelContext {
|
|
|
433
497
|
});
|
|
434
498
|
try {
|
|
435
499
|
const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
436
|
-
const oracle = new UtilityExecutionOracle(
|
|
500
|
+
const oracle = new UtilityExecutionOracle({
|
|
501
|
+
contractAddress: call.to,
|
|
502
|
+
authWitnesses: [],
|
|
503
|
+
capsules: [],
|
|
504
|
+
anchorBlockHeader,
|
|
505
|
+
contractStore: this.contractStore,
|
|
506
|
+
noteStore: this.noteStore,
|
|
507
|
+
keyStore: this.keyStore,
|
|
508
|
+
addressStore: this.addressStore,
|
|
509
|
+
aztecNode: this.stateMachine.node,
|
|
510
|
+
recipientTaggingStore: this.recipientTaggingStore,
|
|
511
|
+
senderAddressBookStore: this.senderAddressBookStore,
|
|
512
|
+
capsuleStore: this.capsuleStore,
|
|
513
|
+
privateEventStore: this.privateEventStore,
|
|
514
|
+
messageContextService: this.stateMachine.messageContextService,
|
|
515
|
+
contractSyncService: this.contractSyncService,
|
|
516
|
+
jobId,
|
|
517
|
+
scopes
|
|
518
|
+
});
|
|
437
519
|
const acirExecutionResult = await new WASMSimulator().executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback()).catch((err)=>{
|
|
438
520
|
err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
|
|
439
521
|
throw new ExecutionError(err.message, {
|
|
@@ -443,10 +525,10 @@ export class TXEOracleTopLevelContext {
|
|
|
443
525
|
cause: err
|
|
444
526
|
});
|
|
445
527
|
});
|
|
446
|
-
this.logger.verbose(`Utility
|
|
528
|
+
this.logger.verbose(`Utility execution for ${call.to}.${call.selector} completed`);
|
|
447
529
|
return witnessMapToFields(acirExecutionResult.returnWitness);
|
|
448
530
|
} catch (err) {
|
|
449
|
-
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility
|
|
531
|
+
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility execution'));
|
|
450
532
|
}
|
|
451
533
|
}
|
|
452
534
|
close() {
|