Skip to content

Commit

Permalink
feat(noir): update to noir master (#903)
Browse files Browse the repository at this point in the history
* feat: first usage of noir master

* chore: use published package

* try to fix nullifier generation

* feat: updated contracts

* style: prettier

* style: add temporary jsdoc

* refactor: use acvm-simulator compatible types

* chore: compile with aztec3 branch
  • Loading branch information
sirasistant authored Jun 26, 2023
1 parent 1bc76ba commit 4777601
Show file tree
Hide file tree
Showing 58 changed files with 254 additions and 233 deletions.
2 changes: 1 addition & 1 deletion circuits/cpp/src/aztec3/circuits/abis/c_bind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ WASM_EXPORT void abis__compute_message_secret_hash(uint8_t const* secret, uint8_
NT::fr message_secret;
read(secret, message_secret);
// TODO(sean): This is not using the generator correctly and is unsafe, update
auto secret_hash = crypto::pedersen_commitment::compress_native(
auto secret_hash = crypto::pedersen_commitment::lookup::compress_native(
{ aztec3::GeneratorIndex::L1_TO_L2_MESSAGE_SECRET, message_secret });
NT::fr::serialize_to_buffer(secret_hash, output);
}
Expand Down
3 changes: 1 addition & 2 deletions yarn-project/acir-simulator/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@
"@aztec/merkle-tree": "workspace:^",
"@aztec/noir-contracts": "workspace:^",
"@aztec/types": "workspace:^",
"@noir-lang/aztec_backend_wasm": "github:joss-aztec/barretenberg_browser_stopgap_wasm_build#f2e10698dfa11cd46f7373cec1ed6184b0505f1e",
"@noir-lang/noir_util_wasm": "github:joss-aztec/noir_util_wasm#7dc410f4b4c00b9cfa9e726ae7fca3a3a4a237c5",
"acvm-simulator": "github:sirasistant/acvm-simulator-wasm#180bc5bec8b79034e9e3a508a959cac3fe801ed1",
"levelup": "^5.1.1",
"memdown": "^6.1.1",
"tslib": "^2.4.0"
Expand Down
38 changes: 17 additions & 21 deletions yarn-project/acir-simulator/src/acvm/acvm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@ 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 { solve_intermediate_witness as solveIntermediateWitness } from '@noir-lang/aztec_backend_wasm';
import { WitnessMap, executeCircuit } from 'acvm-simulator';

/**
* The format for fields on the ACVM.
*/
export type ACVMField = `0x${string}`;
export type ACVMField = string;
/**
* The format for addresses on the ACVM.
* The format for witnesses of the ACVM.
*/
export type ACVMWitness = Map<number, ACVMField>;
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`;
Expand Down Expand Up @@ -67,21 +67,17 @@ export type execute = (acir: Buffer, initialWitness: ACVMWitness, oracle: ACIRCa

export const acvm: execute = async (acir, initialWitness, callback) => {
const logger = createDebugLogger('aztec:simulator:acvm');
const partialWitness = await solveIntermediateWitness(
acir,
initialWitness,
async (name: string, args: ACVMField[]) => {
try {
logger(`Oracle callback ${name}`);
if (!(name in callback)) throw new Error(`Callback ${name} not found`);
const result = await callback[name as keyof ACIRCallback](args);
return result;
} catch (err: any) {
logger(`Error in ACVM callback ${name}: ${err.message ?? err ?? 'Unknown'}`);
throw err;
}
},
);
const partialWitness = await executeCircuit(acir, initialWitness, async (name: string, args: string[]) => {
try {
logger(`Oracle callback ${name}`);
if (!(name in callback)) throw new Error(`Callback ${name} not found`);
const result = await callback[name as keyof ACIRCallback](args);
return result;
} catch (err: any) {
logger(`Error in ACVM callback ${name}: ${err.message ?? err ?? 'Unknown'}`);
throw err;
}
});
return Promise.resolve({ partialWitness });
};

Expand Down Expand Up @@ -130,7 +126,7 @@ export function toACVMField(value: AztecAddress | EthAddress | Fr | Buffer | boo
* @param field - The ACVM field to convert.
* @returns The Buffer.
*/
export function convertACVMFieldToBuffer(field: `0x${string}`): Buffer {
export function convertACVMFieldToBuffer(field: ACVMField): Buffer {
return Buffer.from(field.slice(2), 'hex');
}

Expand All @@ -139,7 +135,7 @@ export function convertACVMFieldToBuffer(field: `0x${string}`): Buffer {
* @param field - The ACVM field to convert.
* @returns The Fr.
*/
export function fromACVMField(field: `0x${string}`): Fr {
export function fromACVMField(field: ACVMField): Fr {
return Fr.fromBuffer(convertACVMFieldToBuffer(field));
}

Expand Down
16 changes: 14 additions & 2 deletions yarn-project/acir-simulator/src/acvm/deserialize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
import { AztecAddress } from '@aztec/foundation/aztec-address';
import { EthAddress } from '@aztec/foundation/eth-address';
import { Fr } from '@aztec/foundation/fields';
import { select_return_flattened as selectPublicWitnessFlattened } from '@noir-lang/noir_util_wasm';
import { getReturnWitness } from 'acvm-simulator';

// Utilities to read TS classes from ACVM Field arrays
// In the order that the ACVM provides them
Expand Down Expand Up @@ -57,14 +57,26 @@ export function frToSelector(fr: Fr): Buffer {
return fr.toBuffer().slice(-4);
}

/**
* Extracts the return fields of a given partial witness.
* @param acir - The bytecode of the function.
* @param partialWitness - The witness to extract from.
* @returns The return values.
*/
export function extractReturnWitness(acir: Buffer, partialWitness: ACVMWitness): ACVMField[] {
const returnWitness = getReturnWitness(acir, partialWitness);
const sortedKeys = [...returnWitness.keys()].sort((a, b) => a - b);
return sortedKeys.map(key => returnWitness.get(key)!);
}

/**
* A utility reader for the public inputs of the ACVM generated partial witness.
*/
export class PublicInputsReader {
private publicInputs: ACVMField[];

constructor(witness: ACVMWitness, acir: Buffer) {
this.publicInputs = selectPublicWitnessFlattened(acir, witness);
this.publicInputs = extractReturnWitness(acir, witness);
}

/**
Expand Down
18 changes: 10 additions & 8 deletions yarn-project/acir-simulator/src/client/private_execution.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
TxContext,
} from '@aztec/circuits.js';
import { computeSecretMessageHash, siloCommitment } from '@aztec/circuits.js/abis';
import { Grumpkin, pedersenCompressInputs } from '@aztec/circuits.js/barretenberg';
import { Grumpkin, pedersenPlookupCommitInputs } from '@aztec/circuits.js/barretenberg';
import { FunctionAbi } from '@aztec/foundation/abi';
import { AztecAddress } from '@aztec/foundation/aztec-address';
import { toBufferBE } from '@aztec/foundation/bigint-buffer';
Expand Down Expand Up @@ -103,7 +103,7 @@ describe('Private Execution test suite', () => {
let recipient: NoirPoint;

const buildNote = (amount: bigint, owner: NoirPoint) => {
return [new Fr(1n), new Fr(currentNonce++), new Fr(owner.x), new Fr(owner.y), Fr.random(), new Fr(amount)];
return [new Fr(amount), new Fr(owner.x), new Fr(owner.y), Fr.random(), new Fr(currentNonce++), new Fr(1n)];
};

beforeAll(() => {
Expand Down Expand Up @@ -215,8 +215,8 @@ describe('Private Execution test suite', () => {
Fr.fromBuffer(acirSimulator.computeNoteHash(changeNote.preimage, circuitsWasm)),
);

expect(recipientNote.preimage[5]).toEqual(new Fr(amountToTransfer));
expect(changeNote.preimage[5]).toEqual(new Fr(40n));
expect(recipientNote.preimage[0]).toEqual(new Fr(amountToTransfer));
expect(changeNote.preimage[0]).toEqual(new Fr(40n));
}, 30_000);

it('should be able to transfer with dummy notes', async () => {
Expand Down Expand Up @@ -260,16 +260,16 @@ describe('Private Execution test suite', () => {
const result = await acirSimulator.run(txRequest, abi, AztecAddress.random(), EthAddress.ZERO, historicRoots);

const newNullifiers = result.callStackItem.publicInputs.newNullifiers.filter(field => !field.equals(Fr.ZERO));
expect(newNullifiers).toHaveLength(2);
expect(newNullifiers).toHaveLength(1);

expect(newNullifiers[0]).toEqual(
Fr.fromBuffer(acirSimulator.computeNullifier(preimages[0], ownerPk, circuitsWasm)),
);

expect(result.preimages.newNotes).toHaveLength(2);
const [recipientNote, changeNote] = result.preimages.newNotes;
expect(recipientNote.preimage[5]).toEqual(new Fr(amountToTransfer));
expect(changeNote.preimage[5]).toEqual(new Fr(balance - amountToTransfer));
expect(recipientNote.preimage[0]).toEqual(new Fr(amountToTransfer));
expect(changeNote.preimage[0]).toEqual(new Fr(balance - amountToTransfer));
}, 30_000);
});

Expand Down Expand Up @@ -380,7 +380,9 @@ describe('Private Execution test suite', () => {
const wasm = await CircuitsWasm.get();
const secret = new Fr(1n);
const secretHash = computeSecretMessageHash(wasm, secret);
const commitment = Fr.fromBuffer(pedersenCompressInputs(wasm, [toBufferBE(amount, 32), secretHash.toBuffer()]));
const commitment = Fr.fromBuffer(
pedersenPlookupCommitInputs(wasm, [toBufferBE(amount, 32), secretHash.toBuffer()]),
);
const siloedCommitment = siloCommitment(wasm, contractAddress, commitment);

const tree: AppendOnlyTree = await newTree(
Expand Down
22 changes: 10 additions & 12 deletions yarn-project/acir-simulator/src/client/private_execution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,26 +249,24 @@ export class PrivateFunctionExecution {
const argsSize = this.abi.parameters.reduce((acc, param) => acc + sizeOfType(param.type), 0);
const contractDeploymentData = this.context.txContext.contractDeploymentData ?? ContractDeploymentData.empty();

// NOTE: PSA to anyone updating this code: within the structs, the members must be in alphabetical order, this
// is a current quirk in noir struct encoding, feel free to remove this note when this changes
const fields = [
this.callContext.isContractDeployment,
this.callContext.isDelegateCall,
this.callContext.isStaticCall,
this.callContext.msgSender,
this.callContext.portalContractAddress,
this.callContext.storageContractAddress,
this.callContext.portalContractAddress,
this.callContext.isDelegateCall,
this.callContext.isStaticCall,
this.callContext.isContractDeployment,

this.context.historicRoots.privateDataTreeRoot,
this.context.historicRoots.nullifierTreeRoot,
this.context.historicRoots.contractTreeRoot,
this.context.historicRoots.l1ToL2MessagesTreeRoot,

contractDeploymentData.constructorVkHash,
contractDeploymentData.contractAddressSalt,
contractDeploymentData.functionTreeRoot,
contractDeploymentData.contractAddressSalt,
contractDeploymentData.portalContractAddress,

this.context.historicRoots.contractTreeRoot,
this.context.historicRoots.l1ToL2MessagesTreeRoot,
this.context.historicRoots.nullifierTreeRoot,
this.context.historicRoots.privateDataTreeRoot,

...this.args.slice(0, argsSize),
];

Expand Down
10 changes: 7 additions & 3 deletions yarn-project/acir-simulator/src/client/simulator.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { pedersenCompressInputs, pedersenCompressWithHashIndex } from '@aztec/circuits.js/barretenberg';
import { pedersenCompressWithHashIndex, pedersenPlookupCommitInputs } from '@aztec/circuits.js/barretenberg';
import { CallContext, CircuitsWasm, PrivateHistoricTreeRoots, TxContext } from '@aztec/circuits.js';
import { FunctionAbi, FunctionType } from '@aztec/foundation/abi';
import { AztecAddress } from '@aztec/foundation/aztec-address';
Expand All @@ -15,6 +15,7 @@ import { DebugLogger, createDebugLogger } from '@aztec/foundation/log';
export const NOTE_PEDERSEN_CONSTANT = new Fr(2n);
export const MAPPING_SLOT_PEDERSEN_CONSTANT = new Fr(4n);
export const NULLIFIER_PEDERSEN_CONSTANT = new Fr(5n);
export const MESSAGE_SECRET_PEDERSEN_CONSTANT = new Fr(29n);

const OUTER_NULLIFIER_GENERATOR_INDEX = 7;

Expand Down Expand Up @@ -121,7 +122,10 @@ export class AcirSimulator {
* @returns The note hash.
*/
public computeNoteHash(notePreimage: Fr[], bbWasm: CircuitsWasm) {
return pedersenCompressInputs(bbWasm, [NOTE_PEDERSEN_CONSTANT.toBuffer(), ...notePreimage.map(x => x.toBuffer())]);
return pedersenPlookupCommitInputs(bbWasm, [
NOTE_PEDERSEN_CONSTANT.toBuffer(),
...notePreimage.map(x => x.toBuffer()),
]);
}

// TODO Should be run as unconstrained function
Expand All @@ -134,7 +138,7 @@ export class AcirSimulator {
*/
public computeNullifier(notePreimage: Fr[], privateKey: Buffer, bbWasm: CircuitsWasm) {
const noteHash = this.computeNoteHash(notePreimage, bbWasm);
return pedersenCompressInputs(bbWasm, [NULLIFIER_PEDERSEN_CONSTANT.toBuffer(), noteHash, privateKey]);
return pedersenPlookupCommitInputs(bbWasm, [NULLIFIER_PEDERSEN_CONSTANT.toBuffer(), noteHash, privateKey]);
}

// TODO Should be run as unconstrained function
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ describe('Unconstrained Execution test suite', () => {
let owner: NoirPoint;

const buildNote = (amount: bigint, owner: NoirPoint) => {
return [new Fr(1n), new Fr(currentNonce++), new Fr(owner.x), new Fr(owner.y), Fr.random(), new Fr(amount)];
return [new Fr(amount), new Fr(owner.x), new Fr(owner.y), Fr.random(), new Fr(currentNonce++), new Fr(1n)];
};

beforeAll(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ import { FunctionAbi } from '@aztec/foundation/abi';
import { AztecAddress } from '@aztec/foundation/aztec-address';
import { Fr, Point } from '@aztec/foundation/fields';
import { createDebugLogger } from '@aztec/foundation/log';
import { select_return_flattened as selectReturnFlattened } from '@noir-lang/noir_util_wasm';
import { decodeReturnValues } from '../abi_coder/decoder.js';
import { frToNumber } from '../acvm/deserialize.js';
import { extractReturnWitness, frToNumber } from '../acvm/deserialize.js';
import { ACVMField, ZERO_ACVM_FIELD, acvm, fromACVMField, toACVMField, toACVMWitness } from '../acvm/index.js';
import { ClientTxExecutionContext } from './client_execution_context.js';
import { fieldsToFormattedStr } from './debug.js';
Expand Down Expand Up @@ -87,7 +86,7 @@ export class UnconstrainedFunctionExecution {
emitUnencryptedLog: notAvailable,
});

const returnValues: ACVMField[] = selectReturnFlattened(acir, partialWitness);
const returnValues: ACVMField[] = extractReturnWitness(acir, partialWitness);

return decodeReturnValues(this.abi, returnValues.map(fromACVMField));
}
Expand Down
17 changes: 9 additions & 8 deletions yarn-project/acir-simulator/src/public/executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import { AztecAddress, CallContext, EthAddress, Fr, FunctionData, PrivateHistori
import { padArrayEnd } from '@aztec/foundation/collection';
import { createDebugLogger } from '@aztec/foundation/log';
import { FunctionL2Logs } from '@aztec/types';
import { select_return_flattened as selectPublicWitnessFlattened } from '@noir-lang/noir_util_wasm';
import {
ACVMField,
ZERO_ACVM_FIELD,
acvm,
convertACVMFieldToBuffer,
extractReturnWitness,
frToAztecAddress,
frToSelector,
fromACVMField,
Expand Down Expand Up @@ -140,7 +140,8 @@ export class PublicExecutor {
},
});

const returnValues = selectPublicWitnessFlattened(acir, partialWitness).map(fromACVMField);
const returnValues = extractReturnWitness(acir, partialWitness).map(fromACVMField);

const [contractStorageReads, contractStorageUpdateRequests] = storageActions.collect();

return {
Expand Down Expand Up @@ -199,17 +200,17 @@ function getInitialWitness(
witnessStartIndex = 1,
) {
return toACVMWitness(witnessStartIndex, [
callContext.isContractDeployment,
callContext.isDelegateCall,
callContext.isStaticCall,
callContext.msgSender,
callContext.portalContractAddress,
callContext.storageContractAddress,
callContext.portalContractAddress,
callContext.isDelegateCall,
callContext.isStaticCall,
callContext.isContractDeployment,

commitmentTreeRoots.privateDataTreeRoot,
commitmentTreeRoots.nullifierTreeRoot,
commitmentTreeRoots.contractTreeRoot,
commitmentTreeRoots.l1ToL2MessagesTreeRoot,
commitmentTreeRoots.nullifierTreeRoot,
commitmentTreeRoots.privateDataTreeRoot,

...args,
]);
Expand Down
8 changes: 4 additions & 4 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 { Grumpkin, pedersenCompressInputs } from '@aztec/circuits.js/barretenberg';
import { Grumpkin, pedersenPlookupCommitInputs } from '@aztec/circuits.js/barretenberg';
import {
CallContext,
FunctionData,
Expand Down Expand Up @@ -270,7 +270,7 @@ describe('ACIR public execution simulator', () => {
// Assert the commitment was created
expect(result.newCommitments.length).toEqual(1);

const expectedNewCommitmentValue = pedersenCompressInputs(
const expectedNewCommitmentValue = pedersenPlookupCommitInputs(
wasm,
params.map(a => a.toBuffer()),
);
Expand Down Expand Up @@ -300,7 +300,7 @@ describe('ACIR public execution simulator', () => {
// Assert the l2 to l1 message was created
expect(result.newL2ToL1Messages.length).toEqual(1);

const expectedNewMessageValue = pedersenCompressInputs(
const expectedNewMessageValue = pedersenPlookupCommitInputs(
wasm,
params.map(a => a.toBuffer()),
);
Expand Down Expand Up @@ -388,7 +388,7 @@ describe('ACIR public execution simulator', () => {
// Assert the l2 to l1 message was created
expect(result.newNullifiers.length).toEqual(1);

const expectedNewMessageValue = pedersenCompressInputs(
const expectedNewMessageValue = pedersenPlookupCommitInputs(
wasm,
params.map(a => a.toBuffer()),
);
Expand Down
4 changes: 2 additions & 2 deletions yarn-project/acir-simulator/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { MAPPING_SLOT_PEDERSEN_CONSTANT } from './client/simulator.js';
import { Fr } from '@aztec/foundation/fields';
import { toBigIntBE } from '@aztec/foundation/bigint-buffer';
import { Grumpkin, pedersenCompressInputs } from '@aztec/circuits.js/barretenberg';
import { Grumpkin, pedersenPlookupCommitInputs } from '@aztec/circuits.js/barretenberg';
import { CircuitsWasm } from '@aztec/circuits.js';

/**
Expand All @@ -26,7 +26,7 @@ export function computeSlotForMapping(mappingSlot: Fr, owner: NoirPoint | Fr, bb
const ownerField = isFr(owner) ? owner : new Fr(owner.x);

return Fr.fromBuffer(
pedersenCompressInputs(
pedersenPlookupCommitInputs(
bbWasm,
[MAPPING_SLOT_PEDERSEN_CONSTANT, mappingSlot, ownerField].map(f => f.toBuffer()),
),
Expand Down
Loading

0 comments on commit 4777601

Please sign in to comment.