Skip to content

Commit

Permalink
refactor(avm): Introduce fixed gas cost instruction abstraction
Browse files Browse the repository at this point in the history
  • Loading branch information
spalladino committed Mar 29, 2024
1 parent 9f4063b commit edb982e
Show file tree
Hide file tree
Showing 17 changed files with 157 additions and 144 deletions.
3 changes: 2 additions & 1 deletion yarn-project/simulator/src/avm/avm_gas.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { TypeTag } from './avm_memory_types.js';
import { InstructionExecutionError } from './errors.js';
import { Addressing, AddressingMode } from './opcodes/addressing_mode.js';
import { Opcode } from './serialization/instruction_serialization.js';

Expand Down Expand Up @@ -167,6 +168,6 @@ export function getGasCostMultiplierFromTypeTag(tag: TypeTag) {
return 32;
case TypeTag.INVALID:
case TypeTag.UNINITIALIZED:
throw new Error(`Invalid tag type for gas cost multiplier: ${TypeTag[tag]}`);
throw new InstructionExecutionError(`Invalid tag type for gas cost multiplier: ${TypeTag[tag]}`);
}
}
2 changes: 1 addition & 1 deletion yarn-project/simulator/src/avm/avm_simulator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export class AvmSimulator {
// Execute the instruction.
// Normal returns and reverts will return normally here.
// "Exceptional halts" will throw.
await instruction.run(this.context);
await instruction.execute(this.context);

if (this.context.machineState.pc >= instructions.length) {
this.log('Passed end of program!');
Expand Down
30 changes: 15 additions & 15 deletions yarn-project/simulator/src/avm/opcodes/accrued_substate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import { InstructionExecutionError } from '../errors.js';
import { NullifierCollisionError } from '../journal/nullifiers.js';
import { Opcode, OperandType } from '../serialization/instruction_serialization.js';
import { Addressing } from './addressing_mode.js';
import { Instruction } from './instruction.js';
import { FixedGasInstruction } from './fixed_gas_instruction.js';
import { StaticCallStorageAlterError } from './storage.js';

export class NoteHashExists extends Instruction {
export class NoteHashExists extends FixedGasInstruction {
static type: string = 'NOTEHASHEXISTS';
static readonly opcode: Opcode = Opcode.NOTEHASHEXISTS;
// Informs (de)serialization. See Instruction.deserialize.
Expand All @@ -28,7 +28,7 @@ export class NoteHashExists extends Instruction {
super();
}

async execute(context: AvmContext): Promise<void> {
protected async internalExecute(context: AvmContext): Promise<void> {
// Note that this instruction accepts any type in memory, and converts to Field.
const noteHash = context.machineState.memory.get(this.noteHashOffset).toFr();
const leafIndex = context.machineState.memory.get(this.leafIndexOffset).toFr();
Expand All @@ -44,7 +44,7 @@ export class NoteHashExists extends Instruction {
}
}

export class EmitNoteHash extends Instruction {
export class EmitNoteHash extends FixedGasInstruction {
static type: string = 'EMITNOTEHASH';
static readonly opcode: Opcode = Opcode.EMITNOTEHASH;
// Informs (de)serialization. See Instruction.deserialize.
Expand All @@ -54,7 +54,7 @@ export class EmitNoteHash extends Instruction {
super();
}

async execute(context: AvmContext): Promise<void> {
protected async internalExecute(context: AvmContext): Promise<void> {
if (context.environment.isStaticCall) {
throw new StaticCallStorageAlterError();
}
Expand All @@ -66,7 +66,7 @@ export class EmitNoteHash extends Instruction {
}
}

export class NullifierExists extends Instruction {
export class NullifierExists extends FixedGasInstruction {
static type: string = 'NULLIFIEREXISTS';
static readonly opcode: Opcode = Opcode.NULLIFIEREXISTS;
// Informs (de)serialization. See Instruction.deserialize.
Expand All @@ -76,7 +76,7 @@ export class NullifierExists extends Instruction {
super();
}

async execute(context: AvmContext): Promise<void> {
protected async internalExecute(context: AvmContext): Promise<void> {
const nullifier = context.machineState.memory.get(this.nullifierOffset).toFr();
const exists = await context.persistableState.checkNullifierExists(context.environment.storageAddress, nullifier);

Expand All @@ -86,7 +86,7 @@ export class NullifierExists extends Instruction {
}
}

export class EmitNullifier extends Instruction {
export class EmitNullifier extends FixedGasInstruction {
static type: string = 'EMITNULLIFIER';
static readonly opcode: Opcode = Opcode.EMITNULLIFIER;
// Informs (de)serialization. See Instruction.deserialize.
Expand All @@ -96,7 +96,7 @@ export class EmitNullifier extends Instruction {
super();
}

async execute(context: AvmContext): Promise<void> {
protected async internalExecute(context: AvmContext): Promise<void> {
if (context.environment.isStaticCall) {
throw new StaticCallStorageAlterError();
}
Expand All @@ -119,7 +119,7 @@ export class EmitNullifier extends Instruction {
}
}

export class L1ToL2MessageExists extends Instruction {
export class L1ToL2MessageExists extends FixedGasInstruction {
static type: string = 'L1TOL2MSGEXISTS';
static readonly opcode: Opcode = Opcode.L1TOL2MSGEXISTS;
// Informs (de)serialization. See Instruction.deserialize.
Expand All @@ -140,7 +140,7 @@ export class L1ToL2MessageExists extends Instruction {
super();
}

async execute(context: AvmContext): Promise<void> {
protected async internalExecute(context: AvmContext): Promise<void> {
const msgHash = context.machineState.memory.get(this.msgHashOffset).toFr();
const msgLeafIndex = context.machineState.memory.get(this.msgLeafIndexOffset).toFr();
const exists = await context.persistableState.checkL1ToL2MessageExists(msgHash, msgLeafIndex);
Expand All @@ -150,7 +150,7 @@ export class L1ToL2MessageExists extends Instruction {
}
}

export class EmitUnencryptedLog extends Instruction {
export class EmitUnencryptedLog extends FixedGasInstruction {
static type: string = 'EMITUNENCRYPTEDLOG';
static readonly opcode: Opcode = Opcode.EMITUNENCRYPTEDLOG;
// Informs (de)serialization. See Instruction.deserialize.
Expand All @@ -171,7 +171,7 @@ export class EmitUnencryptedLog extends Instruction {
super();
}

async execute(context: AvmContext): Promise<void> {
protected async internalExecute(context: AvmContext): Promise<void> {
if (context.environment.isStaticCall) {
throw new StaticCallStorageAlterError();
}
Expand All @@ -190,7 +190,7 @@ export class EmitUnencryptedLog extends Instruction {
}
}

export class SendL2ToL1Message extends Instruction {
export class SendL2ToL1Message extends FixedGasInstruction {
static type: string = 'SENDL2TOL1MSG';
static readonly opcode: Opcode = Opcode.SENDL2TOL1MSG;
// Informs (de)serialization. See Instruction.deserialize.
Expand All @@ -200,7 +200,7 @@ export class SendL2ToL1Message extends Instruction {
super();
}

async execute(context: AvmContext): Promise<void> {
protected async internalExecute(context: AvmContext): Promise<void> {
if (context.environment.isStaticCall) {
throw new StaticCallStorageAlterError();
}
Expand Down
12 changes: 6 additions & 6 deletions yarn-project/simulator/src/avm/opcodes/arithmetic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import {
} from '../avm_gas.js';
import { Field, MemoryValue, TypeTag } from '../avm_memory_types.js';
import { Opcode, OperandType } from '../serialization/instruction_serialization.js';
import { Instruction } from './instruction.js';
import { ThreeOperandInstruction } from './instruction_impl.js';
import { FixedGasInstruction } from './fixed_gas_instruction.js';
import { ThreeOperandFixedGasInstruction } from './instruction_impl.js';

export abstract class ThreeOperandArithmeticInstruction extends ThreeOperandInstruction {
async execute(context: AvmContext): Promise<void> {
export abstract class ThreeOperandArithmeticInstruction extends ThreeOperandFixedGasInstruction {
protected async internalExecute(context: AvmContext): Promise<void> {
context.machineState.memory.checkTags(this.inTag, this.aOffset, this.bOffset);

const a = context.machineState.memory.get(this.aOffset);
Expand Down Expand Up @@ -71,7 +71,7 @@ export class Div extends ThreeOperandArithmeticInstruction {
}
}

export class FieldDiv extends Instruction {
export class FieldDiv extends FixedGasInstruction {
static type: string = 'FDIV';
static readonly opcode = Opcode.FDIV;

Expand All @@ -88,7 +88,7 @@ export class FieldDiv extends Instruction {
super();
}

async execute(context: AvmContext): Promise<void> {
protected async internalExecute(context: AvmContext): Promise<void> {
context.machineState.memory.checkTags(TypeTag.FIELD, this.aOffset, this.bOffset);

const a = context.machineState.memory.getAs<Field>(this.aOffset);
Expand Down
26 changes: 13 additions & 13 deletions yarn-project/simulator/src/avm/opcodes/bitwise.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import type { AvmContext } from '../avm_context.js';
import { IntegralValue } from '../avm_memory_types.js';
import { Opcode } from '../serialization/instruction_serialization.js';
import { ThreeOperandInstruction, TwoOperandInstruction } from './instruction_impl.js';
import { ThreeOperandFixedGasInstruction, TwoOperandFixedGasInstruction } from './instruction_impl.js';

export class And extends ThreeOperandInstruction {
export class And extends ThreeOperandFixedGasInstruction {
static readonly type: string = 'AND';
static readonly opcode = Opcode.AND;

constructor(indirect: number, inTag: number, aOffset: number, bOffset: number, dstOffset: number) {
super(indirect, inTag, aOffset, bOffset, dstOffset);
}

async execute(context: AvmContext): Promise<void> {
protected async internalExecute(context: AvmContext): Promise<void> {
context.machineState.memory.checkTags(this.inTag, this.aOffset, this.bOffset);

const a = context.machineState.memory.getAs<IntegralValue>(this.aOffset);
Expand All @@ -24,15 +24,15 @@ export class And extends ThreeOperandInstruction {
}
}

export class Or extends ThreeOperandInstruction {
export class Or extends ThreeOperandFixedGasInstruction {
static readonly type: string = 'OR';
static readonly opcode = Opcode.OR;

constructor(indirect: number, inTag: number, aOffset: number, bOffset: number, dstOffset: number) {
super(indirect, inTag, aOffset, bOffset, dstOffset);
}

async execute(context: AvmContext): Promise<void> {
protected async internalExecute(context: AvmContext): Promise<void> {
context.machineState.memory.checkTags(this.inTag, this.aOffset, this.bOffset);

const a = context.machineState.memory.getAs<IntegralValue>(this.aOffset);
Expand All @@ -45,15 +45,15 @@ export class Or extends ThreeOperandInstruction {
}
}

export class Xor extends ThreeOperandInstruction {
export class Xor extends ThreeOperandFixedGasInstruction {
static readonly type: string = 'XOR';
static readonly opcode = Opcode.XOR;

constructor(indirect: number, inTag: number, aOffset: number, bOffset: number, dstOffset: number) {
super(indirect, inTag, aOffset, bOffset, dstOffset);
}

async execute(context: AvmContext): Promise<void> {
protected async internalExecute(context: AvmContext): Promise<void> {
context.machineState.memory.checkTags(this.inTag, this.aOffset, this.bOffset);

const a = context.machineState.memory.getAs<IntegralValue>(this.aOffset);
Expand All @@ -66,15 +66,15 @@ export class Xor extends ThreeOperandInstruction {
}
}

export class Not extends TwoOperandInstruction {
export class Not extends TwoOperandFixedGasInstruction {
static readonly type: string = 'NOT';
static readonly opcode = Opcode.NOT;

constructor(indirect: number, inTag: number, aOffset: number, dstOffset: number) {
super(indirect, inTag, aOffset, dstOffset);
}

async execute(context: AvmContext): Promise<void> {
protected async internalExecute(context: AvmContext): Promise<void> {
context.machineState.memory.checkTags(this.inTag, this.aOffset);

const a = context.machineState.memory.getAs<IntegralValue>(this.aOffset);
Expand All @@ -86,15 +86,15 @@ export class Not extends TwoOperandInstruction {
}
}

export class Shl extends ThreeOperandInstruction {
export class Shl extends ThreeOperandFixedGasInstruction {
static readonly type: string = 'SHL';
static readonly opcode = Opcode.SHL;

constructor(indirect: number, inTag: number, aOffset: number, bOffset: number, dstOffset: number) {
super(indirect, inTag, aOffset, bOffset, dstOffset);
}

async execute(context: AvmContext): Promise<void> {
protected async internalExecute(context: AvmContext): Promise<void> {
context.machineState.memory.checkTags(this.inTag, this.aOffset, this.bOffset);

const a = context.machineState.memory.getAs<IntegralValue>(this.aOffset);
Expand All @@ -107,15 +107,15 @@ export class Shl extends ThreeOperandInstruction {
}
}

export class Shr extends ThreeOperandInstruction {
export class Shr extends ThreeOperandFixedGasInstruction {
static readonly type: string = 'SHR';
static readonly opcode = Opcode.SHR;

constructor(indirect: number, inTag: number, aOffset: number, bOffset: number, dstOffset: number) {
super(indirect, inTag, aOffset, bOffset, dstOffset);
}

async execute(context: AvmContext): Promise<void> {
protected async internalExecute(context: AvmContext): Promise<void> {
context.machineState.memory.checkTags(this.inTag, this.aOffset, this.bOffset);

const a = context.machineState.memory.getAs<IntegralValue>(this.aOffset);
Expand Down
14 changes: 7 additions & 7 deletions yarn-project/simulator/src/avm/opcodes/comparators.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import type { AvmContext } from '../avm_context.js';
import { Uint8 } from '../avm_memory_types.js';
import { Opcode } from '../serialization/instruction_serialization.js';
import { ThreeOperandInstruction } from './instruction_impl.js';
import { ThreeOperandFixedGasInstruction } from './instruction_impl.js';

export class Eq extends ThreeOperandInstruction {
export class Eq extends ThreeOperandFixedGasInstruction {
static readonly type: string = 'EQ';
static readonly opcode = Opcode.EQ;

constructor(indirect: number, inTag: number, aOffset: number, bOffset: number, dstOffset: number) {
super(indirect, inTag, aOffset, bOffset, dstOffset);
}

async execute(context: AvmContext): Promise<void> {
protected async internalExecute(context: AvmContext): Promise<void> {
context.machineState.memory.checkTags(this.inTag, this.aOffset, this.bOffset);

const a = context.machineState.memory.get(this.aOffset);
Expand All @@ -24,15 +24,15 @@ export class Eq extends ThreeOperandInstruction {
}
}

export class Lt extends ThreeOperandInstruction {
export class Lt extends ThreeOperandFixedGasInstruction {
static readonly type: string = 'LT';
static readonly opcode = Opcode.LT;

constructor(indirect: number, inTag: number, aOffset: number, bOffset: number, dstOffset: number) {
super(indirect, inTag, aOffset, bOffset, dstOffset);
}

async execute(context: AvmContext): Promise<void> {
protected async internalExecute(context: AvmContext): Promise<void> {
context.machineState.memory.checkTags(this.inTag, this.aOffset, this.bOffset);

const a = context.machineState.memory.get(this.aOffset);
Expand All @@ -45,15 +45,15 @@ export class Lt extends ThreeOperandInstruction {
}
}

export class Lte extends ThreeOperandInstruction {
export class Lte extends ThreeOperandFixedGasInstruction {
static readonly type: string = 'LTE';
static readonly opcode = Opcode.LTE;

constructor(indirect: number, inTag: number, aOffset: number, bOffset: number, dstOffset: number) {
super(indirect, inTag, aOffset, bOffset, dstOffset);
}

async execute(context: AvmContext): Promise<void> {
protected async internalExecute(context: AvmContext): Promise<void> {
context.machineState.memory.checkTags(this.inTag, this.aOffset, this.bOffset);

const a = context.machineState.memory.get(this.aOffset);
Expand Down
Loading

0 comments on commit edb982e

Please sign in to comment.