diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index b9e22c3eb70..d6a26714388 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -118,8 +118,10 @@ library Constants { uint256 internal constant NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH = 4; uint256 internal constant PARTIAL_STATE_REFERENCE_LENGTH = 6; uint256 internal constant READ_REQUEST_LENGTH = 2; + uint256 internal constant NOTE_HASH_LENGTH = 2; + uint256 internal constant NOTE_HASH_CONTEXT_LENGTH = 3; + uint256 internal constant NULLIFIER_LENGTH = 3; uint256 internal constant SIDE_EFFECT_LENGTH = 2; - uint256 internal constant SIDE_EFFECT_LINKED_TO_NOTE_HASH_LENGTH = 3; uint256 internal constant STATE_REFERENCE_LENGTH = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH; uint256 internal constant TX_CONTEXT_LENGTH = 2 + GAS_SETTINGS_LENGTH; @@ -130,9 +132,9 @@ library Constants { + MAX_BLOCK_NUMBER_LENGTH + (SIDE_EFFECT_LENGTH * MAX_NOTE_HASH_READ_REQUESTS_PER_CALL) + (READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL) + (NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH * MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL) - + (SIDE_EFFECT_LENGTH * MAX_NEW_NOTE_HASHES_PER_CALL) - + (SIDE_EFFECT_LINKED_TO_NOTE_HASH_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL) - + MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + + (NOTE_HASH_LENGTH * MAX_NEW_NOTE_HASHES_PER_CALL) + + (NULLIFIER_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL) + MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL + + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + (L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL) + 2 + (SIDE_EFFECT_LENGTH * MAX_ENCRYPTED_LOGS_PER_CALL) + (SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + 2 + HEADER_LENGTH + TX_CONTEXT_LENGTH; @@ -141,8 +143,8 @@ library Constants { + (READ_REQUEST_LENGTH * MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL) + (CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH * MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL) + (CONTRACT_STORAGE_READ_LENGTH * MAX_PUBLIC_DATA_READS_PER_CALL) - + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + (SIDE_EFFECT_LENGTH * MAX_NEW_NOTE_HASHES_PER_CALL) - + (SIDE_EFFECT_LINKED_TO_NOTE_HASH_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL) + + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + (NOTE_HASH_LENGTH * MAX_NEW_NOTE_HASHES_PER_CALL) + + (NULLIFIER_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL) + (L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL) + 2 + (SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + 1 + HEADER_LENGTH + GLOBAL_VARIABLES_LENGTH + AZTEC_ADDRESS_LENGTH /* revert_code */ + 1 + 2 * GAS_LENGTH /* transaction_fee */ diff --git a/noir-projects/aztec-nr/aztec/src/keys.nr b/noir-projects/aztec-nr/aztec/src/keys.nr new file mode 100644 index 00000000000..20d48201aca --- /dev/null +++ b/noir-projects/aztec-nr/aztec/src/keys.nr @@ -0,0 +1 @@ +mod point_to_symmetric_key; \ No newline at end of file diff --git a/noir-projects/aztec-nr/aztec/src/keys/point_to_symmetric_key.nr b/noir-projects/aztec-nr/aztec/src/keys/point_to_symmetric_key.nr new file mode 100644 index 00000000000..b708d00e8bc --- /dev/null +++ b/noir-projects/aztec-nr/aztec/src/keys/point_to_symmetric_key.nr @@ -0,0 +1,34 @@ +use dep::protocol_types::{constants::GENERATOR_INDEX__SYMMETRIC_KEY, grumpkin_point::GrumpkinPoint, utils::arr_copy_slice}; +use dep::std::{hash::sha256, grumpkin_scalar::GrumpkinScalar, scalar_mul::variable_base_embedded_curve}; + +// TODO(#5726): This function is called deriveAESSecret in TS. I don't like point_to_symmetric_key name much since +// point is not the only input of the function. Unify naming with TS once we have a better name. +pub fn point_to_symmetric_key(secret: GrumpkinScalar, point: GrumpkinPoint) -> [u8; 32] { + let shared_secret_fields = variable_base_embedded_curve(point.x, point.y, secret.low, secret.high); + // TODO(https://github.com/AztecProtocol/aztec-packages/issues/6061): make the func return Point struct directly + let shared_secret = GrumpkinPoint::new(shared_secret_fields[0], shared_secret_fields[1]); + let mut shared_secret_bytes_with_separator = [0 as u8; 65]; + shared_secret_bytes_with_separator = arr_copy_slice(shared_secret.to_be_bytes(), shared_secret_bytes_with_separator, 0); + shared_secret_bytes_with_separator[64] = GENERATOR_INDEX__SYMMETRIC_KEY; + sha256(shared_secret_bytes_with_separator) +} + +#[test] +fn check_point_to_symmetric_key() { + // Value taken from "derive shared secret" test in encrypt_buffer.test.ts + let secret = GrumpkinScalar::new( + 0x00000000000000000000000000000000649e7ca01d9de27b21624098b897babd, + 0x0000000000000000000000000000000023b3127c127b1f29a7adff5cccf8fb06 + ); + let point = GrumpkinPoint::new( + 0x2688431c705a5ff3e6c6f2573c9e3ba1c1026d2251d0dbbf2d810aa53fd1d186, + 0x1e96887b117afca01c00468264f4f80b5bb16d94c1808a448595f115556e5c8e + ); + + let key = point_to_symmetric_key(secret, point); + // The following value gets updated when running encrypt_buffer.test.ts with AZTEC_GENERATE_TEST_DATA=1 + let expected_key = [ + 198, 74, 242, 51, 177, 36, 183, 8, 2, 246, 197, 138, 59, 166, 86, 96, 155, 50, 186, 34, 242, 3, 208, 144, 161, 64, 69, 165, 70, 57, 226, 139 + ]; + assert_eq(key, expected_key); +} diff --git a/noir-projects/aztec-nr/aztec/src/lib.nr b/noir-projects/aztec-nr/aztec/src/lib.nr index 81390fb52eb..67a3c8c55b4 100644 --- a/noir-projects/aztec-nr/aztec/src/lib.nr +++ b/noir-projects/aztec-nr/aztec/src/lib.nr @@ -3,6 +3,7 @@ mod deploy; mod hash; mod history; mod initializer; +mod keys; mod log; mod messaging; mod note; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr index 61924a73f8e..37c7bc84848 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -255,3 +255,4 @@ global GENERATOR_INDEX__PUBLIC_KEYS_HASH = 51; global GENERATOR_INDEX__NOTE_NULLIFIER = 52; global GENERATOR_INDEX__INNER_NOTE_HASH = 53; global GENERATOR_INDEX__NOTE_CONTENT_HASH = 54; +global GENERATOR_INDEX__SYMMETRIC_KEY: u8 = 55; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/grumpkin_point.nr b/noir-projects/noir-protocol-circuits/crates/types/src/grumpkin_point.nr index ec334d78b50..467a022947b 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/grumpkin_point.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/grumpkin_point.nr @@ -51,4 +51,15 @@ impl GrumpkinPoint { assert(self.x == 0); assert(self.y == 0); } + + pub fn to_be_bytes(self: Self) -> [u8; 64] { + let mut result = [0 as u8; 64]; + let x_bytes = self.x.to_be_bytes(32); + let y_bytes = self.y.to_be_bytes(32); + for i in 0..32 { + result[i] = x_bytes[i]; + result[i + 32] = y_bytes[i]; + } + result + } } diff --git a/yarn-project/circuit-types/src/logs/l1_note_payload/encrypt_buffer.test.ts b/yarn-project/circuit-types/src/logs/l1_note_payload/encrypt_buffer.test.ts index b34baa4fb01..d8a0c4b9998 100644 --- a/yarn-project/circuit-types/src/logs/l1_note_payload/encrypt_buffer.test.ts +++ b/yarn-project/circuit-types/src/logs/l1_note_payload/encrypt_buffer.test.ts @@ -1,6 +1,7 @@ -import { GrumpkinScalar } from '@aztec/circuits.js'; +import { Fq, GrumpkinScalar } from '@aztec/circuits.js'; import { Grumpkin } from '@aztec/circuits.js/barretenberg'; import { randomBytes } from '@aztec/foundation/crypto'; +import { updateInlineTestData } from '@aztec/foundation/testing'; import { decryptBuffer, deriveAESSecret, encryptBuffer } from './encrypt_buffer.js'; @@ -12,38 +13,51 @@ describe('encrypt buffer', () => { }); it('derive shared secret', () => { - const ownerPrivKey = GrumpkinScalar.random(); - const ownerPubKey = grumpkin.mul(Grumpkin.generator, ownerPrivKey); - const ephPrivKey = GrumpkinScalar.random(); - const ephPubKey = grumpkin.mul(Grumpkin.generator, ephPrivKey); + // The following 2 are arbitrary fixed values - fixed in order to test a match with Noir + const ownerSecretKey: GrumpkinScalar = new Fq(0x23b3127c127b1f29a7adff5cccf8fb06649e7ca01d9de27b21624098b897babdn); + const ephSecretKey: GrumpkinScalar = new Fq(0x1fdd0dd8c99b21af8e00d2d130bdc263b36dadcbea84ac5ec9293a0660deca01n); - const secretBySender = deriveAESSecret(ownerPubKey, ephPrivKey, grumpkin); - const secretByReceiver = deriveAESSecret(ephPubKey, ownerPrivKey, grumpkin); + const ownerPubKey = grumpkin.mul(Grumpkin.generator, ownerSecretKey); + const ephPubKey = grumpkin.mul(Grumpkin.generator, ephSecretKey); + + const secretBySender = deriveAESSecret(ephSecretKey, ownerPubKey); + const secretByReceiver = deriveAESSecret(ownerSecretKey, ephPubKey); expect(secretBySender.toString('hex')).toEqual(secretByReceiver.toString('hex')); + + const byteArrayString = `[${secretBySender + .toString('hex') + .match(/.{1,2}/g)! + .map(byte => parseInt(byte, 16))}]`; + // Run with AZTEC_GENERATE_TEST_DATA=1 to update noir test data + updateInlineTestData( + 'noir-projects/aztec-nr/aztec/src/keys/point_to_symmetric_key.nr', + 'expected_key', + byteArrayString, + ); }); it('convert to and from encrypted buffer', () => { const data = randomBytes(253); - const ownerPrivKey = GrumpkinScalar.random(); - const ownerPubKey = grumpkin.mul(Grumpkin.generator, ownerPrivKey); - const ephPrivKey = GrumpkinScalar.random(); - const encrypted = encryptBuffer(data, ownerPubKey, ephPrivKey, grumpkin); - const decrypted = decryptBuffer(encrypted, ownerPrivKey, grumpkin); + const ownerSecretKey = GrumpkinScalar.random(); + const ownerPubKey = grumpkin.mul(Grumpkin.generator, ownerSecretKey); + const ephSecretKey = GrumpkinScalar.random(); + const encrypted = encryptBuffer(data, ephSecretKey, ownerPubKey); + const decrypted = decryptBuffer(encrypted, ownerSecretKey); expect(decrypted).not.toBeUndefined(); expect(decrypted).toEqual(data); }); it('decrypting gibberish returns undefined', () => { const data = randomBytes(253); - const ownerPrivKey = GrumpkinScalar.random(); - const ephPrivKey = GrumpkinScalar.random(); - const ownerPubKey = grumpkin.mul(Grumpkin.generator, ownerPrivKey); - const encrypted = encryptBuffer(data, ownerPubKey, ephPrivKey, grumpkin); + const ownerSecretKey = GrumpkinScalar.random(); + const ephSecretKey = GrumpkinScalar.random(); + const ownerPubKey = grumpkin.mul(Grumpkin.generator, ownerSecretKey); + const encrypted = encryptBuffer(data, ephSecretKey, ownerPubKey); // Introduce gibberish. const gibberish = Buffer.concat([randomBytes(8), encrypted.subarray(8)]); - const decrypted = decryptBuffer(gibberish, ownerPrivKey, grumpkin); + const decrypted = decryptBuffer(gibberish, ownerSecretKey); expect(decrypted).toBeUndefined(); }); }); diff --git a/yarn-project/circuit-types/src/logs/l1_note_payload/encrypt_buffer.ts b/yarn-project/circuit-types/src/logs/l1_note_payload/encrypt_buffer.ts index 314ef0d6c28..28262ff3ba6 100644 --- a/yarn-project/circuit-types/src/logs/l1_note_payload/encrypt_buffer.ts +++ b/yarn-project/circuit-types/src/logs/l1_note_payload/encrypt_buffer.ts @@ -1,5 +1,5 @@ -import { type GrumpkinPrivateKey, type PublicKey } from '@aztec/circuits.js'; -import { type Grumpkin } from '@aztec/circuits.js/barretenberg'; +import { GeneratorIndex, type GrumpkinPrivateKey, type PublicKey } from '@aztec/circuits.js'; +import { Grumpkin } from '@aztec/circuits.js/barretenberg'; import { sha256 } from '@aztec/foundation/crypto'; import { Point } from '@aztec/foundation/fields'; import { numToUInt8 } from '@aztec/foundation/serialize'; @@ -12,14 +12,16 @@ import { createCipheriv, createDecipheriv } from 'browserify-cipher'; * the shared secret. The shared secret is then hashed using SHA-256 to produce the final * AES secret key. * - * @param ecdhPubKey - The ECDH public key represented as a PublicKey object. - * @param ecdhPrivKey - The ECDH private key represented as a Buffer object. - * @param grumpkin - The curve to use for curve operations. - * @returns A Buffer containing the derived AES secret key. + * @param secretKey - The secret key used to derive shared secret. + * @param publicKey - The public key used to derive shared secret. + * @returns A derived AES secret key. + * TODO(#5726): This function is called point_to_symmetric_key in Noir. I don't like that name much since point is not + * the only input of the function. Unify naming once we have a better name. */ -export function deriveAESSecret(ecdhPubKey: PublicKey, ecdhPrivKey: GrumpkinPrivateKey, curve: Grumpkin): Buffer { - const sharedSecret = curve.mul(ecdhPubKey, ecdhPrivKey); - const secretBuffer = Buffer.concat([sharedSecret.toBuffer(), numToUInt8(1)]); +export function deriveAESSecret(secretKey: GrumpkinPrivateKey, publicKey: PublicKey): Buffer { + const curve = new Grumpkin(); + const sharedSecret = curve.mul(publicKey, secretKey); + const secretBuffer = Buffer.concat([sharedSecret.toBuffer(), numToUInt8(GeneratorIndex.SYMMETRIC_KEY)]); const hash = sha256(secretBuffer); return hash; } @@ -31,40 +33,37 @@ export function deriveAESSecret(ecdhPubKey: PublicKey, ecdhPrivKey: GrumpkinPriv * with the provided curve instance for elliptic curve operations. * * @param data - The data buffer to be encrypted. - * @param ownerPubKey - The owner's public key as a PublicKey instance. - * @param ephPrivKey - The ephemeral private key as a Buffer instance. - * @param curve - The curve instance used for elliptic curve operations. + * @param ephSecretKey - The ephemeral secret key.. + * @param incomingViewingPublicKey - The note owner's incoming viewing public key. * @returns A Buffer containing the encrypted data and the ephemeral public key. */ export function encryptBuffer( data: Buffer, - ownerPubKey: PublicKey, - ephPrivKey: GrumpkinPrivateKey, - curve: Grumpkin, + ephSecretKey: GrumpkinPrivateKey, + incomingViewingPublicKey: PublicKey, ): Buffer { - const aesSecret = deriveAESSecret(ownerPubKey, ephPrivKey, curve); + const aesSecret = deriveAESSecret(ephSecretKey, incomingViewingPublicKey); 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]); - const ephPubKey = curve.mul(curve.generator(), ephPrivKey); + const curve = new Grumpkin(); + const ephPubKey = curve.mul(curve.generator(), ephSecretKey); + return Buffer.concat([cipher.update(plaintext), cipher.final(), ephPubKey.toBuffer()]); } /** - * Decrypts the given encrypted data buffer using the owner's private key and a Grumpkin curve. - * Extracts the ephemeral public key from the input data, derives the AES secret using - * the owner's private key, and decrypts the plaintext. - * If the decryption is successful, returns the decrypted plaintext, otherwise returns undefined. - * + * Decrypts the given encrypted data buffer using the provided secret key. * @param data - The encrypted data buffer to be decrypted. - * @param ownerPrivKey - The private key of the owner used for decryption. - * @param curve - The curve object used in the decryption process. + * @param incomingViewingSecretKey - The secret key used for decryption. * @returns The decrypted plaintext as a Buffer or undefined if decryption fails. */ -export function decryptBuffer(data: Buffer, ownerPrivKey: GrumpkinPrivateKey, curve: Grumpkin): Buffer | undefined { +export function decryptBuffer(data: Buffer, incomingViewingSecretKey: GrumpkinPrivateKey): Buffer | undefined { + // Extract the ephemeral public key from the end of the data const ephPubKey = Point.fromBuffer(data.subarray(-64)); - const aesSecret = deriveAESSecret(ephPubKey, ownerPrivKey, curve); + // Derive the AES secret key using the secret key and the ephemeral public key + const aesSecret = deriveAESSecret(incomingViewingSecretKey, ephPubKey); const aesKey = aesSecret.subarray(0, 16); const iv = aesSecret.subarray(16, 32); const cipher = createDecipheriv('aes-128-cbc', aesKey, iv); diff --git a/yarn-project/circuit-types/src/logs/l1_note_payload/l1_note_payload.test.ts b/yarn-project/circuit-types/src/logs/l1_note_payload/l1_note_payload.test.ts index d5a909fe779..288e46db36d 100644 --- a/yarn-project/circuit-types/src/logs/l1_note_payload/l1_note_payload.test.ts +++ b/yarn-project/circuit-types/src/logs/l1_note_payload/l1_note_payload.test.ts @@ -20,8 +20,8 @@ describe('L1 Note Payload', () => { const payload = L1NotePayload.random(); const ownerPrivKey = GrumpkinScalar.random(); const ownerPubKey = grumpkin.mul(Grumpkin.generator, ownerPrivKey); - const encrypted = payload.toEncryptedBuffer(ownerPubKey, grumpkin); - const decrypted = L1NotePayload.fromEncryptedBuffer(encrypted, ownerPrivKey, grumpkin); + const encrypted = payload.toEncryptedBuffer(ownerPubKey); + const decrypted = L1NotePayload.fromEncryptedBuffer(encrypted, ownerPrivKey); expect(decrypted).not.toBeUndefined(); expect(decrypted).toEqual(payload); }); @@ -29,9 +29,9 @@ describe('L1 Note Payload', () => { it('return undefined if unable to decrypt the encrypted buffer', () => { const payload = L1NotePayload.random(); const ownerPubKey = Point.random(); - const encrypted = payload.toEncryptedBuffer(ownerPubKey, grumpkin); + const encrypted = payload.toEncryptedBuffer(ownerPubKey); const randomPrivKey = GrumpkinScalar.random(); - const decrypted = L1NotePayload.fromEncryptedBuffer(encrypted, randomPrivKey, grumpkin); + const decrypted = L1NotePayload.fromEncryptedBuffer(encrypted, randomPrivKey); expect(decrypted).toBeUndefined(); }); }); diff --git a/yarn-project/circuit-types/src/logs/l1_note_payload/l1_note_payload.ts b/yarn-project/circuit-types/src/logs/l1_note_payload/l1_note_payload.ts index 8b34dd37b8f..463512782a7 100644 --- a/yarn-project/circuit-types/src/logs/l1_note_payload/l1_note_payload.ts +++ b/yarn-project/circuit-types/src/logs/l1_note_payload/l1_note_payload.ts @@ -1,5 +1,4 @@ import { AztecAddress, type GrumpkinPrivateKey, type PublicKey } from '@aztec/circuits.js'; -import { type Grumpkin } from '@aztec/circuits.js/barretenberg'; import { Fr, GrumpkinScalar } from '@aztec/foundation/fields'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; @@ -56,28 +55,22 @@ export class L1NotePayload { /** * Encrypt the L1NotePayload object using the owner's public key and the ephemeral private key. - * @param ownerPubKey - Public key of the owner of the L1NotePayload object. - * @param curve - The curve instance to use. + * @param incomingViewingPubKey - Public key of the owner of the L1NotePayload object. * @returns The encrypted L1NotePayload object. */ - public toEncryptedBuffer(ownerPubKey: PublicKey, curve: Grumpkin): Buffer { - const ephPrivKey: GrumpkinPrivateKey = GrumpkinScalar.random(); - return encryptBuffer(this.toBuffer(), ownerPubKey, ephPrivKey, curve); + public toEncryptedBuffer(incomingViewingPubKey: PublicKey): Buffer { + const ephSecretKey: GrumpkinPrivateKey = GrumpkinScalar.random(); + return encryptBuffer(this.toBuffer(), ephSecretKey, incomingViewingPubKey); } /** - * Decrypts the L1NotePayload object using the owner's private key. + * Decrypts the L1NotePayload object using the owner's incoming viewing secret key. * @param data - Encrypted L1NotePayload object. - * @param ownerPrivKey - Private key of the owner of the L1NotePayload object. - * @param curve - The curve instance to use. + * @param incomingViewingSecretKey - Incoming viewing secret key of the owner of the L1NotePayload object. * @returns Instance of L1NotePayload if the decryption was successful, undefined otherwise. */ - static fromEncryptedBuffer( - data: Buffer, - ownerPrivKey: GrumpkinPrivateKey, - curve: Grumpkin, - ): L1NotePayload | undefined { - const buf = decryptBuffer(data, ownerPrivKey, curve); + static fromEncryptedBuffer(data: Buffer, incomingViewingSecretKey: GrumpkinPrivateKey): L1NotePayload | undefined { + const buf = decryptBuffer(data, incomingViewingSecretKey); if (!buf) { return; } diff --git a/yarn-project/circuit-types/src/logs/l1_note_payload/tagged_note.test.ts b/yarn-project/circuit-types/src/logs/l1_note_payload/tagged_note.test.ts index 2eb74ba247a..bbd171f3702 100644 --- a/yarn-project/circuit-types/src/logs/l1_note_payload/tagged_note.test.ts +++ b/yarn-project/circuit-types/src/logs/l1_note_payload/tagged_note.test.ts @@ -23,8 +23,8 @@ describe('L1 Note Payload', () => { const taggedNote = new TaggedNote(payload); const ownerPrivKey = GrumpkinScalar.random(); const ownerPubKey = grumpkin.mul(Grumpkin.generator, ownerPrivKey); - const encrypted = taggedNote.toEncryptedBuffer(ownerPubKey, grumpkin); - const decrypted = TaggedNote.fromEncryptedBuffer(encrypted, ownerPrivKey, grumpkin); + const encrypted = taggedNote.toEncryptedBuffer(ownerPubKey); + const decrypted = TaggedNote.fromEncryptedBuffer(encrypted, ownerPrivKey); expect(decrypted).not.toBeUndefined(); expect(decrypted?.notePayload).toEqual(payload); }); @@ -33,9 +33,9 @@ describe('L1 Note Payload', () => { const payload = L1NotePayload.random(); const taggedNote = new TaggedNote(payload); const ownerPubKey = Point.random(); - const encrypted = taggedNote.toEncryptedBuffer(ownerPubKey, grumpkin); + const encrypted = taggedNote.toEncryptedBuffer(ownerPubKey); const randomPrivKey = GrumpkinScalar.random(); - const decrypted = TaggedNote.fromEncryptedBuffer(encrypted, randomPrivKey, grumpkin); + const decrypted = TaggedNote.fromEncryptedBuffer(encrypted, randomPrivKey); expect(decrypted).toBeUndefined(); }); }); diff --git a/yarn-project/circuit-types/src/logs/l1_note_payload/tagged_note.ts b/yarn-project/circuit-types/src/logs/l1_note_payload/tagged_note.ts index ddc362e4628..4e698e382eb 100644 --- a/yarn-project/circuit-types/src/logs/l1_note_payload/tagged_note.ts +++ b/yarn-project/circuit-types/src/logs/l1_note_payload/tagged_note.ts @@ -1,5 +1,4 @@ import { type GrumpkinPrivateKey, type PublicKey } from '@aztec/circuits.js'; -import { type Grumpkin } from '@aztec/circuits.js/barretenberg'; import { Fr } from '@aztec/foundation/fields'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; @@ -37,11 +36,10 @@ export class TaggedNote { /** * Encrypt the L1NotePayload object using the owner's public key and the ephemeral private key, then attach the tag. * @param ownerPubKey - Public key of the owner of the TaggedNote object. - * @param curve - The curve instance to use. * @returns The encrypted TaggedNote object. */ - public toEncryptedBuffer(ownerPubKey: PublicKey, curve: Grumpkin): Buffer { - const encryptedL1NotePayload = this.notePayload.toEncryptedBuffer(ownerPubKey, curve); + public toEncryptedBuffer(ownerPubKey: PublicKey): Buffer { + const encryptedL1NotePayload = this.notePayload.toEncryptedBuffer(ownerPubKey); return serializeToBuffer(this.tag, encryptedL1NotePayload); } @@ -49,16 +47,15 @@ export class TaggedNote { * Decrypts the L1NotePayload object using the owner's private key. * @param data - Encrypted TaggedNote object. * @param ownerPrivKey - Private key of the owner of the TaggedNote object. - * @param curve - The curve instance to use. * @returns Instance of TaggedNote if the decryption was successful, undefined otherwise. */ - static fromEncryptedBuffer(data: Buffer, ownerPrivKey: GrumpkinPrivateKey, curve: Grumpkin): TaggedNote | undefined { + static fromEncryptedBuffer(data: Buffer, ownerPrivKey: GrumpkinPrivateKey): TaggedNote | undefined { const reader = BufferReader.asReader(data); const tag = Fr.fromBuffer(reader); const encryptedL1NotePayload = reader.readToEnd(); - const payload = L1NotePayload.fromEncryptedBuffer(encryptedL1NotePayload, ownerPrivKey, curve); + const payload = L1NotePayload.fromEncryptedBuffer(encryptedL1NotePayload, ownerPrivKey); if (!payload) { return; } diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index 1b98ef98a39..0e2f73c46d2 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -101,8 +101,10 @@ export const NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = 3; export const NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH = 4; export const PARTIAL_STATE_REFERENCE_LENGTH = 6; export const READ_REQUEST_LENGTH = 2; +export const NOTE_HASH_LENGTH = 2; +export const NOTE_HASH_CONTEXT_LENGTH = 3; +export const NULLIFIER_LENGTH = 3; export const SIDE_EFFECT_LENGTH = 2; -export const SIDE_EFFECT_LINKED_TO_NOTE_HASH_LENGTH = 3; export const STATE_REFERENCE_LENGTH = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH; export const TX_CONTEXT_LENGTH = 2 + GAS_SETTINGS_LENGTH; export const TX_REQUEST_LENGTH = 2 + TX_CONTEXT_LENGTH + FUNCTION_DATA_LENGTH; @@ -115,8 +117,8 @@ export const PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = SIDE_EFFECT_LENGTH * MAX_NOTE_HASH_READ_REQUESTS_PER_CALL + READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL + NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH * MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL + - SIDE_EFFECT_LENGTH * MAX_NEW_NOTE_HASHES_PER_CALL + - SIDE_EFFECT_LINKED_TO_NOTE_HASH_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL + + NOTE_HASH_LENGTH * MAX_NEW_NOTE_HASHES_PER_CALL + + NULLIFIER_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL + MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL + @@ -134,8 +136,8 @@ export const PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH * MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL + CONTRACT_STORAGE_READ_LENGTH * MAX_PUBLIC_DATA_READS_PER_CALL + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + - SIDE_EFFECT_LENGTH * MAX_NEW_NOTE_HASHES_PER_CALL + - SIDE_EFFECT_LINKED_TO_NOTE_HASH_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL + + NOTE_HASH_LENGTH * MAX_NEW_NOTE_HASHES_PER_CALL + + NULLIFIER_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL + L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL + 2 + SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL + @@ -210,4 +212,5 @@ export enum GeneratorIndex { NOTE_NULLIFIER = 52, INNER_NOTE_HASH = 53, NOTE_CONTENT_HASH = 54, + SYMMETRIC_KEY = 55, } diff --git a/yarn-project/foundation/src/testing/test_data.ts b/yarn-project/foundation/src/testing/test_data.ts index a92794e64f6..dba6932cd5c 100644 --- a/yarn-project/foundation/src/testing/test_data.ts +++ b/yarn-project/foundation/src/testing/test_data.ts @@ -66,7 +66,7 @@ export function updateInlineTestData(targetFileFromRepoRoot: string, itemName: s const logger = createConsoleLogger('aztec:testing:test_data'); const targetFile = getPathToFile(targetFileFromRepoRoot); const contents = readFileSync(targetFile, 'utf8').toString(); - const regex = new RegExp(`let ${itemName} = .*;`, 'g'); + const regex = new RegExp(`let ${itemName} = [\\s\\S]*?;`, 'g'); if (!regex.exec(contents)) { throw new Error(`Test data marker for ${itemName} not found in ${targetFile}`); } diff --git a/yarn-project/pxe/src/note_processor/note_processor.test.ts b/yarn-project/pxe/src/note_processor/note_processor.test.ts index b182e5caeb5..1ddd5bd1ce6 100644 --- a/yarn-project/pxe/src/note_processor/note_processor.test.ts +++ b/yarn-project/pxe/src/note_processor/note_processor.test.ts @@ -17,7 +17,6 @@ import { type PublicKey, deriveKeys, } from '@aztec/circuits.js'; -import { Grumpkin } from '@aztec/circuits.js/barretenberg'; import { pedersenHash } from '@aztec/foundation/crypto'; import { Point } from '@aztec/foundation/fields'; import { openTmpStore } from '@aztec/kv-store/utils'; @@ -34,7 +33,6 @@ import { NoteProcessor } from './note_processor.js'; const TXS_PER_BLOCK = 4; describe('Note Processor', () => { - const grumpkin = new Grumpkin(); let database: PxeDatabase; let aztecNode: ReturnType>; let addNotesSpy: any; @@ -72,7 +70,7 @@ describe('Note Processor', () => { ownedL1NotePayloads.push(note.notePayload); } // const encryptedNote = - const log = note.toEncryptedBuffer(publicKey, grumpkin); + const log = note.toEncryptedBuffer(publicKey); // 1 tx containing 1 function invocation containing 1 log logs.push(new EncryptedFunctionL2Logs([new EncryptedL2Log(log)])); } diff --git a/yarn-project/pxe/src/note_processor/note_processor.ts b/yarn-project/pxe/src/note_processor/note_processor.ts index 0950a427598..3eaa6b3006d 100644 --- a/yarn-project/pxe/src/note_processor/note_processor.ts +++ b/yarn-project/pxe/src/note_processor/note_processor.ts @@ -8,7 +8,6 @@ import { } from '@aztec/circuit-types'; import { type NoteProcessorStats } from '@aztec/circuit-types/stats'; import { INITIAL_L2_BLOCK_NUM, MAX_NEW_NOTE_HASHES_PER_TX, type PublicKey } from '@aztec/circuits.js'; -import { Grumpkin } from '@aztec/circuits.js/barretenberg'; import { type Fr } from '@aztec/foundation/fields'; import { createDebugLogger } from '@aztec/foundation/log'; import { Timer } from '@aztec/foundation/timer'; @@ -99,7 +98,6 @@ export class NoteProcessor { return; } - const curve = new Grumpkin(); const blocksAndNotes: ProcessedData[] = []; // Keep track of notes that we couldn't process because the contract was not found. const deferredNoteDaos: DeferredNoteDao[] = []; @@ -132,7 +130,7 @@ export class NoteProcessor { for (const functionLogs of txFunctionLogs) { for (const log of functionLogs.logs) { this.stats.seen++; - const taggedNote = TaggedNote.fromEncryptedBuffer(log.data, secretKey, curve); + const taggedNote = TaggedNote.fromEncryptedBuffer(log.data, secretKey); if (taggedNote?.notePayload) { const { notePayload: payload } = taggedNote; // We have successfully decrypted the data. diff --git a/yarn-project/simulator/src/client/client_execution_context.ts b/yarn-project/simulator/src/client/client_execution_context.ts index 57a79776a97..22beba44aa1 100644 --- a/yarn-project/simulator/src/client/client_execution_context.ts +++ b/yarn-project/simulator/src/client/client_execution_context.ts @@ -21,7 +21,7 @@ import { type SideEffect, type TxContext, } from '@aztec/circuits.js'; -import { Aes128, type Grumpkin } from '@aztec/circuits.js/barretenberg'; +import { Aes128 } from '@aztec/circuits.js/barretenberg'; import { computePublicDataTreeLeafSlot, computeUniqueNoteHash, siloNoteHash } from '@aztec/circuits.js/hash'; import { type FunctionAbi, type FunctionArtifact, countArgumentsSize } from '@aztec/foundation/abi'; import { type AztecAddress } from '@aztec/foundation/aztec-address'; @@ -77,7 +77,6 @@ export class ClientExecutionContext extends ViewDataOracle { private readonly packedValuesCache: PackedValuesCache, private readonly noteCache: ExecutionNoteCache, db: DBOracle, - private readonly curve: Grumpkin, private node: AztecNode, protected sideEffectCounter: number = 0, log = createDebugLogger('aztec:simulator:client_execution_context'), @@ -345,7 +344,7 @@ export class ClientExecutionContext extends ViewDataOracle { const note = new Note(log); const l1NotePayload = new L1NotePayload(note, contractAddress, storageSlot, noteTypeId); const taggedNote = new TaggedNote(l1NotePayload); - const encryptedNote = taggedNote.toEncryptedBuffer(publicKey, this.curve); + const encryptedNote = taggedNote.toEncryptedBuffer(publicKey); const encryptedLog = new EncryptedL2Log(encryptedNote); this.encryptedLogs.push(encryptedLog); return Fr.fromBuffer(encryptedLog.hash()); @@ -421,7 +420,6 @@ export class ClientExecutionContext extends ViewDataOracle { this.packedValuesCache, this.noteCache, this.db, - this.curve, this.node, sideEffectCounter, ); diff --git a/yarn-project/simulator/src/client/simulator.ts b/yarn-project/simulator/src/client/simulator.ts index a0499982a29..cb767ea4d24 100644 --- a/yarn-project/simulator/src/client/simulator.ts +++ b/yarn-project/simulator/src/client/simulator.ts @@ -1,6 +1,5 @@ import { type AztecNode, type FunctionCall, type Note, type TxExecutionRequest } from '@aztec/circuit-types'; import { CallContext, FunctionData } from '@aztec/circuits.js'; -import { Grumpkin } from '@aztec/circuits.js/barretenberg'; import { type ArrayType, type FunctionArtifactWithDebugMetadata, @@ -79,8 +78,6 @@ export class AcirSimulator { ); } - const curve = new Grumpkin(); - const header = await this.db.getHeader(); // reserve the first side effect for the tx hash (inserted by the private kernel) @@ -104,7 +101,6 @@ export class AcirSimulator { PackedValuesCache.create(request.argsOfCalls), new ExecutionNoteCache(), this.db, - curve, this.node, startSideEffectCounter, );