Skip to content

Commit

Permalink
refactor: call stack item cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
benesjan committed Feb 2, 2024
1 parent 85f0712 commit 76b9578
Show file tree
Hide file tree
Showing 10 changed files with 197 additions and 125 deletions.
1 change: 1 addition & 0 deletions yarn-project/acir-simulator/src/acvm/serialize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export function toACVMField(
* are empty since this is just an execution request, so we don't send them to the circuit.
* @param item - The public call stack item to serialize to be passed onto Noir.
* @returns The fields expected by the enqueue_public_function_call_oracle Aztec.nr function.
* TODO(#4380): Nuke this and replace it with PublicCallRequest.toFields()
*/
export function toAcvmEnqueuePublicFunctionResult(item: PublicCallRequest): ACVMField[] {
return [
Expand Down
3 changes: 2 additions & 1 deletion yarn-project/circuits.js/src/structs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ export * from '@aztec/foundation/eth-address';
export * from './aggregation_object.js';
export * from './call_context.js';
export * from './call_request.js';
export * from './call_stack_item.js';
export * from './complete_address.js';
export * from './contract_deployment_data.js';
export * from './contract_storage_read.js';
Expand All @@ -20,9 +19,11 @@ export * from './kernel/public_inputs_final.js';
export * from './kernel/public_kernel.js';
export * from './membership_witness.js';
export * from './nullifier_key_validation_request.js';
export * from './private_call_stack_item.js';
export * from './private_circuit_public_inputs.js';
export * from './proof.js';
export * from './public_call_request.js';
export * from './public_call_stack_item.js';
export * from './public_circuit_public_inputs.js';
export * from './read_request_membership_witness.js';
export * from './rollup/append_only_tree_snapshot.js';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,15 +77,6 @@ describe('CallRequest', () => {
});
});

describe('PrivateCallStackcItem', () => {
it('convert to and from buffer', () => {
const fad = makePrivateCallStackItem(0);

const buf = fad.toBuffer();
expect(PrivateCallStackItem.fromBuffer(buf)).toEqual(fad);
});
});

describe('Private Circuit Public Inputs', () => {
it('convert to and from buffer', () => {
const pkpi = makePrivateCircuitPublicInputs();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ import {
} from '../../constants.gen.js';
import { GrumpkinPrivateKey } from '../../types/grumpkin_private_key.js';
import { CallRequest } from '../call_request.js';
import { PrivateCallStackItem } from '../call_stack_item.js';
import { MembershipWitness } from '../membership_witness.js';
import { Proof } from '../proof.js';
import { ReadRequestMembershipWitness } from '../read_request_membership_witness.js';
import { SideEffect, SideEffectLinkedToNoteHash } from '../side_effects.js';
import { TxRequest } from '../tx_request.js';
import { VerificationKey } from '../verification_key.js';
import { PreviousKernelData } from './previous_kernel_data.js';
import { PrivateCallStackItem } from '../private_call_stack_item.js';

/**
* Private call data.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import {
PUBLIC_DATA_TREE_HEIGHT,
} from '../../constants.gen.js';
import { CallRequest } from '../call_request.js';
import { PublicCallStackItem } from '../call_stack_item.js';
import { MembershipWitness } from '../membership_witness.js';
import { Proof } from '../proof.js';
import { PreviousKernelData } from './previous_kernel_data.js';
import { PublicCallStackItem } from '../public_call_stack_item.js';

/**
* Inputs to the public kernel circuit.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { makePrivateCallStackItem } from '../tests/factories.js';
import { PrivateCallStackItem } from './call_stack_item.js';
import { PrivateCallStackItem } from './private_call_stack_item.js';

describe('PrivateCallStackItem', () => {
it('serializes to buffer and deserializes it back', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { AztecAddress } from '@aztec/foundation/aztec-address';
import { Fr } from '@aztec/foundation/fields';
import { BufferReader, FieldReader, serializeToBuffer } from '@aztec/foundation/serialize';
import { BufferReader, FieldReader, serializeToBuffer, serializeToFields } from '@aztec/foundation/serialize';
import { FieldsOf } from '@aztec/foundation/types';

import { computePrivateCallStackItemHash, computePublicCallStackItemHash } from '../abis/abis.js';
import { computePrivateCallStackItemHash } from '../abis/abis.js';
import { CallRequest, CallerContext } from './call_request.js';
import { FunctionData } from './function_data.js';
import { PrivateCircuitPublicInputs } from './private_circuit_public_inputs.js';
import { PublicCircuitPublicInputs } from './public_circuit_public_inputs.js';

/**
* Call stack item on a private call.
Expand Down Expand Up @@ -35,17 +35,16 @@ export class PrivateCallStackItem {
}
}

static getFields(fields: FieldsOf<PrivateCallStackItem>) {
return [fields.contractAddress, fields.functionData, fields.publicInputs, fields.isExecutionRequest] as const;
}

toBuffer() {
return serializeToBuffer(this.contractAddress, this.functionData, this.publicInputs, this.isExecutionRequest);
return serializeToBuffer(...PrivateCallStackItem.getFields(this));
}

toFields(): Fr[] {
return [
this.contractAddress.toField(),
...this.functionData.toFields(),
...this.publicInputs.toFields(),
new Fr(this.isExecutionRequest),
];
return serializeToFields(...PrivateCallStackItem.getFields(this));
}

/**
Expand Down Expand Up @@ -116,74 +115,3 @@ export class PrivateCallStackItem {
return new CallRequest(this.hash(), callContext.msgSender, callerContext, Fr.ZERO, Fr.ZERO);
}
}

/**
* Call stack item on a public call.
* @see cpp/src/aztec3/circuits/abis/call_stack_item.hpp.
*/
export class PublicCallStackItem {
constructor(
/**
* Address of the contract on which the function is invoked.
*/
public contractAddress: AztecAddress,
/**
* Data identifying the function being called.
*/
public functionData: FunctionData,
/**
* Public inputs to the public kernel circuit.
*/
public publicInputs: PublicCircuitPublicInputs,
/**
* Whether the current callstack item should be considered a public fn execution request.
*/
public isExecutionRequest: boolean,
) {}

toBuffer() {
return serializeToBuffer(this.contractAddress, this.functionData, this.publicInputs, this.isExecutionRequest);
}

/**
* Returns a new instance of PublicCallStackItem with zero contract address, function data and public inputs.
* @returns A new instance of PublicCallStackItem with zero contract address, function data and public inputs.
*/
public static empty(): PublicCallStackItem {
return new PublicCallStackItem(
AztecAddress.ZERO,
FunctionData.empty({ isPrivate: false }),
PublicCircuitPublicInputs.empty(),
false,
);
}

isEmpty() {
return this.contractAddress.isZero() && this.functionData.isEmpty() && this.publicInputs.isEmpty();
}

/**
* Computes this call stack item hash.
* @returns Hash.
*/
public hash() {
return computePublicCallStackItemHash(this);
}

/**
* Creates a new CallRequest with values of the calling contract.
* @returns A CallRequest instance with the contract address, caller context, and the hash of the call stack item.
*/
public toCallRequest() {
if (this.isEmpty()) {
return CallRequest.empty();
}

const callContext = this.publicInputs.callContext;
const callerContext = callContext.isDelegateCall
? new CallerContext(callContext.msgSender, callContext.storageContractAddress)
: CallerContext.empty();
// todo: populate side effect counters correctly
return new CallRequest(this.hash(), callContext.msgSender, callerContext, Fr.ZERO, Fr.ZERO);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { makePublicCallStackItem } from '../tests/factories.js';
import { PublicCallStackItem } from './public_call_stack_item.js';

describe('PublicCallStackItem', () => {
it('serializes to buffer and deserializes it back', () => {
const randomInt = Math.floor(Math.random() * 1000);
const expected = makePublicCallStackItem(randomInt);
const buffer = expected.toBuffer();
const res = PublicCallStackItem.fromBuffer(buffer);
expect(res).toEqual(expected);
});

it('serializes to field array and deserializes it back', () => {
const randomInt = Math.floor(Math.random() * 1000);
const expected = makePublicCallStackItem(randomInt);

const fieldArray = expected.toFields();
const res = PublicCallStackItem.fromFields(fieldArray);
expect(res).toEqual(expected);
});

it('computes hash', () => {
const seed = 9870243;
const PublicCallStackItem = makePublicCallStackItem(seed);
const hash = PublicCallStackItem.hash();
expect(hash).toMatchSnapshot();
});
});
113 changes: 113 additions & 0 deletions yarn-project/circuits.js/src/structs/public_call_stack_item.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import { AztecAddress } from '@aztec/foundation/aztec-address';
import { Fr } from '@aztec/foundation/fields';
import { BufferReader, FieldReader, serializeToBuffer, serializeToFields } from '@aztec/foundation/serialize';
import { FieldsOf } from '@aztec/foundation/types';

import { computePublicCallStackItemHash } from '../abis/abis.js';
import { CallRequest, CallerContext } from './call_request.js';
import { FunctionData } from './function_data.js';
import { PublicCircuitPublicInputs } from './public_circuit_public_inputs.js';

/**
* Call stack item on a public call.
*/
export class PublicCallStackItem {
constructor(
/**
* Address of the contract on which the function is invoked.
*/
public contractAddress: AztecAddress,
/**
* Data identifying the function being called.
*/
public functionData: FunctionData,
/**
* Public inputs to the public kernel circuit.
*/
public publicInputs: PublicCircuitPublicInputs,
/**
* Whether the current callstack item should be considered a public fn execution request.
*/
public isExecutionRequest: boolean,
) {}

static getFields(fields: FieldsOf<PublicCallStackItem>) {
return [fields.contractAddress, fields.functionData, fields.publicInputs, fields.isExecutionRequest] as const;
}

toBuffer() {
return serializeToBuffer(...PublicCallStackItem.getFields(this));
}

toFields(): Fr[] {
return serializeToFields(...PublicCallStackItem.getFields(this));
}

/**
* Deserializes from a buffer or reader.
* @param buffer - Buffer or reader to read from.
* @returns The deserialized instance.
*/
static fromBuffer(buffer: Buffer | BufferReader): PublicCallStackItem {
const reader = BufferReader.asReader(buffer);
return new PublicCallStackItem(
reader.readObject(AztecAddress),
reader.readObject(FunctionData),
reader.readObject(PublicCircuitPublicInputs),
reader.readBoolean(),
);
}

static fromFields(fields: Fr[] | FieldReader): PublicCallStackItem {
const reader = FieldReader.asReader(fields);

const contractAddress = AztecAddress.fromFields(reader);
const functionData = FunctionData.fromFields(reader);
const publicInputs = PublicCircuitPublicInputs.fromFields(reader);
const isExecutionRequest = reader.readBoolean();

return new PublicCallStackItem(contractAddress, functionData, publicInputs, isExecutionRequest);
}

/**
* Returns a new instance of PublicCallStackItem with zero contract address, function data and public inputs.
* @returns A new instance of PublicCallStackItem with zero contract address, function data and public inputs.
*/
public static empty(): PublicCallStackItem {
return new PublicCallStackItem(
AztecAddress.ZERO,
FunctionData.empty({ isPrivate: false }),
PublicCircuitPublicInputs.empty(),
false,
);
}

isEmpty() {
return this.contractAddress.isZero() && this.functionData.isEmpty() && this.publicInputs.isEmpty();
}

/**
* Computes this call stack item hash.
* @returns Hash.
*/
public hash() {
return computePublicCallStackItemHash(this);
}

/**
* Creates a new CallRequest with values of the calling contract.
* @returns A CallRequest instance with the contract address, caller context, and the hash of the call stack item.
*/
public toCallRequest() {
if (this.isEmpty()) {
return CallRequest.empty();
}

const callContext = this.publicInputs.callContext;
const callerContext = callContext.isDelegateCall
? new CallerContext(callContext.msgSender, callContext.storageContractAddress)
: CallerContext.empty();
// todo: populate side effect counters correctly
return new CallRequest(this.hash(), callContext.msgSender, callerContext, Fr.ZERO, Fr.ZERO);
}
}
Loading

0 comments on commit 76b9578

Please sign in to comment.