Skip to content

Commit

Permalink
feat: Counters in private functions (AztecProtocol#3850)
Browse files Browse the repository at this point in the history
This PR adds counter usage in private functions. The counters are used
in the ordering kernel to ensure correct squashing and to reorder
commitment and nullifier arrays.
  • Loading branch information
sirasistant authored Jan 11, 2024
1 parent 483d9d2 commit 2b80ded
Show file tree
Hide file tree
Showing 34 changed files with 719 additions and 517 deletions.
4 changes: 2 additions & 2 deletions yarn-project/acir-simulator/src/acvm/deserialize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ export function extractPrivateCircuitPublicInputs(
frToBoolean(witnessReader.readField()),
frToBoolean(witnessReader.readField()),
frToBoolean(witnessReader.readField()),
witnessReader.readField(),
frToNumber(witnessReader.readField()),
);

const argsHash = witnessReader.readField();
Expand Down Expand Up @@ -251,7 +251,7 @@ export function extractPublicCircuitPublicInputs(partialWitness: ACVMWitness, ac
frToBoolean(witnessReader.readField()),
frToBoolean(witnessReader.readField()),
frToBoolean(witnessReader.readField()),
witnessReader.readField(),
frToNumber(witnessReader.readField()),
);

const argsHash = witnessReader.readField();
Expand Down
4 changes: 4 additions & 0 deletions yarn-project/acir-simulator/src/acvm/oracle/oracle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -291,11 +291,13 @@ export class Oracle {
[contractAddress]: ACVMField[],
[functionSelector]: ACVMField[],
[argsHash]: ACVMField[],
[sideffectCounter]: ACVMField[],
): Promise<ACVMField[]> {
const callStackItem = await this.typedOracle.callPrivateFunction(
AztecAddress.fromField(fromACVMField(contractAddress)),
FunctionSelector.fromField(fromACVMField(functionSelector)),
fromACVMField(argsHash),
frToNumber(fromACVMField(sideffectCounter)),
);
return toAcvmCallPrivateStackItem(callStackItem);
}
Expand All @@ -317,11 +319,13 @@ export class Oracle {
[contractAddress]: ACVMField[],
[functionSelector]: ACVMField[],
[argsHash]: ACVMField[],
[sideffectCounter]: ACVMField[],
) {
const enqueuedRequest = await this.typedOracle.enqueuePublicFunctionCall(
AztecAddress.fromString(contractAddress),
FunctionSelector.fromField(fromACVMField(functionSelector)),
fromACVMField(argsHash),
frToNumber(fromACVMField(sideffectCounter)),
);
return toAcvmEnqueuePublicFunctionResult(enqueuedRequest);
}
Expand Down
2 changes: 2 additions & 0 deletions yarn-project/acir-simulator/src/acvm/oracle/typed_oracle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ export abstract class TypedOracle {
_targetContractAddress: AztecAddress,
_functionSelector: FunctionSelector,
_argsHash: Fr,
_sideffectCounter: number,
): Promise<PrivateCallStackItem> {
throw new Error('Not available.');
}
Expand All @@ -197,6 +198,7 @@ export abstract class TypedOracle {
_targetContractAddress: AztecAddress,
_functionSelector: FunctionSelector,
_argsHash: Fr,
_sideffectCounter: number,
): Promise<PublicCallRequest> {
throw new Error('Not available.');
}
Expand Down
35 changes: 26 additions & 9 deletions yarn-project/acir-simulator/src/client/client_execution_context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import {
toACVMContractDeploymentData,
toACVMWitness,
} from '../acvm/index.js';
import { SideEffectCounter } from '../common/index.js';
import { PackedArgsCache } from '../common/packed_args_cache.js';
import { DBOracle } from './db_oracle.js';
import { ExecutionNoteCache } from './execution_note_cache.js';
Expand Down Expand Up @@ -71,7 +70,6 @@ export class ClientExecutionContext extends ViewDataOracle {
protected readonly authWitnesses: AuthWitness[],
private readonly packedArgsCache: PackedArgsCache,
private readonly noteCache: ExecutionNoteCache,
private readonly sideEffectCounter: SideEffectCounter,
protected readonly db: DBOracle,
private readonly curve: Grumpkin,
protected log = createDebugLogger('aztec:simulator:client_execution_context'),
Expand Down Expand Up @@ -301,9 +299,15 @@ export class ClientExecutionContext extends ViewDataOracle {
* @param targetContractAddress - The address of the contract to call.
* @param functionSelector - The function selector of the function to call.
* @param argsHash - The packed arguments to pass to the function.
* @param sideffectCounter - The side effect counter at the start of the call.
* @returns The execution result.
*/
async callPrivateFunction(targetContractAddress: AztecAddress, functionSelector: FunctionSelector, argsHash: Fr) {
async callPrivateFunction(
targetContractAddress: AztecAddress,
functionSelector: FunctionSelector,
argsHash: Fr,
sideffectCounter: number,
) {
this.log(
`Calling private function ${this.contractAddress}:${functionSelector} from ${this.callContext.storageContractAddress}`,
);
Expand All @@ -320,7 +324,13 @@ export class ClientExecutionContext extends ViewDataOracle {
this.txContext.version,
);

const derivedCallContext = await this.deriveCallContext(targetContractAddress, targetArtifact, false, false);
const derivedCallContext = await this.deriveCallContext(
targetContractAddress,
targetArtifact,
sideffectCounter,
false,
false,
);

const context = new ClientExecutionContext(
targetContractAddress,
Expand All @@ -331,7 +341,6 @@ export class ClientExecutionContext extends ViewDataOracle {
this.authWitnesses,
this.packedArgsCache,
this.noteCache,
this.sideEffectCounter,
this.db,
this.curve,
);
Expand All @@ -355,23 +364,29 @@ export class ClientExecutionContext extends ViewDataOracle {
* @param targetContractAddress - The address of the contract to call.
* @param functionSelector - The function selector of the function to call.
* @param argsHash - The packed arguments to pass to the function.
* @param sideEffectCounter - The side effect counter at the start of the call.
* @returns The public call stack item with the request information.
*/
public async enqueuePublicFunctionCall(
targetContractAddress: AztecAddress,
functionSelector: FunctionSelector,
argsHash: Fr,
sideEffectCounter: number,
): Promise<PublicCallRequest> {
const targetArtifact = await this.db.getFunctionArtifact(targetContractAddress, functionSelector);
const derivedCallContext = await this.deriveCallContext(targetContractAddress, targetArtifact, false, false);
const derivedCallContext = await this.deriveCallContext(
targetContractAddress,
targetArtifact,
sideEffectCounter,
false,
false,
);
const args = this.packedArgsCache.unpack(argsHash);
const sideEffectCounter = this.sideEffectCounter.count();
const enqueuedRequest = PublicCallRequest.from({
args,
callContext: derivedCallContext,
functionData: FunctionData.fromAbi(targetArtifact),
contractAddress: targetContractAddress,
sideEffectCounter,
});

// TODO($846): if enqueued public calls are associated with global
Expand All @@ -391,13 +406,15 @@ export class ClientExecutionContext extends ViewDataOracle {
* Derives the call context for a nested execution.
* @param targetContractAddress - The address of the contract being called.
* @param targetArtifact - The artifact of the function being called.
* @param startSideEffectCounter - The side effect counter at the start of the call.
* @param isDelegateCall - Whether the call is a delegate call.
* @param isStaticCall - Whether the call is a static call.
* @returns The derived call context.
*/
private async deriveCallContext(
targetContractAddress: AztecAddress,
targetArtifact: FunctionArtifact,
startSideEffectCounter: number,
isDelegateCall = false,
isStaticCall = false,
) {
Expand All @@ -410,7 +427,7 @@ export class ClientExecutionContext extends ViewDataOracle {
isDelegateCall,
isStaticCall,
false,
Fr.ZERO,
startSideEffectCounter,
);
}
}
2 changes: 1 addition & 1 deletion yarn-project/acir-simulator/src/client/execution_result.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,5 +83,5 @@ export function collectEnqueuedPublicFunctionCalls(execResult: ExecutionResult):
return [
...execResult.enqueuedPublicFunctionCalls,
...[...execResult.nestedExecutions].flatMap(collectEnqueuedPublicFunctionCalls),
].sort((a, b) => b.sideEffectCounter! - a.sideEffectCounter!); // REVERSE SORT!
].sort((a, b) => b.callContext.startSideEffectCounter - a.callContext.startSideEffectCounter);
}
Original file line number Diff line number Diff line change
Expand Up @@ -581,9 +581,8 @@ describe('Private Execution test suite', () => {
isContractDeployment: false,
isDelegateCall: false,
isStaticCall: false,
startSideEffectCounter: Fr.ZERO,
startSideEffectCounter: 2,
}),
sideEffectCounter: 0,
});

const publicCallRequestHash = publicCallRequest.toPublicCallStackItem().hash();
Expand Down
5 changes: 2 additions & 3 deletions yarn-project/acir-simulator/src/client/simulator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { AztecNode, FunctionCall, Note, TxExecutionRequest } from '@aztec/types'
import { WasmBlackBoxFunctionSolver, createBlackBoxSolver } from '@noir-lang/acvm_js';

import { createSimulationError } from '../common/errors.js';
import { SideEffectCounter } from '../common/index.js';
import { PackedArgsCache } from '../common/packed_args_cache.js';
import { ClientExecutionContext } from './client_execution_context.js';
import { DBOracle, FunctionArtifactWithDebugMetadata } from './db_oracle.js';
Expand Down Expand Up @@ -88,7 +87,8 @@ export class AcirSimulator {
false,
false,
request.functionData.isConstructor,
Fr.ZERO, // TODO(dan): actual value
// TODO: when contract deployment is done in-app, we should only reserve one counter for the tx hash
2, // 2 counters are reserved for tx hash and contract deployment nullifier
);
const context = new ClientExecutionContext(
contractAddress,
Expand All @@ -99,7 +99,6 @@ export class AcirSimulator {
request.authWitnesses,
PackedArgsCache.create(request.packedArguments),
new ExecutionNoteCache(),
new SideEffectCounter(),
this.db,
curve,
);
Expand Down
14 changes: 7 additions & 7 deletions yarn-project/acir-simulator/src/public/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ describe('ACIR public execution simulator', () => {
isContractDeployment: false,
isDelegateCall: false,
isStaticCall: false,
startSideEffectCounter: Fr.ZERO,
startSideEffectCounter: 0,
});

publicContracts.getBytecode.mockResolvedValue(Buffer.from(mintArtifact.bytecode, 'base64'));
Expand Down Expand Up @@ -140,7 +140,7 @@ describe('ACIR public execution simulator', () => {
isContractDeployment: false,
isDelegateCall: false,
isStaticCall: false,
startSideEffectCounter: Fr.ZERO,
startSideEffectCounter: 0,
});

recipientStorageSlot = computeSlotForMapping(new Fr(6n), recipient.toField());
Expand Down Expand Up @@ -236,7 +236,7 @@ describe('ACIR public execution simulator', () => {
isContractDeployment: false,
isDelegateCall: false,
isStaticCall: false,
startSideEffectCounter: Fr.ZERO,
startSideEffectCounter: 0,
});

// eslint-disable-next-line require-await
Expand Down Expand Up @@ -305,7 +305,7 @@ describe('ACIR public execution simulator', () => {
isContractDeployment: false,
isDelegateCall: false,
isStaticCall: false,
startSideEffectCounter: Fr.ZERO,
startSideEffectCounter: 0,
});

publicContracts.getBytecode.mockResolvedValue(Buffer.from(shieldArtifact.bytecode, 'base64'));
Expand Down Expand Up @@ -338,7 +338,7 @@ describe('ACIR public execution simulator', () => {
isContractDeployment: false,
isDelegateCall: false,
isStaticCall: false,
startSideEffectCounter: Fr.ZERO,
startSideEffectCounter: 0,
});

publicContracts.getBytecode.mockResolvedValue(Buffer.from(createL2ToL1MessagePublicArtifact.bytecode, 'base64'));
Expand Down Expand Up @@ -388,7 +388,7 @@ describe('ACIR public execution simulator', () => {
isContractDeployment: false,
isDelegateCall: false,
isStaticCall: false,
startSideEffectCounter: Fr.ZERO,
startSideEffectCounter: 0,
});

publicContracts.getBytecode.mockResolvedValue(Buffer.from(mintPublicArtifact.bytecode, 'base64'));
Expand Down Expand Up @@ -431,7 +431,7 @@ describe('ACIR public execution simulator', () => {
isContractDeployment: false,
isDelegateCall: false,
isStaticCall: false,
startSideEffectCounter: Fr.ZERO,
startSideEffectCounter: 0,
});

publicContracts.getBytecode.mockResolvedValue(Buffer.from(createNullifierPublicArtifact.bytecode, 'base64'));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ export class PublicExecutionContext extends TypedOracle {
isContractDeployment: false,
isDelegateCall: false,
isStaticCall: false,
startSideEffectCounter: Fr.ZERO,
startSideEffectCounter: 0, // TODO use counters in public execution
});

const nestedExecution: PublicExecution = {
Expand Down
Loading

0 comments on commit 2b80ded

Please sign in to comment.