Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
fcarreiro committed Apr 2, 2024
1 parent ae747ff commit a6565aa
Show file tree
Hide file tree
Showing 6 changed files with 32 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,11 @@ contract AvmTest {
context.nullifier_exists(nullifier)
}

#[aztec(public-vm)]
fn assert_nullifier_exists(nullifier: Field) {
assert(context.nullifier_exists(nullifier));
}

// Use the standard context interface to emit a new nullifier
#[aztec(public-vm)]
fn emit_nullifier_and_check(nullifier: Field) {
Expand Down
17 changes: 15 additions & 2 deletions yarn-project/end-to-end/src/e2e_avm_simulator.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { AztecAddress, TxStatus, type Wallet } from '@aztec/aztec.js';
import { AztecAddress, Fr, TxStatus, type Wallet } from '@aztec/aztec.js';
import { siloNullifier } from '@aztec/circuits.js/hash';
import { AvmTestContract } from '@aztec/noir-contracts.js';

import { jest } from '@jest/globals';
Expand Down Expand Up @@ -51,9 +52,21 @@ describe('e2e_avm_simulator', () => {
});

describe('Nullifiers', () => {
it('Emit and check', async () => {
// Nullifier will not be siloed.
it('Emit and check in the same tx', async () => {
const tx = await avmContact.methods.emit_nullifier_and_check(123456).send().wait();
expect(tx.status).toEqual(TxStatus.MINED);
});

// Nullifier will be siloed.
it('Emit and check in separate tx', async () => {
const nullifier = new Fr(123456);
let tx = await avmContact.methods.new_nullifier(nullifier).send().wait();
expect(tx.status).toEqual(TxStatus.MINED);

const siloedNullifier = siloNullifier(avmContact.address, nullifier);
tx = await avmContact.methods.assert_nullifier_exists(siloedNullifier).send().wait();
expect(tx.status).toEqual(TxStatus.MINED);
});
});
});
5 changes: 2 additions & 3 deletions yarn-project/simulator/src/avm/journal/nullifiers.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { siloNullifier } from '@aztec/circuits.js/hash';
import { Fr } from '@aztec/foundation/fields';

import type { CommitmentsDB } from '../../index.js';
Expand Down Expand Up @@ -49,8 +48,8 @@ export class Nullifiers {
// If the value is found in the database, it will be associated with a leaf index!
let leafIndex: bigint | undefined = undefined;
if (!existsAsPending) {
// silo the nullifier before checking for its existence in the host
leafIndex = await this.hostNullifiers.getNullifierIndex(siloNullifier(storageAddress, nullifier));
// We don't silo the nullifier here, because if it's pending, it hasn't yet been siloed by the kernel.
leafIndex = await this.hostNullifiers.getNullifierIndex(nullifier);
}
const exists = existsAsPending || leafIndex !== undefined;
leafIndex = leafIndex === undefined ? BigInt(0) : leafIndex;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
L2ToL1Message,
type ReadRequest,
SideEffect,
type SideEffectLinkedToNoteHash,
SideEffectLinkedToNoteHash,
} from '@aztec/circuits.js';
import { Fr } from '@aztec/foundation/fields';

Expand Down Expand Up @@ -95,7 +95,9 @@ export function temporaryConvertAvmResults(
const nestedExecutions: PublicExecutionResult[] = [];
const nullifierReadRequests: ReadRequest[] = [];
const nullifierNonExistentReadRequests: ReadRequest[] = [];
const newNullifiers: SideEffectLinkedToNoteHash[] = [];
const newNullifiers: SideEffectLinkedToNoteHash[] = newWorldState.newNullifiers.map(
(nullifier, i) => new SideEffectLinkedToNoteHash(nullifier.toField(), Fr.zero(), new Fr(i + 1)),
);
const unencryptedLogs = UnencryptedFunctionL2Logs.empty();
const newL2ToL1Messages = newWorldState.newL1Messages.map(() => L2ToL1Message.empty());
// TODO keep track of side effect counters
Expand Down
5 changes: 3 additions & 2 deletions yellow-paper/docs/public-vm/gen/_instruction-set.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -1463,7 +1463,7 @@ Check whether a nullifier exists in the nullifier tree (including nullifiers fro
- **Flags**:
- **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`.
- **Args**:
- **nullifierOffset**: memory offset of the unsiloed nullifier
- **nullifierOffset**: memory offset of the nullifier
- **existsOffset**: memory offset specifying where to store operation's result (whether the nullifier exists)
- **Expression**:
<CodeBlock language="jsx">
Expand All @@ -1472,6 +1472,7 @@ Check whether a nullifier exists in the nullifier tree (including nullifiers fro
)
M[existsOffset] = exists`}
</CodeBlock>
- **Details**: The nullifier is expected to be _unsiloed_ if checking for nullifiers from the current transaction and _siloed_ if checking for nullifiers from previous transactions
- **World State access tracing**:
<CodeBlock language="jsx">
{`context.worldStateAccessTrace.nullifierChecks.append(
Expand All @@ -1483,7 +1484,7 @@ M[existsOffset] = exists`}
}
)`}
</CodeBlock>
- **Triggers downstream circuit operations**: Nullifier siloing (hash with storage contract address), nullifier tree membership check
- **Triggers downstream circuit operations**: Nullifier tree membership check
- **Tag updates**: `T[existsOffset] = u8`
- **Bit-size**: 88

Expand Down
5 changes: 3 additions & 2 deletions yellow-paper/src/preprocess/InstructionSet/InstructionSet.js
Original file line number Diff line number Diff line change
Expand Up @@ -911,7 +911,7 @@ context.worldStateAccessTrace.newNoteHashes.append(
{"name": "indirect", "description": INDIRECT_FLAG_DESCRIPTION},
],
"Args": [
{"name": "nullifierOffset", "description": "memory offset of the unsiloed nullifier"},
{"name": "nullifierOffset", "description": "memory offset of the nullifier"},
{"name": "existsOffset", "description": "memory offset specifying where to store operation's result (whether the nullifier exists)"},
],
"Expression": `
Expand All @@ -921,6 +921,7 @@ exists = context.worldState.nullifiers.has(
M[existsOffset] = exists
`,
"Summary": "Check whether a nullifier exists in the nullifier tree (including nullifiers from earlier in the current transaction or from earlier in the current block)",
"Details": "The nullifier is expected to be _unsiloed_ if checking for nullifiers from the current transaction and _siloed_ if checking for nullifiers from previous transactions",
"World State access tracing": `
context.worldStateAccessTrace.nullifierChecks.append(
TracedNullifierCheck {
Expand All @@ -931,7 +932,7 @@ context.worldStateAccessTrace.nullifierChecks.append(
}
)
`,
"Triggers downstream circuit operations": "Nullifier siloing (hash with storage contract address), nullifier tree membership check",
"Triggers downstream circuit operations": "Nullifier tree membership check",
"Tag checks": "",
"Tag updates": "`T[existsOffset] = u8`",
},
Expand Down

0 comments on commit a6565aa

Please sign in to comment.