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: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ The Aztec 3 system consists of the following sub projects.
- `aztec-rpc`
- `aztec.js`
- `ethereum.js`
- `kernel-simulator`
- `kernel-prover`
- `key-store`
- `l1-contracts`
- `p2p`
Expand Down
8 changes: 4 additions & 4 deletions build_manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,11 @@
"rebuildPatterns": ["^yarn-project/foundation/"],
"dependencies": []
},
"kernel-simulator": {
"kernel-prover": {
"buildDir": "yarn-project",
"projectDir": "yarn-project/kernel-simulator",
"dockerfile": "kernel-simulator/Dockerfile",
"rebuildPatterns": ["^yarn-project/kernel-simulator/"],
"projectDir": "yarn-project/kernel-prover",
"dockerfile": "kernel-prover/Dockerfile",
"rebuildPatterns": ["^yarn-project/kernel-prover/"],
"dependencies": ["yarn-project-base"]
},
"key-store": {
Expand Down
2 changes: 1 addition & 1 deletion build_manifest.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ PROJECTS=(
# aztec.js:yarn-project
# end-to-end:yarn-project
# ethereum.js:yarn-project
# kernel-simulator:yarn-project
# kernel-prover:yarn-project
# key-store:yarn-project
# merkle-tree:yarn-project
# p2p:yarn-project
Expand Down
31 changes: 31 additions & 0 deletions yarn-project/acir-simulator/src/acvm.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { AztecAddress, CallContext, ContractDeploymentData } from './circuits.js';
import { NoteLoadOracleInputs } from './db_oracle.js';

export interface ACIRCallback {
getSecretKey(keyId: Buffer): Promise<Buffer>;
getNotes(storageSlot: Buffer): Promise<NoteLoadOracleInputs[]>;
getRandomField(): Promise<Buffer>;
privateFunctionCall(
contractAddress: AztecAddress,
functionSelector: string,
args: Array<Buffer>,
): Promise<Array<Buffer>>;
}

export interface ExecutionPreimages {
newNotes: Buffer[];
nullifiedNotes: Buffer[];
}

export interface ACIRExecutionResult {
preimages: ExecutionPreimages;
partialWitness: Buffer;
}

export type execute = (
acir: Buffer,
args: Array<Buffer>,
callContext: CallContext,
contractDeploymentData: ContractDeploymentData,
oracle: ACIRCallback,
) => Promise<ACIRExecutionResult>;
229 changes: 229 additions & 0 deletions yarn-project/acir-simulator/src/circuits.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
// See aztec3/constants.hpp
// Copied here for prototyping purposes
// In future: structured serialization?
export const ARGS_LENGTH = 8;
export const RETURN_VALUES_LENGTH = 4;
export const EMITTED_EVENTS_LENGTH = 4;

export const NEW_COMMITMENTS_LENGTH = 4;
export const NEW_NULLIFIERS_LENGTH = 4;

export const STATE_TRANSITIONS_LENGTH = 4;
export const STATE_READS_LENGTH = 4;

export const PRIVATE_CALL_STACK_LENGTH = 4;
export const PUBLIC_CALL_STACK_LENGTH = 4;
export const L1_MSG_STACK_LENGTH = 2;

export const KERNEL_NEW_COMMITMENTS_LENGTH = 16;
export const KERNEL_NEW_NULLIFIERS_LENGTH = 16;
export const KERNEL_NEW_CONTRACTS_LENGTH = 8;
export const KERNEL_PRIVATE_CALL_STACK_LENGTH = 8;
export const KERNEL_PUBLIC_CALL_STACK_LENGTH = 8;
export const KERNEL_L1_MSG_STACK_LENGTH = 4;
export const KERNEL_OPTIONALLY_REVEALED_DATA_LENGTH = 4;

export const VK_TREE_HEIGHT = 3;
export const CONTRACT_TREE_HEIGHT = 4;
export const PRIVATE_DATA_TREE_HEIGHT = 8;
export const NULLIFIER_TREE_HEIGHT = 8;

export const PRIVATE_DATA_TREE_ROOTS_TREE_HEIGHT = 8;
export const CONTRACT_TREE_ROOTS_TREE_HEIGHT = 8;

export const FUNCTION_SELECTOR_NUM_BYTES = 31;

/**
* Assert a member is a certain length.
* @param obj - An object.
* @param member - A member string.
* @param length - The length.
*/
export function assertLength<F extends string, T extends { [f in F]: { length: number } }>(
obj: T,
member: F,
length: number,
) {
if (obj[member].length !== length) {
throw new Error(`Expected ${member} to have length ${length}! Was: ${obj[member].length}`);
}
}

export class Fr {
public static ZERO = new Fr(Buffer.alloc(32));

constructor(public readonly buffer: Buffer) {}
}

export class AztecAddress {
public static SIZE = 64;

public static ZERO = new AztecAddress(Buffer.alloc(AztecAddress.SIZE));

constructor(public readonly buffer: Buffer) {}

public equals(rhs: AztecAddress) {
return this.buffer.equals(rhs.buffer);
}
}

export class EthAddress {
public static ZERO = new EthAddress(Buffer.alloc(20));

constructor(public readonly buffer: Buffer) {}
}

/**
* Call context.
* @see abis/call_context.hpp
*/
export class CallContext {
constructor(
public msgSender: AztecAddress,
public storageContractAddress: AztecAddress,
public portalContractAddress: EthAddress,
public isDelegateCall: boolean,
public isStaticCall: boolean,
public isContractDeployment: boolean,
) {}
}

/**
* Contract deployment data in a @TxContext.
* cpp/src/aztec3/circuits/abis/contract_deployment_data.hpp
*/
export class ContractDeploymentData {
constructor(
public constructorVkHash: Fr,
public functionTreeRoot: Fr,
public contractAddressSalt: Fr,
public portalContractAddress: EthAddress,
) {}
}

/**
* Public inputs to a private circuit.
* @see abis/private_circuit_public_inputs.hpp.
*/
export class PrivateCircuitPublicInputs {
constructor(
// NOTE: Must have same order as CPP.
public callContext: CallContext,
public args: Fr[],
public returnValues: Fr[],
public emittedEvents: Fr[],
public newCommitments: Fr[],
public newNullifiers: Fr[],
public privateCallStack: Fr[],
public publicCallStack: Fr[],
public l1MsgStack: Fr[],
public historicPrivateDataTreeRoot: Fr,
public historicPrivateNullifierTreeRoot: Fr,
public historicContractTreeRoot: Fr,
public contractDeploymentData: ContractDeploymentData,
) {
assertLength(this, 'args', ARGS_LENGTH);
assertLength(this, 'returnValues', RETURN_VALUES_LENGTH);
assertLength(this, 'emittedEvents', EMITTED_EVENTS_LENGTH);
assertLength(this, 'newCommitments', NEW_COMMITMENTS_LENGTH);
assertLength(this, 'newNullifiers', NEW_NULLIFIERS_LENGTH);
assertLength(this, 'privateCallStack', PRIVATE_CALL_STACK_LENGTH);
assertLength(this, 'publicCallStack', PUBLIC_CALL_STACK_LENGTH);
assertLength(this, 'l1MsgStack', L1_MSG_STACK_LENGTH);
}
}

export class TxContext {
constructor(
public readonly isFeePaymentTx: boolean,
public readonly isRebatePaymentTx: boolean,
public readonly isContractDeploymentTx: boolean,
public readonly contractDeploymentData: ContractDeploymentData,
) {}
}

export interface FunctionData {
functionSelector: Buffer;
isSecret: boolean;
isContructor: boolean;
}

export class TxRequest {
constructor(
public readonly from: AztecAddress,
public readonly to: AztecAddress,
public readonly functionData: FunctionData,
public readonly args: Fr[],
public readonly txContext: TxContext,
public readonly nonce: Fr,
public readonly chainId: Fr,
) {}

toBuffer() {
return Buffer.alloc(0);
}
}

export class PrivateCallStackItem {
constructor(
public readonly contractAddress: AztecAddress,
public readonly functionSelector: Buffer,
public readonly publicInputs: PrivateCircuitPublicInputs,
) {}
}

export class OldTreeRoots {
constructor(
public privateDataTreeRoot: Fr,
public nullifierTreeRoot: Fr,
public contractTreeRoot: Fr,
public privateKernelVkTreeRoot: Fr, // future enhancement
) {}
}

export class ConstantData {
constructor(public oldTreeRoots: OldTreeRoots, public txContext: TxContext) {}
}

export class AggregationObject {}

export class NewContractData {
constructor(
public readonly contractAddress: AztecAddress,
public readonly portalContractAddress: EthAddress,
public readonly functionTreeRoot: Fr,
) {}
}

export class OptionallyRevealedData {}

export class AccumulatedTxData {
constructor(
public aggregationObject: AggregationObject, // Contains the aggregated proof of all previous kernel iterations

public privateCallCount: Fr,

public newCommitments: Fr[],
public newNullifiers: Fr[],

public privateCallStack: Fr[],
public publicCallStack: Fr[],
public l1MsgStack: Fr[],

public newContracts: NewContractData[],

public optionallyRevealedData: OptionallyRevealedData[],
) {
assertLength(this, 'newCommitments', KERNEL_NEW_COMMITMENTS_LENGTH);
assertLength(this, 'newNullifiers', KERNEL_NEW_NULLIFIERS_LENGTH);
assertLength(this, 'privateCallStack', KERNEL_PRIVATE_CALL_STACK_LENGTH);
assertLength(this, 'publicCallStack', KERNEL_PUBLIC_CALL_STACK_LENGTH);
assertLength(this, 'l1MsgStack', KERNEL_L1_MSG_STACK_LENGTH);
assertLength(this, 'newContracts', KERNEL_NEW_CONTRACTS_LENGTH);
assertLength(this, 'optionallyRevealedData', KERNEL_OPTIONALLY_REVEALED_DATA_LENGTH);
}
}

export class PrivateKernelPublicInputs {
constructor(public end: AccumulatedTxData, public constants: ConstantData, public isPrivateKernel: true) {}
}
16 changes: 16 additions & 0 deletions yarn-project/acir-simulator/src/db_oracle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { AztecAddress, EthAddress } from './circuits.js';

export interface NoteLoadOracleInputs {
note: Buffer;
siblingPath: Buffer;
leafIndex: number;
root: Buffer;
}

export interface DBOracle {
getSecretKey(contractAddress: AztecAddress, keyId: Buffer): Promise<Buffer>;
getNotes(contractAddress: AztecAddress, storageSlot: Buffer): Promise<NoteLoadOracleInputs[]>;
getBytecode(contractAddress: AztecAddress, functionSelector: string): Promise<Buffer>;
getProvingKey(contractAddress: AztecAddress, functionSelector: string): Promise<Buffer>;
getPortalContractAddress(contractAddress: AztecAddress): Promise<EthAddress>;
}
7 changes: 3 additions & 4 deletions yarn-project/acir-simulator/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/**
* A placeholder for the Acir Simulator.
*/
export class AcirSimulator {}
export * from './simulator.js';
export * from './db_oracle.js';
export * from './acvm.js';
69 changes: 69 additions & 0 deletions yarn-project/acir-simulator/src/simulator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { ExecutionPreimages } from './acvm.js';
import {
CallContext,
PrivateCircuitPublicInputs,
TxRequest,
EthAddress,
PrivateCallStackItem,
OldTreeRoots,
} from './circuits.js';

export interface ExecutionResult {
// Needed for prover
acir: Buffer;
partialWitness: Buffer;
// Needed for the verifier (kernel)
callStackItem: PrivateCallStackItem;
// Needed for the user
preimages: ExecutionPreimages;
// Nested executions
nestedExecutions: this[];
}

/**
* A placeholder for the Acir Simulator.
*/
export class AcirSimulator {
run(
request: TxRequest,
entryPointACIR: Buffer,
portalContractAddress: EthAddress,
oldRoots: OldTreeRoots,
): Promise<ExecutionResult> {
const callContext = new CallContext(
request.from,
request.to,
portalContractAddress,
false,
false,
request.functionData.isContructor,
);

const publicInputs = new PrivateCircuitPublicInputs(
callContext,
request.args,
[], // returnValues,
[], // emittedEvents,
[], // newCommitments,
[], // newNullifiers,
[], // privateCallStack,
[], // publicCallStack,
[], // l1MsgStack,
oldRoots.privateDataTreeRoot,
oldRoots.nullifierTreeRoot,
oldRoots.contractTreeRoot,
request.txContext.contractDeploymentData,
);

return Promise.resolve({
acir: entryPointACIR,
partialWitness: Buffer.alloc(0),
callStackItem: new PrivateCallStackItem(request.to, request.functionData.functionSelector, publicInputs),
preimages: {
newNotes: [],
nullifiedNotes: [],
},
nestedExecutions: [],
});
}
}
Loading