-
Notifications
You must be signed in to change notification settings - Fork 224
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: Reproduce and fix bytecode blowup (#6972)
Co-authored-by: Tom French <[email protected]>
- Loading branch information
1 parent
526c84e
commit 724547d
Showing
10 changed files
with
128 additions
and
9 deletions.
There are no files selected for viewing
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
7 changes: 7 additions & 0 deletions
7
test_programs/execution_success/encrypted_log_regression/Nargo.toml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
[package] | ||
name = "encrypted_log_regression" | ||
type = "bin" | ||
authors = [""] | ||
compiler_version = ">=0.31.0" | ||
|
||
[dependencies] |
9 changes: 9 additions & 0 deletions
9
test_programs/execution_success/encrypted_log_regression/Prover.toml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# Using the smaller sizes defined in `main.nr`. | ||
# The reason this program is in the `execution_success` directory is because | ||
# `rebuild.sh` only goes over these programs, but all we really care about is | ||
# any potential future bytecode size regression. | ||
eph_pk_bytes = [1, 2, 3] | ||
incoming_header_ciphertext = [1, 2] | ||
incoming_body_ciphertext = [9, 8, 7, 6, 5, 4, 3, 2, 1] | ||
flag = true | ||
return = [1, 2, 3, 1, 2, 0, 9, 8, 7, 6, 5, 4, 3, 2, 1] |
94 changes: 94 additions & 0 deletions
94
test_programs/execution_success/encrypted_log_regression/src/main.nr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
// The code below is inspired by [compute_encrypted_log](https://github.com/AztecProtocol/aztec-packages/blob/b42756bc10175fea9eb60544759e9dbe41ae5e76/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr#L111) | ||
// which resulted in a bytecode size blowup when compiled to ACIR, see https://github.com/noir-lang/noir/issues/6929 | ||
// The issue was around `encrypted_bytes[offset + i]` generating large amounts of gates, as per the `flamegraph.sh` tool in aztec-packages. | ||
// The details around encryption and addresses have been stripped away, focusing on just copying bytes of equivalent size arrays. | ||
|
||
// Original values which resulted in huge bytecode even on this example (500K long SSA) | ||
// global PRIVATE_LOG_SIZE_IN_FIELDS: u32 = 18; | ||
// global ENCRYPTED_PAYLOAD_SIZE_IN_BYTES: u32 = (PRIVATE_LOG_SIZE_IN_FIELDS - 1) * 31; | ||
// global EPH_PK_SIZE: u32 = 32; | ||
// global HEADER_SIZE: u32 = 48; | ||
// global OVERHEAD_PADDING: u32 = 15; | ||
|
||
// Using the same formulas with smaller numbers; the effect is the same, but the SSA is more manageable. | ||
global PRIVATE_LOG_SIZE_IN_FIELDS: u32 = 4; | ||
global ENCRYPTED_PAYLOAD_SIZE_IN_BYTES: u32 = (PRIVATE_LOG_SIZE_IN_FIELDS - 1) * 5; | ||
global EPH_PK_SIZE: u32 = 3; | ||
global HEADER_SIZE: u32 = 2; | ||
global OVERHEAD_PADDING: u32 = 1; | ||
|
||
// Unused because encryption didn't play a role: | ||
// global OVERHEAD_SIZE: u32 = EPH_PK_SIZE + HEADER_SIZE + OVERHEAD_PADDING; | ||
// global PLAINTEXT_LENGTH_SIZE: u32 = 2; | ||
// global MAX_PRIVATE_LOG_PLAINTEXT_SIZE_IN_BYTES: u32 = | ||
// ENCRYPTED_PAYLOAD_SIZE_IN_BYTES - OVERHEAD_SIZE - PLAINTEXT_LENGTH_SIZE - 1 /* aes padding */; | ||
|
||
global BODY_SIZE: u32 = | ||
ENCRYPTED_PAYLOAD_SIZE_IN_BYTES - EPH_PK_SIZE - HEADER_SIZE - OVERHEAD_PADDING; | ||
|
||
fn main( | ||
eph_pk_bytes: [u8; EPH_PK_SIZE], | ||
incoming_header_ciphertext: [u8; HEADER_SIZE], | ||
incoming_body_ciphertext: [u8; BODY_SIZE], | ||
flag: bool, | ||
) -> pub [u8; ENCRYPTED_PAYLOAD_SIZE_IN_BYTES] { | ||
compute_encrypted_log( | ||
eph_pk_bytes, | ||
incoming_header_ciphertext, | ||
incoming_body_ciphertext, | ||
flag, | ||
) | ||
} | ||
|
||
fn compute_encrypted_log<let M: u32>( | ||
eph_pk_bytes: [u8; EPH_PK_SIZE], | ||
incoming_header_ciphertext: [u8; HEADER_SIZE], | ||
incoming_body_ciphertext: [u8; BODY_SIZE], | ||
flag: bool, | ||
) -> [u8; M] { | ||
let mut encrypted_bytes = [0; M]; | ||
let mut offset = 0; | ||
|
||
// NOTE: Adding a conditional variable can result in the array being fully copied, item by item, | ||
// in each iteration in the second loop that copies incoming_body_ciphertext into encrypted_bytes. | ||
// Depending on where we place the `flag` we either get the item-by-item copying (blowup), | ||
// or just a single array item gets read and a new array constructed in each iteration (no blowup). | ||
|
||
// If the `flag` is here then it blows up. | ||
if flag { | ||
// eph_pk | ||
for i in 0..EPH_PK_SIZE { | ||
encrypted_bytes[offset + i] = eph_pk_bytes[i]; | ||
} | ||
offset += EPH_PK_SIZE; | ||
|
||
// If the `flag` is here then it blows up. | ||
// if flag { | ||
|
||
// incoming_header | ||
for i in 0..HEADER_SIZE { | ||
encrypted_bytes[offset + i] = incoming_header_ciphertext[i]; | ||
} | ||
offset += HEADER_SIZE; | ||
|
||
// Padding. | ||
offset += OVERHEAD_PADDING; | ||
|
||
// If the `flag` is here then it does not blow up. | ||
//if flag { | ||
// incoming_body | ||
// Then we fill in the rest as the incoming body ciphertext | ||
let size = M - offset; | ||
|
||
// NOTE: This made the bytecode size blowup disappear in aztec packages, | ||
// but in this reproduction the size seems to be statically known regardless. | ||
// let size = M - 32 - HEADER_SIZE - OVERHEAD_PADDING; | ||
|
||
assert_eq(size, incoming_body_ciphertext.len(), "ciphertext length mismatch"); | ||
for i in 0..size { | ||
encrypted_bytes[offset + i] = incoming_body_ciphertext[i]; | ||
} | ||
} | ||
|
||
encrypted_bytes | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,8 @@ | ||
// Test Noir implementations of SHA256 and SHA512 on a one-byte message. | ||
fn main(x: Field, result256: [u8; 32], result512: [u8; 64]) { | ||
let digest256 = std::sha256::digest([x as u8]); | ||
let digest256 = std::hash::sha256([x as u8]); | ||
assert(digest256 == result256); | ||
|
||
let digest512 = std::sha512::digest([x as u8]); | ||
let digest512 = std::hash::sha512::digest([x as u8]); | ||
assert(digest512 == result512); | ||
} |