@aztec/simulator 0.0.1-commit.993d52e → 0.0.1-commit.9badcec54
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/private/circuit_recording/circuit_recorder.js +2 -2
- package/dest/public/avm/avm_simulator.js +1 -1
- package/dest/public/avm/calldata.d.ts +1 -1
- package/dest/public/avm/calldata.d.ts.map +1 -1
- package/dest/public/avm/calldata.js +3 -2
- package/dest/public/contracts_db_checkpoint.d.ts +2 -2
- package/dest/public/contracts_db_checkpoint.d.ts.map +1 -1
- package/dest/public/contracts_db_checkpoint.js +1 -1
- package/dest/public/fixtures/bulk_test.d.ts +1 -1
- package/dest/public/fixtures/bulk_test.d.ts.map +1 -1
- package/dest/public/fixtures/bulk_test.js +4 -4
- package/dest/public/fixtures/public_tx_simulation_tester.d.ts +6 -5
- package/dest/public/fixtures/public_tx_simulation_tester.d.ts.map +1 -1
- package/dest/public/fixtures/public_tx_simulation_tester.js +37 -10
- package/dest/public/fixtures/utils.d.ts +2 -2
- package/dest/public/fixtures/utils.d.ts.map +1 -1
- package/dest/public/fixtures/utils.js +6 -6
- package/dest/public/hinting_db_sources.d.ts +4 -4
- package/dest/public/hinting_db_sources.d.ts.map +1 -1
- package/dest/public/hinting_db_sources.js +6 -5
- package/dest/public/public_db_sources.d.ts +3 -3
- package/dest/public/public_db_sources.d.ts.map +1 -1
- package/dest/public/public_db_sources.js +10 -10
- package/dest/public/public_processor/guarded_merkle_tree.d.ts +4 -4
- package/dest/public/public_processor/guarded_merkle_tree.d.ts.map +1 -1
- package/dest/public/public_processor/guarded_merkle_tree.js +4 -4
- package/dest/public/public_processor/public_processor.d.ts +2 -2
- package/dest/public/public_processor/public_processor.d.ts.map +1 -1
- package/dest/public/public_processor/public_processor.js +37 -37
- package/dest/public/public_tx_simulator/contract_provider_for_cpp.d.ts +1 -1
- package/dest/public/public_tx_simulator/contract_provider_for_cpp.d.ts.map +1 -1
- package/dest/public/public_tx_simulator/contract_provider_for_cpp.js +2 -1
- package/dest/public/public_tx_simulator/public_tx_context.d.ts +7 -3
- package/dest/public/public_tx_simulator/public_tx_context.d.ts.map +1 -1
- package/dest/public/public_tx_simulator/public_tx_context.js +8 -10
- package/dest/public/public_tx_simulator/public_tx_simulator.d.ts +6 -2
- package/dest/public/public_tx_simulator/public_tx_simulator.d.ts.map +1 -1
- package/dest/public/public_tx_simulator/public_tx_simulator.js +12 -7
- package/dest/public/test_executor_metrics.d.ts +6 -1
- package/dest/public/test_executor_metrics.d.ts.map +1 -1
- package/dest/public/test_executor_metrics.js +22 -0
- package/package.json +15 -16
- package/src/private/circuit_recording/circuit_recorder.ts +2 -2
- package/src/public/avm/avm_simulator.ts +1 -1
- package/src/public/avm/calldata.ts +3 -2
- package/src/public/avm/opcodes/external_calls.ts +1 -1
- package/src/public/contracts_db_checkpoint.ts +1 -1
- package/src/public/fixtures/bulk_test.ts +2 -4
- package/src/public/fixtures/public_tx_simulation_tester.ts +44 -11
- package/src/public/fixtures/utils.ts +13 -8
- package/src/public/hinting_db_sources.ts +8 -6
- package/src/public/public_db_sources.ts +12 -14
- package/src/public/public_processor/guarded_merkle_tree.ts +5 -5
- package/src/public/public_processor/public_processor.ts +46 -42
- package/src/public/public_tx_simulator/contract_provider_for_cpp.ts +2 -1
- package/src/public/public_tx_simulator/public_tx_context.ts +8 -10
- package/src/public/public_tx_simulator/public_tx_simulator.ts +11 -7
- package/src/public/test_executor_metrics.ts +24 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/simulator",
|
|
3
|
-
"version": "0.0.1-commit.
|
|
3
|
+
"version": "0.0.1-commit.9badcec54",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
"./server": "./dest/server.js",
|
|
@@ -64,26 +64,25 @@
|
|
|
64
64
|
]
|
|
65
65
|
},
|
|
66
66
|
"dependencies": {
|
|
67
|
-
"@aztec/constants": "0.0.1-commit.
|
|
68
|
-
"@aztec/foundation": "0.0.1-commit.
|
|
69
|
-
"@aztec/native": "0.0.1-commit.
|
|
70
|
-
"@aztec/noir-acvm_js": "0.0.1-commit.
|
|
71
|
-
"@aztec/noir-noirc_abi": "0.0.1-commit.
|
|
72
|
-
"@aztec/noir-protocol-circuits-types": "0.0.1-commit.
|
|
73
|
-
"@aztec/noir-types": "0.0.1-commit.
|
|
74
|
-
"@aztec/protocol-contracts": "0.0.1-commit.
|
|
75
|
-
"@aztec/stdlib": "0.0.1-commit.
|
|
76
|
-
"@aztec/telemetry-client": "0.0.1-commit.
|
|
77
|
-
"@aztec/world-state": "0.0.1-commit.
|
|
67
|
+
"@aztec/constants": "0.0.1-commit.9badcec54",
|
|
68
|
+
"@aztec/foundation": "0.0.1-commit.9badcec54",
|
|
69
|
+
"@aztec/native": "0.0.1-commit.9badcec54",
|
|
70
|
+
"@aztec/noir-acvm_js": "0.0.1-commit.9badcec54",
|
|
71
|
+
"@aztec/noir-noirc_abi": "0.0.1-commit.9badcec54",
|
|
72
|
+
"@aztec/noir-protocol-circuits-types": "0.0.1-commit.9badcec54",
|
|
73
|
+
"@aztec/noir-types": "0.0.1-commit.9badcec54",
|
|
74
|
+
"@aztec/protocol-contracts": "0.0.1-commit.9badcec54",
|
|
75
|
+
"@aztec/stdlib": "0.0.1-commit.9badcec54",
|
|
76
|
+
"@aztec/telemetry-client": "0.0.1-commit.9badcec54",
|
|
77
|
+
"@aztec/world-state": "0.0.1-commit.9badcec54",
|
|
78
78
|
"lodash.clonedeep": "^4.5.0",
|
|
79
79
|
"lodash.merge": "^4.6.2",
|
|
80
80
|
"tslib": "^2.4.0"
|
|
81
81
|
},
|
|
82
82
|
"devDependencies": {
|
|
83
|
-
"@aztec/kv-store": "0.0.1-commit.
|
|
84
|
-
"@aztec/
|
|
85
|
-
"@aztec/noir-contracts.js": "0.0.1-commit.
|
|
86
|
-
"@aztec/noir-test-contracts.js": "0.0.1-commit.993d52e",
|
|
83
|
+
"@aztec/kv-store": "0.0.1-commit.9badcec54",
|
|
84
|
+
"@aztec/noir-contracts.js": "0.0.1-commit.9badcec54",
|
|
85
|
+
"@aztec/noir-test-contracts.js": "0.0.1-commit.9badcec54",
|
|
87
86
|
"@jest/globals": "^30.0.0",
|
|
88
87
|
"@types/jest": "^30.0.0",
|
|
89
88
|
"@types/lodash.clonedeep": "^4.5.7",
|
|
@@ -161,11 +161,11 @@ export class CircuitRecorder {
|
|
|
161
161
|
throw new Error(`Oracle method ${name} not found when setting up recording callback`);
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
-
const isExternalCall = (name as keyof ACIRCallback) === '
|
|
164
|
+
const isExternalCall = (name as keyof ACIRCallback) === 'aztec_prv_callPrivateFunction';
|
|
165
165
|
|
|
166
166
|
recordingCallback[name as keyof ACIRCallback] = (...args: ForeignCallInput[]): ReturnType<typeof fn> => {
|
|
167
167
|
const timer = new Timer();
|
|
168
|
-
// If we're entering another circuit via `
|
|
168
|
+
// If we're entering another circuit via `aztec_prv_callPrivateFunction`, we increase the stack depth and set the
|
|
169
169
|
// newCircuit variable to ensure we are creating a new recording object.
|
|
170
170
|
if (isExternalCall) {
|
|
171
171
|
this.stackDepth++;
|
|
@@ -63,7 +63,7 @@ export class AvmSimulator implements AvmSimulatorInterface {
|
|
|
63
63
|
public static async build(context: AvmContext): Promise<AvmSimulator> {
|
|
64
64
|
const simulator = new AvmSimulator(context);
|
|
65
65
|
const fnName = await context.persistableState.getPublicFunctionDebugName(context.environment);
|
|
66
|
-
simulator.log = createLogger(`simulator:avm(f:${fnName})`);
|
|
66
|
+
simulator.log = createLogger(`simulator:avm(f:${fnName.slice(0, 128)})`);
|
|
67
67
|
|
|
68
68
|
return simulator;
|
|
69
69
|
}
|
|
@@ -33,13 +33,14 @@ export class LazyReaderMemory implements LazyReader {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
public slice(start: number, end: number): Fr[] {
|
|
36
|
-
const clampedEnd = Math.min(end, this.size);
|
|
36
|
+
const clampedEnd = Math.min(end, this.size, TaggedMemory.MAX_MEMORY_SIZE - this.offset);
|
|
37
37
|
const length = Math.max(0, clampedEnd - start);
|
|
38
38
|
return this.memory.getSlice(this.offset + start, length).map(word => word.toFr());
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
public readAll(): Fr[] {
|
|
42
|
-
|
|
42
|
+
const size = Math.min(this.size, TaggedMemory.MAX_MEMORY_SIZE - this.offset);
|
|
43
|
+
return this.memory.getSlice(this.offset, size).map(word => word.toFr());
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
public length(): number {
|
|
@@ -14,8 +14,8 @@ abstract class ExternalCall extends Instruction {
|
|
|
14
14
|
OperandType.UINT16, // L2 gas offset
|
|
15
15
|
OperandType.UINT16, // DA gas offset
|
|
16
16
|
OperandType.UINT16, // Address offset
|
|
17
|
-
OperandType.UINT16, // Args offset
|
|
18
17
|
OperandType.UINT16, // Args size offset
|
|
18
|
+
OperandType.UINT16, // Args offset
|
|
19
19
|
];
|
|
20
20
|
|
|
21
21
|
constructor(
|
|
@@ -31,7 +31,7 @@ export class ContractsDbCheckpoint {
|
|
|
31
31
|
return this.bytecodeCommitments.get(classId.toString());
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
public
|
|
34
|
+
public fork(): ContractsDbCheckpoint {
|
|
35
35
|
const copy = new ContractsDbCheckpoint();
|
|
36
36
|
this.instances.forEach((value, key) => copy.instances.set(key, value));
|
|
37
37
|
this.classes.forEach((value, key) => copy.classes.set(key, value));
|
|
@@ -30,9 +30,7 @@ export async function bulkTest(
|
|
|
30
30
|
// for it to use as "expected" values when testing contract instance retrieval.
|
|
31
31
|
const expectContractInstance = avmTestContract;
|
|
32
32
|
const argsField = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(x => new Fr(x));
|
|
33
|
-
const argsU8 = [1, 2, 3, 4, 5, 6, 7, 8].map(x => new Fr(x));
|
|
34
|
-
argsU8.push(new Fr(2n ** 128n + 9n)); // Trigger truncation from large (> 128 bits) value (canonical decomposition event)
|
|
35
|
-
argsU8.push(new Fr(2n ** 125n + 10n)); // Trigger truncation from small (< 128 bits) value (no canonical decomposition event)
|
|
33
|
+
const argsU8 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(x => new Fr(x));
|
|
36
34
|
const args = [
|
|
37
35
|
argsField,
|
|
38
36
|
argsU8,
|
|
@@ -62,7 +60,7 @@ export async function bulkTest(
|
|
|
62
60
|
{
|
|
63
61
|
address: avmTestContract.address,
|
|
64
62
|
fnName: 'assert_calldata_copy',
|
|
65
|
-
args: [argsField.slice(3), /* with_selector: */ true],
|
|
63
|
+
args: [argsField.slice(0, 3), /* with_selector: */ true],
|
|
66
64
|
},
|
|
67
65
|
{
|
|
68
66
|
address: avmTestContract.address,
|
|
@@ -1,16 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
DEFAULT_TEARDOWN_DA_GAS_LIMIT,
|
|
3
|
-
DEFAULT_TEARDOWN_L2_GAS_LIMIT,
|
|
4
|
-
PUBLIC_TX_L2_GAS_OVERHEAD,
|
|
5
|
-
TX_DA_GAS_OVERHEAD,
|
|
6
|
-
} from '@aztec/constants';
|
|
1
|
+
import { PUBLIC_TX_L2_GAS_OVERHEAD, TX_DA_GAS_OVERHEAD } from '@aztec/constants';
|
|
7
2
|
import { asyncMap } from '@aztec/foundation/async-map';
|
|
8
3
|
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
9
4
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
10
5
|
import { type ContractArtifact, encodeArguments } from '@aztec/stdlib/abi';
|
|
11
6
|
import { PublicSimulatorConfig, type PublicTxResult } from '@aztec/stdlib/avm';
|
|
12
7
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
13
|
-
import { Gas, GasFees } from '@aztec/stdlib/gas';
|
|
8
|
+
import { FALLBACK_TEARDOWN_DA_GAS_LIMIT, FALLBACK_TEARDOWN_L2_GAS_LIMIT, Gas, GasFees } from '@aztec/stdlib/gas';
|
|
14
9
|
import type { MerkleTreeWriteOperations } from '@aztec/stdlib/interfaces/server';
|
|
15
10
|
import { PublicCallRequest } from '@aztec/stdlib/kernel';
|
|
16
11
|
import { GlobalVariables, PublicCallRequestWithCalldata, type Tx } from '@aztec/stdlib/tx';
|
|
@@ -117,6 +112,7 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
|
|
|
117
112
|
feePayer: AztecAddress = sender,
|
|
118
113
|
/* need some unique first nullifier for note-nonce computations */
|
|
119
114
|
privateInsertions: TestPrivateInsertions = { nonRevertible: { nullifiers: [new Fr(420000 + this.txCount)] } },
|
|
115
|
+
gasLimits?: Gas,
|
|
120
116
|
): Promise<Tx> {
|
|
121
117
|
const setupCallRequests = await asyncMap(setupCalls, call =>
|
|
122
118
|
this.#createPubicCallRequestForCall(call, call.sender ?? sender),
|
|
@@ -137,11 +133,12 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
|
|
|
137
133
|
feePayer,
|
|
138
134
|
/*gasUsedByPrivate*/ teardownCall
|
|
139
135
|
? new Gas(
|
|
140
|
-
|
|
141
|
-
|
|
136
|
+
FALLBACK_TEARDOWN_DA_GAS_LIMIT + TX_DA_GAS_OVERHEAD,
|
|
137
|
+
FALLBACK_TEARDOWN_L2_GAS_LIMIT + PUBLIC_TX_L2_GAS_OVERHEAD,
|
|
142
138
|
)
|
|
143
139
|
: new Gas(TX_DA_GAS_OVERHEAD, PUBLIC_TX_L2_GAS_OVERHEAD),
|
|
144
140
|
defaultGlobals(),
|
|
141
|
+
gasLimits,
|
|
145
142
|
);
|
|
146
143
|
}
|
|
147
144
|
|
|
@@ -154,8 +151,9 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
|
|
|
154
151
|
/* need some unique first nullifier for note-nonce computations */
|
|
155
152
|
privateInsertions?: TestPrivateInsertions,
|
|
156
153
|
txLabel: string = 'unlabeledTx',
|
|
154
|
+
gasLimits?: Gas,
|
|
157
155
|
): Promise<PublicTxResult> {
|
|
158
|
-
const tx = await this.createTx(sender, setupCalls, appCalls, teardownCall, feePayer, privateInsertions);
|
|
156
|
+
const tx = await this.createTx(sender, setupCalls, appCalls, teardownCall, feePayer, privateInsertions, gasLimits);
|
|
159
157
|
|
|
160
158
|
await this.setFeePayerBalance(feePayer);
|
|
161
159
|
|
|
@@ -169,6 +167,8 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
|
|
|
169
167
|
}
|
|
170
168
|
const avmResult = await this.simulator.simulate(tx, fullTxLabel);
|
|
171
169
|
|
|
170
|
+
await this.#recordBytecodeSizes(fullTxLabel, [...setupCalls, ...appCalls, ...(teardownCall ? [teardownCall] : [])]);
|
|
171
|
+
|
|
172
172
|
// Something like this is often useful for debugging:
|
|
173
173
|
//if (avmResult.revertReason) {
|
|
174
174
|
// // resolve / enrich revert reason
|
|
@@ -198,8 +198,18 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
|
|
|
198
198
|
teardownCall?: TestEnqueuedCall,
|
|
199
199
|
feePayer?: AztecAddress,
|
|
200
200
|
privateInsertions?: TestPrivateInsertions,
|
|
201
|
+
gasLimits?: Gas,
|
|
201
202
|
): Promise<PublicTxResult> {
|
|
202
|
-
return await this.simulateTx(
|
|
203
|
+
return await this.simulateTx(
|
|
204
|
+
sender,
|
|
205
|
+
setupCalls,
|
|
206
|
+
appCalls,
|
|
207
|
+
teardownCall,
|
|
208
|
+
feePayer,
|
|
209
|
+
privateInsertions,
|
|
210
|
+
txLabel,
|
|
211
|
+
gasLimits,
|
|
212
|
+
);
|
|
203
213
|
}
|
|
204
214
|
|
|
205
215
|
/**
|
|
@@ -217,6 +227,7 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
|
|
|
217
227
|
teardownCall?: TestEnqueuedCall,
|
|
218
228
|
feePayer?: AztecAddress,
|
|
219
229
|
privateInsertions?: TestPrivateInsertions,
|
|
230
|
+
gasLimits?: Gas,
|
|
220
231
|
): Promise<PublicTxResult> {
|
|
221
232
|
return await this.simulateTxWithLabel(
|
|
222
233
|
txLabel,
|
|
@@ -226,6 +237,7 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
|
|
|
226
237
|
teardownCall,
|
|
227
238
|
feePayer,
|
|
228
239
|
privateInsertions,
|
|
240
|
+
gasLimits,
|
|
229
241
|
);
|
|
230
242
|
}
|
|
231
243
|
|
|
@@ -285,6 +297,27 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
|
|
|
285
297
|
|
|
286
298
|
return new PublicCallRequestWithCalldata(request, calldata);
|
|
287
299
|
}
|
|
300
|
+
|
|
301
|
+
// WARNING: Deduplicates by artifact name, so two different artifacts with the same name
|
|
302
|
+
// in a single tx would only record the first one's bytecode size.
|
|
303
|
+
async #recordBytecodeSizes(txLabel: string, calls: TestEnqueuedCall[]) {
|
|
304
|
+
const seenArtifactNames = new Set<string>();
|
|
305
|
+
for (const call of calls) {
|
|
306
|
+
const artifact = await this.contractDataSource.getContractArtifact(call.address);
|
|
307
|
+
if (!artifact || seenArtifactNames.has(artifact.name)) {
|
|
308
|
+
continue;
|
|
309
|
+
}
|
|
310
|
+
seenArtifactNames.add(artifact.name);
|
|
311
|
+
const instance = await this.contractDataSource.getContract(call.address);
|
|
312
|
+
if (!instance) {
|
|
313
|
+
continue;
|
|
314
|
+
}
|
|
315
|
+
const contractClass = await this.contractDataSource.getContractClass(instance.currentContractClassId);
|
|
316
|
+
if (contractClass) {
|
|
317
|
+
this.metrics.recordBytecodeSize(txLabel, artifact.name, contractClass.packedBytecode.length);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
288
321
|
}
|
|
289
322
|
|
|
290
323
|
export function defaultGlobals() {
|
|
@@ -2,10 +2,8 @@ import {
|
|
|
2
2
|
CONTRACT_CLASS_PUBLISHED_MAGIC_VALUE,
|
|
3
3
|
CONTRACT_CLASS_REGISTRY_CONTRACT_ADDRESS,
|
|
4
4
|
CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS,
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
DEFAULT_TEARDOWN_DA_GAS_LIMIT,
|
|
8
|
-
DEFAULT_TEARDOWN_L2_GAS_LIMIT,
|
|
5
|
+
MAX_PROCESSABLE_DA_GAS_PER_CHECKPOINT,
|
|
6
|
+
MAX_PROCESSABLE_L2_GAS,
|
|
9
7
|
PRIVATE_LOG_SIZE_IN_FIELDS,
|
|
10
8
|
} from '@aztec/constants';
|
|
11
9
|
import { padArrayEnd } from '@aztec/foundation/collection';
|
|
@@ -14,7 +12,13 @@ import { CONTRACT_INSTANCE_PUBLISHED_EVENT_TAG } from '@aztec/protocol-contracts
|
|
|
14
12
|
import { bufferAsFields } from '@aztec/stdlib/abi';
|
|
15
13
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
16
14
|
import type { ContractClassPublic, ContractInstanceWithAddress } from '@aztec/stdlib/contract';
|
|
17
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
FALLBACK_TEARDOWN_DA_GAS_LIMIT,
|
|
17
|
+
FALLBACK_TEARDOWN_L2_GAS_LIMIT,
|
|
18
|
+
Gas,
|
|
19
|
+
GasFees,
|
|
20
|
+
GasSettings,
|
|
21
|
+
} from '@aztec/stdlib/gas';
|
|
18
22
|
import { siloNullifier } from '@aztec/stdlib/hash';
|
|
19
23
|
import {
|
|
20
24
|
LogHash,
|
|
@@ -62,13 +66,14 @@ export async function createTxForPublicCalls(
|
|
|
62
66
|
feePayer = AztecAddress.zero(),
|
|
63
67
|
gasUsedByPrivate: Gas = Gas.empty(),
|
|
64
68
|
globals: GlobalVariables = GlobalVariables.empty(),
|
|
69
|
+
gasLimits?: Gas,
|
|
65
70
|
): Promise<Tx> {
|
|
66
71
|
assert(
|
|
67
72
|
setupCallRequests.length > 0 || appCallRequests.length > 0 || teardownCallRequest !== undefined,
|
|
68
73
|
"Can't create public tx with no enqueued calls",
|
|
69
74
|
);
|
|
70
75
|
// use max limits
|
|
71
|
-
|
|
76
|
+
gasLimits = gasLimits ?? new Gas(MAX_PROCESSABLE_DA_GAS_PER_CHECKPOINT, MAX_PROCESSABLE_L2_GAS);
|
|
72
77
|
|
|
73
78
|
const forPublic = PartialPrivateTailPublicInputsForPublic.empty();
|
|
74
79
|
|
|
@@ -128,7 +133,7 @@ export async function createTxForPublicCalls(
|
|
|
128
133
|
|
|
129
134
|
const maxFeesPerGas = feePayer.isZero() ? GasFees.empty() : new GasFees(10, 10);
|
|
130
135
|
const teardownGasLimits = teardownCallRequest
|
|
131
|
-
? new Gas(
|
|
136
|
+
? new Gas(FALLBACK_TEARDOWN_DA_GAS_LIMIT, FALLBACK_TEARDOWN_L2_GAS_LIMIT)
|
|
132
137
|
: Gas.empty();
|
|
133
138
|
const gasSettings = new GasSettings(gasLimits, teardownGasLimits, maxFeesPerGas, GasFees.empty());
|
|
134
139
|
const txContext = new TxContext(Fr.zero(), Fr.zero(), gasSettings);
|
|
@@ -163,7 +168,7 @@ export async function createTxForPrivateOnly(
|
|
|
163
168
|
gasUsedByPrivate: Gas = new Gas(10, 10),
|
|
164
169
|
): Promise<Tx> {
|
|
165
170
|
// use max limits
|
|
166
|
-
const gasLimits = new Gas(
|
|
171
|
+
const gasLimits = new Gas(MAX_PROCESSABLE_DA_GAS_PER_CHECKPOINT, MAX_PROCESSABLE_L2_GAS);
|
|
167
172
|
|
|
168
173
|
const forRollup = PartialPrivateTailPublicInputsForRollup.empty();
|
|
169
174
|
|
|
@@ -410,12 +410,12 @@ export class HintingMerkleWriteOperations implements MerkleTreeWriteOperations {
|
|
|
410
410
|
}
|
|
411
411
|
}
|
|
412
412
|
|
|
413
|
-
public async createCheckpoint(): Promise<
|
|
413
|
+
public async createCheckpoint(): Promise<number> {
|
|
414
414
|
const actionCounter = this.checkpointActionCounter++;
|
|
415
415
|
const oldCheckpointId = this.getCurrentCheckpointId();
|
|
416
416
|
const treesStateHash = await this.getTreesStateHash();
|
|
417
417
|
|
|
418
|
-
await this.db.createCheckpoint();
|
|
418
|
+
const depth = await this.db.createCheckpoint();
|
|
419
419
|
this.checkpointStack.push(this.nextCheckpointId++);
|
|
420
420
|
const newCheckpointId = this.getCurrentCheckpointId();
|
|
421
421
|
|
|
@@ -424,14 +424,16 @@ export class HintingMerkleWriteOperations implements MerkleTreeWriteOperations {
|
|
|
424
424
|
HintingMerkleWriteOperations.log.trace(
|
|
425
425
|
`[createCheckpoint:${actionCounter}] Checkpoint evolved ${oldCheckpointId} -> ${newCheckpointId} at trees state ${treesStateHash}.`,
|
|
426
426
|
);
|
|
427
|
+
|
|
428
|
+
return depth;
|
|
427
429
|
}
|
|
428
430
|
|
|
429
|
-
public
|
|
430
|
-
throw new Error('
|
|
431
|
+
public commitAllCheckpointsTo(_depth: number): Promise<void> {
|
|
432
|
+
throw new Error('commitAllCheckpointsTo is not supported in HintingMerkleWriteOperations.');
|
|
431
433
|
}
|
|
432
434
|
|
|
433
|
-
public
|
|
434
|
-
throw new Error('
|
|
435
|
+
public revertAllCheckpointsTo(_depth: number): Promise<void> {
|
|
436
|
+
throw new Error('revertAllCheckpointsTo is not supported in HintingMerkleWriteOperations.');
|
|
435
437
|
}
|
|
436
438
|
|
|
437
439
|
public async commitCheckpoint(): Promise<void> {
|
|
@@ -55,10 +55,10 @@ export class PublicContractsDB implements PublicContractsDBInterface {
|
|
|
55
55
|
this.log = createLogger('simulator:contracts-data-source', bindings);
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
public
|
|
58
|
+
public addContracts(contractDeploymentData: ContractDeploymentData): void {
|
|
59
59
|
const currentState = this.getCurrentState();
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
this.addContractClassesFromEvents(
|
|
62
62
|
ContractClassPublishedEvent.extractContractClassEvents(contractDeploymentData.getContractClassLogs()),
|
|
63
63
|
currentState,
|
|
64
64
|
);
|
|
@@ -69,10 +69,10 @@ export class PublicContractsDB implements PublicContractsDBInterface {
|
|
|
69
69
|
);
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
public
|
|
72
|
+
public addNewContracts(tx: Tx): void {
|
|
73
73
|
const contractDeploymentData = AllContractDeploymentData.fromTx(tx);
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
this.addContracts(contractDeploymentData.getNonRevertibleContractDeploymentData());
|
|
75
|
+
this.addContracts(contractDeploymentData.getRevertibleContractDeploymentData());
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
/**
|
|
@@ -81,7 +81,7 @@ export class PublicContractsDB implements PublicContractsDBInterface {
|
|
|
81
81
|
*/
|
|
82
82
|
public createCheckpoint(): void {
|
|
83
83
|
const currentState = this.getCurrentState();
|
|
84
|
-
const newState = currentState.
|
|
84
|
+
const newState = currentState.fork();
|
|
85
85
|
this.contractStateStack.push(newState);
|
|
86
86
|
}
|
|
87
87
|
|
|
@@ -174,17 +174,15 @@ export class PublicContractsDB implements PublicContractsDBInterface {
|
|
|
174
174
|
return await this.dataSource.getDebugFunctionName(address, selector);
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
-
private
|
|
177
|
+
private addContractClassesFromEvents(
|
|
178
178
|
contractClassEvents: ContractClassPublishedEvent[],
|
|
179
179
|
state: ContractsDbCheckpoint,
|
|
180
180
|
) {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
}),
|
|
187
|
-
);
|
|
181
|
+
for (const event of contractClassEvents) {
|
|
182
|
+
this.log.debug(`Adding class ${event.contractClassId.toString()} to contract state`);
|
|
183
|
+
const contractClass = event.toContractClassPublic();
|
|
184
|
+
state.addClass(event.contractClassId, contractClass);
|
|
185
|
+
}
|
|
188
186
|
}
|
|
189
187
|
|
|
190
188
|
private addContractInstancesFromEvents(
|
|
@@ -134,7 +134,7 @@ export class GuardedMerkleTreeOperations implements MerkleTreeWriteOperations {
|
|
|
134
134
|
): Promise<(BlockNumber | undefined)[]> {
|
|
135
135
|
return this.guardAndPush(() => this.target.getBlockNumbersForLeafIndices(treeId, leafIndices));
|
|
136
136
|
}
|
|
137
|
-
createCheckpoint(): Promise<
|
|
137
|
+
createCheckpoint(): Promise<number> {
|
|
138
138
|
return this.guardAndPush(() => this.target.createCheckpoint());
|
|
139
139
|
}
|
|
140
140
|
commitCheckpoint(): Promise<void> {
|
|
@@ -143,11 +143,11 @@ export class GuardedMerkleTreeOperations implements MerkleTreeWriteOperations {
|
|
|
143
143
|
revertCheckpoint(): Promise<void> {
|
|
144
144
|
return this.guardAndPush(() => this.target.revertCheckpoint());
|
|
145
145
|
}
|
|
146
|
-
|
|
147
|
-
return this.guardAndPush(() => this.target.
|
|
146
|
+
commitAllCheckpointsTo(depth: number): Promise<void> {
|
|
147
|
+
return this.guardAndPush(() => this.target.commitAllCheckpointsTo(depth));
|
|
148
148
|
}
|
|
149
|
-
|
|
150
|
-
return this.guardAndPush(() => this.target.
|
|
149
|
+
revertAllCheckpointsTo(depth: number): Promise<void> {
|
|
150
|
+
return this.guardAndPush(() => this.target.revertAllCheckpointsTo(depth));
|
|
151
151
|
}
|
|
152
152
|
findSiblingPaths<ID extends MerkleTreeId>(
|
|
153
153
|
treeId: ID,
|
|
@@ -160,8 +160,8 @@ export class PublicProcessor implements Traceable {
|
|
|
160
160
|
txs: Iterable<Tx> | AsyncIterable<Tx>,
|
|
161
161
|
limits: PublicProcessorLimits = {},
|
|
162
162
|
validator: PublicProcessorValidator = {},
|
|
163
|
-
): Promise<[ProcessedTx[], FailedTx[], Tx[], NestedProcessReturnValues[],
|
|
164
|
-
const { maxTransactions,
|
|
163
|
+
): Promise<[ProcessedTx[], FailedTx[], Tx[], NestedProcessReturnValues[], DebugLog[]]> {
|
|
164
|
+
const { maxTransactions, deadline, maxBlockGas, maxBlobFields, isBuildingProposal } = limits;
|
|
165
165
|
const { preprocessValidator, nullifierCache } = validator;
|
|
166
166
|
const result: ProcessedTx[] = [];
|
|
167
167
|
const usedTxs: Tx[] = [];
|
|
@@ -188,22 +188,23 @@ export class PublicProcessor implements Traceable {
|
|
|
188
188
|
break;
|
|
189
189
|
}
|
|
190
190
|
|
|
191
|
-
// Skip this tx if it'd exceed max block size
|
|
192
191
|
const txHash = tx.getTxHash().toString();
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
192
|
+
|
|
193
|
+
// Skip this tx if its estimated blob fields would exceed the limit.
|
|
194
|
+
// Only done during proposal building: during re-execution we must process the exact txs from the proposal.
|
|
195
|
+
const txBlobFields = tx.getPrivateTxEffectsSizeInFields();
|
|
196
|
+
if (isBuildingProposal && maxBlobFields !== undefined && totalBlobFields + txBlobFields > maxBlobFields) {
|
|
197
|
+
this.log.warn(
|
|
198
|
+
`Skipping tx ${txHash} with ${txBlobFields} fields from private side effects due to blob fields limit`,
|
|
199
|
+
{ txHash, txBlobFields, totalBlobFields, maxBlobFields },
|
|
200
|
+
);
|
|
201
201
|
continue;
|
|
202
202
|
}
|
|
203
203
|
|
|
204
|
-
// Skip this tx if its gas limit would exceed the block gas limit
|
|
204
|
+
// Skip this tx if its gas limit would exceed the block gas limit (either da or l2).
|
|
205
|
+
// Only done during proposal building: during re-execution we must process the exact txs from the proposal.
|
|
205
206
|
const txGasLimit = tx.data.constants.txContext.gasSettings.gasLimits;
|
|
206
|
-
if (maxBlockGas !== undefined && totalBlockGas.add(txGasLimit).gtAny(maxBlockGas)) {
|
|
207
|
+
if (isBuildingProposal && maxBlockGas !== undefined && totalBlockGas.add(txGasLimit).gtAny(maxBlockGas)) {
|
|
207
208
|
this.log.warn(`Skipping processing of tx ${txHash} due to block gas limit`, {
|
|
208
209
|
txHash,
|
|
209
210
|
txGasLimit,
|
|
@@ -252,23 +253,9 @@ export class PublicProcessor implements Traceable {
|
|
|
252
253
|
}
|
|
253
254
|
|
|
254
255
|
const txBlobFields = processedTx.txEffect.getNumBlobFields();
|
|
255
|
-
|
|
256
|
-
// If the actual size of this tx would exceed block size, skip it
|
|
257
256
|
const txSize = txBlobFields * Fr.SIZE_IN_BYTES;
|
|
258
|
-
if (maxBlockSize !== undefined && totalSizeInBytes + txSize > maxBlockSize) {
|
|
259
|
-
this.log.debug(`Skipping processed tx ${txHash} sized ${txSize} due to max block size.`, {
|
|
260
|
-
txHash,
|
|
261
|
-
sizeInBytes: txSize,
|
|
262
|
-
totalSizeInBytes,
|
|
263
|
-
maxBlockSize,
|
|
264
|
-
});
|
|
265
|
-
// Need to revert the checkpoint here and don't go any further
|
|
266
|
-
await checkpoint.revert();
|
|
267
|
-
this.contractsDB.revertCheckpoint();
|
|
268
|
-
continue;
|
|
269
|
-
}
|
|
270
257
|
|
|
271
|
-
// If the actual blob fields of this tx would exceed the limit, skip it
|
|
258
|
+
// If the actual blob fields of this tx would exceed the limit, skip it.
|
|
272
259
|
// Note: maxBlobFields already accounts for block end blob fields and previous blocks in checkpoint.
|
|
273
260
|
if (maxBlobFields !== undefined && totalBlobFields + txBlobFields > maxBlobFields) {
|
|
274
261
|
this.log.debug(
|
|
@@ -286,6 +273,25 @@ export class PublicProcessor implements Traceable {
|
|
|
286
273
|
continue;
|
|
287
274
|
}
|
|
288
275
|
|
|
276
|
+
// During re-execution, check if the actual gas used by this tx would push the block over the gas limit.
|
|
277
|
+
// Unlike the proposal-building check (which uses declared gas limits pessimistically before processing),
|
|
278
|
+
// this uses actual gas and stops processing when the limit is exceeded.
|
|
279
|
+
if (
|
|
280
|
+
!isBuildingProposal &&
|
|
281
|
+
maxBlockGas !== undefined &&
|
|
282
|
+
totalBlockGas.add(processedTx.gasUsed.totalGas).gtAny(maxBlockGas)
|
|
283
|
+
) {
|
|
284
|
+
this.log.warn(`Stopping re-execution since tx ${txHash} would push block gas over limit`, {
|
|
285
|
+
txHash,
|
|
286
|
+
txGas: processedTx.gasUsed.totalGas,
|
|
287
|
+
totalBlockGas,
|
|
288
|
+
maxBlockGas,
|
|
289
|
+
});
|
|
290
|
+
await checkpoint.revert();
|
|
291
|
+
this.contractsDB.revertCheckpoint();
|
|
292
|
+
break;
|
|
293
|
+
}
|
|
294
|
+
|
|
289
295
|
// FIXME(fcarreiro): it's ugly to have to notify the validator of nullifiers.
|
|
290
296
|
// I'd rather pass the validators the processedTx as well and let them deal with it.
|
|
291
297
|
nullifierCache?.addNullifiers(processedTx.txEffect.nullifiers.map(n => n.toBuffer()));
|
|
@@ -300,6 +306,9 @@ export class PublicProcessor implements Traceable {
|
|
|
300
306
|
totalBlockGas = totalBlockGas.add(processedTx.gasUsed.totalGas);
|
|
301
307
|
totalSizeInBytes += txSize;
|
|
302
308
|
totalBlobFields += txBlobFields;
|
|
309
|
+
|
|
310
|
+
// Commit the tx-level contracts checkpoint on success
|
|
311
|
+
this.contractsDB.commitCheckpoint();
|
|
303
312
|
} catch (err: any) {
|
|
304
313
|
if (err?.name === 'PublicProcessorTimeoutError') {
|
|
305
314
|
this.log.warn(`Stopping tx processing due to timeout.`);
|
|
@@ -319,14 +328,10 @@ export class PublicProcessor implements Traceable {
|
|
|
319
328
|
// 1. At least one outstanding checkpoint that has not been committed (the one created before we processed the tx).
|
|
320
329
|
// 2. Possible state updates on that checkpoint or any others created during execution.
|
|
321
330
|
|
|
322
|
-
//
|
|
323
|
-
//
|
|
324
|
-
//
|
|
325
|
-
await checkpoint.
|
|
326
|
-
|
|
327
|
-
// Now we want to revert any/all remaining checkpoints, destroying any outstanding state updates.
|
|
328
|
-
// This needs to be done directly on the underlying fork as the guarded fork has been stopped.
|
|
329
|
-
await this.guardedMerkleTree.getUnderlyingFork().revertAllCheckpoints();
|
|
331
|
+
// Revert all checkpoints at or above this checkpoint's depth (inclusive), destroying any outstanding state
|
|
332
|
+
// updates from this tx and any nested checkpoints created during execution. This preserves any checkpoints
|
|
333
|
+
// created by callers below our depth.
|
|
334
|
+
await checkpoint.revertToCheckpoint();
|
|
330
335
|
|
|
331
336
|
// Revert any contracts added to the DB for the tx.
|
|
332
337
|
this.contractsDB.revertCheckpoint();
|
|
@@ -338,9 +343,9 @@ export class PublicProcessor implements Traceable {
|
|
|
338
343
|
break;
|
|
339
344
|
}
|
|
340
345
|
|
|
341
|
-
// Roll back state to start of TX before proceeding to next TX
|
|
342
|
-
|
|
343
|
-
await
|
|
346
|
+
// Roll back state to start of TX before proceeding to next TX.
|
|
347
|
+
// Reverts all checkpoints at or above this checkpoint's depth, preserving any caller checkpoints below.
|
|
348
|
+
await checkpoint.revertToCheckpoint();
|
|
344
349
|
this.contractsDB.revertCheckpoint();
|
|
345
350
|
const errorMessage = err instanceof Error || err instanceof AssertionError ? err.message : 'Unknown error';
|
|
346
351
|
this.log.warn(`Failed to process tx ${txHash.toString()}: ${errorMessage} ${err?.stack}`);
|
|
@@ -352,7 +357,6 @@ export class PublicProcessor implements Traceable {
|
|
|
352
357
|
} finally {
|
|
353
358
|
// Base case is we always commit the checkpoint. Using the ForkCheckpoint means this has no effect if the tx was previously reverted
|
|
354
359
|
await checkpoint.commit();
|
|
355
|
-
this.contractsDB.commitCheckpointOkIfNone();
|
|
356
360
|
}
|
|
357
361
|
}
|
|
358
362
|
|
|
@@ -368,7 +372,7 @@ export class PublicProcessor implements Traceable {
|
|
|
368
372
|
totalSizeInBytes,
|
|
369
373
|
});
|
|
370
374
|
|
|
371
|
-
return [result, failed, usedTxs, returns,
|
|
375
|
+
return [result, failed, usedTxs, returns, debugLogs];
|
|
372
376
|
}
|
|
373
377
|
|
|
374
378
|
private async checkWorldStateUnchanged(
|
|
@@ -544,7 +548,7 @@ export class PublicProcessor implements Traceable {
|
|
|
544
548
|
// Fee payment insertion has already been done. Do the rest.
|
|
545
549
|
await this.doTreeInsertionsForPrivateOnlyTx(processedTx);
|
|
546
550
|
|
|
547
|
-
|
|
551
|
+
this.contractsDB.addNewContracts(tx);
|
|
548
552
|
|
|
549
553
|
return [processedTx, undefined, []];
|
|
550
554
|
}
|
|
@@ -52,6 +52,7 @@ export class ContractProviderForCpp implements ContractProvider {
|
|
|
52
52
|
return serializeWithMessagePack(contractClass);
|
|
53
53
|
};
|
|
54
54
|
|
|
55
|
+
// eslint-disable-next-line require-await
|
|
55
56
|
public addContracts = async (contractDeploymentDataBuffer: Buffer): Promise<void> => {
|
|
56
57
|
this.log.trace(`Contract provider callback: addContracts`);
|
|
57
58
|
|
|
@@ -62,7 +63,7 @@ export class ContractProviderForCpp implements ContractProvider {
|
|
|
62
63
|
|
|
63
64
|
// Add contracts to the contracts DB
|
|
64
65
|
this.log.trace(`Calling contractsDB.addContracts`);
|
|
65
|
-
|
|
66
|
+
this.contractsDB.addContracts(contractDeploymentData);
|
|
66
67
|
};
|
|
67
68
|
|
|
68
69
|
public getBytecodeCommitment = async (classId: string): Promise<Buffer | undefined> => {
|