diff --git a/yarn-project/aztec-rpc/src/aztec_rpc_server/note_preimage/index.ts b/yarn-project/aztec-rpc/src/aztec_rpc_server/note_preimage/index.ts deleted file mode 100644 index 9f87e68e478..00000000000 --- a/yarn-project/aztec-rpc/src/aztec_rpc_server/note_preimage/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './note_preimage.js'; -export * from './encrypt_note_preimage.js'; diff --git a/yarn-project/aztec-rpc/src/aztec_rpc_server/note_preimage/note_preimage.test.ts b/yarn-project/aztec-rpc/src/aztec_rpc_server/note_preimage/note_preimage.test.ts deleted file mode 100644 index 8aafb8dc855..00000000000 --- a/yarn-project/aztec-rpc/src/aztec_rpc_server/note_preimage/note_preimage.test.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Grumpkin } from '@aztec/barretenberg.js/crypto'; -import { BarretenbergWasm } from '@aztec/barretenberg.js/wasm'; -import { AztecAddress } from '@aztec/foundation/aztec-address'; -import { randomBytes } from '@aztec/foundation/crypto'; -import { Fr } from '@aztec/foundation/fields'; -import { NotePreImage } from './note_preimage.js'; - -describe('note_preimage', () => { - it('convert to and from buffer', () => { - const fields = Array.from({ length: 5 }).map(() => Fr.random()); - const notePreImage = new NotePreImage(fields); - const buf = notePreImage.toBuffer(); - expect(NotePreImage.fromBuffer(buf)).toEqual(notePreImage); - }); - - it('convert to and from encrypted buffer', async () => { - const grumpkin = new Grumpkin(await BarretenbergWasm.new()); - const fields = Array.from({ length: 5 }).map(() => Fr.random()); - const notePreImage = new NotePreImage(fields); - const ownerPrivKey = randomBytes(32); - const ownerPubKey = AztecAddress.fromBuffer(grumpkin.mul(Grumpkin.generator, ownerPrivKey)); - const ephPrivKey = randomBytes(32); - const encrypted = notePreImage.toEncryptedBuffer(ownerPubKey, ephPrivKey, grumpkin); - const decrypted = NotePreImage.fromEncryptedBuffer(encrypted, ownerPrivKey, grumpkin); - expect(decrypted).not.toBeUndefined(); - expect(decrypted).toEqual(notePreImage); - }); -}); diff --git a/yarn-project/aztec-rpc/src/aztec_rpc_server/note_preimage/note_preimage.ts b/yarn-project/aztec-rpc/src/aztec_rpc_server/note_preimage/note_preimage.ts deleted file mode 100644 index 29e4f43db2b..00000000000 --- a/yarn-project/aztec-rpc/src/aztec_rpc_server/note_preimage/note_preimage.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { BufferReader, serializeBufferArrayToVector } from '@aztec/foundation'; -import { decryptNotePreimage, encryptNotePreimage } from './encrypt_note_preimage.js'; -import { Grumpkin } from '@aztec/barretenberg.js/crypto'; -import { Fr } from '@aztec/foundation/fields'; -import { AztecAddress } from '@aztec/foundation/aztec-address'; - -export class NotePreImage { - constructor(public readonly fields: Fr[]) {} - - static fromBuffer(buf: Buffer | BufferReader) { - const reader = BufferReader.asReader(buf); - const fields = reader.readVector(Fr); - return new NotePreImage(fields); - } - - public toBuffer() { - return serializeBufferArrayToVector(this.fields.map(f => f.toBuffer())); - } - - public toEncryptedBuffer(ownerPubKey: AztecAddress, ephPrivKey: Buffer, grumpkin: Grumpkin) { - return encryptNotePreimage(this, ownerPubKey, ephPrivKey, grumpkin); - } - - static fromEncryptedBuffer(data: Buffer, ownerPrivKey: Buffer, grumpkin: Grumpkin) { - const buf = decryptNotePreimage(data, ownerPrivKey, grumpkin); - if (!buf) { - return; - } - return NotePreImage.fromBuffer(buf); - } -} diff --git a/yarn-project/aztec-rpc/src/aztec_rpc_server/note_preimage/browserify-cipher.d.ts b/yarn-project/aztec-rpc/src/aztec_rpc_server/tx_aux_data/browserify-cipher.d.ts similarity index 100% rename from yarn-project/aztec-rpc/src/aztec_rpc_server/note_preimage/browserify-cipher.d.ts rename to yarn-project/aztec-rpc/src/aztec_rpc_server/tx_aux_data/browserify-cipher.d.ts diff --git a/yarn-project/aztec-rpc/src/aztec_rpc_server/tx_aux_data/encrypt_buffer.test.ts b/yarn-project/aztec-rpc/src/aztec_rpc_server/tx_aux_data/encrypt_buffer.test.ts new file mode 100644 index 00000000000..d94c4a3b5f9 --- /dev/null +++ b/yarn-project/aztec-rpc/src/aztec_rpc_server/tx_aux_data/encrypt_buffer.test.ts @@ -0,0 +1,34 @@ +import { Grumpkin } from '@aztec/barretenberg.js/crypto'; +import { BarretenbergWasm } from '@aztec/barretenberg.js/wasm'; +import { AztecAddress } from '@aztec/foundation/aztec-address'; +import { randomBytes } from '@aztec/foundation/crypto'; +import { decryptBuffer, encryptBuffer } from './encrypt_buffer.js'; + +describe('encrypt buffer', () => { + it('convert to and from encrypted buffer', async () => { + const grumpkin = new Grumpkin(await BarretenbergWasm.new()); + const data = randomBytes(253); + const ownerPrivKey = randomBytes(32); + const ownerPubKey = AztecAddress.fromBuffer(grumpkin.mul(Grumpkin.generator, ownerPrivKey)); + const ephPrivKey = randomBytes(32); + const encrypted = encryptBuffer(data, ownerPubKey, ephPrivKey, grumpkin); + const decrypted = decryptBuffer(encrypted, ownerPrivKey, grumpkin); + expect(decrypted).not.toBeUndefined(); + expect(decrypted).toEqual(data); + }); + + it('decrypting gibberish returns undefined', async () => { + const grumpkin = new Grumpkin(await BarretenbergWasm.new()); + const data = randomBytes(253); + const ownerPrivKey = randomBytes(32); + const ephPrivKey = randomBytes(32); + const ownerPubKey = AztecAddress.fromBuffer(grumpkin.mul(Grumpkin.generator, ownerPrivKey)); + const encrypted = encryptBuffer(data, ownerPubKey, ephPrivKey, grumpkin); + + // Introduce gibberish. + const gibberish = Buffer.concat([randomBytes(8), encrypted.subarray(8)]); + + const decrypted = decryptBuffer(gibberish, ownerPrivKey, grumpkin); + expect(decrypted).toBeUndefined(); + }); +}); diff --git a/yarn-project/aztec-rpc/src/aztec_rpc_server/note_preimage/encrypt_note_preimage.ts b/yarn-project/aztec-rpc/src/aztec_rpc_server/tx_aux_data/encrypt_buffer.ts similarity index 64% rename from yarn-project/aztec-rpc/src/aztec_rpc_server/note_preimage/encrypt_note_preimage.ts rename to yarn-project/aztec-rpc/src/aztec_rpc_server/tx_aux_data/encrypt_buffer.ts index cb7d2bc589a..11f59bf7461 100644 --- a/yarn-project/aztec-rpc/src/aztec_rpc_server/note_preimage/encrypt_note_preimage.ts +++ b/yarn-project/aztec-rpc/src/aztec_rpc_server/tx_aux_data/encrypt_buffer.ts @@ -1,7 +1,6 @@ import { createCipheriv, createDecipheriv } from 'browserify-cipher'; import { Grumpkin } from '@aztec/barretenberg.js/crypto'; import { numToUInt8 } from '@aztec/foundation/serialize'; -import { NotePreImage } from './note_preimage.js'; import { sha256 } from '@aztec/foundation/crypto'; import { AztecAddress } from '@aztec/foundation/aztec-address'; @@ -12,29 +11,17 @@ function deriveAESSecret(ecdhPubKey: AztecAddress, ecdhPrivKey: Buffer, grumpkin return hash; } -/** - * Returns the AES encrypted "viewing key". - * [AES: [32 bytes value][4 bytes assetId][4 bytes accountRequired][32 bytes creatorPubKey]] [64 bytes ephPubKey] - * @param data = { value, assetId, accountRequired, creatorPubKey }; - * @param ownerPubKey - the public key contained within a value note - * @param ephPrivKey - a random field element (also used alongside the ownerPubKey in deriving a value note's secret) - */ -export function encryptNotePreimage( - data: NotePreImage, - ownerPubKey: AztecAddress, - ephPrivKey: Buffer, - grumpkin: Grumpkin, -) { +export function encryptBuffer(data: Buffer, ownerPubKey: AztecAddress, ephPrivKey: Buffer, grumpkin: Grumpkin) { const ephPubKey = grumpkin.mul(Grumpkin.generator, ephPrivKey); const aesSecret = deriveAESSecret(ownerPubKey, ephPrivKey, grumpkin); const aesKey = aesSecret.subarray(0, 16); const iv = aesSecret.subarray(16, 32); const cipher = createCipheriv('aes-128-cbc', aesKey, iv); - const plaintext = Buffer.concat([iv.subarray(0, 8), data.toBuffer()]); + const plaintext = Buffer.concat([iv.subarray(0, 8), data]); return Buffer.concat([cipher.update(plaintext), cipher.final(), ephPubKey]); } -export function decryptNotePreimage(data: Buffer, ownerPrivKey: Buffer, grumpkin: Grumpkin) { +export function decryptBuffer(data: Buffer, ownerPrivKey: Buffer, grumpkin: Grumpkin) { const ephPubKey = new AztecAddress(data.subarray(-64)); const aesSecret = deriveAESSecret(ephPubKey, ownerPrivKey, grumpkin); const aesKey = aesSecret.subarray(0, 16); diff --git a/yarn-project/aztec-rpc/src/aztec_rpc_server/tx_aux_data/index.ts b/yarn-project/aztec-rpc/src/aztec_rpc_server/tx_aux_data/index.ts new file mode 100644 index 00000000000..397972f4947 --- /dev/null +++ b/yarn-project/aztec-rpc/src/aztec_rpc_server/tx_aux_data/index.ts @@ -0,0 +1,2 @@ +export * from './note_preimage.js'; +export * from './encrypt_buffer.js'; diff --git a/yarn-project/aztec-rpc/src/aztec_rpc_server/tx_aux_data/note_preimage.test.ts b/yarn-project/aztec-rpc/src/aztec_rpc_server/tx_aux_data/note_preimage.test.ts new file mode 100644 index 00000000000..e27a3fa4c54 --- /dev/null +++ b/yarn-project/aztec-rpc/src/aztec_rpc_server/tx_aux_data/note_preimage.test.ts @@ -0,0 +1,11 @@ +import { Fr } from '@aztec/foundation/fields'; +import { NotePreimage } from './note_preimage.js'; + +describe('note_preimage', () => { + it('convert to and from buffer', () => { + const fields = Array.from({ length: 5 }).map(() => Fr.random()); + const notePreImage = new NotePreimage(fields); + const buf = notePreImage.toBuffer(); + expect(NotePreimage.fromBuffer(buf)).toEqual(notePreImage); + }); +}); diff --git a/yarn-project/aztec-rpc/src/aztec_rpc_server/tx_aux_data/note_preimage.ts b/yarn-project/aztec-rpc/src/aztec_rpc_server/tx_aux_data/note_preimage.ts new file mode 100644 index 00000000000..39c6a7a97c1 --- /dev/null +++ b/yarn-project/aztec-rpc/src/aztec_rpc_server/tx_aux_data/note_preimage.ts @@ -0,0 +1,10 @@ +import { Fr } from '@aztec/foundation/fields'; +import { Vector } from '@aztec/circuits.js'; +import { BufferReader } from '@aztec/foundation/serialize'; + +export class NotePreimage extends Vector { + static fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new NotePreimage(reader.readVector(Fr)); + } +} diff --git a/yarn-project/aztec-rpc/src/aztec_rpc_server/tx_aux_data/tx_aux_data.test.ts b/yarn-project/aztec-rpc/src/aztec_rpc_server/tx_aux_data/tx_aux_data.test.ts new file mode 100644 index 00000000000..b8d2f538f09 --- /dev/null +++ b/yarn-project/aztec-rpc/src/aztec_rpc_server/tx_aux_data/tx_aux_data.test.ts @@ -0,0 +1,34 @@ +import { Grumpkin } from '@aztec/barretenberg.js/crypto'; +import { BarretenbergWasm } from '@aztec/barretenberg.js/wasm'; +import { AztecAddress, randomBytes } from '@aztec/foundation'; +import { Fr } from '@aztec/foundation/fields'; +import { NotePreimage } from './note_preimage.js'; +import { TxAuxData } from './tx_aux_data.js'; + +const randomTxAuxData = () => { + const fields = Array.from({ length: 5 }).map(() => Fr.random()); + const notePreImage = new NotePreimage(fields); + const contractAddress = AztecAddress.random(); + const storageSlot = Fr.random(); + return new TxAuxData(notePreImage, contractAddress, storageSlot); +}; + +describe('tx_aux_data', () => { + it('convert to and from buffer', () => { + const txAuxData = randomTxAuxData(); + const buf = txAuxData.toBuffer(); + expect(TxAuxData.fromBuffer(buf)).toEqual(txAuxData); + }); + + it('convert to and from encrypted buffer', async () => { + const grumpkin = new Grumpkin(await BarretenbergWasm.new()); + const txAuxData = randomTxAuxData(); + const ownerPrivKey = randomBytes(32); + const ownerPubKey = AztecAddress.fromBuffer(grumpkin.mul(Grumpkin.generator, ownerPrivKey)); + const ephPrivKey = randomBytes(32); + const encrypted = txAuxData.toEncryptedBuffer(ownerPubKey, ephPrivKey, grumpkin); + const decrypted = TxAuxData.fromEncryptedBuffer(encrypted, ownerPrivKey, grumpkin); + expect(decrypted).not.toBeUndefined(); + expect(decrypted).toEqual(txAuxData); + }); +}); diff --git a/yarn-project/aztec-rpc/src/aztec_rpc_server/tx_aux_data/tx_aux_data.ts b/yarn-project/aztec-rpc/src/aztec_rpc_server/tx_aux_data/tx_aux_data.ts new file mode 100644 index 00000000000..196c0790b20 --- /dev/null +++ b/yarn-project/aztec-rpc/src/aztec_rpc_server/tx_aux_data/tx_aux_data.ts @@ -0,0 +1,32 @@ +import { Fr } from '@aztec/foundation/fields'; +import { AztecAddress } from '@aztec/circuits.js'; +import { BufferReader } from '@aztec/foundation/serialize'; +import { NotePreimage } from './note_preimage.js'; +import { serializeToBuffer } from '@aztec/circuits.js/utils'; +import { decryptBuffer, encryptBuffer } from './encrypt_buffer.js'; +import { Grumpkin } from '@aztec/barretenberg.js/crypto'; + +export class TxAuxData { + constructor(public notePreImage: NotePreimage, public contractAddress: AztecAddress, public storageSlot: Fr) {} + + static fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new TxAuxData(reader.readObject(NotePreimage), reader.readObject(AztecAddress), reader.readFr()); + } + + toBuffer() { + return serializeToBuffer([this.notePreImage, this.contractAddress, this.storageSlot]); + } + + public toEncryptedBuffer(ownerPubKey: AztecAddress, ephPrivKey: Buffer, grumpkin: Grumpkin) { + return encryptBuffer(this.toBuffer(), ownerPubKey, ephPrivKey, grumpkin); + } + + static fromEncryptedBuffer(data: Buffer, ownerPrivKey: Buffer, grumpkin: Grumpkin) { + const buf = decryptBuffer(data, ownerPrivKey, grumpkin); + if (!buf) { + return; + } + return TxAuxData.fromBuffer(buf); + } +} diff --git a/yarn-project/aztec-rpc/src/database/note_dao.ts b/yarn-project/aztec-rpc/src/database/note_dao.ts index 244b9771cb0..d2d3361e47c 100644 --- a/yarn-project/aztec-rpc/src/database/note_dao.ts +++ b/yarn-project/aztec-rpc/src/database/note_dao.ts @@ -1,11 +1,11 @@ import { AztecAddress, Fr } from '@aztec/circuits.js'; -import { NotePreImage } from '../aztec_rpc_server/note_preimage/note_preimage.js'; +import { NotePreimage } from '../aztec_rpc_server/tx_aux_data/note_preimage.js'; export interface NoteDao { // Properties from the encrypted note contractAddress: AztecAddress; contractSlot: Fr; - notePreimage: NotePreImage; + notePreimage: NotePreimage; // Computed properties nullifier: Fr; // The location in the tree diff --git a/yarn-project/aztec-rpc/src/simulator_oracle/index.ts b/yarn-project/aztec-rpc/src/simulator_oracle/index.ts index f81cd582461..cdcf072b862 100644 --- a/yarn-project/aztec-rpc/src/simulator_oracle/index.ts +++ b/yarn-project/aztec-rpc/src/simulator_oracle/index.ts @@ -13,7 +13,7 @@ export class SimulatorOracle implements DBOracle { async getNotes(contractAddress: AztecAddress, storageSlot: Fr): Promise { const noteDaos = await this.db.getNotes(contractAddress, storageSlot); return noteDaos.map(noteDao => ({ - note: noteDao.notePreimage.fields, + note: noteDao.notePreimage.items, siblingPath: [], // TODO get this from node index: noteDao.index, })); diff --git a/yarn-project/foundation/src/aztec-address/index.ts b/yarn-project/foundation/src/aztec-address/index.ts index 8c575146260..fb0db5746dc 100644 --- a/yarn-project/foundation/src/aztec-address/index.ts +++ b/yarn-project/foundation/src/aztec-address/index.ts @@ -13,7 +13,7 @@ export class AztecAddress { static fromBuffer(bufferOrReader: Buffer | BufferReader) { const reader = BufferReader.asReader(bufferOrReader); - return new AztecAddress(reader.readBytes(AztecAddress.SIZE_IN_BYTES)); + return new AztecAddress(reader.readBytes(this.SIZE_IN_BYTES)); } public static fromString(address: string) { @@ -21,7 +21,7 @@ export class AztecAddress { } public static random() { - return new AztecAddress(randomBytes(AztecAddress.SIZE_IN_BYTES)); + return new AztecAddress(randomBytes(this.SIZE_IN_BYTES)); } public equals(rhs: AztecAddress) {