Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: PublicCircuitPublicInputs and PrivateCircuitPublicInputs cleanup #4360

Merged
merged 8 commits into from
Feb 1, 2024
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
169 changes: 2 additions & 167 deletions yarn-project/acir-simulator/src/acvm/deserialize.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,4 @@
import {
CallContext,
ContractDeploymentData,
ContractStorageRead,
ContractStorageUpdateRequest,
HEADER_LENGTH,
Header,
MAX_NEW_COMMITMENTS_PER_CALL,
MAX_NEW_L2_TO_L1_MSGS_PER_CALL,
MAX_NEW_NULLIFIERS_PER_CALL,
MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL,
MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL,
MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,
MAX_PUBLIC_DATA_READS_PER_CALL,
MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL,
MAX_READ_REQUESTS_PER_CALL,
NUM_FIELDS_PER_SHA256,
NullifierKeyValidationRequest,
PrivateCircuitPublicInputs,
PublicCircuitPublicInputs,
RETURN_VALUES_LENGTH,
SideEffect,
SideEffectLinkedToNoteHash,
} from '@aztec/circuits.js';
import { AztecAddress } from '@aztec/foundation/aztec-address';
import { EthAddress } from '@aztec/foundation/eth-address';
import { Fr, Point } from '@aztec/foundation/fields';
import { FieldReader, Tuple } from '@aztec/foundation/serialize';
import { Fr } from '@aztec/foundation/fields';

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹

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

