@aztec/txe 0.0.1-commit.e588bc7e5 → 0.0.1-commit.e5a3663dd
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/oracle/interfaces.d.ts +7 -2
- package/dest/oracle/interfaces.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_top_level_context.d.ts +14 -6
- package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_top_level_context.js +46 -21
- package/dest/rpc_translator.d.ts +44 -3
- package/dest/rpc_translator.d.ts.map +1 -1
- package/dest/rpc_translator.js +207 -26
- package/dest/state_machine/archiver.d.ts +1 -1
- package/dest/state_machine/archiver.d.ts.map +1 -1
- package/dest/state_machine/archiver.js +6 -5
- 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 +9 -3
- package/dest/state_machine/index.d.ts +1 -1
- package/dest/state_machine/index.d.ts.map +1 -1
- package/dest/state_machine/index.js +2 -2
- package/dest/state_machine/mock_epoch_cache.d.ts +2 -1
- package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
- package/dest/state_machine/mock_epoch_cache.js +3 -0
- package/dest/txe_session.d.ts +48 -4
- package/dest/txe_session.d.ts.map +1 -1
- package/dest/txe_session.js +77 -17
- package/dest/util/encoding.d.ts +3 -1
- package/dest/util/encoding.d.ts.map +1 -1
- package/dest/util/encoding.js +4 -0
- package/package.json +15 -15
- package/src/oracle/interfaces.ts +3 -1
- package/src/oracle/txe_oracle_top_level_context.ts +46 -21
- package/src/rpc_translator.ts +254 -37
- package/src/state_machine/archiver.ts +4 -5
- package/src/state_machine/global_variable_builder.ts +13 -4
- package/src/state_machine/index.ts +3 -1
- package/src/state_machine/mock_epoch_cache.ts +4 -0
- package/src/txe_session.ts +130 -12
- package/src/util/encoding.ts +5 -0
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS,
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
DEFAULT_TEARDOWN_DA_GAS_LIMIT,
|
|
6
|
-
DEFAULT_TEARDOWN_L2_GAS_LIMIT,
|
|
3
|
+
MAX_PROCESSABLE_DA_GAS_PER_CHECKPOINT,
|
|
4
|
+
MAX_PROCESSABLE_L2_GAS,
|
|
7
5
|
NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
|
|
8
6
|
} from '@aztec/constants';
|
|
9
7
|
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
@@ -17,9 +15,8 @@ import {
|
|
|
17
15
|
CapsuleService,
|
|
18
16
|
CapsuleStore,
|
|
19
17
|
type ContractStore,
|
|
20
|
-
type ContractSyncService,
|
|
21
18
|
NoteStore,
|
|
22
|
-
|
|
19
|
+
ORACLE_VERSION_MAJOR,
|
|
23
20
|
PrivateEventStore,
|
|
24
21
|
RecipientTaggingStore,
|
|
25
22
|
SenderAddressBookStore,
|
|
@@ -57,7 +54,13 @@ import { AuthWitness } from '@aztec/stdlib/auth-witness';
|
|
|
57
54
|
import { PublicSimulatorConfig } from '@aztec/stdlib/avm';
|
|
58
55
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
59
56
|
import { type ContractInstanceWithAddress, computePartialAddress } from '@aztec/stdlib/contract';
|
|
60
|
-
import {
|
|
57
|
+
import {
|
|
58
|
+
FALLBACK_TEARDOWN_DA_GAS_LIMIT,
|
|
59
|
+
FALLBACK_TEARDOWN_L2_GAS_LIMIT,
|
|
60
|
+
Gas,
|
|
61
|
+
GasFees,
|
|
62
|
+
GasSettings,
|
|
63
|
+
} from '@aztec/stdlib/gas';
|
|
61
64
|
import { computeCalldataHash, computeProtocolNullifier, siloNullifier } from '@aztec/stdlib/hash';
|
|
62
65
|
import {
|
|
63
66
|
PartialPrivateTailPublicInputsForPublic,
|
|
@@ -112,22 +115,29 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
112
115
|
private version: Fr,
|
|
113
116
|
private chainId: Fr,
|
|
114
117
|
private authwits: Map<string, AuthWitness>,
|
|
115
|
-
private readonly contractSyncService: ContractSyncService,
|
|
116
118
|
) {
|
|
117
119
|
this.logger = createLogger('txe:top_level_context');
|
|
118
120
|
this.logger.debug('Entering Top Level Context');
|
|
119
121
|
}
|
|
120
122
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
+
private contractOracleVersion: { major: number; minor: number } | undefined;
|
|
124
|
+
|
|
125
|
+
assertCompatibleOracleVersion(major: number, minor: number): void {
|
|
126
|
+
if (major !== ORACLE_VERSION_MAJOR) {
|
|
123
127
|
const hint =
|
|
124
|
-
|
|
128
|
+
major > ORACLE_VERSION_MAJOR
|
|
125
129
|
? '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
130
|
: '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.';
|
|
127
131
|
throw new Error(
|
|
128
|
-
`Incompatible aztec cli version: ${hint} See https://docs.aztec.network/errors/8 (expected oracle version ${
|
|
132
|
+
`Incompatible aztec cli version: ${hint} See https://docs.aztec.network/errors/8 (expected oracle major version ${ORACLE_VERSION_MAJOR}, got ${major})`,
|
|
129
133
|
);
|
|
130
134
|
}
|
|
135
|
+
this.contractOracleVersion = { major, minor };
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Prefixed with "nonOracleFunction" as it is not used as an oracle handler.
|
|
139
|
+
nonOracleFunctionGetContractOracleVersion(): { major: number; minor: number } | undefined {
|
|
140
|
+
return this.contractOracleVersion;
|
|
131
141
|
}
|
|
132
142
|
|
|
133
143
|
// This is typically only invoked in private contexts, but it is convenient to also have it in top-level for testing
|
|
@@ -174,7 +184,12 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
174
184
|
|
|
175
185
|
const txEffects = block!.body.txEffects[0];
|
|
176
186
|
|
|
177
|
-
return {
|
|
187
|
+
return {
|
|
188
|
+
txHash: txEffects.txHash,
|
|
189
|
+
noteHashes: txEffects.noteHashes,
|
|
190
|
+
nullifiers: txEffects.nullifiers,
|
|
191
|
+
privateLogs: txEffects.privateLogs,
|
|
192
|
+
};
|
|
178
193
|
}
|
|
179
194
|
|
|
180
195
|
async syncContractNonOracleMethod(contractAddress: AztecAddress, scope: AztecAddress, jobId: string) {
|
|
@@ -346,8 +361,8 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
346
361
|
|
|
347
362
|
const callContext = new CallContext(from, targetContractAddress, functionSelector, isStaticCall);
|
|
348
363
|
|
|
349
|
-
const gasLimits = new Gas(
|
|
350
|
-
const teardownGasLimits = new Gas(
|
|
364
|
+
const gasLimits = new Gas(MAX_PROCESSABLE_DA_GAS_PER_CHECKPOINT, MAX_PROCESSABLE_L2_GAS);
|
|
365
|
+
const teardownGasLimits = new Gas(FALLBACK_TEARDOWN_DA_GAS_LIMIT, FALLBACK_TEARDOWN_L2_GAS_LIMIT);
|
|
351
366
|
const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
|
|
352
367
|
|
|
353
368
|
const txContext = new TxContext(this.chainId, this.version, gasSettings);
|
|
@@ -394,6 +409,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
394
409
|
senderForTags: from,
|
|
395
410
|
simulator,
|
|
396
411
|
messageContextService: this.stateMachine.messageContextService,
|
|
412
|
+
l2TipsStore: this.stateMachine.node,
|
|
397
413
|
});
|
|
398
414
|
|
|
399
415
|
// 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.
|
|
@@ -501,11 +517,17 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
501
517
|
}
|
|
502
518
|
}
|
|
503
519
|
|
|
520
|
+
// Walk the nested private-call tree and collect every offchain effect the transaction emitted.
|
|
521
|
+
// PXE stores these on each `PrivateCallExecutionResult` and they never reach TXE via the
|
|
522
|
+
// `aztec_utl_emitOffchainEffect` foreign-call path (that path only fires at the top-level), so
|
|
523
|
+
// we pull them out here and the RPC wrapper will hand them to `TXESession` for buffering.
|
|
524
|
+
const offchainEffects = collectNested([executionResult], r => r.offchainEffects.map(e => e.data));
|
|
525
|
+
|
|
504
526
|
if (isStaticCall) {
|
|
505
527
|
await checkpoint!.revert();
|
|
506
528
|
|
|
507
529
|
await forkedWorldTrees.close();
|
|
508
|
-
return executionResult.returnValues ?? [];
|
|
530
|
+
return { returnValues: executionResult.returnValues ?? [], offchainEffects };
|
|
509
531
|
}
|
|
510
532
|
|
|
511
533
|
const txEffect = TxEffect.empty();
|
|
@@ -527,7 +549,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
527
549
|
|
|
528
550
|
await forkedWorldTrees.close();
|
|
529
551
|
|
|
530
|
-
return executionResult.returnValues ?? [];
|
|
552
|
+
return { returnValues: executionResult.returnValues ?? [], offchainEffects };
|
|
531
553
|
}
|
|
532
554
|
|
|
533
555
|
async publicCallNewFlow(
|
|
@@ -542,9 +564,9 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
542
564
|
|
|
543
565
|
const blockNumber = await this.getNextBlockNumber();
|
|
544
566
|
|
|
545
|
-
const gasLimits = new Gas(
|
|
567
|
+
const gasLimits = new Gas(MAX_PROCESSABLE_DA_GAS_PER_CHECKPOINT, MAX_PROCESSABLE_L2_GAS);
|
|
546
568
|
|
|
547
|
-
const teardownGasLimits = new Gas(
|
|
569
|
+
const teardownGasLimits = new Gas(FALLBACK_TEARDOWN_DA_GAS_LIMIT, FALLBACK_TEARDOWN_L2_GAS_LIMIT);
|
|
548
570
|
|
|
549
571
|
const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
|
|
550
572
|
|
|
@@ -736,6 +758,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
736
758
|
|
|
737
759
|
try {
|
|
738
760
|
const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
761
|
+
const simulator = new WASMSimulator();
|
|
739
762
|
const oracle = new UtilityExecutionOracle({
|
|
740
763
|
contractAddress: call.to,
|
|
741
764
|
authWitnesses: [],
|
|
@@ -751,11 +774,13 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
751
774
|
capsuleService: new CapsuleService(this.capsuleStore, scopes),
|
|
752
775
|
privateEventStore: this.privateEventStore,
|
|
753
776
|
messageContextService: this.stateMachine.messageContextService,
|
|
754
|
-
contractSyncService: this.contractSyncService,
|
|
777
|
+
contractSyncService: this.stateMachine.contractSyncService,
|
|
778
|
+
l2TipsStore: this.stateMachine.node,
|
|
755
779
|
jobId,
|
|
756
780
|
scopes,
|
|
781
|
+
simulator,
|
|
757
782
|
});
|
|
758
|
-
const acirExecutionResult = await
|
|
783
|
+
const acirExecutionResult = await simulator
|
|
759
784
|
.executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
|
|
760
785
|
.catch((err: Error) => {
|
|
761
786
|
err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
|
package/src/rpc_translator.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import type { ContractInstanceWithAddress } from '@aztec/aztec.js/contracts';
|
|
2
2
|
import { Fr, Point } from '@aztec/aztec.js/fields';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
MAX_NOTE_HASHES_PER_TX,
|
|
5
|
+
MAX_NULLIFIERS_PER_TX,
|
|
6
|
+
MAX_PRIVATE_LOGS_PER_TX,
|
|
7
|
+
PRIVATE_LOG_CIPHERTEXT_LEN,
|
|
8
|
+
PRIVATE_LOG_SIZE_IN_FIELDS,
|
|
9
|
+
} from '@aztec/constants';
|
|
4
10
|
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
5
11
|
import {
|
|
6
12
|
type IMiscOracle,
|
|
@@ -10,7 +16,6 @@ import {
|
|
|
10
16
|
} from '@aztec/pxe/simulator';
|
|
11
17
|
import { type ContractArtifact, EventSelector, FunctionSelector, NoteSelector } from '@aztec/stdlib/abi';
|
|
12
18
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
13
|
-
import { BlockHash } from '@aztec/stdlib/block';
|
|
14
19
|
|
|
15
20
|
import type { IAvmExecutionOracle, ITxeExecutionOracle } from './oracle/interfaces.js';
|
|
16
21
|
import type { TXESessionStateHandler } from './txe_session.js';
|
|
@@ -20,6 +25,7 @@ import {
|
|
|
20
25
|
addressFromSingle,
|
|
21
26
|
arrayOfArraysToBoundedVecOfArrays,
|
|
22
27
|
arrayToBoundedVec,
|
|
28
|
+
blockHashFromSingle,
|
|
23
29
|
bufferToU8Array,
|
|
24
30
|
fromArray,
|
|
25
31
|
fromSingle,
|
|
@@ -264,10 +270,11 @@ export class RPCTranslator {
|
|
|
264
270
|
// PXE oracles
|
|
265
271
|
|
|
266
272
|
// eslint-disable-next-line camelcase
|
|
267
|
-
|
|
268
|
-
const
|
|
273
|
+
aztec_utl_assertCompatibleOracleVersionV2(foreignMajor: ForeignCallSingle, foreignMinor: ForeignCallSingle) {
|
|
274
|
+
const major = fromSingle(foreignMajor).toNumber();
|
|
275
|
+
const minor = fromSingle(foreignMinor).toNumber();
|
|
269
276
|
|
|
270
|
-
this.handlerAsMisc().assertCompatibleOracleVersion(
|
|
277
|
+
this.handlerAsMisc().assertCompatibleOracleVersion(major, minor);
|
|
271
278
|
|
|
272
279
|
return toForeignCallResult([]);
|
|
273
280
|
}
|
|
@@ -288,15 +295,81 @@ export class RPCTranslator {
|
|
|
288
295
|
|
|
289
296
|
// eslint-disable-next-line camelcase
|
|
290
297
|
async aztec_txe_getLastTxEffects() {
|
|
291
|
-
const { txHash, noteHashes, nullifiers } = await this.handlerAsTxe().getLastTxEffects();
|
|
298
|
+
const { txHash, noteHashes, nullifiers, privateLogs } = await this.handlerAsTxe().getLastTxEffects();
|
|
299
|
+
|
|
300
|
+
if (privateLogs.length > MAX_PRIVATE_LOGS_PER_TX) {
|
|
301
|
+
throw new Error(`${privateLogs.length} private logs exceed max ${MAX_PRIVATE_LOGS_PER_TX}`);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// Same workaround as `aztec_txe_getPrivateEvents`: Noir cannot yet return nested structs with arrays, so we return
|
|
305
|
+
// a flat multidimensional array plus per-log lengths and the total count, and reassemble into a
|
|
306
|
+
// `BoundedVec<BoundedVec<T>>` on the Noir side. Each log contributes only its emitted fields. The rest
|
|
307
|
+
// is zero-padded to `PRIVATE_LOG_SIZE_IN_FIELDS`.
|
|
308
|
+
const emittedLogs = privateLogs.map(log => log.getEmittedFields());
|
|
309
|
+
|
|
310
|
+
const rawLogStorage = emittedLogs
|
|
311
|
+
.map(fields => fields.concat(Array(PRIVATE_LOG_SIZE_IN_FIELDS - fields.length).fill(new Fr(0))))
|
|
312
|
+
.concat(
|
|
313
|
+
Array(MAX_PRIVATE_LOGS_PER_TX - emittedLogs.length).fill(Array(PRIVATE_LOG_SIZE_IN_FIELDS).fill(new Fr(0))),
|
|
314
|
+
)
|
|
315
|
+
.flat();
|
|
316
|
+
|
|
317
|
+
const logLengths = emittedLogs
|
|
318
|
+
.map(fields => new Fr(fields.length))
|
|
319
|
+
.concat(Array(MAX_PRIVATE_LOGS_PER_TX - emittedLogs.length).fill(new Fr(0)));
|
|
320
|
+
|
|
321
|
+
const logCount = new Fr(emittedLogs.length);
|
|
292
322
|
|
|
293
323
|
return toForeignCallResult([
|
|
294
324
|
toSingle(txHash.hash),
|
|
295
325
|
...arrayToBoundedVec(toArray(noteHashes), MAX_NOTE_HASHES_PER_TX),
|
|
296
326
|
...arrayToBoundedVec(toArray(nullifiers), MAX_NULLIFIERS_PER_TX),
|
|
327
|
+
toArray(rawLogStorage),
|
|
328
|
+
toArray(logLengths),
|
|
329
|
+
toSingle(logCount),
|
|
297
330
|
]);
|
|
298
331
|
}
|
|
299
332
|
|
|
333
|
+
// eslint-disable-next-line camelcase
|
|
334
|
+
aztec_txe_getLastCallOffchainEffects() {
|
|
335
|
+
// This oracle returns all offchain effect payloads (messages, authwit requests, etc.) emitted by the last top-level call,
|
|
336
|
+
// MAX_OFFCHAIN_EFFECTS_PER_TXE_QUERY is arbitrarily set at 64 because we need a bound. Nothing inherent about it.
|
|
337
|
+
const MAX_OFFCHAIN_EFFECTS_PER_TXE_QUERY = 64;
|
|
338
|
+
// Must match MAX_OFFCHAIN_EFFECT_LEN in txe_oracles.nr.
|
|
339
|
+
const MAX_OFFCHAIN_EFFECT_LEN = 2 + PRIVATE_LOG_CIPHERTEXT_LEN;
|
|
340
|
+
|
|
341
|
+
const { effects } = this.stateHandler.getLastCallOffchainEffects();
|
|
342
|
+
|
|
343
|
+
if (effects.length > MAX_OFFCHAIN_EFFECTS_PER_TXE_QUERY) {
|
|
344
|
+
throw new Error(`${effects.length} offchain effects exceed max ${MAX_OFFCHAIN_EFFECTS_PER_TXE_QUERY}`);
|
|
345
|
+
}
|
|
346
|
+
if (effects.some(e => e.length > MAX_OFFCHAIN_EFFECT_LEN)) {
|
|
347
|
+
throw new Error(`Some offchain effect has length larger than max ${MAX_OFFCHAIN_EFFECT_LEN}`);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
const rawArrayStorage = effects
|
|
351
|
+
.map(e => e.concat(Array(MAX_OFFCHAIN_EFFECT_LEN - e.length).fill(new Fr(0))))
|
|
352
|
+
.concat(
|
|
353
|
+
Array(MAX_OFFCHAIN_EFFECTS_PER_TXE_QUERY - effects.length).fill(Array(MAX_OFFCHAIN_EFFECT_LEN).fill(new Fr(0))),
|
|
354
|
+
)
|
|
355
|
+
.flat();
|
|
356
|
+
|
|
357
|
+
const effectLengths = effects
|
|
358
|
+
.map(e => new Fr(e.length))
|
|
359
|
+
.concat(Array(MAX_OFFCHAIN_EFFECTS_PER_TXE_QUERY - effects.length).fill(new Fr(0)));
|
|
360
|
+
|
|
361
|
+
const count = new Fr(effects.length);
|
|
362
|
+
|
|
363
|
+
return toForeignCallResult([toArray(rawArrayStorage), toArray(effectLengths), toSingle(count)]);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// eslint-disable-next-line camelcase
|
|
367
|
+
aztec_txe_getLastCallContext() {
|
|
368
|
+
const { txHash, anchorBlockTimestamp } = this.stateHandler.getLastCallContext();
|
|
369
|
+
const isSome = txHash.isZero() ? 0 : 1;
|
|
370
|
+
return toForeignCallResult([toSingle(isSome), toSingle(txHash), toSingle(new Fr(anchorBlockTimestamp))]);
|
|
371
|
+
}
|
|
372
|
+
|
|
300
373
|
// eslint-disable-next-line camelcase
|
|
301
374
|
async aztec_txe_getPrivateEvents(
|
|
302
375
|
foreignSelector: ForeignCallSingle,
|
|
@@ -384,7 +457,7 @@ export class RPCTranslator {
|
|
|
384
457
|
foreignStartStorageSlot: ForeignCallSingle,
|
|
385
458
|
foreignNumberOfElements: ForeignCallSingle,
|
|
386
459
|
) {
|
|
387
|
-
const blockHash =
|
|
460
|
+
const blockHash = blockHashFromSingle(foreignBlockHash);
|
|
388
461
|
const contractAddress = addressFromSingle(foreignContractAddress);
|
|
389
462
|
const startStorageSlot = fromSingle(foreignStartStorageSlot);
|
|
390
463
|
const numberOfElements = fromSingle(foreignNumberOfElements).toNumber();
|
|
@@ -401,7 +474,7 @@ export class RPCTranslator {
|
|
|
401
474
|
|
|
402
475
|
// eslint-disable-next-line camelcase
|
|
403
476
|
async aztec_utl_getPublicDataWitness(foreignBlockHash: ForeignCallSingle, foreignLeafSlot: ForeignCallSingle) {
|
|
404
|
-
const blockHash =
|
|
477
|
+
const blockHash = blockHashFromSingle(foreignBlockHash);
|
|
405
478
|
const leafSlot = fromSingle(foreignLeafSlot);
|
|
406
479
|
|
|
407
480
|
const witness = await this.handlerAsUtility().getPublicDataWitness(blockHash, leafSlot);
|
|
@@ -628,7 +701,7 @@ export class RPCTranslator {
|
|
|
628
701
|
foreignBlockHash: ForeignCallSingle,
|
|
629
702
|
foreignNullifier: ForeignCallSingle,
|
|
630
703
|
) {
|
|
631
|
-
const blockHash =
|
|
704
|
+
const blockHash = blockHashFromSingle(foreignBlockHash);
|
|
632
705
|
const nullifier = fromSingle(foreignNullifier);
|
|
633
706
|
|
|
634
707
|
const witness = await this.handlerAsUtility().getNullifierMembershipWitness(blockHash, nullifier);
|
|
@@ -692,7 +765,7 @@ export class RPCTranslator {
|
|
|
692
765
|
foreignAnchorBlockHash: ForeignCallSingle,
|
|
693
766
|
foreignNoteHash: ForeignCallSingle,
|
|
694
767
|
) {
|
|
695
|
-
const blockHash =
|
|
768
|
+
const blockHash = blockHashFromSingle(foreignAnchorBlockHash);
|
|
696
769
|
const noteHash = fromSingle(foreignNoteHash);
|
|
697
770
|
|
|
698
771
|
const witness = await this.handlerAsUtility().getNoteHashMembershipWitness(blockHash, noteHash);
|
|
@@ -708,8 +781,8 @@ export class RPCTranslator {
|
|
|
708
781
|
foreignAnchorBlockHash: ForeignCallSingle,
|
|
709
782
|
foreignBlockHash: ForeignCallSingle,
|
|
710
783
|
) {
|
|
711
|
-
const anchorBlockHash =
|
|
712
|
-
const blockHash =
|
|
784
|
+
const anchorBlockHash = blockHashFromSingle(foreignAnchorBlockHash);
|
|
785
|
+
const blockHash = blockHashFromSingle(foreignBlockHash);
|
|
713
786
|
|
|
714
787
|
const witness = await this.handlerAsUtility().getBlockHashMembershipWitness(anchorBlockHash, blockHash);
|
|
715
788
|
|
|
@@ -726,7 +799,7 @@ export class RPCTranslator {
|
|
|
726
799
|
foreignBlockHash: ForeignCallSingle,
|
|
727
800
|
foreignNullifier: ForeignCallSingle,
|
|
728
801
|
) {
|
|
729
|
-
const blockHash =
|
|
802
|
+
const blockHash = blockHashFromSingle(foreignBlockHash);
|
|
730
803
|
const nullifier = fromSingle(foreignNullifier);
|
|
731
804
|
|
|
732
805
|
const witness = await this.handlerAsUtility().getLowNullifierMembershipWitness(blockHash, nullifier);
|
|
@@ -750,6 +823,13 @@ export class RPCTranslator {
|
|
|
750
823
|
return toForeignCallResult([]);
|
|
751
824
|
}
|
|
752
825
|
|
|
826
|
+
// eslint-disable-next-line camelcase
|
|
827
|
+
async aztec_utl_getPendingTaggedLogs_v2(foreignScope: ForeignCallSingle) {
|
|
828
|
+
const scope = AztecAddress.fromField(fromSingle(foreignScope));
|
|
829
|
+
const slot = await this.handlerAsUtility().getPendingTaggedLogsV2(scope);
|
|
830
|
+
return toForeignCallResult([toSingle(slot)]);
|
|
831
|
+
}
|
|
832
|
+
|
|
753
833
|
// eslint-disable-next-line camelcase
|
|
754
834
|
public async aztec_utl_validateAndStoreEnqueuedNotesAndEvents(
|
|
755
835
|
foreignContractAddress: ForeignCallSingle,
|
|
@@ -778,6 +858,31 @@ export class RPCTranslator {
|
|
|
778
858
|
return toForeignCallResult([]);
|
|
779
859
|
}
|
|
780
860
|
|
|
861
|
+
// eslint-disable-next-line camelcase
|
|
862
|
+
public async aztec_utl_validateAndStoreEnqueuedNotesAndEvents_v2(
|
|
863
|
+
foreignNoteValidationRequestsArrayBaseSlot: ForeignCallSingle,
|
|
864
|
+
foreignEventValidationRequestsArrayBaseSlot: ForeignCallSingle,
|
|
865
|
+
foreignMaxNotePackedLen: ForeignCallSingle,
|
|
866
|
+
foreignMaxEventSerializedLen: ForeignCallSingle,
|
|
867
|
+
foreignScope: ForeignCallSingle,
|
|
868
|
+
) {
|
|
869
|
+
const noteValidationRequestsArrayBaseSlot = fromSingle(foreignNoteValidationRequestsArrayBaseSlot);
|
|
870
|
+
const eventValidationRequestsArrayBaseSlot = fromSingle(foreignEventValidationRequestsArrayBaseSlot);
|
|
871
|
+
const maxNotePackedLen = fromSingle(foreignMaxNotePackedLen).toNumber();
|
|
872
|
+
const maxEventSerializedLen = fromSingle(foreignMaxEventSerializedLen).toNumber();
|
|
873
|
+
const scope = AztecAddress.fromField(fromSingle(foreignScope));
|
|
874
|
+
|
|
875
|
+
await this.handlerAsUtility().validateAndStoreEnqueuedNotesAndEventsV2(
|
|
876
|
+
noteValidationRequestsArrayBaseSlot,
|
|
877
|
+
eventValidationRequestsArrayBaseSlot,
|
|
878
|
+
maxNotePackedLen,
|
|
879
|
+
maxEventSerializedLen,
|
|
880
|
+
scope,
|
|
881
|
+
);
|
|
882
|
+
|
|
883
|
+
return toForeignCallResult([]);
|
|
884
|
+
}
|
|
885
|
+
|
|
781
886
|
// eslint-disable-next-line camelcase
|
|
782
887
|
public async aztec_utl_getLogsByTag(
|
|
783
888
|
foreignContractAddress: ForeignCallSingle,
|
|
@@ -822,6 +927,20 @@ export class RPCTranslator {
|
|
|
822
927
|
return toForeignCallResult([]);
|
|
823
928
|
}
|
|
824
929
|
|
|
930
|
+
// eslint-disable-next-line camelcase
|
|
931
|
+
async aztec_utl_getLogsByTag_v2(foreignRequestArrayBaseSlot: ForeignCallSingle) {
|
|
932
|
+
const requestArrayBaseSlot = fromSingle(foreignRequestArrayBaseSlot);
|
|
933
|
+
const responseSlot = await this.handlerAsUtility().getLogsByTagV2(requestArrayBaseSlot);
|
|
934
|
+
return toForeignCallResult([toSingle(responseSlot)]);
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
// eslint-disable-next-line camelcase
|
|
938
|
+
async aztec_utl_getMessageContextsByTxHash_v2(foreignRequestArrayBaseSlot: ForeignCallSingle) {
|
|
939
|
+
const requestArrayBaseSlot = fromSingle(foreignRequestArrayBaseSlot);
|
|
940
|
+
const responseSlot = await this.handlerAsUtility().getMessageContextsByTxHashV2(requestArrayBaseSlot);
|
|
941
|
+
return toForeignCallResult([toSingle(responseSlot)]);
|
|
942
|
+
}
|
|
943
|
+
|
|
825
944
|
// eslint-disable-next-line camelcase
|
|
826
945
|
aztec_utl_setCapsule(
|
|
827
946
|
foreignContractAddress: ForeignCallSingle,
|
|
@@ -898,6 +1017,64 @@ export class RPCTranslator {
|
|
|
898
1017
|
return toForeignCallResult([]);
|
|
899
1018
|
}
|
|
900
1019
|
|
|
1020
|
+
// eslint-disable-next-line camelcase
|
|
1021
|
+
aztec_utl_pushEphemeral(foreignSlot: ForeignCallSingle, foreignElements: ForeignCallArray) {
|
|
1022
|
+
const slot = fromSingle(foreignSlot);
|
|
1023
|
+
const elements = fromArray(foreignElements);
|
|
1024
|
+
const newLen = this.handlerAsUtility().pushEphemeral(slot, elements);
|
|
1025
|
+
return toForeignCallResult([toSingle(new Fr(newLen))]);
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
// eslint-disable-next-line camelcase
|
|
1029
|
+
aztec_utl_popEphemeral(foreignSlot: ForeignCallSingle) {
|
|
1030
|
+
const slot = fromSingle(foreignSlot);
|
|
1031
|
+
const element = this.handlerAsUtility().popEphemeral(slot);
|
|
1032
|
+
return toForeignCallResult([toArray(element)]);
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
// eslint-disable-next-line camelcase
|
|
1036
|
+
aztec_utl_getEphemeral(foreignSlot: ForeignCallSingle, foreignIndex: ForeignCallSingle) {
|
|
1037
|
+
const slot = fromSingle(foreignSlot);
|
|
1038
|
+
const index = fromSingle(foreignIndex).toNumber();
|
|
1039
|
+
const element = this.handlerAsUtility().getEphemeral(slot, index);
|
|
1040
|
+
return toForeignCallResult([toArray(element)]);
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
// eslint-disable-next-line camelcase
|
|
1044
|
+
aztec_utl_setEphemeral(
|
|
1045
|
+
foreignSlot: ForeignCallSingle,
|
|
1046
|
+
foreignIndex: ForeignCallSingle,
|
|
1047
|
+
foreignElements: ForeignCallArray,
|
|
1048
|
+
) {
|
|
1049
|
+
const slot = fromSingle(foreignSlot);
|
|
1050
|
+
const index = fromSingle(foreignIndex).toNumber();
|
|
1051
|
+
const elements = fromArray(foreignElements);
|
|
1052
|
+
this.handlerAsUtility().setEphemeral(slot, index, elements);
|
|
1053
|
+
return toForeignCallResult([]);
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
// eslint-disable-next-line camelcase
|
|
1057
|
+
aztec_utl_getEphemeralLen(foreignSlot: ForeignCallSingle) {
|
|
1058
|
+
const slot = fromSingle(foreignSlot);
|
|
1059
|
+
const len = this.handlerAsUtility().getEphemeralLen(slot);
|
|
1060
|
+
return toForeignCallResult([toSingle(new Fr(len))]);
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
// eslint-disable-next-line camelcase
|
|
1064
|
+
aztec_utl_removeEphemeral(foreignSlot: ForeignCallSingle, foreignIndex: ForeignCallSingle) {
|
|
1065
|
+
const slot = fromSingle(foreignSlot);
|
|
1066
|
+
const index = fromSingle(foreignIndex).toNumber();
|
|
1067
|
+
this.handlerAsUtility().removeEphemeral(slot, index);
|
|
1068
|
+
return toForeignCallResult([]);
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
// eslint-disable-next-line camelcase
|
|
1072
|
+
aztec_utl_clearEphemeral(foreignSlot: ForeignCallSingle) {
|
|
1073
|
+
const slot = fromSingle(foreignSlot);
|
|
1074
|
+
this.handlerAsUtility().clearEphemeral(slot);
|
|
1075
|
+
return toForeignCallResult([]);
|
|
1076
|
+
}
|
|
1077
|
+
|
|
901
1078
|
// TODO: I forgot to add a corresponding function here, when I introduced an oracle method to txe_oracle.ts.
|
|
902
1079
|
// The compiler didn't throw an error, so it took me a while to learn of the existence of this file, and that I need
|
|
903
1080
|
// to implement this function here. Isn't there a way to programmatically identify that this is missing, given the
|
|
@@ -966,8 +1143,13 @@ export class RPCTranslator {
|
|
|
966
1143
|
}
|
|
967
1144
|
|
|
968
1145
|
// eslint-disable-next-line camelcase
|
|
969
|
-
aztec_utl_emitOffchainEffect(
|
|
970
|
-
|
|
1146
|
+
aztec_utl_emitOffchainEffect(foreignData: ForeignCallArray) {
|
|
1147
|
+
// Record the raw payload against the currently-executing top-level call. The Noir side
|
|
1148
|
+
// (via `env.offchain_messages()`) is responsible for decoding the protocol-reserved prefix
|
|
1149
|
+
// (`OFFCHAIN_MESSAGE_IDENTIFIER`, recipient) and turning each payload into an `OffchainMessage` struct suitable
|
|
1150
|
+
// for `offchain_receive`.
|
|
1151
|
+
this.stateHandler.recordOffchainEffect(fromArray(foreignData));
|
|
1152
|
+
return Promise.resolve(toForeignCallResult([]));
|
|
971
1153
|
}
|
|
972
1154
|
|
|
973
1155
|
// AVM opcodes
|
|
@@ -1176,18 +1358,38 @@ export class RPCTranslator {
|
|
|
1176
1358
|
const argsHash = fromSingle(foreignArgsHash);
|
|
1177
1359
|
const isStaticCall = fromSingle(foreignIsStaticCall).toBool();
|
|
1178
1360
|
|
|
1179
|
-
const returnValues = await this.
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1361
|
+
const returnValues = await this.stateHandler.withTopLevelCallTracking(async () => {
|
|
1362
|
+
const { returnValues, offchainEffects } = await this.handlerAsTxe().privateCallNewFlow(
|
|
1363
|
+
from,
|
|
1364
|
+
targetContractAddress,
|
|
1365
|
+
functionSelector,
|
|
1366
|
+
args,
|
|
1367
|
+
argsHash,
|
|
1368
|
+
isStaticCall,
|
|
1369
|
+
this.stateHandler.getCurrentJob(),
|
|
1370
|
+
);
|
|
1371
|
+
|
|
1372
|
+
// Private execution collects offchain effects inside PXE's PrivateExecutionOracle rather than
|
|
1373
|
+
// round-tripping them through `aztec_utl_emitOffchainEffect`, so the session buffer is empty
|
|
1374
|
+
// at this point. Drain the effects from the execution tree into the session buffer so the
|
|
1375
|
+
// next `env.offchain_messages()` call in the test sees them.
|
|
1376
|
+
for (const data of offchainEffects) {
|
|
1377
|
+
this.stateHandler.recordOffchainEffect(data);
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1380
|
+
// TODO(F-335): Avoid doing the following call here.
|
|
1381
|
+
await this.stateHandler.cycleJob();
|
|
1382
|
+
|
|
1383
|
+
if (isStaticCall) {
|
|
1384
|
+
// Static calls revert their checkpoint and mine no block, so there is no tx hash to tag
|
|
1385
|
+
// offchain effects with. Querying `getLastTxEffects()` here would return an unrelated
|
|
1386
|
+
// predecessor tx.
|
|
1387
|
+
return { result: returnValues };
|
|
1388
|
+
}
|
|
1389
|
+
const { txHash } = await this.handlerAsTxe().getLastTxEffects();
|
|
1390
|
+
return { result: returnValues, txHash: txHash.hash };
|
|
1391
|
+
});
|
|
1188
1392
|
|
|
1189
|
-
// TODO(F-335): Avoid doing the following call here.
|
|
1190
|
-
await this.stateHandler.cycleJob();
|
|
1191
1393
|
return toForeignCallResult([toArray(returnValues)]);
|
|
1192
1394
|
}
|
|
1193
1395
|
|
|
@@ -1201,15 +1403,20 @@ export class RPCTranslator {
|
|
|
1201
1403
|
const functionSelector = FunctionSelector.fromField(fromSingle(foreignFunctionSelector));
|
|
1202
1404
|
const args = fromArray(foreignArgs);
|
|
1203
1405
|
|
|
1204
|
-
const returnValues = await this.
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1406
|
+
const returnValues = await this.stateHandler.withTopLevelCallTracking(async () => {
|
|
1407
|
+
const returnValues = await this.handlerAsTxe().executeUtilityFunction(
|
|
1408
|
+
targetContractAddress,
|
|
1409
|
+
functionSelector,
|
|
1410
|
+
args,
|
|
1411
|
+
this.stateHandler.getCurrentJob(),
|
|
1412
|
+
);
|
|
1413
|
+
|
|
1414
|
+
// TODO(F-335): Avoid doing the following call here.
|
|
1415
|
+
await this.stateHandler.cycleJob();
|
|
1416
|
+
|
|
1417
|
+
return { result: returnValues };
|
|
1418
|
+
});
|
|
1210
1419
|
|
|
1211
|
-
// TODO(F-335): Avoid doing the following call here.
|
|
1212
|
-
await this.stateHandler.cycleJob();
|
|
1213
1420
|
return toForeignCallResult([toArray(returnValues)]);
|
|
1214
1421
|
}
|
|
1215
1422
|
|
|
@@ -1225,10 +1432,20 @@ export class RPCTranslator {
|
|
|
1225
1432
|
const calldata = fromArray(foreignCalldata);
|
|
1226
1433
|
const isStaticCall = fromSingle(foreignIsStaticCall).toBool();
|
|
1227
1434
|
|
|
1228
|
-
const returnValues = await this.
|
|
1435
|
+
const returnValues = await this.stateHandler.withTopLevelCallTracking(async () => {
|
|
1436
|
+
const returnValues = await this.handlerAsTxe().publicCallNewFlow(from, address, calldata, isStaticCall);
|
|
1437
|
+
|
|
1438
|
+
// TODO(F-335): Avoid doing the following call here.
|
|
1439
|
+
await this.stateHandler.cycleJob();
|
|
1440
|
+
|
|
1441
|
+
if (isStaticCall) {
|
|
1442
|
+
// See equivalent branch in `aztec_txe_privateCallNewFlow`.
|
|
1443
|
+
return { result: returnValues };
|
|
1444
|
+
}
|
|
1445
|
+
const { txHash } = await this.handlerAsTxe().getLastTxEffects();
|
|
1446
|
+
return { result: returnValues, txHash: txHash.hash };
|
|
1447
|
+
});
|
|
1229
1448
|
|
|
1230
|
-
// TODO(F-335): Avoid doing the following call here.
|
|
1231
|
-
await this.stateHandler.cycleJob();
|
|
1232
1449
|
return toForeignCallResult([toArray(returnValues)]);
|
|
1233
1450
|
}
|
|
1234
1451
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ArchiverDataSourceBase, ArchiverDataStoreUpdater,
|
|
1
|
+
import { ArchiverDataSourceBase, ArchiverDataStoreUpdater, createArchiverDataStores } from '@aztec/archiver';
|
|
2
2
|
import { GENESIS_ARCHIVE_ROOT } from '@aztec/constants';
|
|
3
3
|
import { CheckpointNumber, type EpochNumber, type SlotNumber } from '@aztec/foundation/branded-types';
|
|
4
4
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
@@ -14,11 +14,10 @@ import type { L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
|
|
|
14
14
|
* without needing any of the extra overhead that the Archiver itself requires (i.e. an L1 client).
|
|
15
15
|
*/
|
|
16
16
|
export class TXEArchiver extends ArchiverDataSourceBase {
|
|
17
|
-
private readonly updater = new ArchiverDataStoreUpdater(this.
|
|
17
|
+
private readonly updater = new ArchiverDataStoreUpdater(this.stores);
|
|
18
18
|
|
|
19
19
|
constructor(db: AztecAsyncKVStore) {
|
|
20
|
-
|
|
21
|
-
super(store);
|
|
20
|
+
super(createArchiverDataStores(db, { logsMaxPageSize: 9999 }));
|
|
22
21
|
}
|
|
23
22
|
|
|
24
23
|
public async addCheckpoints(checkpoints: PublishedCheckpoint[], result?: ValidateCheckpointResult): Promise<void> {
|
|
@@ -61,7 +60,7 @@ export class TXEArchiver extends ArchiverDataSourceBase {
|
|
|
61
60
|
}
|
|
62
61
|
// TXE uses 1-block-per-checkpoint for testing simplicity, so we can use block number as checkpoint number.
|
|
63
62
|
// This uses the deprecated fromBlockNumber method intentionally for the TXE testing environment.
|
|
64
|
-
const checkpoint = await this.
|
|
63
|
+
const checkpoint = await this.stores.blocks.getRangeOfCheckpoints(CheckpointNumber.fromBlockNumber(number), 1);
|
|
65
64
|
if (checkpoint.length === 0) {
|
|
66
65
|
throw new Error(`L2Tips requested from TXE Archiver but no checkpoint found for block number ${number}`);
|
|
67
66
|
}
|
|
@@ -1,20 +1,29 @@
|
|
|
1
|
+
import type { SimulationOverridesPlan } from '@aztec/ethereum/contracts';
|
|
1
2
|
import { BlockNumber, type SlotNumber } from '@aztec/foundation/branded-types';
|
|
3
|
+
import { times } from '@aztec/foundation/collection';
|
|
2
4
|
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
3
5
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
4
|
-
import { GasFees } from '@aztec/stdlib/gas';
|
|
6
|
+
import { FEE_ORACLE_LAG, GasFees } from '@aztec/stdlib/gas';
|
|
5
7
|
import { makeGlobalVariables } from '@aztec/stdlib/testing';
|
|
6
8
|
import {
|
|
7
|
-
type BuildCheckpointGlobalVariablesOpts,
|
|
8
9
|
type CheckpointGlobalVariables,
|
|
10
|
+
type FeeProvider,
|
|
9
11
|
type GlobalVariableBuilder,
|
|
10
12
|
GlobalVariables,
|
|
11
13
|
} from '@aztec/stdlib/tx';
|
|
12
14
|
|
|
13
|
-
|
|
15
|
+
/** Simple FeeProvider for TXE that returns zero fees. */
|
|
16
|
+
export class TXEFeeProvider implements FeeProvider {
|
|
14
17
|
public getCurrentMinFees(): Promise<GasFees> {
|
|
15
18
|
return Promise.resolve(new GasFees(0, 0));
|
|
16
19
|
}
|
|
17
20
|
|
|
21
|
+
public getPredictedMinFees(): Promise<GasFees[]> {
|
|
22
|
+
return Promise.resolve(times(FEE_ORACLE_LAG, () => new GasFees(0, 0)));
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export class TXEGlobalVariablesBuilder implements GlobalVariableBuilder {
|
|
18
27
|
public buildGlobalVariables(
|
|
19
28
|
_blockNumber: BlockNumber,
|
|
20
29
|
_coinbase: EthAddress,
|
|
@@ -28,7 +37,7 @@ export class TXEGlobalVariablesBuilder implements GlobalVariableBuilder {
|
|
|
28
37
|
_coinbase: EthAddress,
|
|
29
38
|
_feeRecipient: AztecAddress,
|
|
30
39
|
_slotNumber: SlotNumber,
|
|
31
|
-
|
|
40
|
+
_simulationOverridesPlan?: SimulationOverridesPlan,
|
|
32
41
|
): Promise<CheckpointGlobalVariables> {
|
|
33
42
|
const vars = makeGlobalVariables();
|
|
34
43
|
return Promise.resolve({
|