Skip to content

Commit

Permalink
feat: pxe.addNullifiedNote(...)
Browse files Browse the repository at this point in the history
  • Loading branch information
benesjan committed Jun 6, 2024
1 parent eb35e62 commit ed0d5d3
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 7 deletions.
9 changes: 7 additions & 2 deletions noir-projects/aztec-nr/aztec/src/note/utils.nr
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,8 @@ pub fn compute_note_hash_and_nullifier<T, N, M, S>(
// docs:start:compute_note_hash_and_nullifier_args
deserialize_content: fn([Field; N]) -> T,
note_header: NoteHeader,
serialized_note: [Field; S] // docs:end:compute_note_hash_and_nullifier_args
serialized_note: [Field; S], // docs:end:compute_note_hash_and_nullifier_args
compute_nullifier: bool
) -> [Field; 4] where T: NoteInterface<N, M> {
let mut note = deserialize_content(arr_copy_slice(serialized_note, [0; N], 0));
// TODO: change this to note.set_header(header) once https://github.com/noir-lang/noir/issues/4095 is fixed
Expand All @@ -126,7 +127,11 @@ pub fn compute_note_hash_and_nullifier<T, N, M, S>(

let siloed_note_hash = compute_siloed_hash(note_header.contract_address, unique_note_hash);

let inner_nullifier = note.compute_nullifier_without_context();
let inner_nullifier = if compute_nullifier {
note.compute_nullifier_without_context()
} else {
0
};
// docs:start:compute_note_hash_and_nullifier_returns
[inner_note_hash, unique_note_hash, siloed_note_hash, inner_nullifier]
// docs:end:compute_note_hash_and_nullifier_returns
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,8 @@ fn generate_compute_note_hash_and_nullifier_source(
nonce: Field,
storage_slot: Field,
note_type_id: Field,
serialized_note: [Field; {}]
serialized_note: [Field; {}],
compute_nullifier: bool
) -> pub [Field; 4] {{
assert(false, \"This contract does not use private notes\");
[0, 0, 0, 0]
Expand All @@ -191,7 +192,7 @@ fn generate_compute_note_hash_and_nullifier_source(

let if_statements: Vec<String> = note_types.iter().map(|note_type| format!(
"if (note_type_id == {0}::get_note_type_id()) {{
dep::aztec::note::utils::compute_note_hash_and_nullifier({0}::deserialize_content, note_header, serialized_note)
dep::aztec::note::utils::compute_note_hash_and_nullifier({0}::deserialize_content, note_header, serialized_note, compute_nullifier)
}}"
, note_type)).collect();

Expand All @@ -209,7 +210,8 @@ fn generate_compute_note_hash_and_nullifier_source(
nonce: Field,
storage_slot: Field,
note_type_id: Field,
serialized_note: [Field; {}]
serialized_note: [Field; {}],
compute_nullifier: bool
) -> pub [Field; 4] {{
let note_header = dep::aztec::prelude::NoteHeader::new(contract_address, nonce, storage_slot);
Expand Down
3 changes: 3 additions & 0 deletions yarn-project/aztec.js/src/wallet/base_wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,9 @@ export abstract class BaseWallet implements Wallet {
addNote(note: ExtendedNote): Promise<void> {
return this.pxe.addNote(note);
}
addNullifiedNote(note: ExtendedNote): Promise<void> {
return this.pxe.addNullifiedNote(note);
}
getBlock(number: number): Promise<L2Block | undefined> {
return this.pxe.getBlock(number);
}
Expand Down
10 changes: 10 additions & 0 deletions yarn-project/circuit-types/src/interfaces/pxe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,16 @@ export interface PXE {
*/
addNote(note: ExtendedNote): Promise<void>;

/**
* Adds a nullified note to the database.
* @throws If the note hash of the note doesn't exist in the tree.
* @param note - The note to add.
* @dev We are not deriving a nullifier in this function since that would require having the nullifier secret key
* which is undesirable. Instead, we are just adding the note to the database as nullified and the nullifier is set
* to 0 in the db.
*/
addNullifiedNote(note: ExtendedNote): Promise<void>;

/**
* Get the given block.
* @param number - The block number being requested.
Expand Down
5 changes: 4 additions & 1 deletion yarn-project/pxe/src/database/incoming_note_dao.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ export class IncomingNoteDao implements NoteData {
* We can use this value to compute siloedNoteHash and uniqueSiloedNoteHash.
*/
public innerNoteHash: Fr,
/** The nullifier of the note (siloed by contract address). */
/**
* The nullifier of the note (siloed by contract address).
* Note: Might be set as 0 if the note was added to PXE as nullified.
*/
public siloedNullifier: Fr,
/** The location of the relevant note in the note hash tree. */
public index: bigint,
Expand Down
12 changes: 12 additions & 0 deletions yarn-project/pxe/src/database/kv_pxe_database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,18 @@ export class KVPxeDatabase implements PxeDatabase {
});
}

async addNullifiedNote(note: IncomingNoteDao): Promise<void> {
const noteIndex = toBufferBE(note.index, 32).toString('hex');

await this.#nullifiedNotes.set(noteIndex, note.toBuffer());
await this.#nullifiedNotesByContract.set(note.contractAddress.toString(), noteIndex);
await this.#nullifiedNotesByStorageSlot.set(note.storageSlot.toString(), noteIndex);
await this.#nullifiedNotesByTxHash.set(note.txHash.toString(), noteIndex);
await this.#nullifiedNotesByIvpkM.set(note.ivpkM.toString(), noteIndex);

return Promise.resolve();
}

async setHeader(header: Header): Promise<void> {
await this.#synchronizedBlock.set(header.toBuffer());
}
Expand Down
6 changes: 6 additions & 0 deletions yarn-project/pxe/src/database/pxe_database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ export interface PxeDatabase extends ContractArtifactDatabase, ContractInstanceD
*/
addNote(note: IncomingNoteDao): Promise<void>;

/**
* Adds a nullified note to DB.
* @param note - The note to add.
*/
addNullifiedNote(note: IncomingNoteDao): Promise<void>;

/**
* Adds an array of notes to DB.
* This function is used to insert multiple notes to the database at once,
Expand Down
48 changes: 48 additions & 0 deletions yarn-project/pxe/src/pxe_service/pxe_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,7 @@ export class PXEService implements PXE {
note.storageSlot,
note.noteTypeId,
note.note,
true,
);

const index = await this.node.findLeafIndex('latest', MerkleTreeId.NOTE_HASH_TREE, siloedNoteHash);
Expand Down Expand Up @@ -349,6 +350,53 @@ export class PXEService implements PXE {
}
}

public async addNullifiedNote(note: ExtendedNote) {
const owner = await this.db.getCompleteAddress(note.owner);
if (!owner) {
throw new Error(`Unknown account: ${note.owner.toString()}`);
}

const nonces = await this.getNoteNonces(note);
if (nonces.length === 0) {
throw new Error(`Cannot find the note in tx: ${note.txHash}.`);
}

for (const nonce of nonces) {
const { innerNoteHash, siloedNoteHash, innerNullifier } = await this.simulator.computeNoteHashAndNullifier(
note.contractAddress,
nonce,
note.storageSlot,
note.noteTypeId,
note.note,
false,
);

if (!innerNullifier.equals(Fr.ZERO)) {
throw new Error('Unexpectedly received non-zero nullifier.');
}

const index = await this.node.findLeafIndex('latest', MerkleTreeId.NOTE_HASH_TREE, siloedNoteHash);
if (index === undefined) {
throw new Error('Note does not exist.');
}

await this.db.addNullifiedNote(
new IncomingNoteDao(
note.note,
note.contractAddress,
note.storageSlot,
note.noteTypeId,
note.txHash,
nonce,
innerNoteHash,
Fr.ZERO, // We are not able to derive
index,
owner.publicKeys.masterIncomingViewingPublicKey,
),
);
}
}

/**
* Finds the nonce(s) for a given note.
* @param note - The note to find the nonces for.
Expand Down
11 changes: 10 additions & 1 deletion yarn-project/simulator/src/client/simulator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ export class AcirSimulator {
* @param storageSlot - The storage slot.
* @param noteTypeId - The note type identifier.
* @param note - The note.
* @param includeNullifier - A flag indicating whether to compute the nullifier or not.
* @returns The nullifier.
*/
public async computeNoteHashAndNullifier(
Expand All @@ -141,6 +142,7 @@ export class AcirSimulator {
storageSlot: Fr,
noteTypeId: Fr,
note: Note,
includeNullifier = true,
) {
const artifact: FunctionArtifact | undefined = await this.db.getFunctionArtifactByName(
contractAddress,
Expand Down Expand Up @@ -175,7 +177,14 @@ export class AcirSimulator {
selector: FunctionSelector.empty(),
type: FunctionType.UNCONSTRAINED,
isStatic: artifact.isStatic,
args: encodeArguments(artifact, [contractAddress, nonce, storageSlot, noteTypeId, extendedNoteItems]),
args: encodeArguments(artifact, [
contractAddress,
nonce,
storageSlot,
noteTypeId,
extendedNoteItems,
includeNullifier,
]),
returnTypes: artifact.returnTypes,
};

Expand Down

0 comments on commit ed0d5d3

Please sign in to comment.