Expand All @@ -44,6 +17,7 @@ export function fromACVMField(field: ACVMField): Fr {
* Converts a field to a number.
* @param fr - The field to convert.
* @returns The number.
* TODO(#4102): Nuke this once block number is big int.
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added via Giphy

export function frToNumber(fr: Fr): number {
return Number(fr.value);
Expand All @@ -60,142 +34,3 @@ export function extractReturnWitness(acir: Buffer, partialWitness: ACVMWitness):
const sortedKeys = [...returnWitness.keys()].sort((a, b) => a - b);
return sortedKeys.map(key => returnWitness.get(key)!).map(fromACVMField);
}

/**
* Create a reader for the public inputs of the ACVM generated partial witness.
*/
function createPublicInputsReader(witness: ACVMWitness, acir: Buffer) {
const fields = extractReturnWitness(acir, witness);
return new FieldReader(fields);
}

/**
* Extracts the public inputs from the ACVM generated partial witness.
* @param partialWitness - The partial witness.
* @param acir - The ACIR bytecode.
* @returns The public inputs.
*/
export function extractPrivateCircuitPublicInputs(
partialWitness: ACVMWitness,
acir: Buffer,
): PrivateCircuitPublicInputs {
const witnessReader = createPublicInputsReader(partialWitness, acir);

const callContext = witnessReader.readObject(CallContext);
const argsHash = witnessReader.readField();
const returnValues = witnessReader.readFieldArray(RETURN_VALUES_LENGTH);
const readRequests = witnessReader.readArray(MAX_READ_REQUESTS_PER_CALL, SideEffect);
const nullifierKeyValidationRequests = witnessReader.readArray(
MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL,
NullifierKeyValidationRequest,
);
const newCommitments = witnessReader.readArray(MAX_NEW_COMMITMENTS_PER_CALL, SideEffect);
const newNullifiers = witnessReader.readArray(MAX_NEW_NULLIFIERS_PER_CALL, SideEffectLinkedToNoteHash);
const privateCallStack = witnessReader.readFieldArray(MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL);
const publicCallStack = witnessReader.readFieldArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL);
const newL2ToL1Msgs = witnessReader.readFieldArray(MAX_NEW_L2_TO_L1_MSGS_PER_CALL);
const endSideEffectCounter = witnessReader.readField();

const encryptedLogsHash = witnessReader.readFieldArray(NUM_FIELDS_PER_SHA256);
const unencryptedLogsHash = witnessReader.readFieldArray(NUM_FIELDS_PER_SHA256);
const encryptedLogPreimagesLength = witnessReader.readField();
const unencryptedLogPreimagesLength = witnessReader.readField();

const header = Header.fromFields(witnessReader.readFieldArray(HEADER_LENGTH));

const contractDeploymentData = new ContractDeploymentData(
new Point(witnessReader.readField(), witnessReader.readField()),
witnessReader.readField(),
witnessReader.readField(),
witnessReader.readField(),
EthAddress.fromField(witnessReader.readField()),
);

const chainId = witnessReader.readField();
const version = witnessReader.readField();

return new PrivateCircuitPublicInputs(
callContext,
argsHash,
returnValues,
readRequests,
nullifierKeyValidationRequests,
newCommitments,
newNullifiers,
privateCallStack,
publicCallStack,
newL2ToL1Msgs,
endSideEffectCounter,
encryptedLogsHash,
unencryptedLogsHash,
encryptedLogPreimagesLength,
unencryptedLogPreimagesLength,
header,
contractDeploymentData,
chainId,
version,
);
}

/**
* Extracts the public circuit public inputs from the ACVM generated partial witness.
* @param partialWitness - The partial witness.
* @param acir - The ACIR bytecode.
* @returns The public inputs.
*/
export function extractPublicCircuitPublicInputs(partialWitness: ACVMWitness, acir: Buffer): PublicCircuitPublicInputs {
const witnessReader = createPublicInputsReader(partialWitness, acir);

const callContext = witnessReader.readObject(CallContext);

const argsHash = witnessReader.readField();
const returnValues = witnessReader.readFieldArray(RETURN_VALUES_LENGTH);

const contractStorageUpdateRequests = new Array(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL).fill(
ContractStorageUpdateRequest.empty(),
);
for (let i = 0; i < MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL; i++) {
const request = new ContractStorageUpdateRequest(
witnessReader.readField(),
witnessReader.readField(),
witnessReader.readField(),
);
contractStorageUpdateRequests[i] = request;
}
const contractStorageReads = new Array(MAX_PUBLIC_DATA_READS_PER_CALL).fill(ContractStorageRead.empty());
for (let i = 0; i < MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL; i++) {
const request = new ContractStorageRead(witnessReader.readField(), witnessReader.readField());
contractStorageReads[i] = request;
}

const publicCallStack = witnessReader.readFieldArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL);
const newCommitments = witnessReader.readArray(MAX_NEW_COMMITMENTS_PER_CALL, SideEffect);
const newNullifiers = witnessReader.readArray(MAX_NEW_NULLIFIERS_PER_CALL, SideEffectLinkedToNoteHash);
const newL2ToL1Msgs = witnessReader.readFieldArray(MAX_NEW_L2_TO_L1_MSGS_PER_CALL);

const unencryptedLogsHash = witnessReader.readFieldArray(NUM_FIELDS_PER_SHA256);
const unencryptedLogPreimagesLength = witnessReader.readField();

const header = Header.fromFields(witnessReader.readFieldArray(HEADER_LENGTH));

const proverAddress = AztecAddress.fromField(witnessReader.readField());

return new PublicCircuitPublicInputs(
callContext,
argsHash,
returnValues,
contractStorageUpdateRequests as Tuple<
ContractStorageUpdateRequest,
typeof MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL
>,
contractStorageReads as Tuple<ContractStorageRead, typeof MAX_PUBLIC_DATA_READS_PER_CALL>,
publicCallStack,
newCommitments,
newNullifiers,
newL2ToL1Msgs,
unencryptedLogsHash,
unencryptedLogPreimagesLength,
header,
proverAddress,
);
}
25 changes: 15 additions & 10 deletions yarn-project/acir-simulator/src/acvm/oracle/typed_oracle.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
import {
CompleteAddress,
L1ToL2Message,
MerkleTreeId,
Note,
NoteStatus,
NullifierMembershipWitness,
PublicDataWitness,
PublicKey,
SiblingPath,
UnencryptedL2Log,
} from '@aztec/circuit-types';
import { GrumpkinPrivateKey, Header, PrivateCallStackItem, PublicCallRequest } from '@aztec/circuits.js';
import {
GrumpkinPrivateKey,
Header,
L1_TO_L2_MSG_TREE_HEIGHT,
PrivateCallStackItem,
PublicCallRequest,
} from '@aztec/circuits.js';
import { FunctionSelector } from '@aztec/foundation/abi';
import { AztecAddress } from '@aztec/foundation/aztec-address';
import { EthAddress } from '@aztec/foundation/eth-address';
Expand Down Expand Up @@ -48,21 +56,18 @@ export interface NoteData {
index?: bigint;
}

