@aztec/simulator 0.67.1 → 0.68.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/oracle/oracle.d.ts +1 -1
- package/dest/acvm/oracle/oracle.d.ts.map +1 -1
- package/dest/acvm/oracle/oracle.js +3 -3
- package/dest/acvm/oracle/typed_oracle.d.ts +1 -1
- package/dest/acvm/oracle/typed_oracle.d.ts.map +1 -1
- package/dest/acvm/oracle/typed_oracle.js +3 -3
- package/dest/avm/avm_memory_types.d.ts +1 -1
- package/dest/avm/avm_memory_types.d.ts.map +1 -1
- package/dest/avm/avm_memory_types.js +45 -38
- package/dest/avm/avm_simulator.d.ts +1 -0
- package/dest/avm/avm_simulator.d.ts.map +1 -1
- package/dest/avm/avm_simulator.js +38 -18
- package/dest/avm/avm_tree.d.ts +2 -23
- package/dest/avm/avm_tree.d.ts.map +1 -1
- package/dest/avm/avm_tree.js +27 -82
- package/dest/avm/errors.d.ts +8 -1
- package/dest/avm/errors.d.ts.map +1 -1
- package/dest/avm/errors.js +13 -3
- package/dest/avm/fixtures/index.d.ts +2 -0
- package/dest/avm/fixtures/index.d.ts.map +1 -1
- package/dest/avm/fixtures/index.js +4 -4
- package/dest/avm/journal/journal.d.ts +15 -7
- package/dest/avm/journal/journal.d.ts.map +1 -1
- package/dest/avm/journal/journal.js +30 -22
- package/dest/avm/journal/nullifiers.d.ts +0 -4
- package/dest/avm/journal/nullifiers.d.ts.map +1 -1
- package/dest/avm/journal/nullifiers.js +1 -11
- package/dest/avm/journal/public_storage.d.ts +1 -49
- package/dest/avm/journal/public_storage.d.ts.map +1 -1
- package/dest/avm/journal/public_storage.js +1 -19
- package/dest/avm/opcodes/addressing_mode.js +3 -3
- package/dest/avm/opcodes/conversion.d.ts +4 -4
- package/dest/avm/opcodes/conversion.d.ts.map +1 -1
- package/dest/avm/opcodes/conversion.js +22 -18
- package/dest/avm/opcodes/ec_add.d.ts.map +1 -1
- package/dest/avm/opcodes/ec_add.js +5 -4
- package/dest/avm/opcodes/external_calls.js +2 -2
- package/dest/avm/opcodes/hashing.d.ts.map +1 -1
- package/dest/avm/opcodes/hashing.js +5 -5
- package/dest/avm/opcodes/misc.d.ts.map +1 -1
- package/dest/avm/opcodes/misc.js +3 -3
- package/dest/avm/opcodes/multi_scalar_mul.d.ts.map +1 -1
- package/dest/avm/opcodes/multi_scalar_mul.js +9 -6
- package/dest/avm/test_utils.d.ts +1 -0
- package/dest/avm/test_utils.d.ts.map +1 -1
- package/dest/avm/test_utils.js +4 -1
- package/dest/client/client_execution_context.d.ts.map +1 -1
- package/dest/client/client_execution_context.js +2 -1
- package/dest/client/db_oracle.d.ts +7 -3
- package/dest/client/db_oracle.d.ts.map +1 -1
- package/dest/client/index.d.ts +1 -0
- package/dest/client/index.d.ts.map +1 -1
- package/dest/client/index.js +2 -1
- package/dest/client/view_data_oracle.d.ts +2 -2
- package/dest/client/view_data_oracle.d.ts.map +1 -1
- package/dest/client/view_data_oracle.js +5 -4
- package/dest/providers/acvm_wasm.js +2 -2
- package/dest/providers/acvm_wasm_with_blobs.d.ts +7 -0
- package/dest/providers/acvm_wasm_with_blobs.d.ts.map +1 -0
- package/dest/providers/acvm_wasm_with_blobs.js +15 -0
- package/dest/providers/index.d.ts +1 -1
- package/dest/providers/index.d.ts.map +1 -1
- package/dest/providers/index.js +2 -2
- package/dest/public/bytecode_errors.d.ts +4 -0
- package/dest/public/bytecode_errors.d.ts.map +1 -0
- package/dest/public/bytecode_errors.js +7 -0
- package/dest/public/enqueued_call_side_effect_trace.d.ts +10 -4
- package/dest/public/enqueued_call_side_effect_trace.d.ts.map +1 -1
- package/dest/public/enqueued_call_side_effect_trace.js +63 -13
- package/dest/public/execution.d.ts +2 -2
- package/dest/public/execution.d.ts.map +1 -1
- package/dest/public/execution.js +1 -1
- package/dest/public/executor_metrics.d.ts +2 -0
- package/dest/public/executor_metrics.d.ts.map +1 -1
- package/dest/public/executor_metrics.js +11 -1
- package/dest/public/fee_payment.d.ts.map +1 -1
- package/dest/public/fee_payment.js +4 -3
- package/dest/public/fixtures/index.d.ts +17 -11
- package/dest/public/fixtures/index.d.ts.map +1 -1
- package/dest/public/fixtures/index.js +103 -35
- package/dest/public/public_db_sources.d.ts.map +1 -1
- package/dest/public/public_db_sources.js +7 -6
- package/dest/public/public_processor.d.ts +15 -7
- package/dest/public/public_processor.d.ts.map +1 -1
- package/dest/public/public_processor.js +119 -75
- package/dest/public/public_processor_metrics.d.ts +10 -2
- package/dest/public/public_processor_metrics.d.ts.map +1 -1
- package/dest/public/public_processor_metrics.js +49 -2
- package/dest/public/public_tx_context.d.ts +5 -0
- package/dest/public/public_tx_context.d.ts.map +1 -1
- package/dest/public/public_tx_context.js +40 -20
- package/dest/public/public_tx_simulator.d.ts +2 -1
- package/dest/public/public_tx_simulator.d.ts.map +1 -1
- package/dest/public/public_tx_simulator.js +35 -6
- package/dest/public/side_effect_errors.js +2 -2
- package/dest/public/side_effect_trace_interface.d.ts +2 -1
- package/dest/public/side_effect_trace_interface.d.ts.map +1 -1
- package/dest/public/transitional_adapters.d.ts.map +1 -1
- package/dest/public/transitional_adapters.js +2 -35
- package/dest/public/unique_class_ids.d.ts +37 -0
- package/dest/public/unique_class_ids.d.ts.map +1 -0
- package/dest/public/unique_class_ids.js +66 -0
- package/package.json +12 -12
- package/src/acvm/oracle/oracle.ts +2 -2
- package/src/acvm/oracle/typed_oracle.ts +2 -2
- package/src/avm/avm_memory_types.ts +56 -38
- package/src/avm/avm_simulator.ts +48 -20
- package/src/avm/avm_tree.ts +35 -92
- package/src/avm/errors.ts +13 -2
- package/src/avm/fixtures/index.ts +4 -2
- package/src/avm/journal/journal.ts +39 -29
- package/src/avm/journal/nullifiers.ts +0 -11
- package/src/avm/journal/public_storage.ts +2 -21
- package/src/avm/opcodes/addressing_mode.ts +2 -2
- package/src/avm/opcodes/conversion.ts +21 -16
- package/src/avm/opcodes/ec_add.ts +4 -3
- package/src/avm/opcodes/external_calls.ts +1 -1
- package/src/avm/opcodes/hashing.ts +6 -4
- package/src/avm/opcodes/misc.ts +4 -3
- package/src/avm/opcodes/multi_scalar_mul.ts +10 -5
- package/src/avm/test_utils.ts +4 -0
- package/src/client/client_execution_context.ts +2 -0
- package/src/client/db_oracle.ts +8 -3
- package/src/client/index.ts +1 -0
- package/src/client/view_data_oracle.ts +6 -3
- package/src/providers/acvm_wasm.ts +1 -1
- package/src/providers/acvm_wasm_with_blobs.ts +25 -0
- package/src/providers/index.ts +1 -1
- package/src/public/bytecode_errors.ts +6 -0
- package/src/public/enqueued_call_side_effect_trace.ts +83 -19
- package/src/public/execution.ts +1 -2
- package/src/public/executor_metrics.ts +13 -0
- package/src/public/fee_payment.ts +3 -2
- package/src/public/fixtures/index.ts +152 -46
- package/src/public/public_db_sources.ts +6 -5
- package/src/public/public_processor.ts +171 -88
- package/src/public/public_processor_metrics.ts +64 -2
- package/src/public/public_tx_context.ts +57 -21
- package/src/public/public_tx_simulator.ts +34 -6
- package/src/public/side_effect_errors.ts +1 -1
- package/src/public/side_effect_trace_interface.ts +2 -1
- package/src/public/transitional_adapters.ts +0 -51
- package/src/public/unique_class_ids.ts +80 -0
|
@@ -56,6 +56,7 @@ export class PublicTxSimulator {
|
|
|
56
56
|
telemetryClient: TelemetryClient,
|
|
57
57
|
private globalVariables: GlobalVariables,
|
|
58
58
|
private doMerkleOperations: boolean = false,
|
|
59
|
+
private enforceFeePayment: boolean = true,
|
|
59
60
|
) {
|
|
60
61
|
this.log = createLogger(`simulator:public_tx_simulator`);
|
|
61
62
|
this.metrics = new ExecutorMetrics(telemetryClient, 'PublicTxSimulator');
|
|
@@ -90,14 +91,20 @@ export class PublicTxSimulator {
|
|
|
90
91
|
// FIXME: we shouldn't need to directly modify worldStateDb here!
|
|
91
92
|
await this.worldStateDB.addNewContracts(tx);
|
|
92
93
|
|
|
94
|
+
const nonRevertStart = process.hrtime.bigint();
|
|
93
95
|
await this.insertNonRevertiblesFromPrivate(context);
|
|
96
|
+
const nonRevertEnd = process.hrtime.bigint();
|
|
97
|
+
this.metrics.recordPrivateEffectsInsertion(Number(nonRevertEnd - nonRevertStart) / 1_000, 'non-revertible');
|
|
94
98
|
const processedPhases: ProcessedPhase[] = [];
|
|
95
99
|
if (context.hasPhase(TxExecutionPhase.SETUP)) {
|
|
96
100
|
const setupResult: ProcessedPhase = await this.simulateSetupPhase(context);
|
|
97
101
|
processedPhases.push(setupResult);
|
|
98
102
|
}
|
|
99
103
|
|
|
104
|
+
const revertStart = process.hrtime.bigint();
|
|
100
105
|
await this.insertRevertiblesFromPrivate(context);
|
|
106
|
+
const revertEnd = process.hrtime.bigint();
|
|
107
|
+
this.metrics.recordPrivateEffectsInsertion(Number(revertEnd - revertStart) / 1_000, 'revertible');
|
|
101
108
|
if (context.hasPhase(TxExecutionPhase.APP_LOGIC)) {
|
|
102
109
|
const appLogicResult: ProcessedPhase = await this.simulateAppLogicPhase(context);
|
|
103
110
|
processedPhases.push(appLogicResult);
|
|
@@ -134,7 +141,11 @@ export class PublicTxSimulator {
|
|
|
134
141
|
|
|
135
142
|
return {
|
|
136
143
|
avmProvingRequest,
|
|
137
|
-
gasUsed: {
|
|
144
|
+
gasUsed: {
|
|
145
|
+
totalGas: context.getActualGasUsed(),
|
|
146
|
+
teardownGas: context.teardownGasUsed,
|
|
147
|
+
publicGas: context.getActualPublicGasUsed(),
|
|
148
|
+
},
|
|
138
149
|
revertCode,
|
|
139
150
|
revertReason: context.revertReason,
|
|
140
151
|
processedPhases: processedPhases,
|
|
@@ -344,7 +355,7 @@ export class PublicTxSimulator {
|
|
|
344
355
|
const avmCallResult = await simulator.execute();
|
|
345
356
|
const result = avmCallResult.finalize();
|
|
346
357
|
|
|
347
|
-
this.log.
|
|
358
|
+
this.log.verbose(
|
|
348
359
|
result.reverted
|
|
349
360
|
? `Simulation of enqueued public call ${fnName} reverted with reason ${result.revertReason}.`
|
|
350
361
|
: `Simulation of enqueued public call ${fnName} completed successfully.`,
|
|
@@ -378,6 +389,11 @@ export class PublicTxSimulator {
|
|
|
378
389
|
);
|
|
379
390
|
}
|
|
380
391
|
}
|
|
392
|
+
for (const noteHash of context.nonRevertibleAccumulatedDataFromPrivate.noteHashes) {
|
|
393
|
+
if (!noteHash.isEmpty()) {
|
|
394
|
+
stateManager.writeUniqueNoteHash(noteHash);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
381
397
|
}
|
|
382
398
|
|
|
383
399
|
/**
|
|
@@ -397,6 +413,12 @@ export class PublicTxSimulator {
|
|
|
397
413
|
);
|
|
398
414
|
}
|
|
399
415
|
}
|
|
416
|
+
for (const noteHash of context.revertibleAccumulatedDataFromPrivate.noteHashes) {
|
|
417
|
+
if (!noteHash.isEmpty()) {
|
|
418
|
+
// Revertible note hashes from private are not hashed with nonce, since private can't know their final position, only we can.
|
|
419
|
+
stateManager.writeSiloedNoteHash(noteHash);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
400
422
|
}
|
|
401
423
|
|
|
402
424
|
private async payFee(context: PublicTxContext) {
|
|
@@ -413,12 +435,18 @@ export class PublicTxSimulator {
|
|
|
413
435
|
this.log.debug(`Deducting ${txFee.toBigInt()} balance in Fee Juice for ${context.feePayer}`);
|
|
414
436
|
const stateManager = context.state.getActiveStateManager();
|
|
415
437
|
|
|
416
|
-
|
|
438
|
+
let currentBalance = await stateManager.readStorage(feeJuiceAddress, balanceSlot);
|
|
439
|
+
// We allow to fake the balance of the fee payer to allow fee estimation
|
|
440
|
+
// When mocking the balance of the fee payer, the circuit should not be able to prove the simulation
|
|
417
441
|
|
|
418
442
|
if (currentBalance.lt(txFee)) {
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
443
|
+
if (this.enforceFeePayment) {
|
|
444
|
+
throw new Error(
|
|
445
|
+
`Not enough balance for fee payer to pay for transaction (got ${currentBalance.toBigInt()} needs ${txFee.toBigInt()})`,
|
|
446
|
+
);
|
|
447
|
+
} else {
|
|
448
|
+
currentBalance = txFee;
|
|
449
|
+
}
|
|
422
450
|
}
|
|
423
451
|
|
|
424
452
|
const updatedBalance = currentBalance.sub(txFee);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export class SideEffectLimitReachedError extends Error {
|
|
2
2
|
constructor(sideEffectType: string, limit: number) {
|
|
3
|
-
super(`Reached the limit on number of '${sideEffectType}'
|
|
3
|
+
super(`Reached the limit (${limit}) on number of '${sideEffectType}' per tx`);
|
|
4
4
|
this.name = 'SideEffectLimitReachedError';
|
|
5
5
|
}
|
|
6
6
|
}
|
|
@@ -39,7 +39,8 @@ export interface PublicSideEffectTraceInterface {
|
|
|
39
39
|
insertionPath?: Fr[],
|
|
40
40
|
): void;
|
|
41
41
|
traceNoteHashCheck(contractAddress: AztecAddress, noteHash: Fr, leafIndex: Fr, exists: boolean, path?: Fr[]): void;
|
|
42
|
-
traceNewNoteHash(
|
|
42
|
+
traceNewNoteHash(uniqueNoteHash: Fr, leafIndex?: Fr, path?: Fr[]): void;
|
|
43
|
+
getNoteHashCount(): number;
|
|
43
44
|
traceNullifierCheck(
|
|
44
45
|
siloedNullifier: Fr,
|
|
45
46
|
exists: boolean,
|
|
@@ -6,7 +6,6 @@ import {
|
|
|
6
6
|
type GasSettings,
|
|
7
7
|
type GlobalVariables,
|
|
8
8
|
MAX_L2_TO_L1_MSGS_PER_TX,
|
|
9
|
-
MAX_NOTE_HASHES_PER_TX,
|
|
10
9
|
MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
|
|
11
10
|
PrivateToAvmAccumulatedData,
|
|
12
11
|
PrivateToAvmAccumulatedDataArrayLengths,
|
|
@@ -19,7 +18,6 @@ import {
|
|
|
19
18
|
countAccumulatedItems,
|
|
20
19
|
mergeAccumulatedData,
|
|
21
20
|
} from '@aztec/circuits.js';
|
|
22
|
-
import { computeNoteHashNonce, computeUniqueNoteHash, siloNoteHash } from '@aztec/circuits.js/hash';
|
|
23
21
|
import { padArrayEnd } from '@aztec/foundation/collection';
|
|
24
22
|
import { assertLength } from '@aztec/foundation/serialize';
|
|
25
23
|
|
|
@@ -86,55 +84,6 @@ export function generateAvmCircuitPublicInputs(
|
|
|
86
84
|
revertibleAccumulatedDataFromPrivate,
|
|
87
85
|
);
|
|
88
86
|
|
|
89
|
-
const txHash = avmCircuitPublicInputs.previousNonRevertibleAccumulatedData.nullifiers[0];
|
|
90
|
-
|
|
91
|
-
// Add nonces to revertible note hashes from private. These don't have nonces since we don't know
|
|
92
|
-
// the final position in the tx until the AVM has executed.
|
|
93
|
-
// TODO: Use the final position in the tx
|
|
94
|
-
for (
|
|
95
|
-
let revertibleIndex = 0;
|
|
96
|
-
revertibleIndex < avmCircuitPublicInputs.previousRevertibleAccumulatedData.noteHashes.length;
|
|
97
|
-
revertibleIndex++
|
|
98
|
-
) {
|
|
99
|
-
const noteHash = avmCircuitPublicInputs.previousRevertibleAccumulatedData.noteHashes[revertibleIndex];
|
|
100
|
-
if (noteHash.isZero()) {
|
|
101
|
-
continue;
|
|
102
|
-
}
|
|
103
|
-
const indexInTx =
|
|
104
|
-
revertibleIndex + avmCircuitPublicInputs.previousNonRevertibleAccumulatedDataArrayLengths.noteHashes;
|
|
105
|
-
|
|
106
|
-
const nonce = computeNoteHashNonce(txHash, indexInTx);
|
|
107
|
-
const uniqueNoteHash = computeUniqueNoteHash(nonce, noteHash);
|
|
108
|
-
avmCircuitPublicInputs.previousRevertibleAccumulatedData.noteHashes[revertibleIndex] = uniqueNoteHash;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// merge all revertible & non-revertible side effects into output accumulated data
|
|
112
|
-
const noteHashesFromPrivate = revertCode.isOK()
|
|
113
|
-
? mergeAccumulatedData(
|
|
114
|
-
avmCircuitPublicInputs.previousNonRevertibleAccumulatedData.noteHashes,
|
|
115
|
-
avmCircuitPublicInputs.previousRevertibleAccumulatedData.noteHashes,
|
|
116
|
-
)
|
|
117
|
-
: avmCircuitPublicInputs.previousNonRevertibleAccumulatedData.noteHashes;
|
|
118
|
-
avmCircuitPublicInputs.accumulatedData.noteHashes = assertLength(
|
|
119
|
-
mergeAccumulatedData(noteHashesFromPrivate, avmCircuitPublicInputs.accumulatedData.noteHashes),
|
|
120
|
-
MAX_NOTE_HASHES_PER_TX,
|
|
121
|
-
);
|
|
122
|
-
|
|
123
|
-
// Silo and add nonces for note hashes emitted by the AVM
|
|
124
|
-
const scopedNoteHashesFromPublic = trace.getSideEffects().noteHashes;
|
|
125
|
-
for (let i = 0; i < scopedNoteHashesFromPublic.length; i++) {
|
|
126
|
-
const scopedNoteHash = scopedNoteHashesFromPublic[i];
|
|
127
|
-
const noteHash = scopedNoteHash.value;
|
|
128
|
-
if (!noteHash.isZero()) {
|
|
129
|
-
const noteHashIndexInTx = i + countAccumulatedItems(noteHashesFromPrivate);
|
|
130
|
-
const nonce = computeNoteHashNonce(txHash, noteHashIndexInTx);
|
|
131
|
-
const siloedNoteHash = siloNoteHash(scopedNoteHash.contractAddress, noteHash);
|
|
132
|
-
const uniqueNoteHash = computeUniqueNoteHash(nonce, siloedNoteHash);
|
|
133
|
-
|
|
134
|
-
avmCircuitPublicInputs.accumulatedData.noteHashes[noteHashIndexInTx] = uniqueNoteHash;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
87
|
const msgsFromPrivate = revertCode.isOK()
|
|
139
88
|
? mergeAccumulatedData(
|
|
140
89
|
avmCircuitPublicInputs.previousNonRevertibleAccumulatedData.l2ToL1Msgs,
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { MAX_PUBLIC_CALLS_TO_UNIQUE_CONTRACT_CLASS_IDS } from '@aztec/circuits.js';
|
|
2
|
+
|
|
3
|
+
import { strict as assert } from 'assert';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A class manage a de-duplicated set of class IDs that errors if you try to add a duplicate.
|
|
7
|
+
* Useful for bytecode retrieval hints to avoid duplicates in parent trace & grandparent trace....
|
|
8
|
+
*/
|
|
9
|
+
export class UniqueClassIds {
|
|
10
|
+
private readonly classIds: Set<string> = new Set();
|
|
11
|
+
|
|
12
|
+
constructor(private readonly parent?: UniqueClassIds) {}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Create a fork that references this one as its parent
|
|
16
|
+
*/
|
|
17
|
+
public fork() {
|
|
18
|
+
return new UniqueClassIds(/*parent=*/ this);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Check for a class ID here or in parent's (recursively).
|
|
23
|
+
*
|
|
24
|
+
* @param classId - the contract class ID (as a string) to check
|
|
25
|
+
* @returns boolean: whether the class ID is here
|
|
26
|
+
*/
|
|
27
|
+
public has(classId: string): boolean {
|
|
28
|
+
// First try check this' classIds
|
|
29
|
+
let here = this.classIds.has(classId);
|
|
30
|
+
// Then try parent's
|
|
31
|
+
if (!here && this.parent) {
|
|
32
|
+
// Note: this will recurse to grandparent/etc until we reach top or find it
|
|
33
|
+
here = this.parent.has(classId);
|
|
34
|
+
}
|
|
35
|
+
return here;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Get the total number of classIds
|
|
40
|
+
*/
|
|
41
|
+
public size(): number {
|
|
42
|
+
return this.classIds.size + (this.parent ? this.parent.size() : 0);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Add a class ID (if not already present) to the set.
|
|
47
|
+
*
|
|
48
|
+
* @param classId - the contract class ID (as a string)
|
|
49
|
+
*/
|
|
50
|
+
public add(classId: string) {
|
|
51
|
+
assert(!this.has(classId), `Bug! Tried to add duplicate classId ${classId} to set of unique classIds.`);
|
|
52
|
+
if (!this.has(classId)) {
|
|
53
|
+
this.classIds.add(classId);
|
|
54
|
+
assert(
|
|
55
|
+
this.size() <= MAX_PUBLIC_CALLS_TO_UNIQUE_CONTRACT_CLASS_IDS,
|
|
56
|
+
`Bug! Surpassed limit (${MAX_PUBLIC_CALLS_TO_UNIQUE_CONTRACT_CLASS_IDS}) of unique contract class IDs used for bytecode retrievals.`,
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Merge in another set of unique class IDs into this one, but fail on duplicates.
|
|
63
|
+
*
|
|
64
|
+
* @param incoming: other unique class IDs
|
|
65
|
+
*/
|
|
66
|
+
public acceptAndMerge(incoming: UniqueClassIds) {
|
|
67
|
+
for (const classId of incoming.classIds.keys()) {
|
|
68
|
+
assert(
|
|
69
|
+
!this.has(classId),
|
|
70
|
+
`Bug! Cannot merge classId ${classId} into set of unique classIds as it already exists.`,
|
|
71
|
+
);
|
|
72
|
+
this.classIds.add(classId);
|
|
73
|
+
}
|
|
74
|
+
// since set() has an assertion, and size() always checks parent, this should be impossible
|
|
75
|
+
assert(
|
|
76
|
+
this.size() <= MAX_PUBLIC_CALLS_TO_UNIQUE_CONTRACT_CLASS_IDS,
|
|
77
|
+
`Bug! Merging unique class Ids should never exceed the limit of ${MAX_PUBLIC_CALLS_TO_UNIQUE_CONTRACT_CLASS_IDS}.`,
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
}
|