Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
sklppy88 committed Oct 29, 2024
1 parent a00acd4 commit b4a147a
Show file tree
Hide file tree
Showing 13 changed files with 84 additions and 103 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ describe('EncryptedLogPayload', () => {

const ephSk = GrumpkinScalar.random();

encrypted = original.encrypt(ephSk, completeAddress.address, computePoint(completeAddress.address), ovKeys);
encrypted = original.encrypt(ephSk, completeAddress.address, ovKeys);
});

it('decrypt a log as incoming', () => {
Expand Down Expand Up @@ -122,9 +122,7 @@ describe('EncryptedLogPayload', () => {
'0x25afb798ea6d0b8c1618e50fdeafa463059415013d3b7c75d46abf5e242be70c138af8799f2fba962549802469e12e3b7ba4c5f9c999c6421e05c73f45ec68481970dd8ce0250b677759dfc040f6edaf77c5827a7bcd425e66bcdec3fa7e59bc18dd22d6a4032eefe3a7a55703f583396596235f7c186e450c92981186ee74042e49e00996565114016a1a478309842ecbaf930fb716c3f498e7e10370631d7507f696b8b233de2c1935e43c793399586f532da5ff7c0356636a75acb862e964156e8a3e42bfca3663936ba98c7fd26386a14657c23b5f5146f1a94b6c4651542685ea16f17c580a7cc7c8ff2688dce9bde8bf1f50475f4c3281e1c33404ee0025f50db0733f719462b22eff03cec746bb9e3829ae3636c84fbccd2754b5a5a92087a5f41ccf94a03a2671cd341ba3264c45147e75d4ea96e3b1a58498550b89',
);

const encrypted = log
.encrypt(ephSk, recipientCompleteAddress.address, computePoint(recipientCompleteAddress.address), ovKeys)
.toString('hex');
const encrypted = log.encrypt(ephSk, recipientCompleteAddress.address, ovKeys).toString('hex');
expect(encrypted).toMatchInlineSnapshot(
`"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008d460c0e434d846ec1ea286e4090eb56376ff27bddc1aacae1d856549f701fa70577790aeabcc2d81ec8d0c99e7f5d2bf2f1452025dc777a178404f851d93de818923f85187871d99bdf95d695eff0a9e09ba15153fc9b4d224b6e1e71dfbdcaab06c09d5b3c749bfebe1c0407eccd04f51bbb59142680c8a091b97fc6cbcf61f6c2af9b8ebc8f78537ab23fd0c5e818e4d42d459d265adb77c2ef829bf68f87f2c47b478bb57ae7e41a07643f65c353083d557b94e31da4a2a13127498d2eb3f0346da5eed2e9bc245aaf022a954ed0b09132b498f537702899b44e3666776238ebf633b3562d7f124dbba82918e871958a94218fd796bc6983feecc7ce382c82861d63fe45999244ea9494b226ddb694b2640dce005b473acf1ae3be158f558ad1ca228e9f793d09390230a2597e0e53ad28f7aa9a700ccc302607ad6c26ea1410735b6a8c793f6317f7009409a3912b15ee2f28ccf17cf6c94b720301e5c5826de39e85bc7db3dc33aa79afcaf325670d1b359d08b10bd07840d394c9f038"`,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
Point,
type PublicKey,
computeOvskApp,
computePoint,
derivePublicKeyFromSecretKey,
} from '@aztec/circuits.js';
import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
Expand Down Expand Up @@ -45,18 +46,11 @@ export class EncryptedLogPayload {
public readonly incomingBodyPlaintext: Buffer,
) {}

public encrypt(
ephSk: GrumpkinScalar,
recipient: AztecAddress,
ivpk: PublicKey,
ovKeys: KeyValidationRequest,
): Buffer {
if (ivpk.isZero()) {
throw new Error(`Attempting to encrypt an event log with a zero ivpk.`);
}
public encrypt(ephSk: GrumpkinScalar, recipient: AztecAddress, ovKeys: KeyValidationRequest): Buffer {
const addressPoint = computePoint(recipient);

const ephPk = derivePublicKeyFromSecretKey(ephSk);
const incomingHeaderCiphertext = encrypt(this.contractAddress.toBuffer(), ephSk, ivpk);
const incomingHeaderCiphertext = encrypt(this.contractAddress.toBuffer(), ephSk, addressPoint);
const outgoingHeaderCiphertext = encrypt(this.contractAddress.toBuffer(), ephSk, ovKeys.pkM);

if (incomingHeaderCiphertext.length !== HEADER_SIZE) {
Expand All @@ -66,9 +60,9 @@ export class EncryptedLogPayload {
throw new Error(`Invalid outgoing header size: ${outgoingHeaderCiphertext.length}`);
}

const incomingBodyCiphertext = encrypt(this.incomingBodyPlaintext, ephSk, ivpk);
const incomingBodyCiphertext = encrypt(this.incomingBodyPlaintext, ephSk, addressPoint);
// The serialization of Fq is [high, low] check `outgoing_body.nr`
const outgoingBodyPlaintext = serializeToBuffer(ephSk.hi, ephSk.lo, recipient, ivpk.toCompressedBuffer());
const outgoingBodyPlaintext = serializeToBuffer(ephSk.hi, ephSk.lo, recipient, addressPoint.toCompressedBuffer());
const outgoingBodyCiphertext = encrypt(
outgoingBodyPlaintext,
ovKeys.skAppAsGrumpkinScalar,
Expand All @@ -94,18 +88,18 @@ export class EncryptedLogPayload {
/**
* Decrypts a ciphertext as an incoming log.
*
* This is executable by the recipient of the note, and uses the ivsk to decrypt the payload.
* This is executable by the recipient of the note, and uses the addressSecret to decrypt the payload.
* The outgoing parts of the log are ignored entirely.
*
* Produces the same output as `decryptAsOutgoing`.
*
* @param ciphertext - The ciphertext for the log
* @param ivsk - The incoming viewing secret key, used to decrypt the logs
* @param addressSecret - The incoming viewing secret key, used to decrypt the logs
* @returns The decrypted log payload
*/
public static decryptAsIncoming(
ciphertext: Buffer | BufferReader,
ivsk: GrumpkinScalar,
addressSecret: GrumpkinScalar,
): EncryptedLogPayload | undefined {
const reader = BufferReader.asReader(ciphertext);

Expand All @@ -115,14 +109,14 @@ export class EncryptedLogPayload {

const ephPk = Point.fromCompressedBuffer(reader.readBytes(Point.COMPRESSED_SIZE_IN_BYTES));

const incomingHeader = decrypt(reader.readBytes(HEADER_SIZE), ivsk, ephPk);
const incomingHeader = decrypt(reader.readBytes(HEADER_SIZE), addressSecret, ephPk);

// Skipping the outgoing header and body
reader.readBytes(HEADER_SIZE);
reader.readBytes(OUTGOING_BODY_SIZE);

// The incoming can be of variable size, so we read until the end
const incomingBodyPlaintext = decrypt(reader.readToEnd(), ivsk, ephPk);
const incomingBodyPlaintext = decrypt(reader.readToEnd(), addressSecret, ephPk);

return new EncryptedLogPayload(
incomingTag,
Expand Down Expand Up @@ -180,19 +174,19 @@ export class EncryptedLogPayload {
const ovskApp = computeOvskApp(ovsk, contractAddress);

let ephSk: GrumpkinScalar;
let recipientIvpk: PublicKey;
let recipientAddressPoint: PublicKey;
{
const outgoingBody = decrypt(reader.readBytes(OUTGOING_BODY_SIZE), ovskApp, ephPk, derivePoseidonAESSecret);
const obReader = BufferReader.asReader(outgoingBody);

// From outgoing body we extract ephSk, recipient and recipientIvpk
// From outgoing body we extract ephSk, recipient and recipientAddressPoint
ephSk = GrumpkinScalar.fromHighLow(obReader.readObject(Fr), obReader.readObject(Fr));
const _recipient = obReader.readObject(AztecAddress);
recipientIvpk = Point.fromCompressedBuffer(obReader.readBytes(Point.COMPRESSED_SIZE_IN_BYTES));
recipientAddressPoint = Point.fromCompressedBuffer(obReader.readBytes(Point.COMPRESSED_SIZE_IN_BYTES));
}

// Now we decrypt the incoming body using the ephSk and recipientIvpk
const incomingBody = decrypt(reader.readToEnd(), ephSk, recipientIvpk);
// Now we decrypt the incoming body using the ephSk and recipientAddressPoint
const incomingBody = decrypt(reader.readToEnd(), ephSk, recipientAddressPoint);

return new EncryptedLogPayload(incomingTag, outgoingTag, contractAddress, incomingBody);
} catch (e: any) {
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/pxe/src/database/deferred_note_dao.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
*/
export class DeferredNoteDao {
constructor(
/** IvpkM or OvpkM (depending on if incoming or outgoing) the note was encrypted with. */
/** Address Point or OvpkM (depending on if incoming or outgoing) the note was encrypted with. */
public publicKey: PublicKey,
/** The note payload delivered via L1. */
public payload: L1NotePayload,
Expand Down
4 changes: 2 additions & 2 deletions yarn-project/pxe/src/database/incoming_note_dao.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const randomIncomingNoteDao = ({
noteHash = Fr.random(),
siloedNullifier = Fr.random(),
index = Fr.random().toBigInt(),
ivpkM = Point.random(),
addressPoint = Point.random(),
}: Partial<IncomingNoteDao> = {}) => {
return new IncomingNoteDao(
note,
Expand All @@ -26,7 +26,7 @@ export const randomIncomingNoteDao = ({
noteHash,
siloedNullifier,
index,
ivpkM,
addressPoint,
);
};

Expand Down
8 changes: 4 additions & 4 deletions yarn-project/pxe/src/database/incoming_note_dao.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,15 @@ export class IncomingNoteDao implements NoteData {
/** The location of the relevant note in the note hash tree. */
public index: bigint,
/** The public key with which the note was encrypted. */
public ivpkM: PublicKey,
public addressPoint: PublicKey,
) {}

static fromPayloadAndNoteInfo(
note: Note,
payload: L1NotePayload,
noteInfo: NoteInfo,
dataStartIndexForTx: number,
ivpkM: PublicKey,
addressPoint: PublicKey,
) {
const noteHashIndexInTheWholeTree = BigInt(dataStartIndexForTx + noteInfo.noteHashIndex);
return new IncomingNoteDao(
Expand All @@ -58,7 +58,7 @@ export class IncomingNoteDao implements NoteData {
noteInfo.noteHash,
noteInfo.siloedNullifier,
noteHashIndexInTheWholeTree,
ivpkM,
addressPoint,
);
}

Expand All @@ -73,7 +73,7 @@ export class IncomingNoteDao implements NoteData {
this.noteHash,
this.siloedNullifier,
this.index,
this.ivpkM,
this.addressPoint,
]);
}
static fromBuffer(buffer: Buffer | BufferReader) {
Expand Down
15 changes: 7 additions & 8 deletions yarn-project/pxe/src/database/kv_pxe_database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
type ContractInstanceWithAddress,
Header,
SerializableContractInstance,
computePoint,
} from '@aztec/circuits.js';
import { type ContractArtifact } from '@aztec/foundation/abi';
import { toBufferBE } from '@aztec/foundation/bigint-buffer';
Expand Down Expand Up @@ -197,7 +198,7 @@ export class KVPxeDatabase implements PxeDatabase {
void this.#notesByContractAndScope.get(scope.toString())!.set(dao.contractAddress.toString(), noteIndex);
void this.#notesByStorageSlotAndScope.get(scope.toString())!.set(dao.storageSlot.toString(), noteIndex);
void this.#notesByTxHashAndScope.get(scope.toString())!.set(dao.txHash.toString(), noteIndex);
void this.#notesByIvpkMAndScope.get(scope.toString())!.set(dao.ivpkM.toString(), noteIndex);
void this.#notesByIvpkMAndScope.get(scope.toString())!.set(dao.addressPoint.toString(), noteIndex);
}

for (const dao of outgoingNotes) {
Expand Down Expand Up @@ -262,9 +263,7 @@ export class KVPxeDatabase implements PxeDatabase {
}

getIncomingNotes(filter: IncomingNotesFilter): Promise<IncomingNoteDao[]> {
const publicKey: PublicKey | undefined = filter.owner
? this.#getCompleteAddress(filter.owner)?.publicKeys.masterIncomingViewingPublicKey
: undefined;
const publicKey: PublicKey | undefined = filter.owner ? computePoint(filter.owner) : undefined;

filter.status = filter.status ?? NoteStatus.ACTIVE;

Expand Down Expand Up @@ -334,7 +333,7 @@ export class KVPxeDatabase implements PxeDatabase {
continue;
}

if (publicKey && !note.ivpkM.equals(publicKey)) {
if (publicKey && !note.addressPoint.equals(publicKey)) {
continue;
}

Expand Down Expand Up @@ -421,7 +420,7 @@ export class KVPxeDatabase implements PxeDatabase {
}

const note = IncomingNoteDao.fromBuffer(noteBuffer);
if (!note.ivpkM.equals(accountIvpkM)) {
if (!note.addressPoint.equals(accountIvpkM)) {
// tried to nullify someone else's note
continue;
}
Expand All @@ -441,7 +440,7 @@ export class KVPxeDatabase implements PxeDatabase {
void this.#nullifiedNotesByContract.set(note.contractAddress.toString(), noteIndex);
void this.#nullifiedNotesByStorageSlot.set(note.storageSlot.toString(), noteIndex);
void this.#nullifiedNotesByTxHash.set(note.txHash.toString(), noteIndex);
void this.#nullifiedNotesByIvpkM.set(note.ivpkM.toString(), noteIndex);
void this.#nullifiedNotesByIvpkM.set(note.addressPoint.toString(), noteIndex);

void this.#nullifierToNoteId.delete(nullifier.toString());
}
Expand All @@ -457,7 +456,7 @@ export class KVPxeDatabase implements PxeDatabase {
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);
await this.#nullifiedNotesByIvpkM.set(note.addressPoint.toString(), noteIndex);

return Promise.resolve();
}
Expand Down
4 changes: 2 additions & 2 deletions yarn-project/pxe/src/database/outgoing_note_dao.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export class OutgoingNoteDao {
payload: L1NotePayload,
noteInfo: NoteInfo,
dataStartIndexForTx: number,
ivpkM: PublicKey,
ovpkM: PublicKey,
) {
const noteHashIndexInTheWholeTree = BigInt(dataStartIndexForTx + noteInfo.noteHashIndex);
return new OutgoingNoteDao(
Expand All @@ -51,7 +51,7 @@ export class OutgoingNoteDao {
noteInfo.nonce,
noteInfo.noteHash,
noteHashIndexInTheWholeTree,
ivpkM,
ovpkM,
);
}

Expand Down
32 changes: 12 additions & 20 deletions yarn-project/pxe/src/database/pxe_database_test_suite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
INITIAL_L2_BLOCK_NUM,
PublicKeys,
SerializableContractInstance,
computePoint,
} from '@aztec/circuits.js';
import { makeHeader } from '@aztec/circuits.js/testing';
import { randomInt } from '@aztec/foundation/crypto';
Expand Down Expand Up @@ -101,7 +102,7 @@ export function describePxeDatabase(getDatabase: () => PxeDatabase) {

[
() => ({ owner: owners[0].address }),
() => notes.filter(note => note.ivpkM.equals(owners[0].publicKeys.masterIncomingViewingPublicKey)),
() => notes.filter(note => note.addressPoint.equals(computePoint(owners[0].address))),
],

[
Expand All @@ -123,7 +124,7 @@ export function describePxeDatabase(getDatabase: () => PxeDatabase) {
randomIncomingNoteDao({
contractAddress: contractAddresses[i % contractAddresses.length],
storageSlot: storageSlots[i % storageSlots.length],
ivpkM: owners[i % owners.length].publicKeys.masterIncomingViewingPublicKey,
addressPoint: computePoint(owners[i % owners.length].address),
index: BigInt(i),
}),
);
Expand Down Expand Up @@ -155,13 +156,11 @@ export function describePxeDatabase(getDatabase: () => PxeDatabase) {

// Nullify all notes and use the same filter as other test cases
for (const owner of owners) {
const notesToNullify = notes.filter(note =>
note.ivpkM.equals(owner.publicKeys.masterIncomingViewingPublicKey),
);
const notesToNullify = notes.filter(note => note.addressPoint.equals(computePoint(owner.address)));
const nullifiers = notesToNullify.map(note => note.siloedNullifier);
await expect(
database.removeNullifiedNotes(nullifiers, owner.publicKeys.masterIncomingViewingPublicKey),
).resolves.toEqual(notesToNullify);
await expect(database.removeNullifiedNotes(nullifiers, computePoint(owner.address))).resolves.toEqual(
notesToNullify,
);
}

await expect(
Expand All @@ -172,11 +171,9 @@ export function describePxeDatabase(getDatabase: () => PxeDatabase) {
it('skips nullified notes by default or when requesting active', async () => {
await database.addNotes(notes, []);

const notesToNullify = notes.filter(note =>
note.ivpkM.equals(owners[0].publicKeys.masterIncomingViewingPublicKey),
);
const notesToNullify = notes.filter(note => note.addressPoint.equals(computePoint(owners[0].address)));
const nullifiers = notesToNullify.map(note => note.siloedNullifier);
await expect(database.removeNullifiedNotes(nullifiers, notesToNullify[0].ivpkM)).resolves.toEqual(
await expect(database.removeNullifiedNotes(nullifiers, notesToNullify[0].addressPoint)).resolves.toEqual(
notesToNullify,
);

Expand All @@ -190,11 +187,9 @@ export function describePxeDatabase(getDatabase: () => PxeDatabase) {
it('returns active and nullified notes when requesting either', async () => {
await database.addNotes(notes, []);

const notesToNullify = notes.filter(note =>
note.ivpkM.equals(owners[0].publicKeys.masterIncomingViewingPublicKey),
);
const notesToNullify = notes.filter(note => note.addressPoint.equals(computePoint(owners[0].address)));
const nullifiers = notesToNullify.map(note => note.siloedNullifier);
await expect(database.removeNullifiedNotes(nullifiers, notesToNullify[0].ivpkM)).resolves.toEqual(
await expect(database.removeNullifiedNotes(nullifiers, notesToNullify[0].addressPoint)).resolves.toEqual(
notesToNullify,
);

Expand Down Expand Up @@ -251,10 +246,7 @@ export function describePxeDatabase(getDatabase: () => PxeDatabase) {
).resolves.toEqual([notes[0]]);

await expect(
database.removeNullifiedNotes(
[notes[0].siloedNullifier],
owners[0].publicKeys.masterIncomingViewingPublicKey,
),
database.removeNullifiedNotes([notes[0].siloedNullifier], computePoint(owners[0].address)),
).resolves.toEqual([notes[0]]);

await expect(
Expand Down
Loading

0 comments on commit b4a147a

Please sign in to comment.