Skip to content

Commit

Permalink
chore: speed up AVM TS simulator
Browse files Browse the repository at this point in the history
  • Loading branch information
dbanks12 committed Feb 6, 2025
1 parent f8448bf commit da3c2a3
Show file tree
Hide file tree
Showing 22 changed files with 145 additions and 378 deletions.
4 changes: 4 additions & 0 deletions yarn-project/simulator/src/avm/apps_tests/avm_test.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,7 @@ describe('AVM simulator apps tests: AvmTestContract', () => {
);
});
});

//function sha256FromMemoryBytes(bytes: Uint8[]): Promise<Fr[]> {
// return Promise.resolve([...sha256(Buffer.concat(bytes.map(b => b.toBuffer())))].map(b => new Fr(b)));
//}
32 changes: 18 additions & 14 deletions yarn-project/simulator/src/avm/avm_machine_state.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { type Fr } from '@aztec/circuits.js';

import { GAS_DIMENSIONS, type Gas } from './avm_gas.js';
import { type Gas } from './avm_gas.js';
import { TaggedMemory } from './avm_memory_types.js';
import { type AvmRevertReason, OutOfGasError } from './errors.js';

Expand Down Expand Up @@ -92,26 +92,29 @@ export class AvmMachineState {
*/
public consumeGas(gasCost: Partial<Gas>) {
// Assert there is enough gas on every dimension.
const outOfGasDimensions = GAS_DIMENSIONS.filter(
dimension => this[`${dimension}Left`] - (gasCost[dimension] ?? 0) < 0,
);
const outOfL2Gas = this.l2GasLeft - (gasCost.l2Gas ?? 0) < 0;
const outOfDaGas = this.daGasLeft - (gasCost.daGas ?? 0) < 0;
// If not, trigger an exceptional halt.
// See https://yp-aztec.netlify.app/docs/public-vm/execution#gas-checks-and-tracking
if (outOfGasDimensions.length > 0) {
if (outOfL2Gas || outOfDaGas) {
this.exceptionalHalt();
throw new OutOfGasError(outOfGasDimensions);
const dimensions = [];
if (outOfL2Gas) {
dimensions.push('l2Gas');
}
if (outOfDaGas) {
dimensions.push('daGas');
}
throw new OutOfGasError(dimensions);
}
// Otherwise, charge the corresponding gas
for (const dimension of GAS_DIMENSIONS) {
this[`${dimension}Left`] -= gasCost[dimension] ?? 0;
}
this.l2GasLeft -= gasCost.l2Gas ?? 0;
this.daGasLeft -= gasCost.daGas ?? 0;
}

/** Increases the gas left by the amounts specified. */
public refundGas(gasRefund: Partial<Gas>) {
for (const dimension of GAS_DIMENSIONS) {
this[`${dimension}Left`] += gasRefund[dimension] ?? 0;
}
this.l2GasLeft += gasRefund.l2Gas ?? 0;
this.daGasLeft += gasRefund.daGas ?? 0;
}

/**
Expand Down Expand Up @@ -151,7 +154,8 @@ export class AvmMachineState {
* Flag an exceptional halt. Clears gas left and sets the reverted flag. No output data.
*/
private exceptionalHalt() {
GAS_DIMENSIONS.forEach(dimension => (this[`${dimension}Left`] = 0));
this.l2GasLeft = 0;
this.daGasLeft = 0;
this.reverted = true;
this.halted = true;
}
Expand Down
64 changes: 1 addition & 63 deletions yarn-project/simulator/src/avm/avm_memory_types.test.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,6 @@
import { AssertionError } from 'assert';

import {
Field,
MeteredTaggedMemory,
TaggedMemory,
Uint1,
Uint8,
Uint16,
Uint32,
Uint64,
Uint128,
} from './avm_memory_types.js';
import { Field, TaggedMemory, Uint1, Uint8, Uint16, Uint32, Uint64, Uint128 } from './avm_memory_types.js';

describe('TaggedMemory', () => {
it('Elements should be Field(0) after construction', () => {
Expand Down Expand Up @@ -67,58 +57,6 @@ describe('TaggedMemory', () => {
});
});

describe('MeteredTaggedMemory', () => {
let mem: MeteredTaggedMemory;

beforeEach(() => {
mem = new MeteredTaggedMemory(new TaggedMemory());
});

it(`Counts reads`, () => {
mem.get(10);
mem.getAs(20);
expect(mem.reset()).toEqual({ reads: 2, writes: 0 });
});

it(`Counts reading slices`, () => {
const val = [new Field(5), new Field(6), new Field(7)];
mem.setSlice(10, val);
mem.reset();

mem.getSlice(10, 3);
mem.getSliceAs(11, 2);
expect(mem.reset()).toEqual({ reads: 5, writes: 0 });
});

it(`Counts writes`, () => {
mem.set(10, new Uint8(5));
expect(mem.reset()).toEqual({ reads: 0, writes: 1 });
});

it(`Counts writing slices`, () => {
mem.setSlice(10, [new Field(5), new Field(6)]);
expect(mem.reset()).toEqual({ reads: 0, writes: 2 });
});

it(`Clears stats`, () => {
mem.get(10);
mem.set(20, new Uint8(5));
expect(mem.reset()).toEqual({ reads: 1, writes: 1 });
expect(mem.reset()).toEqual({ reads: 0, writes: 0 });
});

it(`Asserts stats`, () => {
mem.get(10);
mem.set(20, new Uint8(5));
expect(() => mem.assert({ reads: 1, writes: 1 })).not.toThrow();
});

it(`Throws on failed stat assertion`, () => {
mem.get(10);
expect(() => mem.assert({ reads: 1, writes: 1 })).toThrow();
});
});

type IntegralClass = typeof Uint1 | typeof Uint8 | typeof Uint16 | typeof Uint32 | typeof Uint64 | typeof Uint128;

describe.each([Uint1])('Integral Types (U1 only)', (clsValue: IntegralClass) => {
Expand Down
Loading

0 comments on commit da3c2a3

Please sign in to comment.