Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions yarn-project/simulator/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,12 @@
"@jest/globals": "^29.5.0",
"@types/jest": "^29.5.0",
"@types/levelup": "^5.1.3",
"@types/lodash.merge": "^4.6.9",
"@types/memdown": "^3.0.2",
"@types/node": "^18.7.23",
"jest": "^29.5.0",
"jest-mock-extended": "^3.0.4",
"lodash.merge": "^4.6.2",
"ts-jest": "^29.1.0",
"ts-node": "^10.9.1",
"typescript": "^5.0.4",
Expand Down
57 changes: 47 additions & 10 deletions yarn-project/simulator/src/avm/avm_context.test.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,55 @@
// import { AztecAddress, Fr } from '@aztec/circuits.js';
// import { initContext } from './fixtures/index.js';
import { AztecAddress, Fr } from '@aztec/circuits.js';

import { allSameExcept, initContext } from './fixtures/index.js';

describe('Avm Context', () => {
it('New call should fork context correctly', () => {
// const context = initContext();
// const newAddress = AztecAddress.random();
// const newCalldata = [new Fr(1), new Fr(2)];
// const newContext = context.createNestedContractCallContext(newAddress, newCalldata);
const context = initContext();
context.machineState.pc = 20;

const newAddress = AztecAddress.random();
const newCalldata = [new Fr(1), new Fr(2)];
const newContext = context.createNestedContractCallContext(newAddress, newCalldata);

expect(newContext.environment).toEqual(
allSameExcept(context.environment, {
address: newAddress,
storageAddress: newAddress,
calldata: newCalldata,
isStaticCall: false,
}),
);
expect(newContext.machineState).toEqual(
allSameExcept(context.machineState, {
pc: 0,
}),
);
// FIXME: I can't get this to work.
// expect(newContext.worldState).toEqual(context.worldState.fork());
});

it('New static call should fork context correctly', () => {
// const context = initContext();
// const newAddress = AztecAddress.random();
// const newCalldata = [new Fr(1), new Fr(2)];
// const newContext = context.createNestedContractStaticCallContext(newAddress, newCalldata);
const context = initContext();
context.machineState.pc = 20;

const newAddress = AztecAddress.random();
const newCalldata = [new Fr(1), new Fr(2)];
const newContext = context.createNestedContractStaticCallContext(newAddress, newCalldata);

expect(newContext.environment).toEqual(
allSameExcept(context.environment, {
address: newAddress,
storageAddress: newAddress,
calldata: newCalldata,
isStaticCall: true,
}),
);
expect(newContext.machineState).toEqual(
allSameExcept(context.machineState, {
pc: 0,
}),
);
// FIXME: I can't get this to work.
// expect(newContext.worldState).toEqual(context.worldState.fork());
});
});
53 changes: 23 additions & 30 deletions yarn-project/simulator/src/avm/avm_execution_environment.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Fr } from '@aztec/foundation/fields';

import { initExecutionEnvironment } from './fixtures/index.js';
import { allSameExcept, initExecutionEnvironment } from './fixtures/index.js';

describe('Execution Environment', () => {
const newAddress = new Fr(123456n);
Expand All @@ -10,46 +10,39 @@ describe('Execution Environment', () => {
const executionEnvironment = initExecutionEnvironment();
const newExecutionEnvironment = executionEnvironment.deriveEnvironmentForNestedCall(newAddress, calldata);

allTheSameExcept(executionEnvironment, newExecutionEnvironment, {
address: newAddress,
storageAddress: newAddress,
calldata,
});
expect(newExecutionEnvironment).toEqual(
allSameExcept(executionEnvironment, {
address: newAddress,
storageAddress: newAddress,
calldata,
}),
);
});

it('New delegate call should fork execution environment correctly', () => {
const executionEnvironment = initExecutionEnvironment();
const newExecutionEnvironment = executionEnvironment.newDelegateCall(newAddress, calldata);

allTheSameExcept(executionEnvironment, newExecutionEnvironment, {
address: newAddress,
isDelegateCall: true,
calldata,
});
expect(newExecutionEnvironment).toEqual(
allSameExcept(executionEnvironment, {
address: newAddress,
isDelegateCall: true,
calldata,
}),
);
});

it('New static call call should fork execution environment correctly', () => {
const executionEnvironment = initExecutionEnvironment();
const newExecutionEnvironment = executionEnvironment.deriveEnvironmentForNestedStaticCall(newAddress, calldata);

allTheSameExcept(executionEnvironment, newExecutionEnvironment, {
address: newAddress,
storageAddress: newAddress,
isStaticCall: true,
calldata,
});
expect(newExecutionEnvironment).toEqual(
allSameExcept(executionEnvironment, {
address: newAddress,
storageAddress: newAddress,
isStaticCall: true,
calldata,
}),
);
});
});

