@aztec/simulator 0.70.0 → 0.72.1
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/acvm/deserialize.d.ts +9 -0
- package/dest/acvm/deserialize.d.ts.map +1 -1
- package/dest/acvm/deserialize.js +12 -1
- package/dest/acvm/oracle/oracle.d.ts +5 -10
- package/dest/acvm/oracle/oracle.d.ts.map +1 -1
- package/dest/acvm/oracle/oracle.js +25 -32
- package/dest/acvm/oracle/typed_oracle.d.ts +5 -3
- package/dest/acvm/oracle/typed_oracle.d.ts.map +1 -1
- package/dest/acvm/oracle/typed_oracle.js +14 -8
- package/dest/avm/errors.d.ts +6 -0
- package/dest/avm/errors.d.ts.map +1 -1
- package/dest/avm/errors.js +10 -1
- package/dest/avm/journal/journal.d.ts +2 -3
- package/dest/avm/journal/journal.d.ts.map +1 -1
- package/dest/avm/journal/journal.js +5 -6
- package/dest/avm/opcodes/accrued_substate.d.ts.map +1 -1
- package/dest/avm/opcodes/accrued_substate.js +3 -2
- package/dest/avm/opcodes/conversion.d.ts.map +1 -1
- package/dest/avm/opcodes/conversion.js +10 -7
- package/dest/avm/opcodes/ec_add.js +2 -2
- package/dest/avm/opcodes/memory.d.ts.map +1 -1
- package/dest/avm/opcodes/memory.js +9 -5
- package/dest/avm/opcodes/multi_scalar_mul.d.ts.map +1 -1
- package/dest/avm/opcodes/multi_scalar_mul.js +9 -7
- package/dest/client/client_execution_context.d.ts +1 -5
- package/dest/client/client_execution_context.d.ts.map +1 -1
- package/dest/client/client_execution_context.js +3 -9
- package/dest/client/db_oracle.d.ts +43 -12
- package/dest/client/db_oracle.d.ts.map +1 -1
- package/dest/client/private_execution.js +2 -2
- package/dest/client/simulator.js +2 -2
- package/dest/client/unconstrained_execution.d.ts.map +1 -1
- package/dest/client/unconstrained_execution.js +5 -2
- package/dest/client/view_data_oracle.d.ts +5 -2
- package/dest/client/view_data_oracle.d.ts.map +1 -1
- package/dest/client/view_data_oracle.js +32 -11
- package/dest/public/enqueued_call_side_effect_trace.d.ts +7 -10
- package/dest/public/enqueued_call_side_effect_trace.d.ts.map +1 -1
- package/dest/public/enqueued_call_side_effect_trace.js +21 -28
- package/dest/public/execution.d.ts +7 -25
- package/dest/public/execution.d.ts.map +1 -1
- package/dest/public/execution.js +1 -1
- package/dest/public/fixtures/index.d.ts +3 -3
- package/dest/public/fixtures/index.d.ts.map +1 -1
- package/dest/public/fixtures/index.js +52 -50
- package/dest/public/public_processor.d.ts +5 -6
- package/dest/public/public_processor.d.ts.map +1 -1
- package/dest/public/public_processor.js +17 -18
- package/dest/public/public_tx_context.js +2 -2
- package/dest/public/public_tx_simulator.d.ts +1 -1
- package/dest/public/public_tx_simulator.d.ts.map +1 -1
- package/dest/public/public_tx_simulator.js +5 -8
- package/dest/public/side_effect_trace_interface.d.ts +3 -4
- package/dest/public/side_effect_trace_interface.d.ts.map +1 -1
- package/package.json +10 -10
- package/src/acvm/deserialize.ts +12 -0
- package/src/acvm/oracle/oracle.ts +70 -34
- package/src/acvm/oracle/typed_oracle.ts +25 -8
- package/src/avm/errors.ts +10 -0
- package/src/avm/journal/journal.ts +4 -5
- package/src/avm/opcodes/accrued_substate.ts +2 -1
- package/src/avm/opcodes/conversion.ts +15 -6
- package/src/avm/opcodes/ec_add.ts +1 -1
- package/src/avm/opcodes/memory.ts +8 -4
- package/src/avm/opcodes/multi_scalar_mul.ts +8 -6
- package/src/client/client_execution_context.ts +2 -9
- package/src/client/db_oracle.ts +55 -12
- package/src/client/private_execution.ts +1 -1
- package/src/client/simulator.ts +1 -1
- package/src/client/unconstrained_execution.ts +4 -1
- package/src/client/view_data_oracle.ts +44 -14
- package/src/public/enqueued_call_side_effect_trace.ts +22 -34
- package/src/public/execution.ts +7 -31
- package/src/public/fixtures/index.ts +66 -66
- package/src/public/public_processor.ts +21 -19
- package/src/public/public_tx_context.ts +1 -1
- package/src/public/public_tx_simulator.ts +3 -10
- package/src/public/side_effect_trace_interface.ts +3 -3
|
@@ -2,15 +2,12 @@ import { MerkleTreeId, UnencryptedL2Log } from '@aztec/circuit-types';
|
|
|
2
2
|
import { FunctionSelector, NoteSelector } from '@aztec/foundation/abi';
|
|
3
3
|
import { AztecAddress } from '@aztec/foundation/aztec-address';
|
|
4
4
|
import { Fr } from '@aztec/foundation/fields';
|
|
5
|
-
import { createLogger } from '@aztec/foundation/log';
|
|
6
5
|
|
|
7
6
|
import { type ACVMField } from '../acvm_types.js';
|
|
8
|
-
import { frToBoolean, frToNumber, fromACVMField } from '../deserialize.js';
|
|
7
|
+
import { frToBoolean, frToNumber, fromACVMField, fromBoundedVec } from '../deserialize.js';
|
|
9
8
|
import { toACVMField } from '../serialize.js';
|
|
10
9
|
import { type TypedOracle } from './typed_oracle.js';
|
|
11
10
|
|
|
12
|
-
const logger = createLogger('simulator:acvm:oracle');
|
|
13
|
-
|
|
14
11
|
/**
|
|
15
12
|
* A data source that has all the apis required by Aztec.nr.
|
|
16
13
|
*/
|
|
@@ -22,11 +19,6 @@ export class Oracle {
|
|
|
22
19
|
return toACVMField(val);
|
|
23
20
|
}
|
|
24
21
|
|
|
25
|
-
async storeArrayInExecutionCache(values: ACVMField[]): Promise<ACVMField> {
|
|
26
|
-
const hash = await this.typedOracle.storeArrayInExecutionCache(values.map(fromACVMField));
|
|
27
|
-
return toACVMField(hash);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
22
|
// Since the argument is a slice, noir automatically adds a length field to oracle call.
|
|
31
23
|
async storeInExecutionCache(_length: ACVMField[], values: ACVMField[]): Promise<ACVMField> {
|
|
32
24
|
const hash = await this.typedOracle.storeInExecutionCache(values.map(fromACVMField));
|
|
@@ -384,34 +376,78 @@ export class Oracle {
|
|
|
384
376
|
await this.typedOracle.syncNotes();
|
|
385
377
|
}
|
|
386
378
|
|
|
387
|
-
async
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
379
|
+
async deliverNote(
|
|
380
|
+
[contractAddress]: ACVMField[],
|
|
381
|
+
[storageSlot]: ACVMField[],
|
|
382
|
+
[nonce]: ACVMField[],
|
|
383
|
+
content: ACVMField[],
|
|
384
|
+
[contentLength]: ACVMField[],
|
|
385
|
+
[noteHash]: ACVMField[],
|
|
386
|
+
[nullifier]: ACVMField[],
|
|
387
|
+
[txHash]: ACVMField[],
|
|
388
|
+
[recipient]: ACVMField[],
|
|
389
|
+
): Promise<ACVMField> {
|
|
390
|
+
// TODO(#10728): try-catch this block and return false if we get an exception so that the contract can decide what
|
|
391
|
+
// to do if a note fails delivery (e.g. not increment the tagging index, or add it to some pending work list).
|
|
392
|
+
// Delivery might fail due to temporary issues, such as poor node connectivity.
|
|
393
|
+
await this.typedOracle.deliverNote(
|
|
394
|
+
AztecAddress.fromString(contractAddress),
|
|
395
|
+
fromACVMField(storageSlot),
|
|
396
|
+
fromACVMField(nonce),
|
|
397
|
+
fromBoundedVec(content, contentLength),
|
|
398
|
+
fromACVMField(noteHash),
|
|
399
|
+
fromACVMField(nullifier),
|
|
400
|
+
fromACVMField(txHash),
|
|
401
|
+
AztecAddress.fromString(recipient),
|
|
402
|
+
);
|
|
403
|
+
|
|
404
|
+
return toACVMField(true);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
async dbStore([contractAddress]: ACVMField[], [slot]: ACVMField[], values: ACVMField[]) {
|
|
408
|
+
await this.typedOracle.dbStore(
|
|
409
|
+
AztecAddress.fromField(fromACVMField(contractAddress)),
|
|
410
|
+
fromACVMField(slot),
|
|
411
|
+
values.map(fromACVMField),
|
|
412
|
+
);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
async dbLoad(
|
|
416
|
+
[contractAddress]: ACVMField[],
|
|
417
|
+
[slot]: ACVMField[],
|
|
418
|
+
[tSize]: ACVMField[],
|
|
419
|
+
): Promise<(ACVMField | ACVMField[])[]> {
|
|
420
|
+
const values = await this.typedOracle.dbLoad(
|
|
421
|
+
AztecAddress.fromField(fromACVMField(contractAddress)),
|
|
422
|
+
fromACVMField(slot),
|
|
423
|
+
);
|
|
424
|
+
|
|
425
|
+
// We are going to return a Noir Option struct to represent the possibility of null values. Options are a struct
|
|
426
|
+
// with two fields: `some` (a boolean) and `value` (a field array in this case).
|
|
406
427
|
if (values === null) {
|
|
407
|
-
// No data was found so we set
|
|
408
|
-
|
|
409
|
-
logger.debug(`No data found for key ${processedKey} in contract ${processedContract}`);
|
|
410
|
-
return [toACVMField(0), Array(processedTSize).fill(toACVMField(0))];
|
|
428
|
+
// No data was found so we set `some` to 0 and pad `value` with zeros get the correct return size.
|
|
429
|
+
return [toACVMField(0), Array(frToNumber(fromACVMField(tSize))).fill(toACVMField(0))];
|
|
411
430
|
} else {
|
|
412
|
-
// Data was found so we set
|
|
413
|
-
logger.debug(`Returning data for key ${processedKey} in contract ${processedContract}. Data: [${values}]`);
|
|
431
|
+
// Data was found so we set `some` to 1 and return it along with `value`.
|
|
414
432
|
return [toACVMField(1), values.map(toACVMField)];
|
|
415
433
|
}
|
|
416
434
|
}
|
|
435
|
+
|
|
436
|
+
async dbDelete([contractAddress]: ACVMField[], [slot]: ACVMField[]) {
|
|
437
|
+
await this.typedOracle.dbDelete(AztecAddress.fromField(fromACVMField(contractAddress)), fromACVMField(slot));
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
async dbCopy(
|
|
441
|
+
[contractAddress]: ACVMField[],
|
|
442
|
+
[srcSlot]: ACVMField[],
|
|
443
|
+
[dstSlot]: ACVMField[],
|
|
444
|
+
[numEntries]: ACVMField[],
|
|
445
|
+
) {
|
|
446
|
+
await this.typedOracle.dbCopy(
|
|
447
|
+
AztecAddress.fromField(fromACVMField(contractAddress)),
|
|
448
|
+
fromACVMField(srcSlot),
|
|
449
|
+
fromACVMField(dstSlot),
|
|
450
|
+
frToNumber(fromACVMField(numEntries)),
|
|
451
|
+
);
|
|
452
|
+
}
|
|
417
453
|
}
|
|
@@ -56,10 +56,6 @@ export abstract class TypedOracle {
|
|
|
56
56
|
return Fr.random();
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
storeArrayInExecutionCache(_args: Fr[]): Promise<Fr> {
|
|
60
|
-
throw new OracleMethodNotAvailableError('storeArrayInExecutionCache');
|
|
61
|
-
}
|
|
62
|
-
|
|
63
59
|
storeInExecutionCache(_values: Fr[]): Promise<Fr> {
|
|
64
60
|
throw new OracleMethodNotAvailableError('storeInExecutionCache');
|
|
65
61
|
}
|
|
@@ -237,11 +233,32 @@ export abstract class TypedOracle {
|
|
|
237
233
|
throw new OracleMethodNotAvailableError('syncNotes');
|
|
238
234
|
}
|
|
239
235
|
|
|
240
|
-
|
|
241
|
-
|
|
236
|
+
deliverNote(
|
|
237
|
+
_contractAddress: AztecAddress,
|
|
238
|
+
_storageSlot: Fr,
|
|
239
|
+
_nonce: Fr,
|
|
240
|
+
_content: Fr[],
|
|
241
|
+
_noteHash: Fr,
|
|
242
|
+
_nullifier: Fr,
|
|
243
|
+
_txHash: Fr,
|
|
244
|
+
_recipient: AztecAddress,
|
|
245
|
+
): Promise<void> {
|
|
246
|
+
throw new OracleMethodNotAvailableError('deliverNote');
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
dbStore(_contractAddress: AztecAddress, _key: Fr, _values: Fr[]): Promise<void> {
|
|
250
|
+
throw new OracleMethodNotAvailableError('dbStore');
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
dbLoad(_contractAddress: AztecAddress, _key: Fr): Promise<Fr[] | null> {
|
|
254
|
+
throw new OracleMethodNotAvailableError('dbLoad');
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
dbDelete(_contractAddress: AztecAddress, _key: Fr): Promise<void> {
|
|
258
|
+
throw new OracleMethodNotAvailableError('dbDelete');
|
|
242
259
|
}
|
|
243
260
|
|
|
244
|
-
|
|
245
|
-
throw new OracleMethodNotAvailableError('
|
|
261
|
+
dbCopy(_contractAddress: AztecAddress, _srcKey: Fr, _dstKey: Fr, _numEntries: number): Promise<void> {
|
|
262
|
+
throw new OracleMethodNotAvailableError('dbCopy');
|
|
246
263
|
}
|
|
247
264
|
}
|
package/src/avm/errors.ts
CHANGED
|
@@ -148,6 +148,16 @@ export class MSMPointNotOnCurveError extends AvmExecutionError {
|
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
+
/**
|
|
152
|
+
* Error is thrown when some inputs of ToRadixBE are not valid.
|
|
153
|
+
*/
|
|
154
|
+
export class InvalidToRadixInputsError extends AvmExecutionError {
|
|
155
|
+
constructor(errorString: string) {
|
|
156
|
+
super(errorString);
|
|
157
|
+
this.name = 'InvalidToRadixInputsError';
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
151
161
|
/**
|
|
152
162
|
* Error is thrown when a static call attempts to alter some state
|
|
153
163
|
*/
|
|
@@ -524,14 +524,13 @@ export class AvmPersistableStateManager {
|
|
|
524
524
|
}
|
|
525
525
|
|
|
526
526
|
/**
|
|
527
|
-
* Write
|
|
527
|
+
* Write a public log
|
|
528
528
|
* @param contractAddress - address of the contract that emitted the log
|
|
529
|
-
* @param event - log event selector
|
|
530
529
|
* @param log - log contents
|
|
531
530
|
*/
|
|
532
|
-
public
|
|
533
|
-
this.log.debug(`
|
|
534
|
-
this.trace.
|
|
531
|
+
public writePublicLog(contractAddress: AztecAddress, log: Fr[]) {
|
|
532
|
+
this.log.debug(`PublicLog(${contractAddress}) += event with ${log.length} fields.`);
|
|
533
|
+
this.trace.tracePublicLog(contractAddress, log);
|
|
535
534
|
}
|
|
536
535
|
|
|
537
536
|
/**
|
|
@@ -201,6 +201,7 @@ export class L1ToL2MessageExists extends Instruction {
|
|
|
201
201
|
}
|
|
202
202
|
|
|
203
203
|
export class EmitUnencryptedLog extends Instruction {
|
|
204
|
+
// TODO(#11124): rename unencrypted -> public
|
|
204
205
|
static type: string = 'EMITUNENCRYPTEDLOG';
|
|
205
206
|
static readonly opcode: Opcode = Opcode.EMITUNENCRYPTEDLOG;
|
|
206
207
|
// Informs (de)serialization. See Instruction.deserialize.
|
|
@@ -228,7 +229,7 @@ export class EmitUnencryptedLog extends Instruction {
|
|
|
228
229
|
|
|
229
230
|
context.machineState.consumeGas(this.gasCost(logSize));
|
|
230
231
|
const log = memory.getSlice(logOffset, logSize).map(f => f.toFr());
|
|
231
|
-
context.persistableState.
|
|
232
|
+
context.persistableState.writePublicLog(contractAddress, log);
|
|
232
233
|
|
|
233
234
|
memory.assert({ reads: 1 + logSize, addressing });
|
|
234
235
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { type AvmContext } from '../avm_context.js';
|
|
2
2
|
import { TypeTag, Uint1, Uint8 } from '../avm_memory_types.js';
|
|
3
|
-
import {
|
|
3
|
+
import { InvalidToRadixInputsError } from '../errors.js';
|
|
4
4
|
import { Opcode, OperandType } from '../serialization/instruction_serialization.js';
|
|
5
5
|
import { Addressing } from './addressing_mode.js';
|
|
6
6
|
import { Instruction } from './instruction.js';
|
|
7
7
|
|
|
8
8
|
export class ToRadixBE extends Instruction {
|
|
9
|
-
static type: string = '
|
|
9
|
+
static type: string = 'TORADIXBE';
|
|
10
10
|
static readonly opcode: Opcode = Opcode.TORADIXBE;
|
|
11
11
|
|
|
12
12
|
// Informs (de)serialization. See Instruction.deserialize.
|
|
@@ -49,12 +49,21 @@ export class ToRadixBE extends Instruction {
|
|
|
49
49
|
|
|
50
50
|
let value: bigint = memory.get(srcOffset).toBigInt();
|
|
51
51
|
const radix: bigint = memory.get(radixOffset).toBigInt();
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
|
|
53
|
+
if (radix < 2 || radix > 256) {
|
|
54
|
+
throw new InvalidToRadixInputsError(`ToRadixBE instruction's radix should be in range [2,256] (was ${radix}).`);
|
|
54
55
|
}
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
|
|
57
|
+
if (numLimbs < 1 && value != BigInt(0n)) {
|
|
58
|
+
throw new InvalidToRadixInputsError(
|
|
59
|
+
`ToRadixBE instruction's input value is not zero (was ${value}) but numLimbs zero.`,
|
|
60
|
+
);
|
|
57
61
|
}
|
|
62
|
+
|
|
63
|
+
if (outputBits != 0 && radix != BigInt(2n)) {
|
|
64
|
+
throw new InvalidToRadixInputsError(`Radix ${radix} is not equal to 2 and bit mode is activated.`);
|
|
65
|
+
}
|
|
66
|
+
|
|
58
67
|
const radixBN: bigint = BigInt(radix);
|
|
59
68
|
const limbArray = new Array(numLimbs);
|
|
60
69
|
|
|
@@ -190,7 +190,10 @@ export class CalldataCopy extends Instruction {
|
|
|
190
190
|
const copySize = memory.get(copySizeOffset).toNumber();
|
|
191
191
|
context.machineState.consumeGas(this.gasCost(copySize));
|
|
192
192
|
|
|
193
|
-
|
|
193
|
+
// Values which are out-of-range of the calldata array will be set with Field(0);
|
|
194
|
+
const slice = context.environment.calldata.slice(cdStart, cdStart + copySize).map(f => new Field(f));
|
|
195
|
+
// slice has size = MIN(copySize, calldata.length - cdStart) as TS truncates out-of-range portion
|
|
196
|
+
const transformedData = [...slice, ...Array(copySize - slice.length).fill(new Field(0))];
|
|
194
197
|
|
|
195
198
|
memory.setSlice(dstOffset, transformedData);
|
|
196
199
|
|
|
@@ -253,9 +256,10 @@ export class ReturndataCopy extends Instruction {
|
|
|
253
256
|
const copySize = memory.get(copySizeOffset).toNumber();
|
|
254
257
|
context.machineState.consumeGas(this.gasCost(copySize));
|
|
255
258
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
+
// Values which are out-of-range of the returndata array will be set with Field(0);
|
|
260
|
+
const slice = context.machineState.nestedReturndata.slice(rdStart, rdStart + copySize).map(f => new Field(f));
|
|
261
|
+
// slice has size = MIN(copySize, returndata.length - rdStart) as TS truncates out-of-range portion
|
|
262
|
+
const transformedData = [...slice, ...Array(copySize - slice.length).fill(new Field(0))];
|
|
259
263
|
|
|
260
264
|
memory.setSlice(dstOffset, transformedData);
|
|
261
265
|
|
|
@@ -95,20 +95,22 @@ export class MultiScalarMul extends Instruction {
|
|
|
95
95
|
const [firstBaseScalarPair, ...rest]: Array<[Point, Fq]> = grumpkinPoints.map((p, idx) => [p, scalarFqVector[idx]]);
|
|
96
96
|
// Fold the points and scalars into a single point
|
|
97
97
|
// We have to ensure get the first point, since the identity element (point at infinity) isn't quite working in ts
|
|
98
|
-
|
|
98
|
+
let acc = await grumpkin.mul(firstBaseScalarPair[0], firstBaseScalarPair[1]);
|
|
99
|
+
for (const curr of rest) {
|
|
99
100
|
if (curr[1] === Fq.ZERO) {
|
|
100
101
|
// If we multiply by 0, the result will the point at infinity - so we ignore it
|
|
101
|
-
|
|
102
|
+
continue;
|
|
102
103
|
} else if (curr[0].inf) {
|
|
103
104
|
// If we multiply the point at infinity by a scalar, it's still the point at infinity
|
|
104
|
-
|
|
105
|
+
continue;
|
|
105
106
|
} else if (acc.inf) {
|
|
106
107
|
// If we accumulator is the point at infinity, we can just return the current point
|
|
107
|
-
|
|
108
|
+
acc = curr[0];
|
|
108
109
|
} else {
|
|
109
|
-
|
|
110
|
+
acc = await grumpkin.add(acc, await grumpkin.mul(curr[0], curr[1]));
|
|
110
111
|
}
|
|
111
|
-
}
|
|
112
|
+
}
|
|
113
|
+
const outputPoint = acc;
|
|
112
114
|
|
|
113
115
|
// Important to use setSlice() and not set() in the two following statements as
|
|
114
116
|
// this checks that the offsets lie within memory range.
|
|
@@ -95,7 +95,7 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
95
95
|
const args = this.executionCache.getPreimage(this.argsHash);
|
|
96
96
|
|
|
97
97
|
if (args.length !== argumentsSize) {
|
|
98
|
-
throw new Error(
|
|
98
|
+
throw new Error(`Invalid arguments size: expected ${argumentsSize}, got ${args.length}`);
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
const privateContextInputs = new PrivateContextInputs(
|
|
@@ -160,14 +160,6 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
160
160
|
return this.publicTeardownFunctionCall;
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
-
/**
|
|
164
|
-
* Store values in the execution cache.
|
|
165
|
-
* @param values - Values to store.
|
|
166
|
-
*/
|
|
167
|
-
public override storeArrayInExecutionCache(args: Fr[]): Promise<Fr> {
|
|
168
|
-
return Promise.resolve(this.executionCache.store(args));
|
|
169
|
-
}
|
|
170
|
-
|
|
171
163
|
/**
|
|
172
164
|
* Store values in the execution cache.
|
|
173
165
|
* @param values - Values to store.
|
|
@@ -327,6 +319,7 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
327
319
|
* This fn exists because sha hashing the preimage
|
|
328
320
|
* is too large to compile (16,200 fields, 518,400 bytes) => the oracle hashes it.
|
|
329
321
|
* See private_context.nr
|
|
322
|
+
* TODO(#8945): Contract class logs are currently sha hashes. When these are fields, delete this.
|
|
330
323
|
* @param log - The unencrypted log to be emitted.
|
|
331
324
|
*/
|
|
332
325
|
public override emitContractClassLog(log: UnencryptedL2Log, counter: number) {
|
package/src/client/db_oracle.ts
CHANGED
|
@@ -233,26 +233,69 @@ export interface DBOracle extends CommitmentsDB {
|
|
|
233
233
|
*/
|
|
234
234
|
processTaggedLogs(logs: TxScopedL2Log[], recipient: AztecAddress): Promise<void>;
|
|
235
235
|
|
|
236
|
+
/**
|
|
237
|
+
* Delivers the preimage and metadata of a committed note so that it can be later requested via the `getNotes`
|
|
238
|
+
* oracle.
|
|
239
|
+
*
|
|
240
|
+
* @param contractAddress - The address of the contract that created the note (i.e. the siloing contract)
|
|
241
|
+
* @param storageSlot - The storage slot of the note - used for indexing in `getNotes`
|
|
242
|
+
* @param nonce - The nonce of the note used by the kernel to compute the unique note hash
|
|
243
|
+
* @param content - The note's content: this is the primary item to return in `getNotes`
|
|
244
|
+
* @param noteHash - The non-unique non-siloed note hash
|
|
245
|
+
* @param nullifier - The inner (non-siloed) note nullifier
|
|
246
|
+
* @param txHash - The transaction in which the note was added to the note hash tree
|
|
247
|
+
* @param recipient - The account that discovered the note
|
|
248
|
+
*/
|
|
249
|
+
deliverNote(
|
|
250
|
+
contractAddress: AztecAddress,
|
|
251
|
+
storageSlot: Fr,
|
|
252
|
+
nonce: Fr,
|
|
253
|
+
content: Fr[],
|
|
254
|
+
noteHash: Fr,
|
|
255
|
+
nullifier: Fr,
|
|
256
|
+
txHash: Fr,
|
|
257
|
+
recipient: AztecAddress,
|
|
258
|
+
): Promise<void>;
|
|
259
|
+
|
|
236
260
|
/**
|
|
237
261
|
* Removes all of a contract's notes that have been nullified from the note database.
|
|
238
262
|
*/
|
|
239
263
|
removeNullifiedNotes(contractAddress: AztecAddress): Promise<void>;
|
|
240
264
|
|
|
241
265
|
/**
|
|
242
|
-
*
|
|
243
|
-
*
|
|
244
|
-
* @param
|
|
245
|
-
* @param
|
|
246
|
-
* @param values -
|
|
266
|
+
* Stores arbitrary information in a per-contract non-volatile database, which can later be retrieved with `dbLoad`.
|
|
267
|
+
* * If data was already stored at this slot, it is overwrriten.
|
|
268
|
+
* @param contractAddress - The contract address to scope the data under.
|
|
269
|
+
* @param slot - The slot in the database in which to store the value. Slots need not be contiguous.
|
|
270
|
+
* @param values - The data to store.
|
|
247
271
|
*/
|
|
248
|
-
|
|
272
|
+
dbStore(contractAddress: AztecAddress, slot: Fr, values: Fr[]): Promise<void>;
|
|
249
273
|
|
|
250
274
|
/**
|
|
251
|
-
*
|
|
252
|
-
*
|
|
253
|
-
* @param
|
|
254
|
-
* @
|
|
255
|
-
|
|
275
|
+
* Returns data previously stored via `dbStore` in the per-contract non-volatile database.
|
|
276
|
+
* @param contractAddress - The contract address under which the data is scoped.
|
|
277
|
+
* @param slot - The slot in the database to read.
|
|
278
|
+
* @returns The stored data or `null` if no data is stored under the slot.
|
|
279
|
+
*/
|
|
280
|
+
dbLoad(contractAddress: AztecAddress, slot: Fr): Promise<Fr[] | null>;
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Deletes data in the per-contract non-volatile database. Does nothing if no data was present.
|
|
284
|
+
* @param contractAddress - The contract address under which the data is scoped.
|
|
285
|
+
* @param slot - The slot in the database to delete.
|
|
286
|
+
*/
|
|
287
|
+
dbDelete(contractAddress: AztecAddress, slot: Fr): Promise<void>;
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Copies a number of contiguous entries in the per-contract non-volatile database. This allows for efficient data
|
|
291
|
+
* structures by avoiding repeated calls to `dbLoad` and `dbStore`.
|
|
292
|
+
* Supports overlapping source and destination regions (which will result in the overlapped source values being
|
|
293
|
+
* overwritten). All copied slots must exist in the database (i.e. have been stored and not deleted)
|
|
294
|
+
*
|
|
295
|
+
* @param contractAddress - The contract address under which the data is scoped.
|
|
296
|
+
* @param srcSlot - The first slot to copy from.
|
|
297
|
+
* @param dstSlot - The first slot to copy to.
|
|
298
|
+
* @param numEntries - The number of entries to copy.
|
|
256
299
|
*/
|
|
257
|
-
|
|
300
|
+
dbCopy(contractAddress: AztecAddress, srcSlot: Fr, dstSlot: Fr, numEntries: number): Promise<void>;
|
|
258
301
|
}
|
|
@@ -29,7 +29,7 @@ export async function executePrivateFunction(
|
|
|
29
29
|
log = createLogger('simulator:private_execution'),
|
|
30
30
|
): Promise<PrivateCallExecutionResult> {
|
|
31
31
|
const functionName = await context.getDebugFunctionName();
|
|
32
|
-
log.verbose(`Executing private function ${functionName}
|
|
32
|
+
log.verbose(`Executing private function ${functionName}`, { contract: contractAddress });
|
|
33
33
|
const acir = artifact.bytecode;
|
|
34
34
|
const initialWitness = context.getInitialWitness(artifact);
|
|
35
35
|
const acvmCallback = new Oracle(context);
|
package/src/client/simulator.ts
CHANGED
|
@@ -192,7 +192,7 @@ export class AcirSimulator {
|
|
|
192
192
|
const execRequest: FunctionCall = {
|
|
193
193
|
name: artifact.name,
|
|
194
194
|
to: contractAddress,
|
|
195
|
-
selector: FunctionSelector.
|
|
195
|
+
selector: FunctionSelector.fromNameAndParameters(artifact),
|
|
196
196
|
type: FunctionType.UNCONSTRAINED,
|
|
197
197
|
isStatic: artifact.isStatic,
|
|
198
198
|
args: encodeArguments(artifact, [
|
|
@@ -22,7 +22,10 @@ export async function executeUnconstrainedFunction(
|
|
|
22
22
|
args: Fr[],
|
|
23
23
|
log = createLogger('simulator:unconstrained_execution'),
|
|
24
24
|
): Promise<AbiDecoded> {
|
|
25
|
-
log.verbose(`Executing unconstrained function ${
|
|
25
|
+
log.verbose(`Executing unconstrained function ${artifact.name}`, {
|
|
26
|
+
contract: contractAddress,
|
|
27
|
+
selector: functionSelector,
|
|
28
|
+
});
|
|
26
29
|
|
|
27
30
|
const acir = artifact.bytecode;
|
|
28
31
|
const initialWitness = toACVMWitness(0, args);
|
|
@@ -310,23 +310,53 @@ export class ViewDataOracle extends TypedOracle {
|
|
|
310
310
|
await this.db.removeNullifiedNotes(this.contractAddress);
|
|
311
311
|
}
|
|
312
312
|
|
|
313
|
-
public override
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
313
|
+
public override async deliverNote(
|
|
314
|
+
contractAddress: AztecAddress,
|
|
315
|
+
storageSlot: Fr,
|
|
316
|
+
nonce: Fr,
|
|
317
|
+
content: Fr[],
|
|
318
|
+
noteHash: Fr,
|
|
319
|
+
nullifier: Fr,
|
|
320
|
+
txHash: Fr,
|
|
321
|
+
recipient: AztecAddress,
|
|
322
|
+
) {
|
|
323
|
+
// TODO(#10727): allow other contracts to deliver notes
|
|
324
|
+
if (!this.contractAddress.equals(contractAddress)) {
|
|
325
|
+
throw new Error(`Got a note delivery request from ${contractAddress}, expected ${this.contractAddress}`);
|
|
319
326
|
}
|
|
320
|
-
|
|
327
|
+
|
|
328
|
+
await this.db.deliverNote(contractAddress, storageSlot, nonce, content, noteHash, nullifier, txHash, recipient);
|
|
321
329
|
}
|
|
322
330
|
|
|
323
|
-
public override
|
|
324
|
-
if (!
|
|
325
|
-
// TODO(#10727): instead of this check
|
|
326
|
-
throw new Error(
|
|
327
|
-
|
|
328
|
-
|
|
331
|
+
public override dbStore(contractAddress: AztecAddress, slot: Fr, values: Fr[]): Promise<void> {
|
|
332
|
+
if (!contractAddress.equals(this.contractAddress)) {
|
|
333
|
+
// TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
|
|
334
|
+
throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
|
|
335
|
+
}
|
|
336
|
+
return this.db.dbStore(this.contractAddress, slot, values);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
public override dbLoad(contractAddress: AztecAddress, slot: Fr): Promise<Fr[] | null> {
|
|
340
|
+
if (!contractAddress.equals(this.contractAddress)) {
|
|
341
|
+
// TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
|
|
342
|
+
throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
|
|
343
|
+
}
|
|
344
|
+
return this.db.dbLoad(this.contractAddress, slot);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
public override dbDelete(contractAddress: AztecAddress, slot: Fr): Promise<void> {
|
|
348
|
+
if (!contractAddress.equals(this.contractAddress)) {
|
|
349
|
+
// TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
|
|
350
|
+
throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
|
|
351
|
+
}
|
|
352
|
+
return this.db.dbDelete(this.contractAddress, slot);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
public override dbCopy(contractAddress: AztecAddress, srcSlot: Fr, dstSlot: Fr, numEntries: number): Promise<void> {
|
|
356
|
+
if (!contractAddress.equals(this.contractAddress)) {
|
|
357
|
+
// TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
|
|
358
|
+
throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
|
|
329
359
|
}
|
|
330
|
-
return this.db.
|
|
360
|
+
return this.db.dbCopy(this.contractAddress, srcSlot, dstSlot, numEntries);
|
|
331
361
|
}
|
|
332
362
|
}
|