export class MessageLoadOracleInputs {
export class MessageLoadOracleInputs<N extends number> {
constructor(
/**
* An collapsed array of fields containing all of the l1 to l2 message components.
* `l1ToL2Message.toFieldArray()` -\> [sender, chainId, recipient, version, content, secretHash, deadline, fee]
*/
public message: Fr[],
/** The message. */
public message: L1ToL2Message,
/** The index of the message commitment in the merkle tree. */
public index: bigint,
/** The path in the merkle tree to the message. */
public siblingPath: Fr[],
public siblingPath: SiblingPath<N>,
) {}

toFields(): Fr[] {
return [...this.message, new Fr(this.index), ...this.siblingPath];
return [...this.message.toFieldArray(), new Fr(this.index), ...this.siblingPath.toFieldArray()];
}
}

Expand Down Expand Up @@ -154,7 +159,7 @@ export abstract class TypedOracle {
throw new Error('Not available.');
}

getL1ToL2Message(_msgKey: Fr): Promise<MessageLoadOracleInputs> {
getL1ToL2Message(_msgKey: Fr): Promise<MessageLoadOracleInputs<typeof L1_TO_L2_MSG_TREE_HEIGHT>> {
throw new Error('Not available.');
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -544,13 +544,7 @@ describe('Private Execution test suite', () => {
const mockOracles = async () => {
const tree = await insertLeaves([messageKey ?? preimage.hash()], 'l1ToL2Messages');
oracle.getL1ToL2Message.mockImplementation(async () => {
return Promise.resolve(
new MessageLoadOracleInputs(
preimage.toFieldArray(),
0n,
(await tree.getSiblingPath(0n, false)).toFieldArray(),
),
);
return Promise.resolve(new MessageLoadOracleInputs(preimage, 0n, await tree.getSiblingPath(0n, false)));
});
};

Expand Down
7 changes: 4 additions & 3 deletions yarn-project/acir-simulator/src/client/private_execution.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { FunctionData, PrivateCallStackItem } from '@aztec/circuits.js';
import { FunctionData, PrivateCallStackItem, PrivateCircuitPublicInputs } from '@aztec/circuits.js';
import { FunctionArtifactWithDebugMetadata, decodeReturnValues } from '@aztec/foundation/abi';
import { AztecAddress } from '@aztec/foundation/aztec-address';
import { Fr } from '@aztec/foundation/fields';
import { createDebugLogger } from '@aztec/foundation/log';
import { to2Fields } from '@aztec/foundation/serialize';

import { extractPrivateCircuitPublicInputs } from '../acvm/deserialize.js';
import { extractReturnWitness } from '../acvm/deserialize.js';
import { Oracle, acvm, extractCallStack } from '../acvm/index.js';
import { ExecutionError } from '../common/errors.js';
import { ClientExecutionContext } from './client_execution_context.js';
Expand Down Expand Up @@ -42,7 +42,8 @@ export async function executePrivateFunction(
},
);

const publicInputs = extractPrivateCircuitPublicInputs(partialWitness, acir);
const returnWitness = extractReturnWitness(acir, partialWitness);
const publicInputs = PrivateCircuitPublicInputs.fromFields(returnWitness);

const encryptedLogs = context.getEncryptedLogs();
const unencryptedLogs = context.getUnencryptedLogs();
Expand Down
4 changes: 2 additions & 2 deletions yarn-project/acir-simulator/src/public/db.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { EthAddress, FunctionSelector } from '@aztec/circuits.js';
import { EthAddress, FunctionSelector, L1_TO_L2_MSG_TREE_HEIGHT } from '@aztec/circuits.js';
import { AztecAddress } from '@aztec/foundation/aztec-address';
import { Fr } from '@aztec/foundation/fields';

Expand Down Expand Up @@ -74,7 +74,7 @@ export interface CommitmentsDB {
* @param msgKey - The message Key.
* @returns - The l1 to l2 message object
*/
getL1ToL2Message(msgKey: Fr): Promise<MessageLoadOracleInputs>;
getL1ToL2Message(msgKey: Fr): Promise<MessageLoadOracleInputs<typeof L1_TO_L2_MSG_TREE_HEIGHT>>;

/**
* Gets the index of a commitment in the note hash tree.
Expand Down
7 changes: 4 additions & 3 deletions yarn-project/acir-simulator/src/public/executor.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { GlobalVariables, Header } from '@aztec/circuits.js';
import { GlobalVariables, Header, PublicCircuitPublicInputs } from '@aztec/circuits.js';
import { createDebugLogger } from '@aztec/foundation/log';

import { Oracle, acvm, extractCallStack, extractPublicCircuitPublicInputs } from '../acvm/index.js';
import { Oracle, acvm, extractCallStack, extractReturnWitness } from '../acvm/index.js';
import { ExecutionError, createSimulationError } from '../common/errors.js';
import { SideEffectCounter } from '../common/index.js';
import { PackedArgsCache } from '../common/packed_args_cache.js';
Expand Down Expand Up @@ -39,12 +39,13 @@ export async function executePublicFunction(
},
);

const returnWitness = extractReturnWitness(acir, partialWitness);
const {
returnValues,
newL2ToL1Msgs,
newCommitments: newCommitmentsPadded,
newNullifiers: newNullifiersPadded,
} = extractPublicCircuitPublicInputs(partialWitness, acir);
} = PublicCircuitPublicInputs.fromFields(returnWitness);

const newL2ToL1Messages = newL2ToL1Msgs.filter(v => !v.isZero());
const newCommitments = newCommitmentsPadded.filter(v => !v.isEmpty());
Expand Down
14 changes: 9 additions & 5 deletions yarn-project/acir-simulator/src/public/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { L1ToL2Message } from '@aztec/circuit-types';
import { L1ToL2Message, SiblingPath } from '@aztec/circuit-types';
import {
AppendOnlyTreeSnapshot,
CallContext,
Expand Down Expand Up @@ -455,13 +455,17 @@ describe('ACIR public execution simulator', () => {
publicContracts.getBytecode.mockResolvedValue(Buffer.from(mintPublicArtifact.bytecode, 'base64'));
publicState.storageRead.mockResolvedValue(Fr.ZERO);

const siblingPath = Array(L1_TO_L2_MSG_TREE_HEIGHT).fill(Fr.random());
const siblingPathBuffers = Array(L1_TO_L2_MSG_TREE_HEIGHT)
.fill(Fr.random())
.map(f => f.toBuffer());
const siblingPath = new SiblingPath(L1_TO_L2_MSG_TREE_HEIGHT, siblingPathBuffers);

let root = messageKey ?? preimage.hash();
for (const sibling of siblingPath) {
root = Fr.fromBuffer(pedersenHash([root.toBuffer(), sibling.toBuffer()]));
for (const sibling of siblingPathBuffers) {
root = Fr.fromBuffer(pedersenHash([root.toBuffer(), sibling]));
}
commitmentsDb.getL1ToL2Message.mockImplementation(() => {
return Promise.resolve(new MessageLoadOracleInputs(preimage.toFieldArray(), 0n, siblingPath));
return Promise.resolve(new MessageLoadOracleInputs(preimage, 0n, siblingPath));
});

return new AppendOnlyTreeSnapshot(
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/aztec-node/src/aztec-node/http_rpc_server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
L2BlockL2Logs,
L2Tx,
LogId,
SiblingPath,
Tx,
TxHash,
} from '@aztec/circuit-types';
Expand All @@ -16,7 +17,6 @@ import { AztecAddress } from '@aztec/foundation/aztec-address';
import { EthAddress } from '@aztec/foundation/eth-address';
import { Fr } from '@aztec/foundation/fields';
import { JsonRpcServer } from '@aztec/foundation/json-rpc/server';
import { SiblingPath } from '@aztec/types/membership';

/**
* Wrap an AztecNode instance with a JSON RPC HTTP server.
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/aztec-node/src/aztec-node/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
NullifierMembershipWitness,
PublicDataWitness,
SequencerConfig,
SiblingPath,
Tx,
TxHash,
} from '@aztec/circuit-types';
Expand Down Expand Up @@ -46,7 +47,6 @@ import {
SequencerClient,
getGlobalVariableBuilder,
} from '@aztec/sequencer-client';
import { SiblingPath } from '@aztec/types/membership';
import {
MerkleTrees,
ServerWorldStateSynchronizer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import { AztecAddress } from '@aztec/foundation/aztec-address';
import { EthAddress } from '@aztec/foundation/eth-address';
import { Fr } from '@aztec/foundation/fields';
import { createJsonRpcClient, defaultFetch } from '@aztec/foundation/json-rpc/client';
import { SiblingPath } from '@aztec/types/membership';

import { ContractData, ExtendedContractData } from '../../contract_data.js';
import { AztecNode } from '../../interfaces/index.js';
import { L1ToL2MessageAndIndex } from '../../l1_to_l2_message.js';
import { L2Block } from '../../l2_block.js';
import { L2Tx } from '../../l2_tx.js';
import { ExtendedUnencryptedL2Log, L2BlockL2Logs, LogId } from '../../logs/index.js';
import { SiblingPath } from '../../sibling_path/index.js';
import { Tx, TxHash } from '../../tx/index.js';

/**
Expand Down
Loading
Loading