Skip to content

Commit 3c39514

Browse files
committed
feat: migrate to the C++ AVM simulator
1 parent 1ae10de commit 3c39514

File tree

12 files changed

+439
-256
lines changed

12 files changed

+439
-256
lines changed

yarn-project/end-to-end/src/e2e_block_building.test.ts

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@ import { StatefulTestContract } from '@aztec/noir-test-contracts.js/StatefulTest
1616
import { TestContract } from '@aztec/noir-test-contracts.js/Test';
1717
import type { BlockBuilder, SequencerClient } from '@aztec/sequencer-client';
1818
import type { TestSequencerClient } from '@aztec/sequencer-client/test';
19-
import { Set } from '@aztec/simulator/public/avm/opcodes';
20-
import { type PublicTxResult, PublicTxSimulator } from '@aztec/simulator/server';
19+
import type { PublicTxResult, PublicTxSimulatorInterface } from '@aztec/simulator/server';
2120
import { getProofSubmissionDeadlineEpoch } from '@aztec/stdlib/epoch-helpers';
2221
import type { AztecNodeAdmin } from '@aztec/stdlib/interfaces/client';
2322
import { TX_ERROR_EXISTING_NULLIFIER, type Tx } from '@aztec/stdlib/tx';
@@ -558,30 +557,30 @@ describe('e2e_block_building', () => {
558557
]);
559558
const batches = times(2, makeBatch);
560559

561-
// This is embarrassingly brittle. What we want to do here is: we want the sequencer to wait until both
562-
// txs have arrived (so minTxsPerBlock=2), but agree to build a block with 1 tx only, so we change the config
563-
// to minTxsPerBlock=1 as soon as we start processing. We also want to simulate an AVM failure in tx processing
564-
// for only one of the txs, and near the end so all nullifiers have been emitted. So we throw on one of the last
565-
// calls to SET. Note that this will break on brillig or AVM changes that change how many SET operations we use.
566-
let setCount = 0;
567-
const origExecute = Set.prototype.execute;
568-
const spy = jest.spyOn(Set.prototype, 'execute').mockImplementation(async function (...args: any[]) {
569-
setCount++;
570-
if (setCount === 1) {
571-
context.sequencer?.updateConfig({ minTxsPerBlock: 1 });
572-
} else if (setCount === 48) {
573-
throw new Error('Simulated failure in AVM opcode SET');
574-
}
575-
// @ts-expect-error: eslint-be-happy
576-
await origExecute.call(this, ...args);
577-
});
560+
// We want the sequencer to wait until both txs have arrived (so minTxsPerBlock=2), but agree to build
561+
// a block with 1 tx only, so we change the config to minTxsPerBlock=1 as soon as we start processing.
562+
// We also want to simulate an AVM failure in tx processing for only one of the txs.
563+
let simulateCount = 0;
564+
interceptTxProcessorSimulate(
565+
aztecNode as AztecNodeService,
566+
async (tx: Tx, originalSimulate: (tx: Tx) => Promise<PublicTxResult>) => {
567+
simulateCount++;
568+
if (simulateCount === 1) {
569+
context.sequencer?.updateConfig({ minTxsPerBlock: 1 });
570+
}
571+
if (simulateCount === 2) {
572+
throw new Error('Simulated failure in public tx simulation');
573+
}
574+
return await originalSimulate(tx);
575+
},
576+
);
578577

579578
const txs = await Promise.all(batches.map(batch => batch.send({ from: ownerAddress })));
580579
logger.warn(`Sent two txs to test contract`, { txs: await Promise.all(txs.map(tx => tx.getTxHash())) });
581580
await Promise.race(txs.map(tx => tx.wait({ timeout: 60 })));
582581

583-
logger.warn(`At least one tx has been mined (after ${spy.mock.calls.length} AVM SET invocations)`);
584-
expect(setCount).toBeGreaterThanOrEqual(48);
582+
logger.warn(`At least one tx has been mined (after ${simulateCount} public tx simulations)`);
583+
expect(simulateCount).toBeGreaterThanOrEqual(2);
585584
const lastBlock = await context.aztecNode.getBlockHeader();
586585
expect(lastBlock).toBeDefined();
587586