/**
* Check all properties of one object are the same, except for the specified differentProperties
*/
function allTheSameExcept(referenceObject: any, comparingObject: any, differentProperties: Record<string, any>): void {
for (const key in referenceObject) {
if (Object.keys(differentProperties).includes(key)) {
expect(comparingObject[key]).toEqual(differentProperties[key]);
} else {
expect(comparingObject[key]).toEqual(referenceObject[key]);
}
}
}
190 changes: 179 additions & 11 deletions yarn-project/simulator/src/avm/avm_memory_types.test.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,190 @@
import { Field, Uint8 } from './avm_memory_types.js';
import { Field, TaggedMemory, Uint8, Uint16, Uint32, Uint64, Uint128 } from './avm_memory_types.js';

// TODO: complete
describe('Uint8', () => {
it('Unsigned 8 max value', () => {
expect(new Uint8(255).toBigInt()).toEqual(255n);
describe('TaggedMemory', () => {
it('Elements should be undefined after construction', () => {
const mem = new TaggedMemory();
expect(mem.get(10)).toBe(undefined);
});

it('Unsigned 8 bit add', () => {
expect(new Uint8(50).add(new Uint8(20))).toEqual(new Uint8(70));
it(`Should set and get integral types`, () => {
const mem = new TaggedMemory();
mem.set(10, new Uint8(5));
expect(mem.get(10)).toStrictEqual(new Uint8(5));
});

it('Unsigned 8 bit add wraps', () => {
expect(new Uint8(200).add(new Uint8(100))).toEqual(new Uint8(44));
it(`Should set and get field elements`, () => {
const mem = new TaggedMemory();
mem.set(10, new Field(5));
expect(mem.get(10)).toStrictEqual(new Field(5));
});

it(`Should getSlice beyond current size`, () => {
const mem = new TaggedMemory();
const val = [new Field(5), new Field(6)];

mem.setSlice(10, val);

expect(mem.getSlice(10, /*size=*/ 4)).toEqual([...val, undefined, undefined]);
});

it(`Should set and get slices`, () => {
const mem = new TaggedMemory();
const val = [new Field(5), new Field(6)];

mem.setSlice(10, val);

expect(mem.getSlice(10, /*size=*/ 2)).toStrictEqual(val);
});
});

type IntegralClass = typeof Uint8 | typeof Uint16 | typeof Uint32 | typeof Uint64 | typeof Uint128;
describe.each([Uint8, Uint16, Uint32, Uint64, Uint128])('Integral Types', (clsValue: IntegralClass) => {
it(`Should construct a new ${clsValue.name} from a number`, () => {
const x = new clsValue(5);
expect(x.toBigInt()).toStrictEqual(5n);
});

it(`Should construct a new ${clsValue.name} from a bigint`, () => {
const x = new clsValue(5n);
expect(x.toBigInt()).toStrictEqual(5n);
});

it(`Should build a new ${clsValue.name}`, () => {
const x = new clsValue(5);
const newX = x.build(10n);
expect(newX).toStrictEqual(new clsValue(10n));
});

it(`Should add two ${clsValue.name} correctly`, () => {
const a = new clsValue(5);
const b = new clsValue(10);
const result = a.add(b);
expect(result).toStrictEqual(new clsValue(15n));
});

it(`Should subtract two ${clsValue.name} correctly`, () => {
const a = new clsValue(10);
const b = new clsValue(5);
const result = a.sub(b);
expect(result).toStrictEqual(new clsValue(5n));
});

it(`Should multiply two ${clsValue.name} correctly`, () => {
const a = new clsValue(5);
const b = new clsValue(10);
const result = a.mul(b);
expect(result).toStrictEqual(new clsValue(50n));
});

it(`Should divide two ${clsValue.name} correctly`, () => {
const a = new clsValue(10);
const b = new clsValue(5);
const result = a.div(b);
expect(result).toStrictEqual(new clsValue(2n));
});

it('Should shift right ${clsValue.name} correctly', () => {
const uintA = new clsValue(10);
const result = uintA.shr(new clsValue(1n));
expect(result).toEqual(new clsValue(5n));
});

it('Should shift left ${clsValue.name} correctly', () => {
const uintA = new clsValue(10);
const result = uintA.shl(new clsValue(1n));
expect(result).toEqual(new clsValue(20n));
});

it('Should and two ${clsValue.name} correctly', () => {
const uintA = new clsValue(10);
const uintB = new clsValue(5);
const result = uintA.and(uintB);
expect(result).toEqual(new clsValue(0n));
});

it('Should or two ${clsValue.name} correctly', () => {
const uintA = new clsValue(10);
const uintB = new clsValue(5);
const result = uintA.or(uintB);
expect(result).toEqual(new clsValue(15n));
});

it('Should xor two ${clsValue.name} correctly', () => {
const uintA = new clsValue(10);
const uintB = new clsValue(5);
const result = uintA.xor(uintB);
expect(result).toEqual(new clsValue(15n));
});

it(`Should check equality of two ${clsValue.name} correctly`, () => {
const a = new clsValue(5);
const b = new clsValue(5);
const c = new clsValue(10);
expect(a.equals(b)).toBe(true);
expect(a.equals(c)).toBe(false);
});

it(`Should check if one ${clsValue.name} is less than another correctly`, () => {
const a = new clsValue(5);
const b = new clsValue(10);
expect(a.lt(b)).toBe(true);
expect(b.lt(a)).toBe(false);
});
});

describe('Field', () => {
it('Add correctly without wrapping', () => {
expect(new Field(27).add(new Field(48))).toEqual(new Field(75));
it(`Should build a new Field`, () => {
const field = new Field(5);
const newField = field.build(10n);
expect(newField.toBigInt()).toStrictEqual(10n);
});

it(`Should add two Fields correctly`, () => {
const field1 = new Field(5);
const field2 = new Field(10);
const result = field1.add(field2);
expect(result).toStrictEqual(new Field(15n));
});

it(`Should subtract two Fields correctly`, () => {
const field1 = new Field(10);
const field2 = new Field(5);
const result = field1.sub(field2);
expect(result).toStrictEqual(new Field(5n));
});

it(`Should multiply two Fields correctly`, () => {
const field1 = new Field(5);
const field2 = new Field(10);
const result = field1.mul(field2);
expect(result).toStrictEqual(new Field(50n));
});

// FIXME: field division is wrong
it.skip(`Should divide two Fields correctly`, () => {
const field1 = new Field(10);
const field2 = new Field(5);
const result = field1.div(field2);
expect(result).toStrictEqual(new Field(2n));
});

it(`Should check equality of two Fields correctly`, () => {
const field1 = new Field(5);
const field2 = new Field(5);
const field3 = new Field(10);
expect(field1.equals(field2)).toBe(true);
expect(field1.equals(field3)).toBe(false);
});

it(`Should check if one Field is less than another correctly`, () => {
const field1 = new Field(5);
const field2 = new Field(10);
expect(field1.lt(field2)).toBe(true);
expect(field2.lt(field1)).toBe(false);
});

it(`Should convert Field to BigInt correctly`, () => {
const field = new Field(5);
expect(field.toBigInt()).toStrictEqual(5n);
});
});
Loading