@aztec/simulator 0.0.1-commit.001888fc → 0.0.1-commit.017a351
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/acvm_wasm.d.ts +1 -1
- package/dest/private/acvm_wasm.d.ts.map +1 -1
- package/dest/private/acvm_wasm.js +3 -1
- 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/avm/fixtures/base_avm_simulation_tester.d.ts +2 -1
- package/dest/public/avm/fixtures/base_avm_simulation_tester.d.ts.map +1 -1
- package/dest/public/avm/fixtures/base_avm_simulation_tester.js +17 -2
- package/dest/public/avm/fixtures/utils.d.ts +1 -1
- package/dest/public/avm/fixtures/utils.d.ts.map +1 -1
- package/dest/public/avm/fixtures/utils.js +3 -0
- package/dest/public/avm/opcodes/contract.d.ts +3 -2
- package/dest/public/avm/opcodes/contract.d.ts.map +1 -1
- package/dest/public/avm/opcodes/contract.js +5 -1
- package/dest/public/avm/opcodes/ec_add.d.ts +2 -4
- package/dest/public/avm/opcodes/ec_add.d.ts.map +1 -1
- package/dest/public/avm/opcodes/ec_add.js +13 -27
- 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 +31 -4
- package/dest/public/fixtures/custom_bytecode_tests.d.ts +3 -1
- package/dest/public/fixtures/custom_bytecode_tests.d.ts.map +1 -1
- package/dest/public/fixtures/custom_bytecode_tests.js +61 -1
- package/dest/public/fixtures/opcode_spammer.d.ts +1 -1
- package/dest/public/fixtures/opcode_spammer.d.ts.map +1 -1
- package/dest/public/fixtures/opcode_spammer.js +2 -10
- package/dest/public/fixtures/public_tx_simulation_tester.d.ts +1 -1
- package/dest/public/fixtures/public_tx_simulation_tester.d.ts.map +1 -1
- package/dest/public/fixtures/public_tx_simulation_tester.js +3 -3
- package/dest/public/fixtures/utils.d.ts +1 -1
- package/dest/public/fixtures/utils.d.ts.map +1 -1
- package/dest/public/fixtures/utils.js +14 -15
- package/dest/public/hinting_db_sources.d.ts +2 -1
- package/dest/public/hinting_db_sources.d.ts.map +1 -1
- package/dest/public/hinting_db_sources.js +4 -1
- package/dest/public/public_db_sources.d.ts +6 -3
- package/dest/public/public_db_sources.d.ts.map +1 -1
- package/dest/public/public_db_sources.js +16 -10
- package/dest/public/public_processor/guarded_merkle_tree.d.ts +4 -3
- package/dest/public/public_processor/guarded_merkle_tree.d.ts.map +1 -1
- package/dest/public/public_processor/guarded_merkle_tree.js +3 -0
- package/dest/public/public_processor/public_processor.d.ts +4 -3
- package/dest/public/public_processor/public_processor.d.ts.map +1 -1
- package/dest/public/public_processor/public_processor.js +60 -34
- package/dest/public/public_processor/public_processor_metrics.d.ts +4 -1
- package/dest/public/public_processor/public_processor_metrics.d.ts.map +1 -1
- package/dest/public/public_processor/public_processor_metrics.js +8 -0
- 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 +3 -2
- package/dest/public/public_tx_simulator/cpp_public_tx_simulator.d.ts +1 -1
- package/dest/public/public_tx_simulator/cpp_public_tx_simulator.d.ts.map +1 -1
- package/dest/public/public_tx_simulator/cpp_public_tx_simulator.js +3 -8
- package/dest/public/public_tx_simulator/cpp_vs_ts_public_tx_simulator.d.ts +1 -1
- package/dest/public/public_tx_simulator/cpp_vs_ts_public_tx_simulator.d.ts.map +1 -1
- package/dest/public/public_tx_simulator/cpp_vs_ts_public_tx_simulator.js +3 -7
- 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/package.json +16 -15
- package/src/private/acvm_wasm.ts +4 -1
- package/src/public/avm/avm_simulator.ts +1 -1
- package/src/public/avm/calldata.ts +3 -2
- package/src/public/avm/fixtures/base_avm_simulation_tester.ts +22 -2
- package/src/public/avm/fixtures/utils.ts +3 -0
- package/src/public/avm/opcodes/contract.ts +5 -1
- package/src/public/avm/opcodes/ec_add.ts +12 -31
- 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 +29 -4
- package/src/public/fixtures/custom_bytecode_tests.ts +139 -1
- package/src/public/fixtures/opcode_spammer.ts +4 -8
- package/src/public/fixtures/public_tx_simulation_tester.ts +4 -9
- package/src/public/fixtures/utils.ts +21 -18
- package/src/public/hinting_db_sources.ts +5 -0
- package/src/public/public_db_sources.ts +21 -14
- package/src/public/public_processor/guarded_merkle_tree.ts +5 -2
- package/src/public/public_processor/public_processor.ts +79 -41
- package/src/public/public_processor/public_processor_metrics.ts +12 -0
- package/src/public/public_tx_simulator/contract_provider_for_cpp.ts +3 -2
- package/src/public/public_tx_simulator/cpp_public_tx_simulator.ts +3 -12
- package/src/public/public_tx_simulator/cpp_vs_ts_public_tx_simulator.ts +3 -10
- package/src/public/public_tx_simulator/public_tx_context.ts +8 -10
- package/src/public/public_tx_simulator/public_tx_simulator.ts +11 -7
|
@@ -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';
|
|
@@ -138,8 +133,8 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
|
|
|
138
133
|
feePayer,
|
|
139
134
|
/*gasUsedByPrivate*/ teardownCall
|
|
140
135
|
? new Gas(
|
|
141
|
-
|
|
142
|
-
|
|
136
|
+
FALLBACK_TEARDOWN_DA_GAS_LIMIT + TX_DA_GAS_OVERHEAD,
|
|
137
|
+
FALLBACK_TEARDOWN_L2_GAS_LIMIT + PUBLIC_TX_L2_GAS_OVERHEAD,
|
|
143
138
|
)
|
|
144
139
|
: new Gas(TX_DA_GAS_OVERHEAD, PUBLIC_TX_L2_GAS_OVERHEAD),
|
|
145
140
|
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,
|
|
@@ -69,7 +73,7 @@ export async function createTxForPublicCalls(
|
|
|
69
73
|
"Can't create public tx with no enqueued calls",
|
|
70
74
|
);
|
|
71
75
|
// use max limits
|
|
72
|
-
gasLimits = gasLimits ?? new Gas(
|
|
76
|
+
gasLimits = gasLimits ?? new Gas(MAX_PROCESSABLE_DA_GAS_PER_CHECKPOINT, MAX_PROCESSABLE_L2_GAS);
|
|
73
77
|
|
|
74
78
|
const forPublic = PartialPrivateTailPublicInputsForPublic.empty();
|
|
75
79
|
|
|
@@ -129,7 +133,7 @@ export async function createTxForPublicCalls(
|
|
|
129
133
|
|
|
130
134
|
const maxFeesPerGas = feePayer.isZero() ? GasFees.empty() : new GasFees(10, 10);
|
|
131
135
|
const teardownGasLimits = teardownCallRequest
|
|
132
|
-
? new Gas(
|
|
136
|
+
? new Gas(FALLBACK_TEARDOWN_DA_GAS_LIMIT, FALLBACK_TEARDOWN_L2_GAS_LIMIT)
|
|
133
137
|
: Gas.empty();
|
|
134
138
|
const gasSettings = new GasSettings(gasLimits, teardownGasLimits, maxFeesPerGas, GasFees.empty());
|
|
135
139
|
const txContext = new TxContext(Fr.zero(), Fr.zero(), gasSettings);
|
|
@@ -164,7 +168,7 @@ export async function createTxForPrivateOnly(
|
|
|
164
168
|
gasUsedByPrivate: Gas = new Gas(10, 10),
|
|
165
169
|
): Promise<Tx> {
|
|
166
170
|
// use max limits
|
|
167
|
-
const gasLimits = new Gas(
|
|
171
|
+
const gasLimits = new Gas(MAX_PROCESSABLE_DA_GAS_PER_CHECKPOINT, MAX_PROCESSABLE_L2_GAS);
|
|
168
172
|
|
|
169
173
|
const forRollup = PartialPrivateTailPublicInputsForRollup.empty();
|
|
170
174
|
|
|
@@ -229,17 +233,15 @@ export async function addNewContractInstanceToTx(
|
|
|
229
233
|
contractInstance: ContractInstanceWithAddress,
|
|
230
234
|
skipNullifierInsertion = false,
|
|
231
235
|
) {
|
|
232
|
-
//
|
|
233
|
-
// is not broadcast in such private logs
|
|
236
|
+
// Only ivpk_m is broadcast as a point (x, y); the other five keys are hashes.
|
|
234
237
|
const publicKeysAsFields = [
|
|
235
|
-
contractInstance.publicKeys.
|
|
236
|
-
contractInstance.publicKeys.
|
|
237
|
-
contractInstance.publicKeys.
|
|
238
|
-
contractInstance.publicKeys.
|
|
239
|
-
contractInstance.publicKeys.
|
|
240
|
-
contractInstance.publicKeys.
|
|
241
|
-
contractInstance.publicKeys.
|
|
242
|
-
contractInstance.publicKeys.masterTaggingPublicKey.y,
|
|
238
|
+
contractInstance.publicKeys.npkMHash,
|
|
239
|
+
contractInstance.publicKeys.ivpkM.x,
|
|
240
|
+
contractInstance.publicKeys.ivpkM.y,
|
|
241
|
+
contractInstance.publicKeys.ovpkMHash,
|
|
242
|
+
contractInstance.publicKeys.tpkMHash,
|
|
243
|
+
contractInstance.publicKeys.mspkMHash,
|
|
244
|
+
contractInstance.publicKeys.fbpkMHash,
|
|
243
245
|
];
|
|
244
246
|
const logFields = [
|
|
245
247
|
CONTRACT_INSTANCE_PUBLISHED_EVENT_TAG,
|
|
@@ -248,6 +250,7 @@ export async function addNewContractInstanceToTx(
|
|
|
248
250
|
new Fr(contractInstance.salt),
|
|
249
251
|
contractInstance.currentContractClassId,
|
|
250
252
|
contractInstance.initializationHash,
|
|
253
|
+
contractInstance.immutablesHash,
|
|
251
254
|
...publicKeysAsFields,
|
|
252
255
|
contractInstance.deployer.toField(),
|
|
253
256
|
];
|
|
@@ -83,6 +83,7 @@ export class HintingPublicContractsDB implements PublicContractsDBInterface {
|
|
|
83
83
|
instance.currentContractClassId,
|
|
84
84
|
instance.originalContractClassId,
|
|
85
85
|
instance.initializationHash,
|
|
86
|
+
instance.immutablesHash,
|
|
86
87
|
instance.publicKeys,
|
|
87
88
|
),
|
|
88
89
|
);
|
|
@@ -554,6 +555,10 @@ export class HintingMerkleWriteOperations implements MerkleTreeWriteOperations {
|
|
|
554
555
|
return this.db.getRevision();
|
|
555
556
|
}
|
|
556
557
|
|
|
558
|
+
public getSocketPath(): string {
|
|
559
|
+
return this.db.getSocketPath();
|
|
560
|
+
}
|
|
561
|
+
|
|
557
562
|
public async updateArchive(header: any): Promise<void> {
|
|
558
563
|
return await this.db.updateArchive(header);
|
|
559
564
|
}
|
|
@@ -55,10 +55,11 @@ export class PublicContractsDB implements PublicContractsDBInterface {
|
|
|
55
55
|
this.log = createLogger('simulator:contracts-data-source', bindings);
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
/** Parses raw log data from the C++/NAPI bridge and inserts the resulting contracts into the current checkpoint. */
|
|
59
|
+
public addContractsFromLogs(contractDeploymentData: ContractDeploymentData): void {
|
|
59
60
|
const currentState = this.getCurrentState();
|
|
60
61
|
|
|
61
|
-
|
|
62
|
+
this.addContractClassesFromEvents(
|
|
62
63
|
ContractClassPublishedEvent.extractContractClassEvents(contractDeploymentData.getContractClassLogs()),
|
|
63
64
|
currentState,
|
|
64
65
|
);
|
|
@@ -69,10 +70,18 @@ export class PublicContractsDB implements PublicContractsDBInterface {
|
|
|
69
70
|
);
|
|
70
71
|
}
|
|
71
72
|
|
|
72
|
-
public
|
|
73
|
+
public addNewContracts(tx: Tx): void {
|
|
73
74
|
const contractDeploymentData = AllContractDeploymentData.fromTx(tx);
|
|
74
|
-
|
|
75
|
-
|
|
75
|
+
this.addContractsFromLogs(contractDeploymentData.getNonRevertibleContractDeploymentData());
|
|
76
|
+
this.addContractsFromLogs(contractDeploymentData.getRevertibleContractDeploymentData());
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Inserts typed contract instances directly into the current checkpoint. */
|
|
80
|
+
public addContracts(contractInstances?: ContractInstanceWithAddress[]): void {
|
|
81
|
+
const currentState = this.getCurrentState();
|
|
82
|
+
for (const instance of contractInstances ?? []) {
|
|
83
|
+
currentState.addInstance(instance.address, instance);
|
|
84
|
+
}
|
|
76
85
|
}
|
|
77
86
|
|
|
78
87
|
/**
|
|
@@ -81,7 +90,7 @@ export class PublicContractsDB implements PublicContractsDBInterface {
|
|
|
81
90
|
*/
|
|
82
91
|
public createCheckpoint(): void {
|
|
83
92
|
const currentState = this.getCurrentState();
|
|
84
|
-
const newState = currentState.
|
|
93
|
+
const newState = currentState.fork();
|
|
85
94
|
this.contractStateStack.push(newState);
|
|
86
95
|
}
|
|
87
96
|
|
|
@@ -174,17 +183,15 @@ export class PublicContractsDB implements PublicContractsDBInterface {
|
|
|
174
183
|
return await this.dataSource.getDebugFunctionName(address, selector);
|
|
175
184
|
}
|
|
176
185
|
|
|
177
|
-
private
|
|
186
|
+
private addContractClassesFromEvents(
|
|
178
187
|
contractClassEvents: ContractClassPublishedEvent[],
|
|
179
188
|
state: ContractsDbCheckpoint,
|
|
180
189
|
) {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
}),
|
|
187
|
-
);
|
|
190
|
+
for (const event of contractClassEvents) {
|
|
191
|
+
this.log.debug(`Adding class ${event.contractClassId.toString()} to contract state`);
|
|
192
|
+
const contractClass = event.toContractClassPublic();
|
|
193
|
+
state.addClass(event.contractClassId, contractClass);
|
|
194
|
+
}
|
|
188
195
|
}
|
|
189
196
|
|
|
190
197
|
private addContractInstancesFromEvents(
|
|
@@ -12,7 +12,7 @@ import type {
|
|
|
12
12
|
TreeInfo,
|
|
13
13
|
} from '@aztec/stdlib/trees';
|
|
14
14
|
import type { BlockHeader, StateReference } from '@aztec/stdlib/tx';
|
|
15
|
-
import type { WorldStateRevision
|
|
15
|
+
import type { WorldStateRevision } from '@aztec/stdlib/world-state';
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* Wraps an instance of `MerkleTreeWriteOperations` to allow the sequencer to gate access.
|
|
@@ -94,9 +94,12 @@ export class GuardedMerkleTreeOperations implements MerkleTreeWriteOperations {
|
|
|
94
94
|
getInitialHeader(): BlockHeader {
|
|
95
95
|
return this.target.getInitialHeader();
|
|
96
96
|
}
|
|
97
|
-
public getRevision(): WorldStateRevision
|
|
97
|
+
public getRevision(): WorldStateRevision {
|
|
98
98
|
return this.target.getRevision();
|
|
99
99
|
}
|
|
100
|
+
public getSocketPath(): string {
|
|
101
|
+
return this.target.getSocketPath();
|
|
102
|
+
}
|
|
100
103
|
getSiblingPath<ID extends MerkleTreeId>(treeId: ID, index: bigint): Promise<SiblingPath<TreeHeights[ID]>> {
|
|
101
104
|
return this.guardAndPush(() => this.target.getSiblingPath(treeId, index));
|
|
102
105
|
}
|
|
@@ -3,7 +3,7 @@ import { padArrayEnd } from '@aztec/foundation/collection';
|
|
|
3
3
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
4
4
|
import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
|
|
5
5
|
import { sleep } from '@aztec/foundation/sleep';
|
|
6
|
-
import { DateProvider, Timer, elapsed,
|
|
6
|
+
import { DateProvider, Timer, elapsed, execWithSignal } from '@aztec/foundation/timer';
|
|
7
7
|
import { ProtocolContractAddress } from '@aztec/protocol-contracts';
|
|
8
8
|
import { ContractClassPublishedEvent } from '@aztec/protocol-contracts/class-registry';
|
|
9
9
|
import { computeFeePayerBalanceLeafSlot, computeFeePayerBalanceStorageSlot } from '@aztec/protocol-contracts/fee-juice';
|
|
@@ -76,17 +76,15 @@ export class PublicProcessorFactory {
|
|
|
76
76
|
/**
|
|
77
77
|
* Creates a new instance of a PublicProcessor.
|
|
78
78
|
* @param globalVariables - The global variables for the block being processed.
|
|
79
|
-
* @param
|
|
79
|
+
* @param contractsDB - Optional pre-populated contracts DB; a fresh one is constructed if omitted.
|
|
80
80
|
* @returns A new instance of a PublicProcessor.
|
|
81
81
|
*/
|
|
82
82
|
public create(
|
|
83
83
|
merkleTree: MerkleTreeWriteOperations,
|
|
84
84
|
globalVariables: GlobalVariables,
|
|
85
85
|
config: PublicSimulatorConfig,
|
|
86
|
+
contractsDB: PublicContractsDB = new PublicContractsDB(this.contractDataSource, this.log.getBindings()),
|
|
86
87
|
): PublicProcessor {
|
|
87
|
-
const bindings = this.log.getBindings();
|
|
88
|
-
const contractsDB = new PublicContractsDB(this.contractDataSource, bindings);
|
|
89
|
-
|
|
90
88
|
const guardedFork = new GuardedMerkleTreeOperations(merkleTree);
|
|
91
89
|
const publicTxSimulator = this.createPublicTxSimulator(guardedFork, contractsDB, globalVariables, config);
|
|
92
90
|
|
|
@@ -97,7 +95,7 @@ export class PublicProcessorFactory {
|
|
|
97
95
|
publicTxSimulator,
|
|
98
96
|
this.dateProvider,
|
|
99
97
|
this.telemetryClient,
|
|
100
|
-
createLogger('simulator:public-processor',
|
|
98
|
+
createLogger('simulator:public-processor', this.log.getBindings()),
|
|
101
99
|
);
|
|
102
100
|
}
|
|
103
101
|
|
|
@@ -125,6 +123,17 @@ class PublicProcessorTimeoutError extends Error {
|
|
|
125
123
|
}
|
|
126
124
|
}
|
|
127
125
|
|
|
126
|
+
class PublicProcessorAbortError extends Error {
|
|
127
|
+
constructor(message: string = 'Aborted while processing tx') {
|
|
128
|
+
super(message);
|
|
129
|
+
this.name = 'PublicProcessorAbortError';
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function isPublicProcessorInterruptError(err: any) {
|
|
134
|
+
return err?.name === 'PublicProcessorTimeoutError' || err?.name === 'PublicProcessorAbortError';
|
|
135
|
+
}
|
|
136
|
+
|
|
128
137
|
/**
|
|
129
138
|
* Converts Txs lifted from the P2P module into ProcessedTx objects by executing
|
|
130
139
|
* any public function calls in them. Txs with private calls only are unaffected.
|
|
@@ -161,7 +170,7 @@ export class PublicProcessor implements Traceable {
|
|
|
161
170
|
limits: PublicProcessorLimits = {},
|
|
162
171
|
validator: PublicProcessorValidator = {},
|
|
163
172
|
): Promise<[ProcessedTx[], FailedTx[], Tx[], NestedProcessReturnValues[], DebugLog[]]> {
|
|
164
|
-
const { maxTransactions, deadline, maxBlockGas, maxBlobFields, isBuildingProposal } = limits;
|
|
173
|
+
const { maxTransactions, deadline, maxBlockGas, maxBlobFields, isBuildingProposal, signal } = limits;
|
|
165
174
|
const { preprocessValidator, nullifierCache } = validator;
|
|
166
175
|
const result: ProcessedTx[] = [];
|
|
167
176
|
const usedTxs: Tx[] = [];
|
|
@@ -174,6 +183,8 @@ export class PublicProcessor implements Traceable {
|
|
|
174
183
|
let totalPublicGas = new Gas(0, 0);
|
|
175
184
|
let totalBlockGas = new Gas(0, 0);
|
|
176
185
|
let totalBlobFields = 0;
|
|
186
|
+
let silentlySkippedCount = 0;
|
|
187
|
+
let totalSilentlySkippedDurationMs = 0;
|
|
177
188
|
|
|
178
189
|
for await (const tx of txs) {
|
|
179
190
|
// Only process up to the max tx limit
|
|
@@ -182,11 +193,15 @@ export class PublicProcessor implements Traceable {
|
|
|
182
193
|
break;
|
|
183
194
|
}
|
|
184
195
|
|
|
185
|
-
// Bail if we've hit the deadline
|
|
196
|
+
// Bail if we've hit the deadline or have been interrupted.
|
|
186
197
|
if (deadline && this.dateProvider.now() > +deadline) {
|
|
187
198
|
this.log.warn(`Stopping tx processing due to timeout.`);
|
|
188
199
|
break;
|
|
189
200
|
}
|
|
201
|
+
if (signal?.aborted) {
|
|
202
|
+
this.log.warn(`Stopping tx processing due to abort signal.`);
|
|
203
|
+
break;
|
|
204
|
+
}
|
|
190
205
|
|
|
191
206
|
const txHash = tx.getTxHash().toString();
|
|
192
207
|
|
|
@@ -224,11 +239,6 @@ export class PublicProcessor implements Traceable {
|
|
|
224
239
|
failed.push({ tx, error: new Error(`Tx failed preprocess validation: ${reason}`) });
|
|
225
240
|
returns.push(new NestedProcessReturnValues([]));
|
|
226
241
|
continue;
|
|
227
|
-
} else if (result.result === 'skipped') {
|
|
228
|
-
const reason = result.reason.join(', ');
|
|
229
|
-
this.log.debug(`Skipping tx ${txHash.toString()} due to pre-process validation: ${reason}`);
|
|
230
|
-
returns.push(new NestedProcessReturnValues([]));
|
|
231
|
-
continue;
|
|
232
242
|
} else {
|
|
233
243
|
this.log.trace(`Tx ${txHash.toString()} is valid before processing.`);
|
|
234
244
|
}
|
|
@@ -244,7 +254,9 @@ export class PublicProcessor implements Traceable {
|
|
|
244
254
|
this.contractsDB.createCheckpoint();
|
|
245
255
|
|
|
246
256
|
try {
|
|
247
|
-
const [processedTx, returnValues, txDebugLogs] = await
|
|
257
|
+
const [txProcessingTimeMs, [processedTx, returnValues, txDebugLogs]] = await elapsed(() =>
|
|
258
|
+
this.processTx(tx, deadline, signal),
|
|
259
|
+
);
|
|
248
260
|
|
|
249
261
|
// Inject a fake processing failure after N txs if requested
|
|
250
262
|
const fakeThrowAfter = this.opts.fakeThrowAfterProcessingTxCount;
|
|
@@ -265,8 +277,12 @@ export class PublicProcessor implements Traceable {
|
|
|
265
277
|
txBlobFields,
|
|
266
278
|
totalBlobFields,
|
|
267
279
|
maxBlobFields,
|
|
280
|
+
txProcessingTimeMs,
|
|
268
281
|
},
|
|
269
282
|
);
|
|
283
|
+
silentlySkippedCount += 1;
|
|
284
|
+
totalSilentlySkippedDurationMs += txProcessingTimeMs;
|
|
285
|
+
this.metrics.recordSilentlySkipped(txProcessingTimeMs);
|
|
270
286
|
// Need to revert the checkpoint here and don't go any further
|
|
271
287
|
await checkpoint.revert();
|
|
272
288
|
this.contractsDB.revertCheckpoint();
|
|
@@ -306,16 +322,15 @@ export class PublicProcessor implements Traceable {
|
|
|
306
322
|
totalBlockGas = totalBlockGas.add(processedTx.gasUsed.totalGas);
|
|
307
323
|
totalSizeInBytes += txSize;
|
|
308
324
|
totalBlobFields += txBlobFields;
|
|
325
|
+
|
|
326
|
+
// Commit the tx-level contracts checkpoint on success
|
|
327
|
+
this.contractsDB.commitCheckpoint();
|
|
309
328
|
} catch (err: any) {
|
|
310
|
-
if (err
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
//
|
|
314
|
-
// Signal cancellation AND WAIT for the simulation to actually stop.
|
|
315
|
-
// This is critical because C++ might be in the middle of a slow operation (e.g., pad_trees)
|
|
316
|
-
// and won't check the cancellation flag until that operation completes.
|
|
317
|
-
// Without waiting, we'd proceed to revert checkpoints while C++ is still writing to state.
|
|
318
|
-
// Wait for C++ to stop gracefully.
|
|
329
|
+
if (isPublicProcessorInterruptError(err)) {
|
|
330
|
+
const interruptReason = err.name === 'PublicProcessorTimeoutError' ? 'timeout' : 'abort signal';
|
|
331
|
+
this.log.warn(`Stopping tx processing due to ${interruptReason}.`);
|
|
332
|
+
// The tx may still be executing on a worker thread (C++ via NAPI).
|
|
333
|
+
// Signal cancellation AND WAIT for the simulation to actually stop before touching fork checkpoints.
|
|
319
334
|
await this.publicTxSimulator.cancel?.();
|
|
320
335
|
|
|
321
336
|
// Now stop the guarded fork to prevent any further TS-side access to the world state.
|
|
@@ -354,7 +369,6 @@ export class PublicProcessor implements Traceable {
|
|
|
354
369
|
} finally {
|
|
355
370
|
// Base case is we always commit the checkpoint. Using the ForkCheckpoint means this has no effect if the tx was previously reverted
|
|
356
371
|
await checkpoint.commit();
|
|
357
|
-
this.contractsDB.commitCheckpointOkIfNone();
|
|
358
372
|
}
|
|
359
373
|
}
|
|
360
374
|
|
|
@@ -362,13 +376,24 @@ export class PublicProcessor implements Traceable {
|
|
|
362
376
|
const rate = duration > 0 ? totalPublicGas.l2Gas / duration : 0;
|
|
363
377
|
this.metrics.recordAllTxs(totalPublicGas, rate);
|
|
364
378
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
379
|
+
const silentlySkippedDurationMs = Math.round(totalSilentlySkippedDurationMs);
|
|
380
|
+
this.log.info(
|
|
381
|
+
`Processed ${result.length} successful txs and ${failed.length} failed txs ` +
|
|
382
|
+
`(${silentlySkippedCount} silently skipped, ${silentlySkippedDurationMs}ms wasted) ` +
|
|
383
|
+
`in ${duration}s`,
|
|
384
|
+
{
|
|
385
|
+
blockNumber: this.globalVariables.blockNumber,
|
|
386
|
+
successfulCount: result.length,
|
|
387
|
+
failedCount: failed.length,
|
|
388
|
+
duration,
|
|
389
|
+
rate,
|
|
390
|
+
totalPublicGas,
|
|
391
|
+
totalBlockGas,
|
|
392
|
+
totalSizeInBytes,
|
|
393
|
+
silentlySkippedCount,
|
|
394
|
+
silentlySkippedDurationMs,
|
|
395
|
+
},
|
|
396
|
+
);
|
|
372
397
|
|
|
373
398
|
return [result, failed, usedTxs, returns, debugLogs];
|
|
374
399
|
}
|
|
@@ -393,9 +418,10 @@ export class PublicProcessor implements Traceable {
|
|
|
393
418
|
private async processTx(
|
|
394
419
|
tx: Tx,
|
|
395
420
|
deadline: Date | undefined,
|
|
421
|
+
signal: AbortSignal | undefined,
|
|
396
422
|
): Promise<[ProcessedTx, NestedProcessReturnValues[], DebugLog[]]> {
|
|
397
423
|
const [time, [processedTx, returnValues, debugLogs]] = await elapsed(() =>
|
|
398
|
-
this.processTxWithinDeadline(tx, deadline),
|
|
424
|
+
this.processTxWithinDeadline(tx, deadline, signal),
|
|
399
425
|
);
|
|
400
426
|
|
|
401
427
|
this.log.verbose(
|
|
@@ -449,10 +475,11 @@ export class PublicProcessor implements Traceable {
|
|
|
449
475
|
this.metrics.recordTreeInsertions(Number(treeInsertionEnd - treeInsertionStart) / 1_000);
|
|
450
476
|
}
|
|
451
477
|
|
|
452
|
-
/** Processes the given tx within deadline
|
|
478
|
+
/** Processes the given tx within deadline or until the signal is aborted. */
|
|
453
479
|
private async processTxWithinDeadline(
|
|
454
480
|
tx: Tx,
|
|
455
481
|
deadline: Date | undefined,
|
|
482
|
+
signal: AbortSignal | undefined,
|
|
456
483
|
): Promise<[ProcessedTx, NestedProcessReturnValues[] | undefined, DebugLog[]]> {
|
|
457
484
|
const innerProcessFn: () => Promise<[ProcessedTx, NestedProcessReturnValues[] | undefined, DebugLog[]]> =
|
|
458
485
|
tx.hasPublicCalls() ? () => this.processTxWithPublicCalls(tx) : () => this.processPrivateOnlyTx(tx);
|
|
@@ -469,27 +496,38 @@ export class PublicProcessor implements Traceable {
|
|
|
469
496
|
}
|
|
470
497
|
: innerProcessFn;
|
|
471
498
|
|
|
472
|
-
|
|
499
|
+
const processingSignal = this.getProcessingSignal(tx, deadline, signal);
|
|
500
|
+
if (!processingSignal) {
|
|
473
501
|
return await processFn();
|
|
474
502
|
}
|
|
475
503
|
|
|
476
|
-
|
|
504
|
+
return await execWithSignal(
|
|
505
|
+
() => processFn(),
|
|
506
|
+
processingSignal,
|
|
507
|
+
signal =>
|
|
508
|
+
signal.reason?.name === 'TimeoutError' ? new PublicProcessorTimeoutError() : new PublicProcessorAbortError(),
|
|
509
|
+
);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
private getProcessingSignal(tx: Tx, deadline: Date | undefined, signal: AbortSignal | undefined) {
|
|
513
|
+
if (!deadline) {
|
|
514
|
+
return signal;
|
|
515
|
+
}
|
|
516
|
+
|
|
477
517
|
const timeout = +deadline - this.dateProvider.now();
|
|
478
518
|
if (timeout <= 0) {
|
|
479
519
|
throw new PublicProcessorTimeoutError();
|
|
480
520
|
}
|
|
481
521
|
|
|
522
|
+
const txHash = tx.getTxHash();
|
|
482
523
|
this.log.debug(`Processing tx ${txHash.toString()} within ${timeout}ms`, {
|
|
483
524
|
deadline: deadline.toISOString(),
|
|
484
525
|
now: new Date(this.dateProvider.now()).toISOString(),
|
|
485
526
|
txHash,
|
|
486
527
|
});
|
|
487
528
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
timeout,
|
|
491
|
-
() => new PublicProcessorTimeoutError(),
|
|
492
|
-
);
|
|
529
|
+
const timeoutSignal = AbortSignal.timeout(timeout);
|
|
530
|
+
return signal ? AbortSignal.any([signal, timeoutSignal]) : timeoutSignal;
|
|
493
531
|
}
|
|
494
532
|
|
|
495
533
|
/**
|
|
@@ -546,7 +584,7 @@ export class PublicProcessor implements Traceable {
|
|
|
546
584
|
// Fee payment insertion has already been done. Do the rest.
|
|
547
585
|
await this.doTreeInsertionsForPrivateOnlyTx(processedTx);
|
|
548
586
|
|
|
549
|
-
|
|
587
|
+
this.contractsDB.addNewContracts(tx);
|
|
550
588
|
|
|
551
589
|
return [processedTx, undefined, []];
|
|
552
590
|
}
|
|
@@ -30,6 +30,9 @@ export class PublicProcessorMetrics {
|
|
|
30
30
|
|
|
31
31
|
private treeInsertionDuration: Histogram;
|
|
32
32
|
|
|
33
|
+
private silentlySkippedCount: UpDownCounter;
|
|
34
|
+
private silentlySkippedDuration: Histogram;
|
|
35
|
+
|
|
33
36
|
constructor(client: TelemetryClient, name = 'PublicProcessor') {
|
|
34
37
|
this.tracer = client.getTracer(name);
|
|
35
38
|
const meter = client.getMeter(name);
|
|
@@ -60,6 +63,10 @@ export class PublicProcessorMetrics {
|
|
|
60
63
|
this.gasRate = meter.createHistogram(Metrics.PUBLIC_PROCESSOR_GAS_RATE);
|
|
61
64
|
|
|
62
65
|
this.treeInsertionDuration = meter.createHistogram(Metrics.PUBLIC_PROCESSOR_TREE_INSERTION);
|
|
66
|
+
|
|
67
|
+
this.silentlySkippedCount = createUpDownCounterWithDefault(meter, Metrics.PUBLIC_PROCESSOR_SILENTLY_SKIPPED_COUNT);
|
|
68
|
+
|
|
69
|
+
this.silentlySkippedDuration = meter.createHistogram(Metrics.PUBLIC_PROCESSOR_SILENTLY_SKIPPED_DURATION);
|
|
63
70
|
}
|
|
64
71
|
|
|
65
72
|
recordPhaseDuration(phaseName: TxExecutionPhase, durationMs: number) {
|
|
@@ -123,4 +130,9 @@ export class PublicProcessorMetrics {
|
|
|
123
130
|
recordTreeInsertions(durationUs: number) {
|
|
124
131
|
this.treeInsertionDuration.record(Math.ceil(durationUs));
|
|
125
132
|
}
|
|
133
|
+
|
|
134
|
+
recordSilentlySkipped(durationMs: number) {
|
|
135
|
+
this.silentlySkippedCount.add(1);
|
|
136
|
+
this.silentlySkippedDuration.record(Math.ceil(durationMs));
|
|
137
|
+
}
|
|
126
138
|
}
|
|
@@ -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
|
|
|
@@ -61,8 +62,8 @@ export class ContractProviderForCpp implements ContractProvider {
|
|
|
61
62
|
const contractDeploymentData = ContractDeploymentData.fromPlainObject(rawData);
|
|
62
63
|
|
|
63
64
|
// Add contracts to the contracts DB
|
|
64
|
-
this.log.trace(`Calling contractsDB.
|
|
65
|
-
|
|
65
|
+
this.log.trace(`Calling contractsDB.addContractsFromLogs`);
|
|
66
|
+
this.contractsDB.addContractsFromLogs(contractDeploymentData);
|
|
66
67
|
};
|
|
67
68
|
|
|
68
69
|
public getBytecodeCommitment = async (classId: string): Promise<Buffer | undefined> => {
|
|
@@ -12,11 +12,8 @@ import {
|
|
|
12
12
|
import { SimulationError } from '@aztec/stdlib/errors';
|
|
13
13
|
import type { MerkleTreeWriteOperations } from '@aztec/stdlib/trees';
|
|
14
14
|
import type { GlobalVariables, Tx } from '@aztec/stdlib/tx';
|
|
15
|
-
import { WorldStateRevisionWithHandle } from '@aztec/stdlib/world-state';
|
|
16
15
|
import { type TelemetryClient, type Tracer, getTelemetryClient } from '@aztec/telemetry-client';
|
|
17
16
|
|
|
18
|
-
import { strict as assert } from 'assert';
|
|
19
|
-
|
|
20
17
|
import { ExecutorMetrics } from '../executor_metrics.js';
|
|
21
18
|
import type { ExecutorMetricsInterface } from '../executor_metrics_interface.js';
|
|
22
19
|
import type { PublicContractsDB } from '../public_db_sources.js';
|
|
@@ -62,14 +59,8 @@ export class CppPublicTxSimulator extends PublicTxSimulator implements PublicTxS
|
|
|
62
59
|
txHash,
|
|
63
60
|
});
|
|
64
61
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
assert(
|
|
68
|
-
wsRevision instanceof WorldStateRevisionWithHandle,
|
|
69
|
-
'CppPublicTxSimulator a real NativeWorldStateInstance with a handle to the C++ WorldState object',
|
|
70
|
-
);
|
|
71
|
-
const wsCppHandle = (wsRevision as WorldStateRevisionWithHandle).handle;
|
|
72
|
-
wsRevision = wsRevision.toWorldStateRevision(); // for msgpack serialization, we don't include the handle in the type
|
|
62
|
+
const wsRevision = this.merkleTree.getRevision();
|
|
63
|
+
const wsdbSocketPath = this.merkleTree.getSocketPath();
|
|
73
64
|
|
|
74
65
|
this.log.trace(`Running C++ simulation with world state revision ${JSON.stringify(wsRevision)}`);
|
|
75
66
|
|
|
@@ -99,7 +90,7 @@ export class CppPublicTxSimulator extends PublicTxSimulator implements PublicTxS
|
|
|
99
90
|
this.simulationPromise = avmSimulate(
|
|
100
91
|
inputBuffer,
|
|
101
92
|
contractProvider,
|
|
102
|
-
|
|
93
|
+
wsdbSocketPath,
|
|
103
94
|
this.log.level,
|
|
104
95
|
undefined,
|
|
105
96
|
this.cancellationToken,
|
|
@@ -11,7 +11,6 @@ import {
|
|
|
11
11
|
import { SimulationError } from '@aztec/stdlib/errors';
|
|
12
12
|
import type { MerkleTreeWriteOperations } from '@aztec/stdlib/trees';
|
|
13
13
|
import type { GlobalVariables, StateReference, Tx } from '@aztec/stdlib/tx';
|
|
14
|
-
import { WorldStateRevisionWithHandle } from '@aztec/stdlib/world-state';
|
|
15
14
|
|
|
16
15
|
import { strict as assert } from 'assert';
|
|
17
16
|
|
|
@@ -81,14 +80,8 @@ export class CppVsTsPublicTxSimulator extends PublicTxSimulator implements Publi
|
|
|
81
80
|
|
|
82
81
|
this.log.debug(`Running C++ simulation for tx ${txHash}`);
|
|
83
82
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
assert(
|
|
87
|
-
wsRevision instanceof WorldStateRevisionWithHandle,
|
|
88
|
-
'CppPublicTxSimulator a real NativeWorldStateInstance with a handle to the C++ WorldState object',
|
|
89
|
-
);
|
|
90
|
-
const wsCppHandle = (wsRevision as WorldStateRevisionWithHandle).handle;
|
|
91
|
-
wsRevision = wsRevision.toWorldStateRevision(); // for msgpack serialization, we don't include the handle in the type
|
|
83
|
+
const wsRevision = this.merkleTree.getRevision();
|
|
84
|
+
const wsdbSocketPath = this.merkleTree.getSocketPath();
|
|
92
85
|
|
|
93
86
|
this.log.debug(`Running C++ simulation with world state revision ${JSON.stringify(wsRevision)}`);
|
|
94
87
|
|
|
@@ -113,7 +106,7 @@ export class CppVsTsPublicTxSimulator extends PublicTxSimulator implements Publi
|
|
|
113
106
|
let resultBuffer: Buffer;
|
|
114
107
|
try {
|
|
115
108
|
this.log.debug(`Calling C++ simulator for tx ${txHash}`);
|
|
116
|
-
resultBuffer = await avmSimulate(inputBuffer, contractProvider,
|
|
109
|
+
resultBuffer = await avmSimulate(inputBuffer, contractProvider, wsdbSocketPath, logLevel);
|
|
117
110
|
} catch (error: any) {
|
|
118
111
|
throw new SimulationError(`C++ simulation failed: ${error.message}`, []);
|
|
119
112
|
}
|
|
@@ -174,14 +174,8 @@ export class PublicTxContext {
|
|
|
174
174
|
}
|
|
175
175
|
if (phase === TxExecutionPhase.SETUP) {
|
|
176
176
|
this.log.warn(`Setup phase reverted! The transaction will be thrown out.`);
|
|
177
|
-
} else if (phase === TxExecutionPhase.APP_LOGIC) {
|
|
178
|
-
this.revertCode = RevertCode.
|
|
179
|
-
} else if (phase === TxExecutionPhase.TEARDOWN) {
|
|
180
|
-
if (this.revertCode.equals(RevertCode.APP_LOGIC_REVERTED)) {
|
|
181
|
-
this.revertCode = RevertCode.BOTH_REVERTED;
|
|
182
|
-
} else {
|
|
183
|
-
this.revertCode = RevertCode.TEARDOWN_REVERTED;
|
|
184
|
-
}
|
|
177
|
+
} else if (phase === TxExecutionPhase.APP_LOGIC || phase === TxExecutionPhase.TEARDOWN) {
|
|
178
|
+
this.revertCode = RevertCode.REVERTED;
|
|
185
179
|
}
|
|
186
180
|
}
|
|
187
181
|
|
|
@@ -247,8 +241,12 @@ export class PublicTxContext {
|
|
|
247
241
|
}
|
|
248
242
|
|
|
249
243
|
/**
|
|
250
|
-
* The gasUsed by public and private,
|
|
251
|
-
*
|
|
244
|
+
* The gasUsed by public and private, as if the entire teardown gas limit was consumed.
|
|
245
|
+
*
|
|
246
|
+
* This is intentional: teardown is used for gas accounting and refunds, so the transaction
|
|
247
|
+
* fee must be deterministic _before_ teardown executes. If fees depended on teardown's actual
|
|
248
|
+
* consumption there would be a circular dependency. Billing the full teardown gas limit
|
|
249
|
+
* (set by the user) makes the fee known in advance and available to the teardown function.
|
|
252
250
|
*/
|
|
253
251
|
getTotalGasUsed(): Gas {
|
|
254
252
|
return this.gasUsedByPrivate.add(this.gasUsedByPublic);
|