@@ -692,7 +691,7 @@ describe('e2e_block_building', () => {
692691
.mockImplementation(async (...args: Parameters<BlockBuilder['makeBlockBuilderDeps']>) => {
693692
logger.warn('Creating mocked public tx simulator');
694693
const deps = await originalCreateDeps(...args);
695-
const simulator: PublicTxSimulator = (deps.processor as any).publicTxSimulator;
694+
const simulator: PublicTxSimulatorInterface = (deps.processor as any).publicTxSimulator;
696695
const originalSimulate = simulator.simulate.bind(simulator);
697696
jest.spyOn(simulator, 'simulate').mockImplementation((tx: Tx) => stub(tx, originalSimulate));
698697
return deps;

yarn-project/end-to-end/src/e2e_p2p/reex.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { sleep } from '@aztec/foundation/sleep';
77
import { unfreeze } from '@aztec/foundation/types';
88
import type { LibP2PService, P2PClient } from '@aztec/p2p';
99
import type { BlockBuilder } from '@aztec/sequencer-client';
10-
import type { PublicTxResult, PublicTxSimulator } from '@aztec/simulator/server';
10+
import type { CppPublicTxSimulator, PublicTxResult } from '@aztec/simulator/server';
1111
import { BlockProposal, SignatureDomainSeparator, getHashedSignaturePayload } from '@aztec/stdlib/p2p';
1212
import { ReExFailedTxsError, ReExStateMismatchError, ReExTimeoutError } from '@aztec/stdlib/validators';
1313
import type { ValidatorClient, ValidatorKeyStore } from '@aztec/validator-client';
@@ -167,7 +167,7 @@ describe('e2e_p2p_reex', () => {
167167
.mockImplementation(async (...args: Parameters<BlockBuilder['makeBlockBuilderDeps']>) => {
168168
const deps = await originalCreateDeps(...args);
169169
t.logger.warn('Creating mocked processor factory');
170-
const simulator: PublicTxSimulator = (deps.processor as any).publicTxSimulator;
170+
const simulator: CppPublicTxSimulator = (deps.processor as any).publicTxSimulator;
171171
const originalSimulate = simulator.simulate.bind(simulator);
172172
// We only stub the simulate method if it's NOT the first time we see the tx
173173
// so the proposer works fine, but we cause the failure in the validators.

yarn-project/sequencer-client/src/sequencer/block_builder.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
GuardedMerkleTreeOperations,
1212
PublicContractsDB,
1313
PublicProcessor,
14-
TelemetryPublicTxSimulator,
14+
TelemetryCppPublicTxSimulator,
1515
} from '@aztec/simulator/server';
1616
import { PublicSimulatorConfig } from '@aztec/stdlib/avm';
1717
import type { ContractDataSource } from '@aztec/stdlib/contract';
@@ -121,7 +121,7 @@ export class FullNodeBlockBuilder implements IFullNodeBlockBuilder {
121121
const contractsDB = new PublicContractsDB(this.contractDataSource);
122122
const guardedFork = new GuardedMerkleTreeOperations(fork);
123123

124-
const publicTxSimulator = new TelemetryPublicTxSimulator(
124+
const publicTxSimulator = new TelemetryCppPublicTxSimulator(
125125
guardedFork,
126126
contractsDB,
127127
globalVariables,

yarn-project/simulator/src/public/fixtures/public_tx_simulation_tester.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {
1818
getFunctionSelector,
1919
} from '../avm/fixtures/utils.js';
2020
import { PublicContractsDB } from '../public_db_sources.js';
21-
import { MeasuredCppPublicTxSimulator } from '../public_tx_simulator/cpp_public_tx_simulator.js';
21+
import { MeasuredCppVsTsPublicTxSimulator } from '../public_tx_simulator/cpp_vs_ts_public_tx_simulator.js';
2222
import { MeasuredPublicTxSimulator } from '../public_tx_simulator/measured_public_tx_simulator.js';
2323
import type { MeasuredPublicTxSimulatorInterface } from '../public_tx_simulator/public_tx_simulator_interface.js';
2424
import { TestExecutorMetrics } from '../test_executor_metrics.js';
@@ -66,7 +66,7 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
6666

6767
const contractsDB = new PublicContractsDB(contractDataSource);
6868
this.simulator = useCppSimulator
69-
? new MeasuredCppPublicTxSimulator(merkleTree, contractsDB, globals, this.metrics, config)
69+
? new MeasuredCppVsTsPublicTxSimulator(merkleTree, contractsDB, globals, this.metrics, config)
7070
: new MeasuredPublicTxSimulator(merkleTree, contractsDB, globals, this.metrics, config);
7171
}
7272

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
export { PublicContractsDB } from './public_db_sources.js';
22
export { GuardedMerkleTreeOperations } from './public_processor/guarded_merkle_tree.js';
33
export { PublicProcessor, PublicProcessorFactory } from './public_processor/public_processor.js';
4-
export { PublicTxSimulator, TelemetryPublicTxSimulator } from './public_tx_simulator/index.js';
4+
export {
5+
CppPublicTxSimulator,
6+
type PublicTxSimulatorInterface,
7+
TelemetryCppPublicTxSimulator,
8+
} from './public_tx_simulator/index.js';
59
export type { PublicTxResult, PublicSimulatorConfig as PublicTxSimulatorConfig } from '@aztec/stdlib/avm';
610
export { getCallRequestsWithCalldataByPhase } from './utils.js';

yarn-project/simulator/src/public/public_processor/apps_tests/token.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { NativeWorldStateService } from '@aztec/world-state';
1212

1313
import { PublicTxSimulationTester, SimpleContractDataSource } from '../../fixtures/index.js';
1414
import { PublicContractsDB } from '../../public_db_sources.js';
15-
import { CppPublicTxSimulator } from '../../public_tx_simulator/cpp_public_tx_simulator.js';
15+
import { CppVsTsPublicTxSimulator } from '../../public_tx_simulator/cpp_vs_ts_public_tx_simulator.js';
1616
import { PublicTxSimulator } from '../../public_tx_simulator/public_tx_simulator.js';
1717
import { GuardedMerkleTreeOperations } from '../guarded_merkle_tree.js';
1818
import { PublicProcessor } from '../public_processor.js';
@@ -51,7 +51,7 @@ describe.each([
5151
collectCallMetadata: true,
5252
});
5353
const simulator = useCppSimulator
54-
? new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config)
54+
? new CppVsTsPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config)
5555
: new PublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config);
5656

5757
processor = new PublicProcessor(

yarn-project/simulator/src/public/public_processor/public_processor.ts

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,9 @@ import { AssertionError } from 'assert';
5151

5252
import { PublicContractsDB, PublicTreesDB } from '../public_db_sources.js';
5353
import {
54-
type PublicTxSimulator,
5554
type PublicTxSimulatorConfig,
56-
TelemetryPublicTxSimulator,
55+
type PublicTxSimulatorInterface,
56+
TelemetryCppPublicTxSimulator,
5757
} from '../public_tx_simulator/index.js';
5858
import { GuardedMerkleTreeOperations } from './guarded_merkle_tree.js';
5959
import { PublicProcessorMetrics } from './public_processor_metrics.js';
@@ -99,8 +99,8 @@ export class PublicProcessorFactory {
9999
contractsDB: PublicContractsDB,
100100
globalVariables: GlobalVariables,
101101
config?: Partial<PublicTxSimulatorConfig>,
102-
): PublicTxSimulator {
103-
return new TelemetryPublicTxSimulator(merkleTree, contractsDB, globalVariables, this.telemetryClient, config);
102+
): PublicTxSimulatorInterface {
103+
return new TelemetryCppPublicTxSimulator(merkleTree, contractsDB, globalVariables, this.telemetryClient, config);
104104
}
105105
}
106106

@@ -122,7 +122,7 @@ export class PublicProcessor implements Traceable {
122122
protected globalVariables: GlobalVariables,
123123
private guardedMerkleTree: GuardedMerkleTreeOperations,
124124
protected contractsDB: PublicContractsDB,
125-
protected publicTxSimulator: PublicTxSimulator,
125+
protected publicTxSimulator: PublicTxSimulatorInterface,
126126
private dateProvider: DateProvider,
127127
telemetryClient: TelemetryClient = getTelemetryClient(),
128128
private log = createLogger('simulator:public-processor'),
@@ -522,13 +522,9 @@ export class PublicProcessor implements Traceable {
522522
const timer = new Timer();
523523

524524
const result = await this.publicTxSimulator.simulate(tx);
525+
// TODO: use the callStackMetadata here to extract more data about public execution
525526
const { hints, publicInputs, gasUsed, revertCode /*callStackMetadata*/ } = result;
526527

527-
if (!hints) {
528-
this.metrics.recordFailedTx();
529-
throw new Error('Avm proving result was not generated.');
530-
}
531-
532528
const contractClassLogs = revertCode.isOK()
533529
? tx.getContractClassLogs()
534530
: tx.getSplitContractClassLogs(false /* revertible */);
@@ -563,7 +559,7 @@ export class PublicProcessor implements Traceable {
563559
*/
564560
private static generateProvingRequest(
565561
publicInputs: AvmCircuitPublicInputs,
566-
hints: AvmExecutionHints,
562+
hints: AvmExecutionHints = AvmExecutionHints.empty(),
567563
): AvmProvingRequest {
568564
return {
569565
type: ProvingRequestType.PUBLIC_VM,

0 commit comments

Comments
 (0)