Skip to content

Commit

Permalink
chore(tests): add tests that you can nullify pending notes (#1109)
Browse files Browse the repository at this point in the history
  • Loading branch information
dbanks12 authored Jul 19, 2023
1 parent 2e25f8a commit f5bf2d8
Show file tree
Hide file tree
Showing 14 changed files with 505 additions and 85 deletions.
70 changes: 42 additions & 28 deletions yarn-project/acir-simulator/src/client/private_execution.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ describe('Private Execution test suite', () => {
});
});

it('should a constructor with arguments that creates notes', async () => {
it('should a constructor with arguments that inserts notes', async () => {
const abi = ZkTokenContractAbi.functions.find(f => f.name === 'constructor')!;

const result = await runSimulator({ args: [140, owner], abi, isConstructor: true });
Expand Down Expand Up @@ -353,11 +353,11 @@ describe('Private Execution test suite', () => {
args: [amount, secret, recipient],
});

// Check a nullifier has been created.
// Check a nullifier has been inserted.
const newNullifiers = result.callStackItem.publicInputs.newNullifiers.filter(field => !field.equals(Fr.ZERO));
expect(newNullifiers).toHaveLength(1);

// Check the read request was created successfully.
// Check the read request was inserted successfully.
const readRequests = result.callStackItem.publicInputs.readRequests.filter(field => !field.equals(Fr.ZERO));
const nonce = Fr.ZERO;
const uniqueNoteHash = computeUniqueCommitment(circuitsWasm, nonce, innerNoteHash);
Expand Down Expand Up @@ -443,7 +443,7 @@ describe('Private Execution test suite', () => {
const args = [bridgedAmount, recipient, messageKey, secret, canceller.toField()];
const result = await runSimulator({ origin: contractAddress, contractAddress, abi, args });

// Check a nullifier has been created
// Check a nullifier has been inserted
const newNullifiers = result.callStackItem.publicInputs.newNullifiers.filter(field => !field.equals(Fr.ZERO));
expect(newNullifiers).toHaveLength(1);
});
Expand Down Expand Up @@ -475,7 +475,7 @@ describe('Private Execution test suite', () => {
args: [amount, secret, recipient],
});

// Check a nullifier has been created.
// Check a nullifier has been inserted.
const newNullifiers = result.callStackItem.publicInputs.newNullifiers.filter(field => !field.equals(Fr.ZERO));
expect(newNullifiers).toHaveLength(1);

Expand Down Expand Up @@ -545,13 +545,15 @@ describe('Private Execution test suite', () => {
);
});

it('should be able to read pending commitments created in same function', async () => {
it('should be able to insert, read, and nullify pending commitments in one call', async () => {
oracle.getNotes.mockResolvedValue([]);

const amountToTransfer = 100n;

const contractAddress = AztecAddress.random();
const abi = PendingCommitmentsContractAbi.functions.find(f => f.name === 'test_insert_then_read_flat')!;
const abi = PendingCommitmentsContractAbi.functions.find(
f => f.name === 'test_insert_then_get_then_nullify_flat',
)!;

const args = [amountToTransfer, owner];
const result = await runSimulator({
Expand All @@ -568,82 +570,90 @@ describe('Private Execution test suite', () => {
expect(note.preimage[0]).toEqual(new Fr(amountToTransfer));

const newCommitments = result.callStackItem.publicInputs.newCommitments.filter(field => !field.equals(Fr.ZERO));

expect(newCommitments).toHaveLength(1);

const commitment = newCommitments[0];
const storageSlot = computeSlotForMapping(new Fr(1n), owner.toField(), circuitsWasm);
expect(commitment).toEqual(await acirSimulator.computeInnerNoteHash(contractAddress, storageSlot, note.preimage));

// read request should match commitment
const nonce = computeCommitmentNonce(circuitsWasm, txNullifier, 0);
const readRequest = result.callStackItem.publicInputs.readRequests[0];
expect(readRequest).toEqual(computeUniqueCommitment(circuitsWasm, nonce, commitment));

const gotNoteValue = result.callStackItem.publicInputs.returnValues[0].value;
expect(gotNoteValue).toEqual(amountToTransfer);

const nullifier = result.callStackItem.publicInputs.newNullifiers[0];
expect(nullifier).toEqual(
await acirSimulator.computeNullifier(contractAddress, nonce, note.storageSlot, note.preimage),
);
});

it('should be able to create and read pending commitments both in nested calls', async () => {
it('should be able to insert, read, and nullify pending commitments in nested calls', async () => {
oracle.getNotes.mockResolvedValue([]);

const amountToTransfer = 100n;

const contractAddress = AztecAddress.random();
const abi = PendingCommitmentsContractAbi.functions.find(
f => f.name === 'test_insert_then_read_both_in_nested_calls',
f => f.name === 'test_insert_then_get_then_nullify_all_in_nested_calls',
)!;
const createAbi = PendingCommitmentsContractAbi.functions.find(f => f.name === 'create_note')!;
const getAndCheckAbi = PendingCommitmentsContractAbi.functions.find(f => f.name === 'get_and_check_note')!;
const insertAbi = PendingCommitmentsContractAbi.functions.find(f => f.name === 'insert_note')!;
const getThenNullifyAbi = PendingCommitmentsContractAbi.functions.find(f => f.name === 'get_then_nullify_note')!;

const createFnSelector = generateFunctionSelector(createAbi.name, createAbi.parameters);
const getAndCheckFnSelector = generateFunctionSelector(getAndCheckAbi.name, getAndCheckAbi.parameters);
const insertFnSelector = generateFunctionSelector(insertAbi.name, insertAbi.parameters);
const getThenNullifyFnSelector = generateFunctionSelector(getThenNullifyAbi.name, getThenNullifyAbi.parameters);

oracle.getPortalContractAddress.mockImplementation(() => Promise.resolve(EthAddress.ZERO));

const args = [amountToTransfer, owner, createFnSelector, getAndCheckFnSelector];
const args = [amountToTransfer, owner, insertFnSelector, getThenNullifyFnSelector];
const result = await runSimulator({
args: args,
abi: abi,
origin: contractAddress,
contractAddress: contractAddress,
});

const execCreate = result.nestedExecutions[0];
const execGetAndCheck = result.nestedExecutions[1];
const execInsert = result.nestedExecutions[0];
const execGetThenNullify = result.nestedExecutions[1];

expect(execCreate.preimages.newNotes).toHaveLength(1);
const note = execCreate.preimages.newNotes[0];
expect(execInsert.preimages.newNotes).toHaveLength(1);
const note = execInsert.preimages.newNotes[0];
expect(note.storageSlot).toEqual(computeSlotForMapping(new Fr(1n), owner.toField(), circuitsWasm));

expect(note.preimage[0]).toEqual(new Fr(amountToTransfer));

const newCommitments = execCreate.callStackItem.publicInputs.newCommitments.filter(
const newCommitments = execInsert.callStackItem.publicInputs.newCommitments.filter(
field => !field.equals(Fr.ZERO),
);

expect(newCommitments).toHaveLength(1);

const commitment = newCommitments[0];
const storageSlot = computeSlotForMapping(new Fr(1n), owner.toField(), circuitsWasm);
expect(commitment).toEqual(await acirSimulator.computeInnerNoteHash(contractAddress, storageSlot, note.preimage));

// read request should match commitment
const nonce = computeCommitmentNonce(circuitsWasm, txNullifier, 0);
const readRequest = execGetAndCheck.callStackItem.publicInputs.readRequests[0];
const readRequest = execGetThenNullify.callStackItem.publicInputs.readRequests[0];
expect(readRequest).toEqual(computeUniqueCommitment(circuitsWasm, nonce, commitment));

const gotNoteValue = execGetAndCheck.callStackItem.publicInputs.returnValues[0].value;
const gotNoteValue = execGetThenNullify.callStackItem.publicInputs.returnValues[0].value;
expect(gotNoteValue).toEqual(amountToTransfer);

// TODO check read request is output that matches pending commitment
const nullifier = execGetThenNullify.callStackItem.publicInputs.newNullifiers[0];
expect(nullifier).toEqual(
await acirSimulator.computeNullifier(contractAddress, nonce, note.storageSlot, note.preimage),
);
});

it('cant read a commitment that is created later in same function', async () => {
it('cant read a commitment that is inserted later in same call', async () => {
oracle.getNotes.mockResolvedValue([]);

const amountToTransfer = 100n;

const contractAddress = AztecAddress.random();
const abi = PendingCommitmentsContractAbi.functions.find(f => f.name === 'test_bad_read_then_insert_flat')!;
const abi = PendingCommitmentsContractAbi.functions.find(f => f.name === 'test_bad_get_then_insert_flat')!;

const args = [amountToTransfer, owner];
const result = await runSimulator({
Expand All @@ -660,19 +670,23 @@ describe('Private Execution test suite', () => {
expect(note.preimage[0]).toEqual(new Fr(amountToTransfer));

const newCommitments = result.callStackItem.publicInputs.newCommitments.filter(field => !field.equals(Fr.ZERO));

expect(newCommitments).toHaveLength(1);

const commitment = newCommitments[0];
const storageSlot = computeSlotForMapping(new Fr(1n), owner.toField(), circuitsWasm);
expect(commitment).toEqual(await acirSimulator.computeInnerNoteHash(contractAddress, storageSlot, note.preimage));

// read requests should be empty
const readRequest = result.callStackItem.publicInputs.readRequests[0].value;
expect(readRequest).toEqual(0n);

// should get note value 0 because it actually gets a fake note since the real one hasn't been inserted yet!
const gotNoteValue = result.callStackItem.publicInputs.returnValues[0].value;
// should get note value 0 because it actually gets a fake note since the real one hasn't been created yet!
expect(gotNoteValue).toEqual(0n);

// there should be no nullifiers
const nullifier = result.callStackItem.publicInputs.newNullifiers[0].value;
expect(nullifier).toEqual(0n);
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ describe('e2e_pending_commitments_contract', () => {

const deployedContract = await deployContract();

const tx = deployedContract.methods.test_insert_then_read_flat(mintAmount, owner).send({ origin: owner });
const tx = deployedContract.methods
.test_insert_then_get_then_nullify_flat(mintAmount, owner)
.send({ origin: owner });

await tx.isMined(0, 0.1);
const receipt = await tx.getReceipt();
Expand All @@ -56,11 +58,11 @@ describe('e2e_pending_commitments_contract', () => {
const deployedContract = await deployContract();

const tx = deployedContract.methods
.test_insert_then_read_both_in_nested_calls(
.test_insert_then_get_then_nullify_all_in_nested_calls(
mintAmount,
owner,
Fr.fromBuffer(deployedContract.methods.create_note.selector),
Fr.fromBuffer(deployedContract.methods.get_and_check_note.selector),
Fr.fromBuffer(deployedContract.methods.insert_note.selector),
Fr.fromBuffer(deployedContract.methods.get_then_nullify_note.selector),
)
.send({ origin: owner });

Expand Down

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Loading

0 comments on commit f5bf2d8

Please sign in to comment.