From 3ddd54234afcf464f75696a6da13f5ea90a22afc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Bene=C5=A1?= Date: Thu, 26 Sep 2024 08:58:40 +0200 Subject: [PATCH] chore: Revert "feat: partial notes log encoding (#8538)" (#8712) As discussed in a call about partial notes the specific partial note log encoding needs to be reverted. --- .../encrypted_logs/encrypted_note_emission.nr | 34 ++----- .../aztec/src/encrypted_logs/outgoing_body.nr | 5 +- .../aztec/src/encrypted_logs/payload.nr | 89 +++---------------- .../aztec-nr/aztec/src/oracle/logs_traits.nr | 75 ++++++++-------- .../aztec-nr/aztec/src/utils/point.nr | 10 ++- .../contracts/counter_contract/src/main.nr | 2 +- .../crates/types/src/utils/field.nr | 8 +- .../src/logs/encrypted_l2_note_log.ts | 8 +- .../src/logs/l1_payload/l1_note_payload.ts | 69 ++++---------- .../src/logs/l1_payload/tagged_log.test.ts | 58 +----------- 10 files changed, 91 insertions(+), 267 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 fc55b43ea64..ef119581594 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,8 +11,7 @@ fn compute_raw_note_log( ovsk_app: Field, ovpk: OvpkM, ivpk: IvpkM, - recipient: AztecAddress, - num_public_values: u8 // Number of values to be appended to the log in public (used in partial note flow). + recipient: AztecAddress ) -> (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; @@ -31,8 +30,7 @@ fn compute_raw_note_log( ovpk, ivpk, recipient, - note, - num_public_values + note ); let log_hash = sha256_to_field(encrypted_log); @@ -44,11 +42,10 @@ 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, num_public_values) + compute_raw_note_log(context, note, ovsk_app, ovpk, ivpk, recipient) } pub fn encode_and_encrypt_note( @@ -61,10 +58,7 @@ pub fn encode_and_encrypt_note( let ivpk = get_public_keys(iv).ivpk_m; let ovsk_app: Field = context.request_ovsk_app(ovpk.hash()); - // 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); + let (note_hash_counter, encrypted_log, log_hash) = compute_raw_note_log(*context, e.note, ovsk_app, ovpk, ivpk, iv); context.emit_raw_note_log(note_hash_counter, encrypted_log, log_hash); } } @@ -80,14 +74,10 @@ pub fn encode_and_encrypt_note_unconstrained( let ovpk = get_public_keys(ov).ovpk_m; let ivpk = get_public_keys(iv).ivpk_m; - // 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; - // See the comment in `encode_and_encrypt_note_with_keys_unconstrained` for why having note hash counter // and log hash unconstrained here is fine. let (note_hash_counter, encrypted_log, log_hash) = unsafe { - compute_raw_note_log_unconstrained(*context, e.note, ovpk, ivpk, iv, num_public_values) + compute_raw_note_log_unconstrained(*context, e.note, ovpk, ivpk, iv) }; context.emit_raw_note_log(note_hash_counter, encrypted_log, log_hash); } @@ -102,11 +92,7 @@ pub fn encode_and_encrypt_note_with_keys( | e: NoteEmission | { let ovsk_app: Field = context.request_ovsk_app(ovpk.hash()); - // 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); + let (note_hash_counter, encrypted_log, log_hash) = compute_raw_note_log(*context, e.note, ovsk_app, ovpk, ivpk, recipient); context.emit_raw_note_log(note_hash_counter, encrypted_log, log_hash); } } @@ -118,10 +104,6 @@ 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 @@ -142,7 +124,7 @@ pub fn encode_and_encrypt_note_with_keys_unconstrained( ovpk: OvpkM, ivpk: IvpkM, recipient: AztecAddress, - note: Note, - num_public_values: u8 // Number of values to be appended to the log in public (used in partial note flow). + note: Note ) -> [u8; M] where Note: NoteInterface { let (eph_sk, eph_pk) = generate_ephemeral_key_pair(); @@ -87,29 +86,27 @@ 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_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]; + encrypted_bytes[64 + i] = eph_pk_bytes[i]; } for i in 0..48 { - encrypted_bytes[97 + i] = incoming_header_ciphertext[i]; - encrypted_bytes[145 + i] = outgoing_header_ciphertext[i]; + encrypted_bytes[96 + i] = incoming_header_ciphertext[i]; + encrypted_bytes[144 + i] = outgoing_header_ciphertext[i]; } for i in 0..144 { - encrypted_bytes[193 + i] = outgoing_body_ciphertext[i]; + encrypted_bytes[192 + i] = outgoing_body_ciphertext[i]; } // Then we fill in the rest as the incoming body ciphertext - let size = M - 337; + let size = M - 336; assert_eq(size, incoming_body_ciphertext.len(), "ciphertext length mismatch"); for i in 0..size { - encrypted_bytes[337 + i] = incoming_body_ciphertext[i]; + encrypted_bytes[336 + i] = incoming_body_ciphertext[i]; } // Current unoptimized size of the encrypted log // incoming_tag (32 bytes) // outgoing_tag (32 bytes) - // num_public_values (1 byte) // eph_pk (32 bytes) // incoming_header (48 bytes) // outgoing_header (48 bytes) @@ -173,88 +170,22 @@ mod test { let _ = OracleMock::mock("getRandomField").returns(eph_sk); let recipient = AztecAddress::from_field(0x10ee41ee4b62703b16f61e03cb0d88c4b306a9eb4a6ceeb2aff13428541689a2); - let num_public_values: u8 = 0; - let log: [u8; 449] = compute_encrypted_note_log( + let log: [u8; 448] = compute_encrypted_note_log( contract_address, storage_slot, ovsk_app, ovpk_m, ivpk_m, recipient, - note, - num_public_values + note ); // 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, 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, 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 ]; assert_eq(encrypted_note_log_from_typescript, log); } - - #[test] - unconstrained 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_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( - contract_address, - storage_slot, - ovsk_app, - ovpk_m, - ivpk_m, - recipient, - note, - 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 - 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 - ]; - assert_eq(encrypted_note_log_of_finalized_partial_from_typescript, log); - } } 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 c8de6c54971..57ab8ae15be 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/logs_traits.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/logs_traits.nr @@ -1,6 +1,5 @@ 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 @@ -12,105 +11,105 @@ use dep::protocol_types::address::AztecAddress; // anything, so we can remove this trait pub trait LensForEncryptedLog { // N = note preimage input in fields - // M = encryption output len in bytes (= 417 + N * 32) + // M = encryption output len in bytes (= 416 + N * 32) fn output_fields(self: [Field; N]) -> [Field; N]; fn output_bytes(self: [Field; N]) -> [u8; M]; } -impl LensForEncryptedLog<1, 449> for [Field; 1] { +impl LensForEncryptedLog<1, 448> for [Field; 1] { fn output_fields(self) -> [Field; 1] { [self[0]; 1] } - fn output_bytes(self) -> [u8; 449] { - [self[0] as u8; 449] + fn output_bytes(self) -> [u8; 448] { + [self[0] as u8; 448] } } -impl LensForEncryptedLog<2, 481> for [Field; 2] { +impl LensForEncryptedLog<2, 480> for [Field; 2] { fn output_fields(self) -> [Field; 2] { [self[0]; 2] } - fn output_bytes(self) -> [u8; 481] { - [self[0] as u8; 481] + fn output_bytes(self) -> [u8; 480] { + [self[0] as u8; 480] } } -impl LensForEncryptedLog<3, 513> for [Field; 3] { +impl LensForEncryptedLog<3, 512> for [Field; 3] { fn output_fields(self) -> [Field; 3] { [self[0]; 3] } - fn output_bytes(self) -> [u8; 513] { - [self[0] as u8; 513] + fn output_bytes(self) -> [u8; 512] { + [self[0] as u8; 512] } } -impl LensForEncryptedLog<4, 545> for [Field; 4] { +impl LensForEncryptedLog<4, 544> for [Field; 4] { fn output_fields(self) -> [Field; 4] { [self[0]; 4] } - fn output_bytes(self) -> [u8; 545] { - [self[0] as u8; 545] + fn output_bytes(self) -> [u8; 544] { + [self[0] as u8; 544] } } -impl LensForEncryptedLog<5, 577> for [Field; 5] { +impl LensForEncryptedLog<5, 576> for [Field; 5] { fn output_fields(self) -> [Field; 5] { [self[0]; 5] } - fn output_bytes(self) -> [u8; 577] { - [self[0] as u8; 577] + fn output_bytes(self) -> [u8; 576] { + [self[0] as u8; 576] } } -impl LensForEncryptedLog<6, 609> for [Field; 6] { +impl LensForEncryptedLog<6, 608> for [Field; 6] { fn output_fields(self) -> [Field; 6] { [self[0]; 6] } - fn output_bytes(self) -> [u8; 609] { - [self[0] as u8; 609] + fn output_bytes(self) -> [u8; 608] { + [self[0] as u8; 608] } } -impl LensForEncryptedLog<7, 641> for [Field; 7] { +impl LensForEncryptedLog<7, 640> for [Field; 7] { fn output_fields(self) -> [Field; 7] { [self[0]; 7] } - fn output_bytes(self) -> [u8; 641] { - [self[0] as u8; 641] + fn output_bytes(self) -> [u8; 640] { + [self[0] as u8; 640] } } -impl LensForEncryptedLog<8, 673> for [Field; 8] { +impl LensForEncryptedLog<8, 672> for [Field; 8] { fn output_fields(self) -> [Field; 8] { [self[0]; 8] } - fn output_bytes(self) -> [u8; 673] { - [self[0] as u8; 673] + fn output_bytes(self) -> [u8; 672] { + [self[0] as u8; 672] } } -impl LensForEncryptedLog<9, 705> for [Field; 9] { +impl LensForEncryptedLog<9, 704> for [Field; 9] { fn output_fields(self) -> [Field; 9] { [self[0]; 9] } - fn output_bytes(self) -> [u8; 705] { - [self[0] as u8; 705] + fn output_bytes(self) -> [u8; 704] { + [self[0] as u8; 704] } } -impl LensForEncryptedLog<10, 737> for [Field; 10] { +impl LensForEncryptedLog<10, 736> for [Field; 10] { fn output_fields(self) -> [Field; 10] { [self[0]; 10] } - fn output_bytes(self) -> [u8; 737] { - [self[0] as u8; 737] + fn output_bytes(self) -> [u8; 736] { + [self[0] as u8; 736] } } -impl LensForEncryptedLog<11, 769> for [Field; 11] { +impl LensForEncryptedLog<11, 768> for [Field; 11] { fn output_fields(self) -> [Field; 11] { [self[0]; 11] } - fn output_bytes(self) -> [u8; 769] { - [self[0] as u8; 769] + fn output_bytes(self) -> [u8; 768] { + [self[0] as u8; 768] } } -impl LensForEncryptedLog<12, 801> for [Field; 12] { +impl LensForEncryptedLog<12, 800> for [Field; 12] { fn output_fields(self) -> [Field; 12] { [self[0]; 12] } - fn output_bytes(self) -> [u8; 801] { - [self[0] as u8; 801] + fn output_bytes(self) -> [u8; 800] { + [self[0] as u8; 800] } } diff --git a/noir-projects/aztec-nr/aztec/src/utils/point.nr b/noir-projects/aztec-nr/aztec/src/utils/point.nr index 65967ce1a57..40b555c5655 100644 --- a/noir-projects/aztec-nr/aztec/src/utils/point.nr +++ b/noir-projects/aztec-nr/aztec/src/utils/point.nr @@ -48,7 +48,10 @@ 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, compressed_point); + 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]); + } } #[test] @@ -65,6 +68,9 @@ 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, compressed_point); + 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]); + } } } 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 dbf98f6719b..42bc8c396f8 100644 --- a/noir-projects/noir-contracts/contracts/counter_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/counter_contract/src/main.nr @@ -44,7 +44,7 @@ contract Counter { // docs:end:get_counter // docs:start:test_imports - use dep::aztec::test::helpers::test_environment::TestEnvironment; + use dep::aztec::test::{helpers::{cheatcodes, 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; 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 d4115e5743d..954ef602f82 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,7 +52,9 @@ unconstrained fn bytes_field_test() { ]; let field = field_from_bytes(inputs, true); let return_bytes: [u8; 31] = field.to_be_bytes(); - assert_eq(inputs, return_bytes); + for i in 0..31 { + assert_eq(inputs[i], return_bytes[i]); + } // 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 @@ -60,7 +62,9 @@ unconstrained fn bytes_field_test() { let field2 = field_from_bytes_32_trunc(inputs2); let return_bytes2: [u8; 31] = field.to_be_bytes(); - assert_eq(return_bytes2, return_bytes); + for i in 0..31 { + assert_eq(return_bytes2[i], return_bytes[i]); + } assert_eq(field2, field); } 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 3cc334a028b..3202155a858 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,15 +61,9 @@ 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([ - Buffer.alloc(1, numPublicValues), - Fr.random().toBuffer(), - randomLogContent, - randomEphPubKey.toCompressedBuffer(), - ]); + const data = Buffer.concat([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 29d53578dd5..1f53c1e00c1 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,11 +67,7 @@ export class L1NotePayload extends L1Payload { } public encrypt(ephSk: GrumpkinScalar, recipient: AztecAddress, ivpk: PublicKey, ovKeys: KeyValidationRequest) { - // 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 numPublicValues = 0; - const encryptedPayload = super._encrypt( + return super._encrypt( this.contractAddress, ephSk, recipient, @@ -79,38 +75,35 @@ export class L1NotePayload extends L1Payload { ovKeys, new EncryptedNoteLogIncomingBody(this.storageSlot, this.noteTypeId, this.note), ); - return Buffer.concat([Buffer.alloc(1, numPublicValues), encryptedPayload]); } /** - * Extracts public values and decrypts a ciphertext as an incoming log. + * 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 content - Content of the log. Contains ciphertext and public values. + * @param ciphertext - The ciphertext for the log * @param ivsk - The incoming viewing secret key, used to decrypt the logs * @returns The decrypted log payload */ - public static decryptAsIncoming(content: Buffer | bigint[], ivsk: GrumpkinScalar) { - const [ciphertext, publicValues] = this.#getCiphertextAndPublicValues(content); + 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); const [address, incomingBody] = super._decryptAsIncoming( - ciphertext, + reader.readToEnd(), ivsk, EncryptedNoteLogIncomingBody.fromCiphertext, ); - // 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); + return new L1NotePayload(incomingBody.note, address, incomingBody.storageSlot, incomingBody.noteTypeId); } /** - * Extracts public values and decrypts a ciphertext as an outgoing log. + * 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 @@ -118,23 +111,21 @@ export class L1NotePayload extends L1Payload { * * Produces the same output as `decryptAsIncoming`. * - * @param content - Content of the log. Contains ciphertext and public values. + * @param ciphertext - The ciphertext for the log * @param ovsk - The outgoing viewing secret key, used to decrypt the logs * @returns The decrypted log payload */ - public static decryptAsOutgoing(content: Buffer | bigint[], ovsk: GrumpkinScalar) { - const [ciphertext, publicValues] = this.#getCiphertextAndPublicValues(content); + 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); const [address, incomingBody] = super._decryptAsOutgoing( - ciphertext, + reader.readToEnd(), ovsk, EncryptedNoteLogIncomingBody.fromCiphertext, ); - // 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); + return new L1NotePayload(incomingBody.note, address, incomingBody.storageSlot, incomingBody.noteTypeId); } public equals(other: L1NotePayload) { @@ -145,34 +136,4 @@ export class L1NotePayload extends L1Payload { this.noteTypeId.equals(other.noteTypeId) ); } - - /** - * Extracts the ciphertext and the public values from the log content. - * 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 #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 ciphertextLength = reader.getLength() - numPublicValues * Fr.SIZE_IN_BYTES - 1; - - 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.test.ts b/yarn-project/circuit-types/src/logs/l1_payload/tagged_log.test.ts index b97d84705d2..05cf0b20921 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( - `"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008d460c0e434d846ec1ea286e4090eb56376ff27bddc1aacae1d856549f701fa77e4f33ba2f47fdac6370f13bc5f16bbae857bbe6ab3ee4ea2a339192eef22a47ce0df4426fc314cb6294ccf291b79c1d8d362cdcc223e51020ccd3318e7052ca74f1fe922ad914bd46e4b6abcd681b63ab1c5bf4151e82f00548ae7c61c59df8c117c14c2e8d9046d32d43a7da818c68be296ef9d1446a87a450eb3f6550200d2663915b0bad97e7f7419975e5a740efb67eeb5304a90808a004ebfc156054a1459191d7fea175f6c64159b3c25a13790cca7250c30e3c80698e64565a6c9ddb16ac1479c3199fec02464b2a252202119514b02012cc387579220f03587b40444ae93f3b83dec2c0a76ed90a804981accd67d43c978d0a97de97b42b5b94c96ea50aee2086eb63d8c8b61f169c12d1deacefc1d456633e46b62daff15bcab3e1ec5f474297e1cb35d8556682060819b4563a8cc66966b12a5e73f7919318e727491b0adb8273bc4a7205b1c753b76a57cceee7482df027ae196235bb9c9ff426"`, + `"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008d460c0e434d846ec1ea286e4090eb56376ff27bddc1aacae1d856549f701fa77e4f33ba2f47fdac6370f13bc5f16bbae857bbe6ab3ee4ea2a339192eef22a47ce0df4426fc314cb6294ccf291b79c1d8d362cdcc223e51020ccd3318e7052ca74f1fe922ad914bd46e4b6abcd681b63ab1c5bf4151e82f00548ae7c61c59df8c117c14c2e8d9046d32d43a7da818c68be296ef9d1446a87a450eb3f6550200d2663915b0bad97e7f7419975e5a740efb67eeb5304a90808a004ebfc156054a1459191d7fea175f6c64159b3c25a13790cca7250c30e3c80698e64565a6c9ddb16ac1479c3199fec02464b2a252202119514b02012cc387579220f03587b40444ae93f3b83dec2c0a76ed90a804981accd67d43c978d0a97de97b42b5b94c96ea50aee2086eb63d8c8b61f169c12d1deacefc1d456633e46b62daff15bcab3e1ec5f474297e1cb35d8556682060819b4563a8cc66966b12a5e73f7919318e727491b0adb8273bc4a7205b1c753b76a57cceee7482df027ae196235bb9c9ff426"`, ); const byteArrayString = `[${encrypted.match(/.{1,2}/g)!.map(byte => parseInt(byte, 16))}]`; @@ -96,62 +96,6 @@ describe('L1 Note Payload', () => { ); }); - 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` - 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);