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

feat!: PXE.getNotes(...) + refactor of note types #3051

Merged
merged 42 commits into from
Oct 30, 2023
Merged
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
a2741ae
WIP
benesjan Oct 26, 2023
81c5b0a
random tx hash mock
benesjan Oct 26, 2023
0ee21d6
WIP
benesjan Oct 26, 2023
f036951
WIP
benesjan Oct 26, 2023
7a5f16f
WIP
benesjan Oct 26, 2023
724d6cd
fix
benesjan Oct 26, 2023
d3f6488
fix
benesjan Oct 26, 2023
06ba890
serialization test
benesjan Oct 26, 2023
826aa1a
including notes in receipt
benesjan Oct 26, 2023
6b2de27
checking whether the a note wsa created using getNotes
benesjan Oct 26, 2023
5724b82
fix
benesjan Oct 26, 2023
29102c7
refactor: NoteSpendingInfoDao --> ExtendedNote
benesjan Oct 26, 2023
d44fb9c
refactor: NoteSpendingInfo -> L1NotePayload
benesjan Oct 26, 2023
24e5301
cleanup
benesjan Oct 26, 2023
8fbefe1
cleanup 2
benesjan Oct 26, 2023
2dab843
refactor: NotePreimage --> Note
benesjan Oct 26, 2023
d3c9722
WIP
benesjan Oct 26, 2023
78393ee
WIP on renaming preimage
benesjan Oct 27, 2023
75dbb5e
WIP
benesjan Oct 27, 2023
445309f
fixes
benesjan Oct 27, 2023
7424dcd
naming fixes
benesjan Oct 27, 2023
1f0d5f4
WIP
benesjan Oct 27, 2023
c1100be
WIP
benesjan Oct 27, 2023
becd6b6
fix
benesjan Oct 27, 2023
47df975
formatting fixes
benesjan Oct 27, 2023
be5e7af
fixes
benesjan Oct 27, 2023
f7c194c
reverting stupid changes
benesjan Oct 27, 2023
dc3522e
cspell
benesjan Oct 27, 2023
8e91d65
reverting unnecessary changes to artifacts
benesjan Oct 27, 2023
b5b346e
fixes
benesjan Oct 27, 2023
1e91d0d
fixes
benesjan Oct 27, 2023
942f861
fix
benesjan Oct 27, 2023
9c9039a
Update yarn-project/pxe/src/database/note_dao.ts
benesjan Oct 30, 2023
9feecb8
Merge branch 'master' into janb/pxe-get-notes
benesjan Oct 30, 2023
c90ce28
fixes after merge
benesjan Oct 30, 2023
a17e9ea
wait options check
benesjan Oct 30, 2023
4a8d7cb
typos
benesjan Oct 30, 2023
9abab92
updated NoteDao.getSize
benesjan Oct 30, 2023
a0663a4
formatting fix
benesjan Oct 30, 2023
14f3a6d
fix addPendingShieldNoteToPXE
benesjan Oct 30, 2023
5ebb99c
fix
benesjan Oct 30, 2023
c68f24d
fix
benesjan Oct 30, 2023
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
1 change: 1 addition & 0 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"barretenberg",
"bbfree",
"bbmalloc",
"benesjan",
"bodyparser",
"bootnode",
"Brillig",
Expand Down
24 changes: 12 additions & 12 deletions yarn-project/acir-simulator/src/acvm/oracle/oracle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export class Oracle {
[offset]: ACVMField[],
[returnSize]: ACVMField[],
): Promise<ACVMField[]> {
const notes = await this.typedOracle.getNotes(
const noteDatas = await this.typedOracle.getNotes(
fromACVMField(storageSlot),
+numSelects,
selectBy.map(s => +s),
Expand All @@ -75,26 +75,26 @@ export class Oracle {
+offset,
);

const preimageLength = notes?.[0]?.preimage.length ?? 0;
if (!notes.every(({ preimage }) => preimageLength === preimage.length)) {
throw new Error('Preimages for a particular note type should all be the same length.');
const noteLength = noteDatas?.[0]?.note.items.length ?? 0;
if (!noteDatas.every(({ note }) => noteLength === note.items.length)) {
throw new Error('Notes should all be the same length.');
}

const contractAddress = notes[0]?.contractAddress ?? Fr.ZERO;
const contractAddress = noteDatas[0]?.contractAddress ?? Fr.ZERO;

// Values indicates whether the note is settled or transient.
const noteTypes = {
isSettled: new Fr(0),
isTransient: new Fr(1),
};
const flattenData = notes.flatMap(({ nonce, preimage, index }) => [
const flattenData = noteDatas.flatMap(({ nonce, note, index }) => [
nonce,
index === undefined ? noteTypes.isTransient : noteTypes.isSettled,
...preimage,
...note.items,
]);

const returnFieldSize = +returnSize;
const returnData = [notes.length, contractAddress, ...flattenData].map(v => toACVMField(v));
const returnData = [noteDatas.length, contractAddress, ...flattenData].map(v => toACVMField(v));
if (returnData.length > returnFieldSize) {
throw new Error(`Return data size too big. Maximum ${returnFieldSize} fields. Got ${flattenData.length}.`);
}
Expand All @@ -103,10 +103,10 @@ export class Oracle {
return returnData.concat(paddedZeros);
}

notifyCreatedNote([storageSlot]: ACVMField[], preimage: ACVMField[], [innerNoteHash]: ACVMField[]): ACVMField {
notifyCreatedNote([storageSlot]: ACVMField[], note: ACVMField[], [innerNoteHash]: ACVMField[]): ACVMField {
this.typedOracle.notifyCreatedNote(
fromACVMField(storageSlot),
preimage.map(fromACVMField),
note.map(fromACVMField),
fromACVMField(innerNoteHash),
);
return toACVMField(0);
Expand Down Expand Up @@ -148,14 +148,14 @@ export class Oracle {
[storageSlot]: ACVMField[],
[publicKeyX]: ACVMField[],
[publicKeyY]: ACVMField[],
preimage: ACVMField[],
log: ACVMField[],
): ACVMField {
const publicKey = new Point(fromACVMField(publicKeyX), fromACVMField(publicKeyY));
this.typedOracle.emitEncryptedLog(
AztecAddress.fromString(contractAddress),
Fr.fromString(storageSlot),
publicKey,
preimage.map(fromACVMField),
log.map(fromACVMField),
);
return toACVMField(0);
}
Expand Down
10 changes: 5 additions & 5 deletions yarn-project/acir-simulator/src/acvm/oracle/typed_oracle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,20 @@ import { FunctionSelector } from '@aztec/foundation/abi';
import { AztecAddress } from '@aztec/foundation/aztec-address';
import { EthAddress } from '@aztec/foundation/eth-address';
import { Fr, GrumpkinScalar } from '@aztec/foundation/fields';
import { CompleteAddress, PublicKey, UnencryptedL2Log } from '@aztec/types';
import { CompleteAddress, Note, PublicKey, UnencryptedL2Log } from '@aztec/types';

/**
* Information about a note needed during execution.
*/
export interface NoteData {
/** The note. */
note: Note;
/** The contract address of the note. */
contractAddress: AztecAddress;
/** The storage slot of the note. */
storageSlot: Fr;
/** The nonce of the note. */
nonce: Fr;
/** The preimage of the note */
preimage: Fr[];
/** The inner note hash of the note. */
innerNoteHash: Fr;
/** The corresponding nullifier of the note. Undefined for pending notes. */
Expand Down Expand Up @@ -93,7 +93,7 @@ export abstract class TypedOracle {
throw new Error('Not available.');
}

notifyCreatedNote(_storageSlot: Fr, _preimage: Fr[], _innerNoteHash: Fr): void {
notifyCreatedNote(_storageSlot: Fr, _note: Fr[], _innerNoteHash: Fr): void {
throw new Error('Not available.');
}

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

emitEncryptedLog(_contractAddress: AztecAddress, _storageSlot: Fr, _publicKey: PublicKey, _preimage: Fr[]): void {
emitEncryptedLog(_contractAddress: AztecAddress, _storageSlot: Fr, _publicKey: PublicKey, _log: Fr[]): void {
throw new Error('Not available.');
}

Expand Down
45 changes: 19 additions & 26 deletions yarn-project/acir-simulator/src/client/client_execution_context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { FunctionAbi, FunctionArtifact, countArgumentsSize } from '@aztec/founda
import { AztecAddress } from '@aztec/foundation/aztec-address';
import { Fr, Point } from '@aztec/foundation/fields';
import { createDebugLogger } from '@aztec/foundation/log';
import { AuthWitness, FunctionL2Logs, NotePreimage, NoteSpendingInfo, UnencryptedL2Log } from '@aztec/types';
import { AuthWitness, FunctionL2Logs, L1NotePayload, Note, UnencryptedL2Log } from '@aztec/types';

import {
NoteData,
Expand All @@ -28,7 +28,7 @@ import { SideEffectCounter } from '../common/index.js';
import { PackedArgsCache } from '../common/packed_args_cache.js';
import { DBOracle } from './db_oracle.js';
import { ExecutionNoteCache } from './execution_note_cache.js';
import { ExecutionResult, NewNoteData } from './execution_result.js';
import { ExecutionResult, NoteAndSlot } from './execution_result.js';
import { pickNotes } from './pick_notes.js';
import { executePrivateFunction } from './private_execution.js';
import { ViewDataOracle } from './view_data_oracle.js';
Expand All @@ -44,7 +44,7 @@ export class ClientExecutionContext extends ViewDataOracle {
* This information is only for references (currently used for tests), and is not used for any sort of constrains.
* Users can also use this to get a clearer idea of what's happened during a simulation.
*/
private newNotes: NewNoteData[] = [];
private newNotes: NoteAndSlot[] = [];
/**
* Notes from previous transactions that are returned to the oracle call `getNotes` during this execution.
* The mapping maps from the unique siloed note hash to the index for notes created in private executions.
Expand Down Expand Up @@ -135,7 +135,7 @@ export class ClientExecutionContext extends ViewDataOracle {
* Get the data for the newly created notes.
* @param innerNoteHashes - Inner note hashes for the notes.
*/
public getNewNotes(): NewNoteData[] {
public getNewNotes(): NoteAndSlot[] {
return this.newNotes;
}

Expand Down Expand Up @@ -176,16 +176,13 @@ export class ClientExecutionContext extends ViewDataOracle {
}

/**
* Gets some notes for a contract address and storage slot.
* Returns a flattened array containing real-note-count and note preimages.
* Gets some notes for a storage slot.
*
* @remarks
*
* Check for pending notes with matching address/slot.
* Check for pending notes with matching slot.
* Real notes coming from DB will have a leafIndex which
* represents their index in the note hash tree.
*
* @param contractAddress - The contract address.
* @param storageSlot - The storage slot.
* @param numSelects - The number of valid selects in selectBy and selectValues.
* @param selectBy - An array of indices of the fields to selects.
Expand All @@ -194,12 +191,7 @@ export class ClientExecutionContext extends ViewDataOracle {
* @param sortOrder - The order of the corresponding index in sortBy. (1: DESC, 2: ASC, 0: Do nothing)
* @param limit - The number of notes to retrieve per query.
* @param offset - The starting index for pagination.
* @param returnSize - The return size.
* @returns Flattened array of ACVMFields (format expected by Noir/ACVM) containing:
* count - number of real (non-padding) notes retrieved,
* contractAddress - the contract address,
* preimages - the real note preimages retrieved, and
* paddedZeros - zeros to ensure an array with length returnSize expected by Noir circuit
* @returns Array of note data.
*/
public async getNotes(
storageSlot: Fr,
Expand Down Expand Up @@ -227,7 +219,7 @@ export class ClientExecutionContext extends ViewDataOracle {

this.log(
`Returning ${notes.length} notes for ${this.contractAddress} at ${storageSlot}: ${notes
.map(n => `${n.nonce.toString()}:[${n.preimage.map(i => i.toString()).join(',')}]`)
.map(n => `${n.nonce.toString()}:[${n.note.items.map(i => i.toString()).join(',')}]`)
.join(', ')}`,
);

Expand All @@ -251,22 +243,23 @@ export class ClientExecutionContext extends ViewDataOracle {
* It can be used in subsequent calls (or transactions when chaining txs is possible).
* @param contractAddress - The contract address.
* @param storageSlot - The storage slot.
* @param preimage - The preimage of the new note.
* @param noteItems - The items to be included in a Note.
* @param innerNoteHash - The inner note hash of the new note.
* @returns
*/
public notifyCreatedNote(storageSlot: Fr, preimage: Fr[], innerNoteHash: Fr) {
public notifyCreatedNote(storageSlot: Fr, noteItems: Fr[], innerNoteHash: Fr) {
const note = new Note(noteItems);
this.noteCache.addNewNote({
contractAddress: this.contractAddress,
storageSlot,
nonce: Fr.ZERO, // Nonce cannot be known during private execution.
preimage,
note,
siloedNullifier: undefined, // Siloed nullifier cannot be known for newly created note.
innerNoteHash,
});
this.newNotes.push({
storageSlot,
preimage,
note,
});
}

Expand All @@ -285,13 +278,13 @@ export class ClientExecutionContext extends ViewDataOracle {
* @param contractAddress - The contract address of the note.
* @param storageSlot - The storage slot the note is at.
* @param publicKey - The public key of the account that can decrypt the log.
* @param preimage - The preimage of the note.
* @param log - The log contents.
*/
public emitEncryptedLog(contractAddress: AztecAddress, storageSlot: Fr, publicKey: Point, preimage: Fr[]) {
const notePreimage = new NotePreimage(preimage);
const noteSpendingInfo = new NoteSpendingInfo(notePreimage, contractAddress, storageSlot);
const encryptedNotePreimage = noteSpendingInfo.toEncryptedBuffer(publicKey, this.curve);
this.encryptedLogs.push(encryptedNotePreimage);
public emitEncryptedLog(contractAddress: AztecAddress, storageSlot: Fr, publicKey: Point, log: Fr[]) {
const note = new Note(log);
const l1NotePayload = new L1NotePayload(note, contractAddress, storageSlot);
const encryptedNote = l1NotePayload.toEncryptedBuffer(publicKey, this.curve);
this.encryptedLogs.push(encryptedNote);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/acir-simulator/src/client/db_oracle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export interface DBOracle extends CommitmentsDB {
/**
* Retrieves a set of notes stored in the database for a given contract address and storage slot.
* The query result is paginated using 'limit' and 'offset' values.
* Returns an object containing an array of note data, including preimage, nonce, and index for each note.
* Returns an object containing an array of note data.
*
* @param contractAddress - The AztecAddress instance representing the contract address.
* @param storageSlot - The Fr instance representing the storage slot of the notes.
Expand Down
10 changes: 5 additions & 5 deletions yarn-project/acir-simulator/src/client/execution_result.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { PrivateCallStackItem, PublicCallRequest, ReadRequestMembershipWitness } from '@aztec/circuits.js';
import { DecodedReturn } from '@aztec/foundation/abi';
import { Fr } from '@aztec/foundation/fields';
import { FunctionL2Logs } from '@aztec/types';
import { FunctionL2Logs, Note } from '@aztec/types';

import { ACVMField } from '../acvm/index.js';

/**
* The contents of a new note.
*/
export interface NewNoteData {
/** The preimage of the note. */
preimage: Fr[];
export interface NoteAndSlot {
/** The note. */
note: Note;
/** The storage slot of the note. */
storageSlot: Fr;
}
Expand All @@ -33,7 +33,7 @@ export interface ExecutionResult {
readRequestPartialWitnesses: ReadRequestMembershipWitness[];
// Needed when we enable chained txs. The new notes can be cached and used in a later transaction.
/** The notes created in the executed function. */
newNotes: NewNoteData[];
newNotes: NoteAndSlot[];
/** The decoded return values of the executed function. */
returnValues: DecodedReturn;
/** The nested executions. */
Expand Down
13 changes: 7 additions & 6 deletions yarn-project/acir-simulator/src/client/pick_notes.test.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
import { Fr } from '@aztec/foundation/fields';
import { Note } from '@aztec/types';

import { SortOrder, pickNotes } from './pick_notes.js';

describe('getNotes', () => {
const expectNotesFields = (notes: { preimage: Fr[] }[], ...expected: [number, bigint[]][]) => {
const expectNotesFields = (notes: { note: Note }[], ...expected: [number, bigint[]][]) => {
expect(notes.length).toBe(expected[0][1].length);
expected.forEach(([fieldIndex, fields]) => {
for (let i = 0; i < notes.length; ++i) {
expect(notes[i].preimage[fieldIndex].value).toBe(fields[i]);
expect(notes[i].note.items[fieldIndex].value).toBe(fields[i]);
}
});
};

const expectNotes = (notes: { preimage: Fr[] }[], expected: bigint[][]) => {
const expectNotes = (notes: { note: Note }[], expected: bigint[][]) => {
expect(notes.length).toBe(expected.length);
notes.forEach((note, i) => {
expect(note.preimage.map(p => p.value)).toEqual(expected[i]);
expect(note.note.items.map(p => p.value)).toEqual(expected[i]);
});
};

const createNote = (preimage: bigint[]) => ({
preimage: preimage.map(f => new Fr(f)),
const createNote = (items: bigint[]) => ({
note: new Note(items.map(f => new Fr(f))),
});

it('should get sorted notes', () => {
Expand Down
21 changes: 11 additions & 10 deletions yarn-project/acir-simulator/src/client/pick_notes.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Fr } from '@aztec/foundation/fields';
import { Note } from '@aztec/types';

/**
* Configuration for selecting values.
Expand Down Expand Up @@ -64,17 +65,17 @@ interface GetOptions {
}

/**
* Basic data needed from a note to perform sort.
* Data needed from to perform sort.
*/
interface BasicNoteData {
interface ContainsNote {
/**
* Preimage of a note.
* The note.
*/
preimage: Fr[];
note: Note;
}

const selectNotes = <T extends BasicNoteData>(notes: T[], selects: Select[]): T[] =>
notes.filter(note => selects.every(({ index, value }) => note.preimage[index]?.equals(value)));
const selectNotes = <T extends ContainsNote>(noteDatas: T[], selects: Select[]): T[] =>
noteDatas.filter(noteData => selects.every(({ index, value }) => noteData.note.items[index]?.equals(value)));

const sortNotes = (a: Fr[], b: Fr[], sorts: Sort[], level = 0): number => {
if (sorts[level] === undefined) return 0;
Expand All @@ -93,11 +94,11 @@ const sortNotes = (a: Fr[], b: Fr[], sorts: Sort[], level = 0): number => {
/**
* Pick from a note array a number of notes that meet the criteria.
*/
export function pickNotes<T extends BasicNoteData>(
notes: T[],
export function pickNotes<T extends ContainsNote>(
noteDatas: T[],
{ selects = [], sorts = [], limit = 0, offset = 0 }: GetOptions,
): T[] {
return selectNotes(notes, selects)
.sort((a, b) => sortNotes(a.preimage, b.preimage, sorts))
return selectNotes(noteDatas, selects)
.sort((a, b) => sortNotes(a.note.items, b.note.items, sorts))
.slice(offset, limit ? offset + limit : undefined);
}
Loading