From 0e72e02f34e4e38d4f2635ff777c87e81fdf023c Mon Sep 17 00:00:00 2001 From: benesjan Date: Fri, 13 Sep 2024 15:10:06 +0000 Subject: [PATCH 01/17] feat: partial notes log encoding --- .../encrypted_logs/encrypted_note_emission.nr | 3 ++- .../aztec/src/encrypted_logs/payload.nr | 25 ++++++++++++------- .../src/logs/l1_payload/l1_note_payload.ts | 13 +++++++++- .../src/logs/l1_payload/tagged_log.test.ts | 2 +- 4 files changed, 31 insertions(+), 12 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr index 16deb152483..67b8b41d63d 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr @@ -30,7 +30,8 @@ fn compute_raw_note_log( ovpk, ivpk, recipient, - note + note, + 0 ); let log_hash = sha256_to_field(encrypted_log); diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr index 84c7a9eacbf..bede005c5da 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr @@ -72,7 +72,8 @@ pub fn compute_encrypted_note_log( ovpk: OvpkM, ivpk: IvpkM, recipient: AztecAddress, - note: Note + note: Note, + num_publicly_deliviered_values: u8 ) -> [u8; M] where Note: NoteInterface { let (eph_sk, eph_pk) = generate_ephemeral_key_pair(); @@ -80,31 +81,35 @@ pub fn compute_encrypted_note_log( let incoming_header_ciphertext: [u8; 48] = header.compute_ciphertext(eph_sk, ivpk); let outgoing_header_ciphertext: [u8; 48] = header.compute_ciphertext(eph_sk, ovpk); + + // Below we would pass in either a partial note or the complete note and it would just call to_be_bytes on it. let incoming_body_ciphertext = EncryptedLogIncomingBody::from_note(note, storage_slot).compute_ciphertext(eph_sk, ivpk); let outgoing_body_ciphertext: [u8; 144] = EncryptedLogOutgoingBody::new(eph_sk, recipient, ivpk).compute_ciphertext(fr_to_fq(ovsk_app), eph_pk); let mut encrypted_bytes: [u8; M] = [0; M]; // @todo We ignore the tags for now + encrypted_bytes[64] = num_publicly_deliviered_values; // TODO(benesjan): This can be just a single bit if we store info about partial fields in ABI let eph_pk_bytes = point_to_bytes(eph_pk); for i in 0..32 { - encrypted_bytes[64 + i] = eph_pk_bytes[i]; + encrypted_bytes[65 + i] = eph_pk_bytes[i]; } for i in 0..48 { - encrypted_bytes[96 + i] = incoming_header_ciphertext[i]; - encrypted_bytes[144 + i] = outgoing_header_ciphertext[i]; + encrypted_bytes[97 + i] = incoming_header_ciphertext[i]; + encrypted_bytes[145 + i] = outgoing_header_ciphertext[i]; } for i in 0..144 { - encrypted_bytes[192 + i] = outgoing_body_ciphertext[i]; + encrypted_bytes[193 + i] = outgoing_body_ciphertext[i]; } // Then we fill in the rest as the incoming body ciphertext - let size = M - 336; + let size = M - 337; assert_eq(size, incoming_body_ciphertext.len(), "ciphertext length mismatch"); for i in 0..size { encrypted_bytes[336 + i] = incoming_body_ciphertext[i]; } // Current unoptimized size of the encrypted log + // num_publicly_delivered_values (1 bytes) // incoming_tag (32 bytes) // outgoing_tag (32 bytes) // eph_pk (32 bytes) @@ -170,21 +175,23 @@ mod test { let _ = OracleMock::mock("getRandomField").returns(eph_sk); let recipient = AztecAddress::from_field(0x10ee41ee4b62703b16f61e03cb0d88c4b306a9eb4a6ceeb2aff13428541689a2); + let num_publicly_deliviered_values: u8 = 0; - let log: [u8; 448] = compute_encrypted_note_log( + let log: [u8; 449] = compute_encrypted_note_log( contract_address, storage_slot, ovsk_app, ovpk_m, ivpk_m, recipient, - note + note, + num_publicly_deliviered_values ); // The following value was generated by `tagged_log.test.ts` // --> Run the test with AZTEC_GENERATE_TEST_DATA=1 flag to update test data. let encrypted_note_log_from_typescript = [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 70, 12, 14, 67, 77, 132, 110, 193, 234, 40, 110, 64, 144, 235, 86, 55, 111, 242, 123, 221, 193, 170, 202, 225, 216, 86, 84, 159, 112, 31, 167, 126, 79, 51, 186, 47, 71, 253, 172, 99, 112, 241, 59, 197, 241, 107, 186, 232, 87, 187, 230, 171, 62, 228, 234, 42, 51, 145, 146, 238, 242, 42, 71, 206, 13, 244, 66, 111, 195, 20, 203, 98, 148, 204, 242, 145, 183, 156, 29, 141, 54, 44, 220, 194, 35, 229, 16, 32, 204, 211, 49, 142, 112, 82, 202, 116, 241, 254, 146, 42, 217, 20, 189, 70, 228, 182, 171, 205, 104, 27, 99, 171, 28, 91, 244, 21, 30, 130, 240, 5, 72, 174, 124, 97, 197, 157, 248, 193, 23, 193, 76, 46, 141, 144, 70, 211, 45, 67, 167, 218, 129, 140, 104, 190, 41, 110, 249, 209, 68, 106, 135, 164, 80, 235, 63, 101, 80, 32, 13, 38, 99, 145, 91, 11, 173, 151, 231, 247, 65, 153, 117, 229, 167, 64, 239, 182, 126, 235, 83, 4, 169, 8, 8, 160, 4, 235, 252, 21, 96, 84, 161, 69, 145, 145, 215, 254, 161, 117, 246, 198, 65, 89, 179, 194, 90, 19, 121, 12, 202, 114, 80, 195, 14, 60, 128, 105, 142, 100, 86, 90, 108, 157, 219, 22, 172, 20, 121, 195, 25, 159, 236, 2, 70, 75, 42, 37, 34, 2, 17, 149, 20, 176, 32, 18, 204, 56, 117, 121, 34, 15, 3, 88, 123, 64, 68, 74, 233, 63, 59, 131, 222, 194, 192, 167, 110, 217, 10, 128, 73, 129, 172, 205, 103, 212, 60, 151, 141, 10, 151, 222, 151, 180, 43, 91, 148, 201, 110, 165, 10, 238, 32, 134, 235, 99, 216, 200, 182, 31, 22, 156, 18, 209, 222, 172, 239, 193, 212, 86, 99, 62, 70, 182, 45, 175, 241, 91, 202, 179, 225, 236, 95, 71, 66, 151, 225, 203, 53, 216, 85, 102, 130, 6, 8, 25, 180, 86, 58, 140, 198, 105, 102, 177, 42, 94, 115, 247, 145, 147, 24, 231, 39, 73, 27, 10, 219, 130, 115, 188, 74, 114, 5, 177, 199, 83, 183, 106, 87, 204, 238, 231, 72, 45, 240, 39, 174, 25, 98, 53, 187, 156, 159, 244, 38 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 70, 12, 14, 67, 77, 132, 110, 193, 234, 40, 110, 64, 144, 235, 86, 55, 111, 242, 123, 221, 193, 170, 202, 225, 216, 86, 84, 159, 112, 31, 167, 126, 79, 51, 186, 47, 71, 253, 172, 99, 112, 241, 59, 197, 241, 107, 186, 232, 87, 187, 230, 171, 62, 228, 234, 42, 51, 145, 146, 238, 242, 42, 71, 206, 13, 244, 66, 111, 195, 20, 203, 98, 148, 204, 242, 145, 183, 156, 29, 141, 54, 44, 220, 194, 35, 229, 16, 32, 204, 211, 49, 142, 112, 82, 202, 116, 241, 254, 146, 42, 217, 20, 189, 70, 228, 182, 171, 205, 104, 27, 99, 171, 28, 91, 244, 21, 30, 130, 240, 5, 72, 174, 124, 97, 197, 157, 248, 193, 23, 193, 76, 46, 141, 144, 70, 211, 45, 67, 167, 218, 129, 140, 104, 190, 41, 110, 249, 209, 68, 106, 135, 164, 80, 235, 63, 101, 80, 32, 13, 38, 99, 145, 91, 11, 173, 151, 231, 247, 65, 153, 117, 229, 167, 64, 239, 182, 126, 235, 83, 4, 169, 8, 8, 160, 4, 235, 252, 21, 96, 84, 161, 69, 145, 145, 215, 254, 161, 117, 246, 198, 65, 89, 179, 194, 90, 19, 121, 12, 202, 114, 80, 195, 14, 60, 128, 105, 142, 100, 86, 90, 108, 157, 219, 22, 172, 20, 121, 195, 25, 159, 236, 2, 70, 75, 42, 37, 34, 2, 17, 149, 20, 176, 32, 18, 204, 56, 117, 121, 34, 15, 3, 88, 123, 64, 68, 74, 233, 63, 59, 131, 222, 194, 192, 167, 110, 217, 10, 128, 73, 129, 172, 205, 103, 212, 60, 151, 141, 10, 151, 222, 151, 180, 43, 91, 148, 201, 110, 165, 10, 238, 32, 134, 235, 99, 216, 200, 182, 31, 22, 156, 18, 209, 222, 172, 239, 193, 212, 86, 99, 62, 70, 182, 45, 175, 241, 91, 202, 179, 225, 236, 95, 71, 66, 151, 225, 203, 53, 216, 85, 102, 130, 6, 8, 25, 180, 86, 58, 140, 198, 105, 102, 177, 42, 94, 115, 247, 145, 147, 24, 231, 39, 73, 27, 10, 219, 130, 115, 188, 74, 114, 5, 177, 199, 83, 183, 106, 87, 204, 238, 231, 72, 45, 240, 39, 174, 25, 98, 53, 187, 156, 159, 244, 38 ]; for i in 0..encrypted_note_log_from_typescript.len() { assert_eq(log[i], encrypted_note_log_from_typescript[i]); diff --git a/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts b/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts index 1f53c1e00c1..e79970b0b2e 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts @@ -67,7 +67,11 @@ export class L1NotePayload extends L1Payload { } public encrypt(ephSk: GrumpkinScalar, recipient: AztecAddress, ivpk: PublicKey, ovKeys: KeyValidationRequest) { - return super._encrypt( + // TODO(benesjan): numPubliclyDeliveredValues could occupy just a single bit if we store info about partial fields + // in the ABI + // We always set the value to 0 here as we don't need partial notes encryption support in TS + const numPubliclyDeliveredValues = 0; + const encryptedPayload = super._encrypt( this.contractAddress, ephSk, recipient, @@ -75,6 +79,7 @@ export class L1NotePayload extends L1Payload { ovKeys, new EncryptedNoteLogIncomingBody(this.storageSlot, this.noteTypeId, this.note), ); + return Buffer.concat([Buffer.alloc(1, numPubliclyDeliveredValues), encryptedPayload]); } /** @@ -93,6 +98,9 @@ export class L1NotePayload extends L1Payload { const input = Buffer.isBuffer(ciphertext) ? ciphertext : Buffer.from(ciphertext.map((x: bigint) => Number(x))); const reader = BufferReader.asReader(input); + // TODO(benesjan): implement pub values extraction. + const _numPubliclyDeliveredValues = reader.readUInt8(); + const [address, incomingBody] = super._decryptAsIncoming( reader.readToEnd(), ivsk, @@ -119,6 +127,9 @@ export class L1NotePayload extends L1Payload { const input = Buffer.isBuffer(ciphertext) ? ciphertext : Buffer.from(ciphertext.map((x: bigint) => Number(x))); const reader = BufferReader.asReader(input); + // TODO(benesjan): implement pub values extraction. + const _numPubliclyDeliveredValues = reader.readUInt8(); + const [address, incomingBody] = super._decryptAsOutgoing( reader.readToEnd(), ovsk, diff --git a/yarn-project/circuit-types/src/logs/l1_payload/tagged_log.test.ts b/yarn-project/circuit-types/src/logs/l1_payload/tagged_log.test.ts index 05cf0b20921..00fc5cf2100 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/tagged_log.test.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/tagged_log.test.ts @@ -83,7 +83,7 @@ describe('L1 Note Payload', () => { const encrypted = taggedLog.encrypt(ephSk, recipientAddress, ivpk, ovKeys).toString('hex'); expect(encrypted).toMatchInlineSnapshot( - `"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008d460c0e434d846ec1ea286e4090eb56376ff27bddc1aacae1d856549f701fa77e4f33ba2f47fdac6370f13bc5f16bbae857bbe6ab3ee4ea2a339192eef22a47ce0df4426fc314cb6294ccf291b79c1d8d362cdcc223e51020ccd3318e7052ca74f1fe922ad914bd46e4b6abcd681b63ab1c5bf4151e82f00548ae7c61c59df8c117c14c2e8d9046d32d43a7da818c68be296ef9d1446a87a450eb3f6550200d2663915b0bad97e7f7419975e5a740efb67eeb5304a90808a004ebfc156054a1459191d7fea175f6c64159b3c25a13790cca7250c30e3c80698e64565a6c9ddb16ac1479c3199fec02464b2a252202119514b02012cc387579220f03587b40444ae93f3b83dec2c0a76ed90a804981accd67d43c978d0a97de97b42b5b94c96ea50aee2086eb63d8c8b61f169c12d1deacefc1d456633e46b62daff15bcab3e1ec5f474297e1cb35d8556682060819b4563a8cc66966b12a5e73f7919318e727491b0adb8273bc4a7205b1c753b76a57cceee7482df027ae196235bb9c9ff426"`, + `"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008d460c0e434d846ec1ea286e4090eb56376ff27bddc1aacae1d856549f701fa77e4f33ba2f47fdac6370f13bc5f16bbae857bbe6ab3ee4ea2a339192eef22a47ce0df4426fc314cb6294ccf291b79c1d8d362cdcc223e51020ccd3318e7052ca74f1fe922ad914bd46e4b6abcd681b63ab1c5bf4151e82f00548ae7c61c59df8c117c14c2e8d9046d32d43a7da818c68be296ef9d1446a87a450eb3f6550200d2663915b0bad97e7f7419975e5a740efb67eeb5304a90808a004ebfc156054a1459191d7fea175f6c64159b3c25a13790cca7250c30e3c80698e64565a6c9ddb16ac1479c3199fec02464b2a252202119514b02012cc387579220f03587b40444ae93f3b83dec2c0a76ed90a804981accd67d43c978d0a97de97b42b5b94c96ea50aee2086eb63d8c8b61f169c12d1deacefc1d456633e46b62daff15bcab3e1ec5f474297e1cb35d8556682060819b4563a8cc66966b12a5e73f7919318e727491b0adb8273bc4a7205b1c753b76a57cceee7482df027ae196235bb9c9ff426"`, ); const byteArrayString = `[${encrypted.match(/.{1,2}/g)!.map(byte => parseInt(byte, 16))}]`; From 5ee9e97133c8324ea624bfcec92916dd2072bb58 Mon Sep 17 00:00:00 2001 From: benesjan Date: Fri, 13 Sep 2024 15:32:36 +0000 Subject: [PATCH 02/17] fix --- noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr index bede005c5da..a9e9eb6608d 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr @@ -105,7 +105,7 @@ pub fn compute_encrypted_note_log( let size = M - 337; assert_eq(size, incoming_body_ciphertext.len(), "ciphertext length mismatch"); for i in 0..size { - encrypted_bytes[336 + i] = incoming_body_ciphertext[i]; + encrypted_bytes[337 + i] = incoming_body_ciphertext[i]; } // Current unoptimized size of the encrypted log From 8f6de1f179cd64b45e33dca17543ee5cd8d6ea74 Mon Sep 17 00:00:00 2001 From: benesjan Date: Mon, 16 Sep 2024 09:45:50 +0000 Subject: [PATCH 03/17] updated log traits --- .../aztec-nr/aztec/src/oracle/logs_traits.nr | 75 ++++++++++--------- .../contracts/counter_contract/src/main.nr | 2 +- 2 files changed, 39 insertions(+), 38 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/oracle/logs_traits.nr b/noir-projects/aztec-nr/aztec/src/oracle/logs_traits.nr index 9417dfe6224..4640068d054 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/logs_traits.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/logs_traits.nr @@ -1,5 +1,6 @@ use dep::protocol_types::address::AztecAddress; +// TODO(#8548): We have arithmetics over generics now so this file can be nuked. // TODO: this is awful but since we can't have a fn that maps [Field; N] -> [u8; 416 + N * 32] // (where N is the note pre-image size and 416 + N * 32 is the encryption output size) // The fns for LensForEncryptedLog are never used, it's just to tell the compiler what the lens are @@ -11,105 +12,105 @@ use dep::protocol_types::address::AztecAddress; // anything, so we can remove this trait trait LensForEncryptedLog { // N = note preimage input in fields - // M = encryption output len in bytes (= 416 + N * 32) + // M = encryption output len in bytes (= 417 + N * 32) fn output_fields(self: [Field; N]) -> [Field; N]; fn output_bytes(self: [Field; N]) -> [u8; M]; } -impl LensForEncryptedLog<1, 448> for [Field; 1] { +impl LensForEncryptedLog<1, 449> for [Field; 1] { fn output_fields(self) -> [Field; 1] { [self[0]; 1] } - fn output_bytes(self) -> [u8; 448] { - [self[0] as u8; 448] + fn output_bytes(self) -> [u8; 449] { + [self[0] as u8; 449] } } -impl LensForEncryptedLog<2, 480> for [Field; 2] { +impl LensForEncryptedLog<2, 481> for [Field; 2] { fn output_fields(self) -> [Field; 2] { [self[0]; 2] } - fn output_bytes(self) -> [u8; 480] { - [self[0] as u8; 480] + fn output_bytes(self) -> [u8; 481] { + [self[0] as u8; 481] } } -impl LensForEncryptedLog<3, 512> for [Field; 3] { +impl LensForEncryptedLog<3, 513> for [Field; 3] { fn output_fields(self) -> [Field; 3] { [self[0]; 3] } - fn output_bytes(self) -> [u8; 512] { - [self[0] as u8; 512] + fn output_bytes(self) -> [u8; 513] { + [self[0] as u8; 513] } } -impl LensForEncryptedLog<4, 544> for [Field; 4] { +impl LensForEncryptedLog<4, 545> for [Field; 4] { fn output_fields(self) -> [Field; 4] { [self[0]; 4] } - fn output_bytes(self) -> [u8; 544] { - [self[0] as u8; 544] + fn output_bytes(self) -> [u8; 545] { + [self[0] as u8; 545] } } -impl LensForEncryptedLog<5, 576> for [Field; 5] { +impl LensForEncryptedLog<5, 577> for [Field; 5] { fn output_fields(self) -> [Field; 5] { [self[0]; 5] } - fn output_bytes(self) -> [u8; 576] { - [self[0] as u8; 576] + fn output_bytes(self) -> [u8; 577] { + [self[0] as u8; 577] } } -impl LensForEncryptedLog<6, 608> for [Field; 6] { +impl LensForEncryptedLog<6, 609> for [Field; 6] { fn output_fields(self) -> [Field; 6] { [self[0]; 6] } - fn output_bytes(self) -> [u8; 608] { - [self[0] as u8; 608] + fn output_bytes(self) -> [u8; 609] { + [self[0] as u8; 609] } } -impl LensForEncryptedLog<7, 640> for [Field; 7] { +impl LensForEncryptedLog<7, 641> for [Field; 7] { fn output_fields(self) -> [Field; 7] { [self[0]; 7] } - fn output_bytes(self) -> [u8; 640] { - [self[0] as u8; 640] + fn output_bytes(self) -> [u8; 641] { + [self[0] as u8; 641] } } -impl LensForEncryptedLog<8, 672> for [Field; 8] { +impl LensForEncryptedLog<8, 673> for [Field; 8] { fn output_fields(self) -> [Field; 8] { [self[0]; 8] } - fn output_bytes(self) -> [u8; 672] { - [self[0] as u8; 672] + fn output_bytes(self) -> [u8; 673] { + [self[0] as u8; 673] } } -impl LensForEncryptedLog<9, 704> for [Field; 9] { +impl LensForEncryptedLog<9, 705> for [Field; 9] { fn output_fields(self) -> [Field; 9] { [self[0]; 9] } - fn output_bytes(self) -> [u8; 704] { - [self[0] as u8; 704] + fn output_bytes(self) -> [u8; 705] { + [self[0] as u8; 705] } } -impl LensForEncryptedLog<10, 736> for [Field; 10] { +impl LensForEncryptedLog<10, 737> for [Field; 10] { fn output_fields(self) -> [Field; 10] { [self[0]; 10] } - fn output_bytes(self) -> [u8; 736] { - [self[0] as u8; 736] + fn output_bytes(self) -> [u8; 737] { + [self[0] as u8; 737] } } -impl LensForEncryptedLog<11, 768> for [Field; 11] { +impl LensForEncryptedLog<11, 769> for [Field; 11] { fn output_fields(self) -> [Field; 11] { [self[0]; 11] } - fn output_bytes(self) -> [u8; 768] { - [self[0] as u8; 768] + fn output_bytes(self) -> [u8; 769] { + [self[0] as u8; 769] } } -impl LensForEncryptedLog<12, 800> for [Field; 12] { +impl LensForEncryptedLog<12, 801> for [Field; 12] { fn output_fields(self) -> [Field; 12] { [self[0]; 12] } - fn output_bytes(self) -> [u8; 800] { - [self[0] as u8; 800] + fn output_bytes(self) -> [u8; 801] { + [self[0] as u8; 801] } } diff --git a/noir-projects/noir-contracts/contracts/counter_contract/src/main.nr b/noir-projects/noir-contracts/contracts/counter_contract/src/main.nr index 62a3afd057d..d454c047f6e 100644 --- a/noir-projects/noir-contracts/contracts/counter_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/counter_contract/src/main.nr @@ -39,7 +39,7 @@ contract Counter { // docs:end:get_counter // docs:start:test_imports - use dep::aztec::test::{helpers::{cheatcodes, test_environment::TestEnvironment}}; + use dep::aztec::test::helpers::test_environment::TestEnvironment; use dep::aztec::protocol_types::storage::map::derive_storage_slot_in_map; use dep::aztec::note::note_getter::{MAX_NOTES_PER_PAGE, view_notes}; use dep::aztec::note::note_viewer_options::NoteViewerOptions; From 6914bbb133188db3159dea9011c456016d91f318 Mon Sep 17 00:00:00 2001 From: benesjan Date: Mon, 16 Sep 2024 10:33:55 +0000 Subject: [PATCH 04/17] WIP --- .../aztec/src/encrypted_logs/payload.nr | 2 +- .../src/logs/l1_payload/l1_note_payload.ts | 46 ++++++++++++++----- 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr index a9e9eb6608d..8d875a5c25c 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr @@ -109,9 +109,9 @@ pub fn compute_encrypted_note_log( } // Current unoptimized size of the encrypted log - // num_publicly_delivered_values (1 bytes) // incoming_tag (32 bytes) // outgoing_tag (32 bytes) + // num_publicly_delivered_values (1 byte) // eph_pk (32 bytes) // incoming_header (48 bytes) // outgoing_header (48 bytes) diff --git a/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts b/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts index e79970b0b2e..efc86130985 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts @@ -96,18 +96,18 @@ export class L1NotePayload extends L1Payload { */ public static decryptAsIncoming(ciphertext: Buffer | bigint[], ivsk: GrumpkinScalar) { const input = Buffer.isBuffer(ciphertext) ? ciphertext : Buffer.from(ciphertext.map((x: bigint) => Number(x))); - const reader = BufferReader.asReader(input); - - // TODO(benesjan): implement pub values extraction. - const _numPubliclyDeliveredValues = reader.readUInt8(); + const [publicValues, remainingCiphertext] = this.#getPublicValuesAndRemainingCipherText(input); const [address, incomingBody] = super._decryptAsIncoming( - reader.readToEnd(), + remainingCiphertext, ivsk, EncryptedNoteLogIncomingBody.fromCiphertext, ); - return new L1NotePayload(incomingBody.note, address, incomingBody.storageSlot, incomingBody.noteTypeId); + // Partial fields are expected to be at the end of the note + const note = new Note([...incomingBody.note.items, ...publicValues]); + + return new L1NotePayload(note, address, incomingBody.storageSlot, incomingBody.noteTypeId); } /** @@ -125,18 +125,18 @@ export class L1NotePayload extends L1Payload { */ public static decryptAsOutgoing(ciphertext: Buffer | bigint[], ovsk: GrumpkinScalar) { const input = Buffer.isBuffer(ciphertext) ? ciphertext : Buffer.from(ciphertext.map((x: bigint) => Number(x))); - const reader = BufferReader.asReader(input); - - // TODO(benesjan): implement pub values extraction. - const _numPubliclyDeliveredValues = reader.readUInt8(); + const [publicValues, remainingCiphertext] = this.#getPublicValuesAndRemainingCipherText(input); const [address, incomingBody] = super._decryptAsOutgoing( - reader.readToEnd(), + remainingCiphertext, ovsk, EncryptedNoteLogIncomingBody.fromCiphertext, ); - return new L1NotePayload(incomingBody.note, address, incomingBody.storageSlot, incomingBody.noteTypeId); + // Partial fields are expected to be at the end of the note + const note = new Note([...incomingBody.note.items, ...publicValues]); + + return new L1NotePayload(note, address, incomingBody.storageSlot, incomingBody.noteTypeId); } public equals(other: L1NotePayload) { @@ -147,4 +147,26 @@ export class L1NotePayload extends L1Payload { this.noteTypeId.equals(other.noteTypeId) ); } + + static #getPublicValuesAndRemainingCipherText(input: Buffer): [Fr[], Buffer] { + const reader = BufferReader.asReader(input); + const numPubliclyDeliveredValues = reader.readUInt8(); + + const remainingData = reader.readToEnd(); + const publicValuesData = remainingData.subarray( + remainingData.length - numPubliclyDeliveredValues * Fr.SIZE_IN_BYTES, + remainingData.length, + ); + if (publicValuesData.length % Fr.SIZE_IN_BYTES !== 0) { + throw new Error('Public values byte length is not a multiple of Fr size'); + } + const publicValues = []; + for (let i = 0; i < publicValuesData.length; i += Fr.SIZE_IN_BYTES) { + publicValues.push(Fr.fromBuffer(publicValuesData.subarray(i, i + Fr.SIZE_IN_BYTES))); + } + + const remainingCiphertext = remainingData.subarray(0, remainingData.length - publicValuesData.length); + + return [publicValues, remainingCiphertext]; + } } From 3efb93f369303a03bb820d1acd2ecf743527e16b Mon Sep 17 00:00:00 2001 From: benesjan Date: Mon, 16 Sep 2024 11:58:16 +0000 Subject: [PATCH 05/17] WIP --- .../aztec/src/encrypted_logs/payload.nr | 75 ++++++++++++++++++- .../src/logs/l1_payload/l1_note_payload.ts | 2 +- .../src/logs/l1_payload/tagged_log.test.ts | 56 ++++++++++++++ 3 files changed, 128 insertions(+), 5 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr index 8d875a5c25c..fcdd895c241 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr @@ -73,7 +73,7 @@ pub fn compute_encrypted_note_log( ivpk: IvpkM, recipient: AztecAddress, note: Note, - num_publicly_deliviered_values: u8 + num_publicly_delivered_values: u8 ) -> [u8; M] where Note: NoteInterface { let (eph_sk, eph_pk) = generate_ephemeral_key_pair(); @@ -89,7 +89,7 @@ pub fn compute_encrypted_note_log( let mut encrypted_bytes: [u8; M] = [0; M]; // @todo We ignore the tags for now - encrypted_bytes[64] = num_publicly_deliviered_values; // TODO(benesjan): This can be just a single bit if we store info about partial fields in ABI + encrypted_bytes[64] = num_publicly_delivered_values; // TODO(#8558): This can be just a single bit if we store info about partial fields in ABI let eph_pk_bytes = point_to_bytes(eph_pk); for i in 0..32 { encrypted_bytes[65 + i] = eph_pk_bytes[i]; @@ -175,7 +175,7 @@ mod test { let _ = OracleMock::mock("getRandomField").returns(eph_sk); let recipient = AztecAddress::from_field(0x10ee41ee4b62703b16f61e03cb0d88c4b306a9eb4a6ceeb2aff13428541689a2); - let num_publicly_deliviered_values: u8 = 0; + let num_publicly_delivered_values: u8 = 0; let log: [u8; 449] = compute_encrypted_note_log( contract_address, @@ -185,7 +185,7 @@ mod test { ivpk_m, recipient, note, - num_publicly_deliviered_values + num_publicly_delivered_values ); // The following value was generated by `tagged_log.test.ts` @@ -198,4 +198,71 @@ mod test { } assert_eq(encrypted_note_log_from_typescript.len(), log.len()); } + + #[test] + fn test_encrypted_note_log_of_finalized_partial_note_matches_typescript() { + // All the values in this test were copied over from `tagged_log.test.ts` + let contract_address = AztecAddress::from_field(0x10f48cd9eff7ae5b209c557c70de2e657ee79166868676b787e9417e19260e04); + let storage_slot = 0x0fe46be583b71f4ab5b70c2657ff1d05cccf1d292a9369628d1a194f944e6599; + let ovsk_app = 0x03a6513d6def49f41d20373d2cec894c23e7492794b08fc50c0e8a1bd2512612; + let ovpk_m = OvpkM { + inner: Point { + x: 0x1961448682803198631f299340e4206bb12809d4bebbf012b30f59af73ba1a15, + y: 0x133674060c3925142aceb4f1dcd9f9137d0217d37ff8729ee5ceaa6e2790353d, + is_infinite: false + } + }; + let ivpk_m = IvpkM { + inner: Point { + x: 0x260cd3904f6df16e974c29944fdc839e40fb5cf293f03df2eb370851d3a527bc, + y: 0x0eef2964fe6640e84c82b5d2915892409b38e9e25d39f68dd79edb725c55387f, + is_infinite: false + } + }; + + let note_value = 0x301640ceea758391b2e161c92c0513f129020f4125256afdae2646ce31099f5c; + let note_public_value1 = 0x14172339287e8d281545c177313f02b6aa2fedfd628cfd8b7f11a136fd0d6557; + let note_public_value2 = 0x0834d81e3f73c7e2809b08ae38600ffc76a2554473eeab6de7bff4b33a84feac; + let note = MockNoteBuilder::new(note_value).contract_address(contract_address).storage_slot(storage_slot).build(); + + let eph_sk = 0x1358d15019d4639393d62b97e1588c095957ce74a1c32d6ec7d62fe6705d9538; + let _ = OracleMock::mock("getRandomField").returns(eph_sk); + + let recipient = AztecAddress::from_field(0x10ee41ee4b62703b16f61e03cb0d88c4b306a9eb4a6ceeb2aff13428541689a2); + let num_publicly_delivered_values: u8 = 2; + + // First we compute the encrypted log without the public values + let log_without_public_values: [u8; 449] = compute_encrypted_note_log( + contract_address, + storage_slot, + ovsk_app, + ovpk_m, + ivpk_m, + recipient, + note, + num_publicly_delivered_values + ); + + // Then we "append" the public values to the log by copying both the original log and the current log into a new byte array + let mut log: [u8; 513] = [0; 513]; + for i in 0..449 { + log[i] = log_without_public_values[i]; + } + let note_public_value1_bytes: [u8; 32] = note_public_value1.to_be_bytes(); + let note_public_value2_bytes: [u8; 32] = note_public_value2.to_be_bytes(); + for i in 0..32 { + log[449 + i] = note_public_value1_bytes[i]; + log[481 + i] = note_public_value2_bytes[i]; + } + + // The following value was generated by `tagged_log.test.ts` + // --> Run the test with AZTEC_GENERATE_TEST_DATA=1 flag to update test data. + let encrypted_note_log_of_finalized_partial_from_typescript = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 141, 70, 12, 14, 67, 77, 132, 110, 193, 234, 40, 110, 64, 144, 235, 86, 55, 111, 242, 123, 221, 193, 170, 202, 225, 216, 86, 84, 159, 112, 31, 167, 126, 79, 51, 186, 47, 71, 253, 172, 99, 112, 241, 59, 197, 241, 107, 186, 232, 87, 187, 230, 171, 62, 228, 234, 42, 51, 145, 146, 238, 242, 42, 71, 206, 13, 244, 66, 111, 195, 20, 203, 98, 148, 204, 242, 145, 183, 156, 29, 141, 54, 44, 220, 194, 35, 229, 16, 32, 204, 211, 49, 142, 112, 82, 202, 116, 241, 254, 146, 42, 217, 20, 189, 70, 228, 182, 171, 205, 104, 27, 99, 171, 28, 91, 244, 21, 30, 130, 240, 5, 72, 174, 124, 97, 197, 157, 248, 193, 23, 193, 76, 46, 141, 144, 70, 211, 45, 67, 167, 218, 129, 140, 104, 190, 41, 110, 249, 209, 68, 106, 135, 164, 80, 235, 63, 101, 80, 32, 13, 38, 99, 145, 91, 11, 173, 151, 231, 247, 65, 153, 117, 229, 167, 64, 239, 182, 126, 235, 83, 4, 169, 8, 8, 160, 4, 235, 252, 21, 96, 84, 161, 69, 145, 145, 215, 254, 161, 117, 246, 198, 65, 89, 179, 194, 90, 19, 121, 12, 202, 114, 80, 195, 14, 60, 128, 105, 142, 100, 86, 90, 108, 157, 219, 22, 172, 20, 121, 195, 25, 159, 236, 2, 70, 75, 42, 37, 34, 2, 17, 149, 20, 176, 32, 18, 204, 56, 117, 121, 34, 15, 3, 88, 123, 64, 68, 74, 233, 63, 59, 131, 222, 194, 192, 167, 110, 217, 10, 128, 73, 129, 172, 205, 103, 212, 60, 151, 141, 10, 151, 222, 151, 180, 43, 91, 148, 201, 110, 165, 10, 238, 32, 134, 235, 99, 216, 200, 182, 31, 22, 156, 18, 209, 222, 172, 239, 193, 212, 86, 99, 62, 70, 182, 45, 175, 241, 91, 202, 179, 225, 236, 95, 71, 66, 151, 225, 203, 53, 216, 85, 102, 130, 6, 8, 25, 180, 86, 58, 140, 198, 105, 102, 177, 42, 94, 115, 247, 145, 147, 24, 231, 39, 73, 27, 10, 219, 130, 115, 188, 74, 114, 5, 177, 199, 83, 183, 106, 87, 204, 238, 231, 72, 45, 240, 39, 174, 25, 98, 53, 187, 156, 159, 244, 38, 20, 23, 35, 57, 40, 126, 141, 40, 21, 69, 193, 119, 49, 63, 2, 182, 170, 47, 237, 253, 98, 140, 253, 139, 127, 17, 161, 54, 253, 13, 101, 87, 8, 52, 216, 30, 63, 115, 199, 226, 128, 155, 8, 174, 56, 96, 15, 252, 118, 162, 85, 68, 115, 238, 171, 109, 231, 191, 244, 179, 58, 132, 254, 172 + ]; + for i in 0..encrypted_note_log_of_finalized_partial_from_typescript.len() { + assert_eq(log[i], encrypted_note_log_of_finalized_partial_from_typescript[i]); + } + assert_eq(encrypted_note_log_of_finalized_partial_from_typescript.len(), log.len()); + } } diff --git a/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts b/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts index efc86130985..750519e4c64 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts @@ -67,7 +67,7 @@ export class L1NotePayload extends L1Payload { } public encrypt(ephSk: GrumpkinScalar, recipient: AztecAddress, ivpk: PublicKey, ovKeys: KeyValidationRequest) { - // TODO(benesjan): numPubliclyDeliveredValues could occupy just a single bit if we store info about partial fields + // TODO(#8558): numPubliclyDeliveredValues could occupy just a single bit if we store info about partial fields // in the ABI // We always set the value to 0 here as we don't need partial notes encryption support in TS const numPubliclyDeliveredValues = 0; diff --git a/yarn-project/circuit-types/src/logs/l1_payload/tagged_log.test.ts b/yarn-project/circuit-types/src/logs/l1_payload/tagged_log.test.ts index 00fc5cf2100..5ef67de5edc 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/tagged_log.test.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/tagged_log.test.ts @@ -96,6 +96,62 @@ describe('L1 Note Payload', () => { ); }); + it.only('encrypted tagged log of finalized partial note matches Noir', () => { + const numPublicValues = 2; + + // All the values in this test were arbitrarily set and copied over to `payload.nr` + const contract = AztecAddress.fromString('0x10f48cd9eff7ae5b209c557c70de2e657ee79166868676b787e9417e19260e04'); + const storageSlot = new Fr(0x0fe46be583b71f4ab5b70c2657ff1d05cccf1d292a9369628d1a194f944e6599n); + const noteValue = new Fr(0x301640ceea758391b2e161c92c0513f129020f4125256afdae2646ce31099f5cn); + const notePublicValue1 = new Fr(0x14172339287e8d281545c177313f02b6aa2fedfd628cfd8b7f11a136fd0d6557n); + const notePublicValue2 = new Fr(0x0834d81e3f73c7e2809b08ae38600ffc76a2554473eeab6de7bff4b33a84feacn); + const noteTypeId = new NoteSelector(4135); // note type id of mock_note.nr + + const payload = new L1NotePayload(new Note([noteValue]), contract, storageSlot, noteTypeId); + + const ovskM = new GrumpkinScalar(0x06b76394ac57b8a18ceb08b14ed15b5b778d5c506b4cfb7edc203324eab27c05n); + const ivskM = new GrumpkinScalar(0x03fd94b1101e834e829cda4f227043f60490b5c7b3073875f5bfbe5028ed05ccn); + + const ovKeys = getKeyValidationRequest(ovskM, payload.contractAddress); + + const ephSk = new GrumpkinScalar(0x1358d15019d4639393d62b97e1588c095957ce74a1c32d6ec7d62fe6705d9538n); + + const recipientAddress = AztecAddress.fromString( + '0x10ee41ee4b62703b16f61e03cb0d88c4b306a9eb4a6ceeb2aff13428541689a2', + ); + + const ivpk = derivePublicKeyFromSecretKey(ivskM); + + const taggedLog = new TaggedLog(payload, new Fr(0), new Fr(0)); + + // We manually update the log because modifying encrypt func to support public values would just polute the code + // because it is never used in prod --> the encrypt functionality is only evner used without the public values. + const encryptedBuf = taggedLog.encrypt(ephSk, recipientAddress, ivpk, ovKeys); + + // We update the encrypted buffer with the public values + encryptedBuf[64] = numPublicValues; + const encryptedBufWithPublicValues = Buffer.concat([ + encryptedBuf, + notePublicValue1.toBuffer(), + notePublicValue2.toBuffer(), + ]); + + const encrypted = encryptedBufWithPublicValues.toString('hex'); + + expect(encrypted).toMatchInlineSnapshot( + `"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028d460c0e434d846ec1ea286e4090eb56376ff27bddc1aacae1d856549f701fa77e4f33ba2f47fdac6370f13bc5f16bbae857bbe6ab3ee4ea2a339192eef22a47ce0df4426fc314cb6294ccf291b79c1d8d362cdcc223e51020ccd3318e7052ca74f1fe922ad914bd46e4b6abcd681b63ab1c5bf4151e82f00548ae7c61c59df8c117c14c2e8d9046d32d43a7da818c68be296ef9d1446a87a450eb3f6550200d2663915b0bad97e7f7419975e5a740efb67eeb5304a90808a004ebfc156054a1459191d7fea175f6c64159b3c25a13790cca7250c30e3c80698e64565a6c9ddb16ac1479c3199fec02464b2a252202119514b02012cc387579220f03587b40444ae93f3b83dec2c0a76ed90a804981accd67d43c978d0a97de97b42b5b94c96ea50aee2086eb63d8c8b61f169c12d1deacefc1d456633e46b62daff15bcab3e1ec5f474297e1cb35d8556682060819b4563a8cc66966b12a5e73f7919318e727491b0adb8273bc4a7205b1c753b76a57cceee7482df027ae196235bb9c9ff42614172339287e8d281545c177313f02b6aa2fedfd628cfd8b7f11a136fd0d65570834d81e3f73c7e2809b08ae38600ffc76a2554473eeab6de7bff4b33a84feac"`, + ); + + const byteArrayString = `[${encrypted.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/encrypted_logs/payload.nr', + 'encrypted_note_log_of_finalized_partial_from_typescript', + byteArrayString, + ); + }); + const getKeyValidationRequest = (ovskM: GrumpkinScalar, app: AztecAddress) => { const ovskApp = computeOvskApp(ovskM, app); const ovpkM = derivePublicKeyFromSecretKey(ovskM); From 55521fe2edff30f733d1ac87292719bd04b2ebfd Mon Sep 17 00:00:00 2001 From: benesjan Date: Mon, 16 Sep 2024 12:07:40 +0000 Subject: [PATCH 06/17] cleanup --- .../aztec/src/encrypted_logs/encrypted_note_emission.nr | 5 ++++- noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr | 2 -- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr index 67b8b41d63d..e18fd7dd8c2 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr @@ -23,6 +23,9 @@ fn compute_raw_note_log( let contract_address: AztecAddress = context.this_address(); + // Number of publicly delivered values is always 0 here because `compute(...)` is only called + // in the non-partial partial note flow. + let num_publicly_delivered_values = 0; let encrypted_log: [u8; M] = compute_encrypted_note_log( contract_address, storage_slot, @@ -31,7 +34,7 @@ fn compute_raw_note_log( ivpk, recipient, note, - 0 + num_publicly_delivered_values ); let log_hash = sha256_to_field(encrypted_log); diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr index fcdd895c241..7538b6fc596 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr @@ -81,8 +81,6 @@ pub fn compute_encrypted_note_log( let incoming_header_ciphertext: [u8; 48] = header.compute_ciphertext(eph_sk, ivpk); let outgoing_header_ciphertext: [u8; 48] = header.compute_ciphertext(eph_sk, ovpk); - - // Below we would pass in either a partial note or the complete note and it would just call to_be_bytes on it. let incoming_body_ciphertext = EncryptedLogIncomingBody::from_note(note, storage_slot).compute_ciphertext(eph_sk, ivpk); let outgoing_body_ciphertext: [u8; 144] = EncryptedLogOutgoingBody::new(eph_sk, recipient, ivpk).compute_ciphertext(fr_to_fq(ovsk_app), eph_pk); From d54ba48f30dc49a35f7b807d1c79d8a2c255a963 Mon Sep 17 00:00:00 2001 From: benesjan Date: Mon, 16 Sep 2024 12:10:28 +0000 Subject: [PATCH 07/17] comment fix --- .../aztec/src/encrypted_logs/encrypted_note_emission.nr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr index e18fd7dd8c2..0610d13c783 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr @@ -24,7 +24,7 @@ fn compute_raw_note_log( let contract_address: AztecAddress = context.this_address(); // Number of publicly delivered values is always 0 here because `compute(...)` is only called - // in the non-partial partial note flow. + // in the non-partial note flow. let num_publicly_delivered_values = 0; let encrypted_log: [u8; M] = compute_encrypted_note_log( contract_address, From 1215f179bca434efbfcb938b5e4b40241199996e Mon Sep 17 00:00:00 2001 From: benesjan Date: Mon, 16 Sep 2024 12:57:10 +0000 Subject: [PATCH 08/17] test fix --- .../circuit-types/src/logs/l1_payload/l1_note_payload.ts | 2 +- .../circuit-types/src/logs/l1_payload/tagged_log.test.ts | 2 +- yarn-project/circuit-types/src/logs/l1_payload/tagged_log.ts | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts b/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts index 750519e4c64..47e64161f94 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts @@ -158,7 +158,7 @@ export class L1NotePayload extends L1Payload { remainingData.length, ); if (publicValuesData.length % Fr.SIZE_IN_BYTES !== 0) { - throw new Error('Public values byte length is not a multiple of Fr size'); + throw new Error(`Public values byte length is not a multiple of Fr size. Length: ${publicValuesData.length}`); } const publicValues = []; for (let i = 0; i < publicValuesData.length; i += Fr.SIZE_IN_BYTES) { diff --git a/yarn-project/circuit-types/src/logs/l1_payload/tagged_log.test.ts b/yarn-project/circuit-types/src/logs/l1_payload/tagged_log.test.ts index 5ef67de5edc..b97d84705d2 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/tagged_log.test.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/tagged_log.test.ts @@ -96,7 +96,7 @@ describe('L1 Note Payload', () => { ); }); - it.only('encrypted tagged log of finalized partial note matches Noir', () => { + it('encrypted tagged log of finalized partial note matches Noir', () => { const numPublicValues = 2; // All the values in this test were arbitrarily set and copied over to `payload.nr` diff --git a/yarn-project/circuit-types/src/logs/l1_payload/tagged_log.ts b/yarn-project/circuit-types/src/logs/l1_payload/tagged_log.ts index 70568c08ad6..b343d3880bb 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/tagged_log.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/tagged_log.ts @@ -99,6 +99,7 @@ export class TaggedLog { if ( !(e instanceof NotOnCurveError) && !e.message.endsWith('is greater or equal to field modulus.') && + !e.message.startsWith('Public values byte length is not a multiple of Fr size.') && !e.message.startsWith('Invalid AztecAddress length') && !e.message.startsWith('Selector must fit in') && !e.message.startsWith('Attempted to read beyond buffer length') @@ -145,6 +146,7 @@ export class TaggedLog { if ( !(e instanceof NotOnCurveError) && !e.message.endsWith('is greater or equal to field modulus.') && + !e.message.startsWith('Public values byte length is not a multiple of Fr size.') && !e.message.startsWith('Invalid AztecAddress length') && !e.message.startsWith('Selector must fit in') && !e.message.startsWith('Attempted to read beyond buffer length') From 784b44f5e7eb821b16374f9d75a5a1d14da9eae4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Bene=C5=A1?= Date: Tue, 17 Sep 2024 08:24:07 +0200 Subject: [PATCH 09/17] Update yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Nicolás Venturo --- .../circuit-types/src/logs/l1_payload/l1_note_payload.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts b/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts index 47e64161f94..37bfbb26234 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts @@ -148,7 +148,7 @@ export class L1NotePayload extends L1Payload { ); } - static #getPublicValuesAndRemainingCipherText(input: Buffer): [Fr[], Buffer] { + static #getPublicValuesAndRemainingCiphertext(input: Buffer): [Fr[], Buffer] { const reader = BufferReader.asReader(input); const numPubliclyDeliveredValues = reader.readUInt8(); From ceccd95a77732a60d7dd9bf4dcaca4c8d0600ed0 Mon Sep 17 00:00:00 2001 From: benesjan Date: Tue, 17 Sep 2024 06:27:42 +0000 Subject: [PATCH 10/17] fix --- .../circuit-types/src/logs/l1_payload/l1_note_payload.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts b/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts index 37bfbb26234..737b7e3479c 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts @@ -96,7 +96,7 @@ export class L1NotePayload extends L1Payload { */ public static decryptAsIncoming(ciphertext: Buffer | bigint[], ivsk: GrumpkinScalar) { const input = Buffer.isBuffer(ciphertext) ? ciphertext : Buffer.from(ciphertext.map((x: bigint) => Number(x))); - const [publicValues, remainingCiphertext] = this.#getPublicValuesAndRemainingCipherText(input); + const [publicValues, remainingCiphertext] = this.#getPublicValuesAndRemainingCiphertext(input); const [address, incomingBody] = super._decryptAsIncoming( remainingCiphertext, @@ -125,7 +125,7 @@ export class L1NotePayload extends L1Payload { */ public static decryptAsOutgoing(ciphertext: Buffer | bigint[], ovsk: GrumpkinScalar) { const input = Buffer.isBuffer(ciphertext) ? ciphertext : Buffer.from(ciphertext.map((x: bigint) => Number(x))); - const [publicValues, remainingCiphertext] = this.#getPublicValuesAndRemainingCipherText(input); + const [publicValues, remainingCiphertext] = this.#getPublicValuesAndRemainingCiphertext(input); const [address, incomingBody] = super._decryptAsOutgoing( remainingCiphertext, From f934b7f7a8f9e64189282a38354f2535a6f3886d Mon Sep 17 00:00:00 2001 From: benesjan Date: Tue, 17 Sep 2024 06:52:41 +0000 Subject: [PATCH 11/17] using array eq --- .../aztec-nr/aztec/src/encrypted_logs/outgoing_body.nr | 5 +---- .../aztec-nr/aztec/src/encrypted_logs/payload.nr | 10 ++-------- noir-projects/aztec-nr/aztec/src/utils/point.nr | 10 ++-------- .../crates/types/src/utils/field.nr | 8 ++------ 4 files changed, 7 insertions(+), 26 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/outgoing_body.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/outgoing_body.nr index 64095b9ad03..a722904c541 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/outgoing_body.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/outgoing_body.nr @@ -92,9 +92,6 @@ mod test { 127, 182, 227, 75, 192, 197, 54, 47, 168, 134, 233, 148, 251, 46, 86, 12, 73, 50, 238, 50, 31, 174, 27, 202, 110, 77, 161, 197, 244, 124, 17, 100, 143, 150, 232, 14, 156, 248, 43, 177, 16, 82, 244, 103, 88, 74, 84, 200, 15, 65, 187, 14, 163, 60, 91, 22, 104, 31, 211, 190, 124, 121, 79, 92, 239, 65, 185, 106, 51, 178, 168, 137, 84, 43, 79, 158, 151, 152, 83, 42, 170, 13, 106, 209, 254, 74, 39, 145, 73, 215, 17, 234, 196, 89, 30, 58, 120, 127, 88, 69, 121, 61, 18, 206, 89, 118, 243, 238, 177, 71, 73, 47, 147, 4, 155, 25, 173, 248, 206, 52, 17, 180, 122, 186, 106, 191, 252, 102, 197, 91, 16, 39, 94, 91, 224, 30, 168, 177, 26, 144, 5, 124, 128, 6 ]; - for i in 0..outgoing_body_ciphertext_from_typescript.len() { - assert_eq(ciphertext[i], outgoing_body_ciphertext_from_typescript[i]); - } - assert_eq(outgoing_body_ciphertext_from_typescript.len(), ciphertext.len()); + assert_eq(outgoing_body_ciphertext_from_typescript, ciphertext); } } diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr index 7538b6fc596..72900c2b7d4 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr @@ -191,10 +191,7 @@ mod test { let encrypted_note_log_from_typescript = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 70, 12, 14, 67, 77, 132, 110, 193, 234, 40, 110, 64, 144, 235, 86, 55, 111, 242, 123, 221, 193, 170, 202, 225, 216, 86, 84, 159, 112, 31, 167, 126, 79, 51, 186, 47, 71, 253, 172, 99, 112, 241, 59, 197, 241, 107, 186, 232, 87, 187, 230, 171, 62, 228, 234, 42, 51, 145, 146, 238, 242, 42, 71, 206, 13, 244, 66, 111, 195, 20, 203, 98, 148, 204, 242, 145, 183, 156, 29, 141, 54, 44, 220, 194, 35, 229, 16, 32, 204, 211, 49, 142, 112, 82, 202, 116, 241, 254, 146, 42, 217, 20, 189, 70, 228, 182, 171, 205, 104, 27, 99, 171, 28, 91, 244, 21, 30, 130, 240, 5, 72, 174, 124, 97, 197, 157, 248, 193, 23, 193, 76, 46, 141, 144, 70, 211, 45, 67, 167, 218, 129, 140, 104, 190, 41, 110, 249, 209, 68, 106, 135, 164, 80, 235, 63, 101, 80, 32, 13, 38, 99, 145, 91, 11, 173, 151, 231, 247, 65, 153, 117, 229, 167, 64, 239, 182, 126, 235, 83, 4, 169, 8, 8, 160, 4, 235, 252, 21, 96, 84, 161, 69, 145, 145, 215, 254, 161, 117, 246, 198, 65, 89, 179, 194, 90, 19, 121, 12, 202, 114, 80, 195, 14, 60, 128, 105, 142, 100, 86, 90, 108, 157, 219, 22, 172, 20, 121, 195, 25, 159, 236, 2, 70, 75, 42, 37, 34, 2, 17, 149, 20, 176, 32, 18, 204, 56, 117, 121, 34, 15, 3, 88, 123, 64, 68, 74, 233, 63, 59, 131, 222, 194, 192, 167, 110, 217, 10, 128, 73, 129, 172, 205, 103, 212, 60, 151, 141, 10, 151, 222, 151, 180, 43, 91, 148, 201, 110, 165, 10, 238, 32, 134, 235, 99, 216, 200, 182, 31, 22, 156, 18, 209, 222, 172, 239, 193, 212, 86, 99, 62, 70, 182, 45, 175, 241, 91, 202, 179, 225, 236, 95, 71, 66, 151, 225, 203, 53, 216, 85, 102, 130, 6, 8, 25, 180, 86, 58, 140, 198, 105, 102, 177, 42, 94, 115, 247, 145, 147, 24, 231, 39, 73, 27, 10, 219, 130, 115, 188, 74, 114, 5, 177, 199, 83, 183, 106, 87, 204, 238, 231, 72, 45, 240, 39, 174, 25, 98, 53, 187, 156, 159, 244, 38 ]; - for i in 0..encrypted_note_log_from_typescript.len() { - assert_eq(log[i], encrypted_note_log_from_typescript[i]); - } - assert_eq(encrypted_note_log_from_typescript.len(), log.len()); + assert_eq(encrypted_note_log_from_typescript, log); } #[test] @@ -258,9 +255,6 @@ mod test { let encrypted_note_log_of_finalized_partial_from_typescript = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 141, 70, 12, 14, 67, 77, 132, 110, 193, 234, 40, 110, 64, 144, 235, 86, 55, 111, 242, 123, 221, 193, 170, 202, 225, 216, 86, 84, 159, 112, 31, 167, 126, 79, 51, 186, 47, 71, 253, 172, 99, 112, 241, 59, 197, 241, 107, 186, 232, 87, 187, 230, 171, 62, 228, 234, 42, 51, 145, 146, 238, 242, 42, 71, 206, 13, 244, 66, 111, 195, 20, 203, 98, 148, 204, 242, 145, 183, 156, 29, 141, 54, 44, 220, 194, 35, 229, 16, 32, 204, 211, 49, 142, 112, 82, 202, 116, 241, 254, 146, 42, 217, 20, 189, 70, 228, 182, 171, 205, 104, 27, 99, 171, 28, 91, 244, 21, 30, 130, 240, 5, 72, 174, 124, 97, 197, 157, 248, 193, 23, 193, 76, 46, 141, 144, 70, 211, 45, 67, 167, 218, 129, 140, 104, 190, 41, 110, 249, 209, 68, 106, 135, 164, 80, 235, 63, 101, 80, 32, 13, 38, 99, 145, 91, 11, 173, 151, 231, 247, 65, 153, 117, 229, 167, 64, 239, 182, 126, 235, 83, 4, 169, 8, 8, 160, 4, 235, 252, 21, 96, 84, 161, 69, 145, 145, 215, 254, 161, 117, 246, 198, 65, 89, 179, 194, 90, 19, 121, 12, 202, 114, 80, 195, 14, 60, 128, 105, 142, 100, 86, 90, 108, 157, 219, 22, 172, 20, 121, 195, 25, 159, 236, 2, 70, 75, 42, 37, 34, 2, 17, 149, 20, 176, 32, 18, 204, 56, 117, 121, 34, 15, 3, 88, 123, 64, 68, 74, 233, 63, 59, 131, 222, 194, 192, 167, 110, 217, 10, 128, 73, 129, 172, 205, 103, 212, 60, 151, 141, 10, 151, 222, 151, 180, 43, 91, 148, 201, 110, 165, 10, 238, 32, 134, 235, 99, 216, 200, 182, 31, 22, 156, 18, 209, 222, 172, 239, 193, 212, 86, 99, 62, 70, 182, 45, 175, 241, 91, 202, 179, 225, 236, 95, 71, 66, 151, 225, 203, 53, 216, 85, 102, 130, 6, 8, 25, 180, 86, 58, 140, 198, 105, 102, 177, 42, 94, 115, 247, 145, 147, 24, 231, 39, 73, 27, 10, 219, 130, 115, 188, 74, 114, 5, 177, 199, 83, 183, 106, 87, 204, 238, 231, 72, 45, 240, 39, 174, 25, 98, 53, 187, 156, 159, 244, 38, 20, 23, 35, 57, 40, 126, 141, 40, 21, 69, 193, 119, 49, 63, 2, 182, 170, 47, 237, 253, 98, 140, 253, 139, 127, 17, 161, 54, 253, 13, 101, 87, 8, 52, 216, 30, 63, 115, 199, 226, 128, 155, 8, 174, 56, 96, 15, 252, 118, 162, 85, 68, 115, 238, 171, 109, 231, 191, 244, 179, 58, 132, 254, 172 ]; - for i in 0..encrypted_note_log_of_finalized_partial_from_typescript.len() { - assert_eq(log[i], encrypted_note_log_of_finalized_partial_from_typescript[i]); - } - assert_eq(encrypted_note_log_of_finalized_partial_from_typescript.len(), log.len()); + assert_eq(encrypted_note_log_of_finalized_partial_from_typescript, log); } } diff --git a/noir-projects/aztec-nr/aztec/src/utils/point.nr b/noir-projects/aztec-nr/aztec/src/utils/point.nr index 633bd837ebb..bf06a87fec2 100644 --- a/noir-projects/aztec-nr/aztec/src/utils/point.nr +++ b/noir-projects/aztec-nr/aztec/src/utils/point.nr @@ -48,10 +48,7 @@ mod test { 154, 244, 31, 93, 233, 100, 70, 220, 55, 118, 161, 235, 45, 152, 187, 149, 107, 122, 205, 153, 121, 166, 120, 84, 190, 198, 250, 124, 41, 115, 189, 115 ]; - assert_eq(expected_compressed_point_positive_sign.len(), compressed_point.len()); - for i in 0..expected_compressed_point_positive_sign.len() { - assert_eq(compressed_point[i], expected_compressed_point_positive_sign[i]); - } + assert_eq(expected_compressed_point_positive_sign, compressed_point); } #[test] @@ -68,9 +65,6 @@ mod test { 36, 115, 113, 101, 46, 85, 221, 116, 201, 175, 141, 190, 159, 180, 73, 49, 186, 41, 169, 34, 153, 148, 56, 75, 215, 7, 119, 150, 193, 78, 226, 181 ]; - assert_eq(expected_compressed_point_negative_sign.len(), compressed_point.len()); - for i in 0..expected_compressed_point_negative_sign.len() { - assert_eq(compressed_point[i], expected_compressed_point_negative_sign[i]); - } + assert_eq(expected_compressed_point_negative_sign, compressed_point); } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/field.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/field.nr index 954ef602f82..d4115e5743d 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/field.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/field.nr @@ -52,9 +52,7 @@ unconstrained fn bytes_field_test() { ]; let field = field_from_bytes(inputs, true); let return_bytes: [u8; 31] = field.to_be_bytes(); - for i in 0..31 { - assert_eq(inputs[i], return_bytes[i]); - } + assert_eq(inputs, return_bytes); // 32 bytes - we remove the final byte, and check it matches the field let inputs2 = [ 84, 62, 10, 102, 66, 255, 235, 128, 57, 41, 104, 97, 118, 90, 83, 64, 123, 186, 98, 189, 28, 151, 202, 67, 55, 77, 233, 80, 187, 224, 167, 158 @@ -62,9 +60,7 @@ unconstrained fn bytes_field_test() { let field2 = field_from_bytes_32_trunc(inputs2); let return_bytes2: [u8; 31] = field.to_be_bytes(); - for i in 0..31 { - assert_eq(return_bytes2[i], return_bytes[i]); - } + assert_eq(return_bytes2, return_bytes); assert_eq(field2, field); } From f7b1ddcc5d0b3ea257bc9816e0f716efec13292b Mon Sep 17 00:00:00 2001 From: benesjan Date: Tue, 17 Sep 2024 07:12:39 +0000 Subject: [PATCH 12/17] docs + naming [no ci] --- .../encrypted_logs/encrypted_note_emission.nr | 4 +-- .../aztec/src/encrypted_logs/payload.nr | 14 +++++----- .../src/logs/l1_payload/l1_note_payload.ts | 27 +++++++++++++++---- 3 files changed, 31 insertions(+), 14 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr index 0610d13c783..bb153ec8484 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr @@ -25,7 +25,7 @@ fn compute_raw_note_log( // Number of publicly delivered values is always 0 here because `compute(...)` is only called // in the non-partial note flow. - let num_publicly_delivered_values = 0; + let num_public_values = 0; let encrypted_log: [u8; M] = compute_encrypted_note_log( contract_address, storage_slot, @@ -34,7 +34,7 @@ fn compute_raw_note_log( ivpk, recipient, note, - num_publicly_delivered_values + num_public_values ); let log_hash = sha256_to_field(encrypted_log); diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr index 72900c2b7d4..4764132dbc6 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr @@ -73,7 +73,7 @@ pub fn compute_encrypted_note_log( ivpk: IvpkM, recipient: AztecAddress, note: Note, - num_publicly_delivered_values: u8 + num_public_values: u8 // Number of values to be appended to the log in public (used in partial note flow). ) -> [u8; M] where Note: NoteInterface { let (eph_sk, eph_pk) = generate_ephemeral_key_pair(); @@ -87,7 +87,7 @@ pub fn compute_encrypted_note_log( let mut encrypted_bytes: [u8; M] = [0; M]; // @todo We ignore the tags for now - encrypted_bytes[64] = num_publicly_delivered_values; // TODO(#8558): This can be just a single bit if we store info about partial fields in ABI + encrypted_bytes[64] = num_public_values; // TODO(#8558): This can be just a single bit if we store info about partial fields in ABI let eph_pk_bytes = point_to_bytes(eph_pk); for i in 0..32 { encrypted_bytes[65 + i] = eph_pk_bytes[i]; @@ -109,7 +109,7 @@ pub fn compute_encrypted_note_log( // Current unoptimized size of the encrypted log // incoming_tag (32 bytes) // outgoing_tag (32 bytes) - // num_publicly_delivered_values (1 byte) + // num_public_values (1 byte) // eph_pk (32 bytes) // incoming_header (48 bytes) // outgoing_header (48 bytes) @@ -173,7 +173,7 @@ mod test { let _ = OracleMock::mock("getRandomField").returns(eph_sk); let recipient = AztecAddress::from_field(0x10ee41ee4b62703b16f61e03cb0d88c4b306a9eb4a6ceeb2aff13428541689a2); - let num_publicly_delivered_values: u8 = 0; + let num_public_values: u8 = 0; let log: [u8; 449] = compute_encrypted_note_log( contract_address, @@ -183,7 +183,7 @@ mod test { ivpk_m, recipient, note, - num_publicly_delivered_values + num_public_values ); // The following value was generated by `tagged_log.test.ts` @@ -224,7 +224,7 @@ mod test { let _ = OracleMock::mock("getRandomField").returns(eph_sk); let recipient = AztecAddress::from_field(0x10ee41ee4b62703b16f61e03cb0d88c4b306a9eb4a6ceeb2aff13428541689a2); - let num_publicly_delivered_values: u8 = 2; + let num_public_values: u8 = 2; // First we compute the encrypted log without the public values let log_without_public_values: [u8; 449] = compute_encrypted_note_log( @@ -235,7 +235,7 @@ mod test { ivpk_m, recipient, note, - num_publicly_delivered_values + num_public_values ); // Then we "append" the public values to the log by copying both the original log and the current log into a new byte array diff --git a/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts b/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts index 737b7e3479c..ed5f9f192f7 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts @@ -67,10 +67,10 @@ export class L1NotePayload extends L1Payload { } public encrypt(ephSk: GrumpkinScalar, recipient: AztecAddress, ivpk: PublicKey, ovKeys: KeyValidationRequest) { - // TODO(#8558): numPubliclyDeliveredValues could occupy just a single bit if we store info about partial fields + // TODO(#8558): numPublicValues could occupy just a single bit if we store info about partial fields // in the ABI // We always set the value to 0 here as we don't need partial notes encryption support in TS - const numPubliclyDeliveredValues = 0; + const numPublicValues = 0; const encryptedPayload = super._encrypt( this.contractAddress, ephSk, @@ -79,7 +79,7 @@ export class L1NotePayload extends L1Payload { ovKeys, new EncryptedNoteLogIncomingBody(this.storageSlot, this.noteTypeId, this.note), ); - return Buffer.concat([Buffer.alloc(1, numPubliclyDeliveredValues), encryptedPayload]); + return Buffer.concat([Buffer.alloc(1, numPublicValues), encryptedPayload]); } /** @@ -148,13 +148,30 @@ export class L1NotePayload extends L1Payload { ); } + /** + * Extracts the public values and the remaining ciphertext from the input buffer. + * Input byte layout: + * +-----------------------------------+ + * | Byte | Description | + * |------|----------------------------| + * | 0 | num_pub_vals | + * |------|----------------------------| + * | 1 to | Ciphertext | + * | N | (N = total_length - 1 | + * | | - num_pub_vals * 32) | + * |------|----------------------------| + * | N+1 | Public values | + * | to | (num_pub_vals * 32 bytes) | + * | end | | + * +-----------------------------------+ + */ static #getPublicValuesAndRemainingCiphertext(input: Buffer): [Fr[], Buffer] { const reader = BufferReader.asReader(input); - const numPubliclyDeliveredValues = reader.readUInt8(); + const numPublicValues = reader.readUInt8(); const remainingData = reader.readToEnd(); const publicValuesData = remainingData.subarray( - remainingData.length - numPubliclyDeliveredValues * Fr.SIZE_IN_BYTES, + remainingData.length - numPublicValues * Fr.SIZE_IN_BYTES, remainingData.length, ); if (publicValuesData.length % Fr.SIZE_IN_BYTES !== 0) { From 0ede13b110186992d93caa6217706b4e83330c40 Mon Sep 17 00:00:00 2001 From: benesjan Date: Tue, 17 Sep 2024 07:20:02 +0000 Subject: [PATCH 13/17] renaming ciphertext [no ci] --- .../src/logs/l1_payload/l1_note_payload.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts b/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts index ed5f9f192f7..35b77312419 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts @@ -83,19 +83,19 @@ export class L1NotePayload extends L1Payload { } /** - * Decrypts a ciphertext as an incoming log. + * Extracts public values and decrypts a ciphertext as an incoming log. * * This is executable by the recipient of the note, and uses the ivsk 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 content - Content of the log. Contains ciphertext and public values. * @param ivsk - The incoming viewing secret key, used to decrypt the logs * @returns The decrypted log payload */ - public static decryptAsIncoming(ciphertext: Buffer | bigint[], ivsk: GrumpkinScalar) { - const input = Buffer.isBuffer(ciphertext) ? ciphertext : Buffer.from(ciphertext.map((x: bigint) => Number(x))); + public static decryptAsIncoming(content: Buffer | bigint[], ivsk: GrumpkinScalar) { + const input = Buffer.isBuffer(content) ? content : Buffer.from(content.map((x: bigint) => Number(x))); const [publicValues, remainingCiphertext] = this.#getPublicValuesAndRemainingCiphertext(input); const [address, incomingBody] = super._decryptAsIncoming( @@ -111,7 +111,7 @@ export class L1NotePayload extends L1Payload { } /** - * Decrypts a ciphertext as an outgoing log. + * Extracts public values and decrypts a ciphertext as an outgoing log. * * This is executable by the sender of the note, and uses the ovsk to decrypt the payload. * The outgoing parts are decrypted to retrieve information that allows the sender to @@ -119,12 +119,12 @@ export class L1NotePayload extends L1Payload { * * Produces the same output as `decryptAsIncoming`. * - * @param ciphertext - The ciphertext for the log + * @param content - Content of the log. Contains ciphertext and public values. * @param ovsk - The outgoing viewing secret key, used to decrypt the logs * @returns The decrypted log payload */ - public static decryptAsOutgoing(ciphertext: Buffer | bigint[], ovsk: GrumpkinScalar) { - const input = Buffer.isBuffer(ciphertext) ? ciphertext : Buffer.from(ciphertext.map((x: bigint) => Number(x))); + public static decryptAsOutgoing(content: Buffer | bigint[], ovsk: GrumpkinScalar) { + const input = Buffer.isBuffer(content) ? content : Buffer.from(content.map((x: bigint) => Number(x))); const [publicValues, remainingCiphertext] = this.#getPublicValuesAndRemainingCiphertext(input); const [address, incomingBody] = super._decryptAsOutgoing( From 4e0c7341ff854269f1a190d130adb156a42dd852 Mon Sep 17 00:00:00 2001 From: benesjan Date: Tue, 17 Sep 2024 07:42:38 +0000 Subject: [PATCH 14/17] cleanup [no ci] --- .../src/logs/l1_payload/l1_note_payload.ts | 37 ++++++++----------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts b/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts index 35b77312419..f001a3bbbea 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts @@ -95,11 +95,10 @@ export class L1NotePayload extends L1Payload { * @returns The decrypted log payload */ public static decryptAsIncoming(content: Buffer | bigint[], ivsk: GrumpkinScalar) { - const input = Buffer.isBuffer(content) ? content : Buffer.from(content.map((x: bigint) => Number(x))); - const [publicValues, remainingCiphertext] = this.#getPublicValuesAndRemainingCiphertext(input); + const [ciphertext, publicValues] = this.#getCiphertextAndPublicValues(content); const [address, incomingBody] = super._decryptAsIncoming( - remainingCiphertext, + ciphertext, ivsk, EncryptedNoteLogIncomingBody.fromCiphertext, ); @@ -124,11 +123,10 @@ export class L1NotePayload extends L1Payload { * @returns The decrypted log payload */ public static decryptAsOutgoing(content: Buffer | bigint[], ovsk: GrumpkinScalar) { - const input = Buffer.isBuffer(content) ? content : Buffer.from(content.map((x: bigint) => Number(x))); - const [publicValues, remainingCiphertext] = this.#getPublicValuesAndRemainingCiphertext(input); + const [ciphertext, publicValues] = this.#getCiphertextAndPublicValues(content); const [address, incomingBody] = super._decryptAsOutgoing( - remainingCiphertext, + ciphertext, ovsk, EncryptedNoteLogIncomingBody.fromCiphertext, ); @@ -149,7 +147,7 @@ export class L1NotePayload extends L1Payload { } /** - * Extracts the public values and the remaining ciphertext from the input buffer. + * Extracts the ciphertext and the public values from the log content. * Input byte layout: * +-----------------------------------+ * | Byte | Description | @@ -165,25 +163,22 @@ export class L1NotePayload extends L1Payload { * | end | | * +-----------------------------------+ */ - static #getPublicValuesAndRemainingCiphertext(input: Buffer): [Fr[], Buffer] { + static #getCiphertextAndPublicValues(content: Buffer | bigint[]): [Buffer, Fr[]] { + const input = Buffer.isBuffer(content) ? content : Buffer.from(content.map((x: bigint) => Number(x))); + const reader = BufferReader.asReader(input); const numPublicValues = reader.readUInt8(); - const remainingData = reader.readToEnd(); - const publicValuesData = remainingData.subarray( - remainingData.length - numPublicValues * Fr.SIZE_IN_BYTES, - remainingData.length, - ); - if (publicValuesData.length % Fr.SIZE_IN_BYTES !== 0) { - throw new Error(`Public values byte length is not a multiple of Fr size. Length: ${publicValuesData.length}`); - } - const publicValues = []; - for (let i = 0; i < publicValuesData.length; i += Fr.SIZE_IN_BYTES) { - publicValues.push(Fr.fromBuffer(publicValuesData.subarray(i, i + Fr.SIZE_IN_BYTES))); + const ciphertextLength = reader.getLength() - numPublicValues * Fr.SIZE_IN_BYTES - 1; + const ciphertext = reader.readBytes(ciphertextLength); + + const publicValuesLength = reader.getLength() - ciphertextLength - 1; + if (publicValuesLength % Fr.SIZE_IN_BYTES !== 0) { + throw new Error(`Public values byte length is not a multiple of Fr size. Length: ${publicValuesLength}`); } - const remainingCiphertext = remainingData.subarray(0, remainingData.length - publicValuesData.length); + const publicValues = reader.readArray(numPublicValues, Fr); - return [publicValues, remainingCiphertext]; + return [ciphertext, publicValues]; } } From 4ffc89f534f8b1ccd5e8d780701dd2376e500a0c Mon Sep 17 00:00:00 2001 From: benesjan Date: Tue, 17 Sep 2024 08:03:37 +0000 Subject: [PATCH 15/17] random log fix --- .../circuit-types/src/logs/encrypted_l2_note_log.ts | 8 +++++++- .../circuit-types/src/logs/l1_payload/l1_note_payload.ts | 8 +------- .../circuit-types/src/logs/l1_payload/tagged_log.ts | 2 -- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/yarn-project/circuit-types/src/logs/encrypted_l2_note_log.ts b/yarn-project/circuit-types/src/logs/encrypted_l2_note_log.ts index 3202155a858..3cc334a028b 100644 --- a/yarn-project/circuit-types/src/logs/encrypted_l2_note_log.ts +++ b/yarn-project/circuit-types/src/logs/encrypted_l2_note_log.ts @@ -61,9 +61,15 @@ export class EncryptedL2NoteLog { * @returns A random log. */ public static random(): EncryptedL2NoteLog { + const numPublicValues = 0; const randomEphPubKey = Point.random(); const randomLogContent = randomBytes(144 - Point.COMPRESSED_SIZE_IN_BYTES); - const data = Buffer.concat([Fr.random().toBuffer(), randomLogContent, randomEphPubKey.toCompressedBuffer()]); + const data = Buffer.concat([ + Buffer.alloc(1, numPublicValues), + Fr.random().toBuffer(), + randomLogContent, + randomEphPubKey.toCompressedBuffer(), + ]); return new EncryptedL2NoteLog(data); } diff --git a/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts b/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts index f001a3bbbea..29d53578dd5 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts @@ -168,15 +168,9 @@ export class L1NotePayload extends L1Payload { const reader = BufferReader.asReader(input); const numPublicValues = reader.readUInt8(); - const ciphertextLength = reader.getLength() - numPublicValues * Fr.SIZE_IN_BYTES - 1; - const ciphertext = reader.readBytes(ciphertextLength); - - const publicValuesLength = reader.getLength() - ciphertextLength - 1; - if (publicValuesLength % Fr.SIZE_IN_BYTES !== 0) { - throw new Error(`Public values byte length is not a multiple of Fr size. Length: ${publicValuesLength}`); - } + const ciphertext = reader.readBytes(ciphertextLength); const publicValues = reader.readArray(numPublicValues, Fr); return [ciphertext, publicValues]; diff --git a/yarn-project/circuit-types/src/logs/l1_payload/tagged_log.ts b/yarn-project/circuit-types/src/logs/l1_payload/tagged_log.ts index b343d3880bb..70568c08ad6 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/tagged_log.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/tagged_log.ts @@ -99,7 +99,6 @@ export class TaggedLog { if ( !(e instanceof NotOnCurveError) && !e.message.endsWith('is greater or equal to field modulus.') && - !e.message.startsWith('Public values byte length is not a multiple of Fr size.') && !e.message.startsWith('Invalid AztecAddress length') && !e.message.startsWith('Selector must fit in') && !e.message.startsWith('Attempted to read beyond buffer length') @@ -146,7 +145,6 @@ export class TaggedLog { if ( !(e instanceof NotOnCurveError) && !e.message.endsWith('is greater or equal to field modulus.') && - !e.message.startsWith('Public values byte length is not a multiple of Fr size.') && !e.message.startsWith('Invalid AztecAddress length') && !e.message.startsWith('Selector must fit in') && !e.message.startsWith('Attempted to read beyond buffer length') From 123b98f9213ea5633444e40eee18b80da773a819 Mon Sep 17 00:00:00 2001 From: benesjan Date: Tue, 17 Sep 2024 08:06:43 +0000 Subject: [PATCH 16/17] updated stale comment --- .../aztec/src/encrypted_logs/encrypted_note_emission.nr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr index bb153ec8484..6dd2b0b5b22 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr @@ -23,8 +23,8 @@ fn compute_raw_note_log( let contract_address: AztecAddress = context.this_address(); - // Number of publicly delivered values is always 0 here because `compute(...)` is only called - // in the non-partial note flow. + // Number of public values is always 0 here because `compute_raw_note_log(...)` is only called in the non-partial + // note flow. let num_public_values = 0; let encrypted_log: [u8; M] = compute_encrypted_note_log( contract_address, From f6b33d78f8a80e14dc431cd69106ca841f54d064 Mon Sep 17 00:00:00 2001 From: benesjan Date: Tue, 17 Sep 2024 08:19:27 +0000 Subject: [PATCH 17/17] exposing num_public_values on compute_raw_note_log --- .../encrypted_logs/encrypted_note_emission.nr | 34 +++++++++++++------ 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr index 6dd2b0b5b22..cf982b8c4ad 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr @@ -11,7 +11,8 @@ fn compute_raw_note_log( ovsk_app: Field, ovpk: OvpkM, ivpk: IvpkM, - recipient: AztecAddress + recipient: AztecAddress, + num_public_values: u8 // Number of values to be appended to the log in public (used in partial note flow). ) -> (u32, [u8; M], Field) where Note: NoteInterface, [Field; N]: LensForEncryptedLog { let note_header = note.get_header(); let note_hash_counter = note_header.note_hash_counter; @@ -23,9 +24,6 @@ fn compute_raw_note_log( let contract_address: AztecAddress = context.this_address(); - // Number of public values is always 0 here because `compute_raw_note_log(...)` is only called in the non-partial - // note flow. - let num_public_values = 0; let encrypted_log: [u8; M] = compute_encrypted_note_log( contract_address, storage_slot, @@ -46,10 +44,11 @@ unconstrained fn compute_raw_note_log_unconstrained (u32, [u8; M], Field) where Note: NoteInterface, [Field; N]: LensForEncryptedLog { let ovsk_app = get_ovsk_app(ovpk.hash()); - compute_raw_note_log(context, note, ovsk_app, ovpk, ivpk, recipient) + compute_raw_note_log(context, note, ovsk_app, ovpk, ivpk, recipient, num_public_values) } pub fn encode_and_encrypt_note( @@ -62,7 +61,10 @@ pub fn encode_and_encrypt_note( let ivpk = get_current_public_keys(context, iv).ivpk_m; let ovsk_app: Field = context.request_ovsk_app(ovpk.hash()); - let (note_hash_counter, encrypted_log, log_hash) = compute_raw_note_log(*context, e.note, ovsk_app, ovpk, ivpk, iv); + // Number of public values is always 0 here because `encode_and_encrypt_note(...)` is only called + // in the non-partial note flow. + let num_public_values = 0; + let (note_hash_counter, encrypted_log, log_hash) = compute_raw_note_log(*context, e.note, ovsk_app, ovpk, ivpk, iv, num_public_values); context.emit_raw_note_log(note_hash_counter, encrypted_log, log_hash); } } @@ -78,10 +80,14 @@ pub fn encode_and_encrypt_note_unconstrained | { let ovsk_app: Field = context.request_ovsk_app(ovpk.hash()); - let (note_hash_counter, encrypted_log, log_hash) = compute_raw_note_log(*context, e.note, ovsk_app, ovpk, ivpk, recipient); + // Number of public values is always 0 here because `encode_and_encrypt_note_unconstrained(...)` is only called + // in the non-partial note flow. + let num_public_values = 0; + + let (note_hash_counter, encrypted_log, log_hash) = compute_raw_note_log(*context, e.note, ovsk_app, ovpk, ivpk, recipient, num_public_values); context.emit_raw_note_log(note_hash_counter, encrypted_log, log_hash); } } @@ -108,6 +118,10 @@ pub fn encode_and_encrypt_note_with_keys_unconstrained fn[(&mut PrivateContext, OvpkM, IvpkM, AztecAddress)](NoteEmission) -> () where Note: NoteInterface, [Field; N]: LensForEncryptedLog { | e: NoteEmission | { + // Number of public values is always 0 here because `encode_and_encrypt_note_with_keys_unconstrained(...)` is only called + // in the non-partial note flow. + let num_public_values = 0; + // Having the log hash be unconstrained here is fine because the way this works is we send the log hash // to the kernel, and it gets included as part of its public inputs. Then we send the tx to the sequencer, // which includes the kernel proof and the log preimages. The sequencer computes the hashes of the logs @@ -128,7 +142,7 @@ pub fn encode_and_encrypt_note_with_keys_unconstrained