Skip to content

Commit

Permalink
refactor: simulator (#2534)
Browse files Browse the repository at this point in the history
- Create an Oracle class that has all the apis needed by Aztec.nr.
- Oracle names are now derived from the class instead of using a
hard-coded type.
- Create a TypedOracle that has typed input args and output values for
real implementation based on the context (public, private, view).
- Converting from and to ACVMField is handled in Oracle class.
- Keep accumulated data in Public/ClientContexts instead of scattering
between Contexts and Public/PrivateExecutions. Executions are stateless
functions now.
- Create a SideEffectCounter class to keep track of the number, which
potentially fixes a bug in previous private_execution where the counter
was not updated after calling another private function.

# Checklist:
Remove the checklist to signal you've completed it. Enable auto-merge if
the PR is ready to merge.
- [ ] If the pull request requires a cryptography review (e.g.
cryptographic algorithm implementations) I have added the 'crypto' tag.
- [ ] I have reviewed my diff in github, line by line and removed
unexpected formatting changes, testing logs, or commented-out code.
- [ ] Every change is related to the PR description.
- [ ] I have
[linked](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue)
this pull request to relevant issues (if any exist).
  • Loading branch information
LeilaWang authored Sep 27, 2023
1 parent 98694e6 commit a26198e
Show file tree
Hide file tree
Showing 26 changed files with 1,405 additions and 1,131 deletions.
103 changes: 6 additions & 97 deletions yarn-project/acir-simulator/src/acvm/acvm.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import { FunctionDebugMetadata, OpcodeLocation } from '@aztec/foundation/abi';
import { AztecAddress } from '@aztec/foundation/aztec-address';
import { EthAddress } from '@aztec/foundation/eth-address';
import { Fr } from '@aztec/foundation/fields';
import { createDebugLogger } from '@aztec/foundation/log';
import { NoirCallStack, SourceCodeLocation } from '@aztec/types';

Expand All @@ -15,55 +12,25 @@ import {
} from '@noir-lang/acvm_js';

import { traverseCauseChain } from '../common/errors.js';
import { ORACLE_NAMES } from './oracle/index.js';

/**
* The format for fields on the ACVM.
*/
export type ACVMField = string;

/**
* The format for witnesses of the ACVM.
*/
export type ACVMWitness = WitnessMap;

export const ZERO_ACVM_FIELD: ACVMField = `0x${'00'.repeat(Fr.SIZE_IN_BYTES)}`;
export const ONE_ACVM_FIELD: ACVMField = `0x${'00'.repeat(Fr.SIZE_IN_BYTES - 1)}01`;

/**
* The supported oracle names.
*/
type ORACLE_NAMES =
| 'computeSelector'
| 'packArguments'
| 'getAuthWitness'
| 'getSecretKey'
| 'getNote'
| 'getNotes'
| 'checkNoteHashExists'
| 'getRandomField'
| 'notifyCreatedNote'
| 'notifyNullifiedNote'
| 'callPrivateFunction'
| 'callPublicFunction'
| 'enqueuePublicFunctionCall'
| 'storageRead'
| 'storageWrite'
| 'getL1ToL2Message'
| 'getPortalContractAddress'
| 'emitEncryptedLog'
| 'emitUnencryptedLog'
| 'getPublicKey'
| 'debugLog'
| 'debugLogWithPrefix';

/**
* A type that does not require all keys to be present.
*/
type PartialRecord<K extends keyof any, T> = Partial<Record<K, T>>;

/**
* The callback interface for the ACIR.
*/
export type ACIRCallback = PartialRecord<ORACLE_NAMES, (...args: ForeignCallInput[]) => Promise<ForeignCallOutput>>;
type ACIRCallback = Record<
ORACLE_NAMES,
(...args: ForeignCallInput[]) => ForeignCallOutput | Promise<ForeignCallOutput>
>;

/**
* The result of executing an ACIR.
Expand Down Expand Up @@ -193,61 +160,3 @@ export function extractCallStack(

return resolveOpcodeLocations(callStack, debug);
}

/**
* Adapts the buffer to the field size.
* @param originalBuf - The buffer to adapt.
* @returns The adapted buffer.
*/
function adaptBufferSize(originalBuf: Buffer) {
const buffer = Buffer.alloc(Fr.SIZE_IN_BYTES);
if (originalBuf.length > buffer.length) {
throw new Error('Buffer does not fit in field');
}
originalBuf.copy(buffer, buffer.length - originalBuf.length);
return buffer;
}

/**
* Converts a value to an ACVM field.
* @param value - The value to convert.
* @returns The ACVM field.
*/
export function toACVMField(value: AztecAddress | EthAddress | Fr | Buffer | boolean | number | bigint): ACVMField {
if (typeof value === 'boolean') {
return value ? ONE_ACVM_FIELD : ZERO_ACVM_FIELD;
}

let buffer;

if (Buffer.isBuffer(value)) {
buffer = value;
} else if (typeof value === 'number') {
buffer = Buffer.alloc(Fr.SIZE_IN_BYTES);
buffer.writeUInt32BE(value, Fr.SIZE_IN_BYTES - 4);
} else if (typeof value === 'bigint') {
buffer = new Fr(value).toBuffer();
} else {
buffer = value.toBuffer();
}

return `0x${adaptBufferSize(buffer).toString('hex')}`;
}

/**
* Converts an ACVM field to a Buffer.
* @param field - The ACVM field to convert.
* @returns The Buffer.
*/
export function convertACVMFieldToBuffer(field: ACVMField): Buffer {
return Buffer.from(field.slice(2), 'hex');
}

/**
* Converts an ACVM field to a Fr.
* @param field - The ACVM field to convert.
* @returns The Fr.
*/
export function fromACVMField(field: ACVMField): Fr {
return Fr.fromBuffer(convertACVMFieldToBuffer(field));
}
59 changes: 0 additions & 59 deletions yarn-project/acir-simulator/src/acvm/acvm_fields_reader.ts

This file was deleted.

20 changes: 19 additions & 1 deletion yarn-project/acir-simulator/src/acvm/deserialize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,25 @@ import { Tuple } from '@aztec/foundation/serialize';

import { getReturnWitness } from '@noir-lang/acvm_js';

import { ACVMField, ACVMWitness, fromACVMField } from './acvm.js';
import { ACVMField, ACVMWitness } from './acvm.js';

/**
* Converts an ACVM field to a Buffer.
* @param field - The ACVM field to convert.
* @returns The Buffer.
*/
export function convertACVMFieldToBuffer(field: ACVMField): Buffer {
return Buffer.from(field.slice(2), 'hex');
}

/**
* Converts an ACVM field to a Fr.
* @param field - The ACVM field to convert.
* @returns The Fr.
*/
export function fromACVMField(field: ACVMField): Fr {
return Fr.fromBuffer(convertACVMFieldToBuffer(field));
}

// Utilities to read TS classes from ACVM Field arrays
// In the order that the ACVM provides them
Expand Down
4 changes: 2 additions & 2 deletions yarn-project/acir-simulator/src/acvm/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export * from './acvm_fields_reader.js';
export * from './serialize.js';
export * from './acvm.js';
export * from './deserialize.js';
export * from './oracle/index.js';
export * from './serialize.js';
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ForeignCallInput } from '@noir-lang/acvm_js';

import { ACVMField } from '../acvm/index.js';
import { ACVMField } from '../acvm.js';

/**
* Convert an array of ACVMFields to a string.
Expand Down
17 changes: 17 additions & 0 deletions yarn-project/acir-simulator/src/acvm/oracle/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Oracle } from './oracle.js';

export * from './debug.js';
export * from './oracle.js';
export * from './typed_oracle.js';

/**
* A conditional type that takes a type `T` and returns a union of its method names.
*/
type MethodNames<T> = {
[K in keyof T]: T[K] extends (...args: any[]) => any ? K : never;
}[keyof T];

/**
* Available oracle function names.
*/
export type ORACLE_NAMES = MethodNames<Oracle>;
Loading

0 comments on commit a26198e

Please sign in to comment.