From 542642be47de26016b34c42e12a0f1d1734c4150 Mon Sep 17 00:00:00 2001 From: TomAFrench Date: Wed, 11 Dec 2024 00:52:57 +0000 Subject: [PATCH 01/14] feat: reenable constrained config for roots --- .../crates/blob/src/blob.nr | 27 +++++-------------- .../crates/blob/src/blob_public_inputs.nr | 3 +-- .../crates/blob/src/config.nr | 4 +-- .../crates/blob/src/lib.nr | 3 +-- 4 files changed, 11 insertions(+), 26 deletions(-) diff --git a/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr b/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr index d2f9d809332f..35d2c2c664f7 100644 --- a/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr +++ b/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr @@ -1,7 +1,6 @@ -// TODO(#9982): Replace unconstrained_config with config and import ROOTS - calculating ROOTS in unconstrained is insecure. use crate::{ blob_public_inputs::{BlobCommitment, BlobPublicInputs, BlockBlobPublicInputs}, - unconstrained_config::{compute_roots_of_unity, D_INV, F, LOG_FIELDS_PER_BLOB}, + config::{D_INV, F, LOG_FIELDS_PER_BLOB, ROOTS}, }; use bigint::BigNum; @@ -184,9 +183,6 @@ pub fn evaluate_blobs( * @return y = p(z) */ fn barycentric_evaluate_blob_at_z(z: F, ys: [F; FIELDS_PER_BLOB]) -> F { - // TODO(#9982): Delete below and go back to using config.nr - calculating ROOTS in unconstrained is insecure. - let ROOTS = unsafe { compute_roots_of_unity() }; - // Note: it's more efficient (saving 30k constraints) to compute: // ___d-1 // \ / y_i \ @@ -205,7 +201,7 @@ fn barycentric_evaluate_blob_at_z(z: F, ys: [F; FIELDS_PER_BLOB]) -> F { // i=0 // // perhaps because all the omega^i terms are constant witnesses? - let fracs = compute_fracs(z, ys, ROOTS); + let fracs = compute_fracs(z, ys); // OK so...we can add multiple product terms into a sum...but I am not sure how many! // we are computing 254 * 254 bit products and we need to ensure each product limb doesn't overflow @@ -224,7 +220,7 @@ fn barycentric_evaluate_blob_at_z(z: F, ys: [F; FIELDS_PER_BLOB]) -> F { let NUM_PARTIAL_SUMS = FIELDS_PER_BLOB / 8; let partial_sums: [F; FIELDS_PER_BLOB / 8] = unsafe { // Safety: This sum is checked by the following `BigNum::evaluate_quadratic_expression` calls. - __compute_partial_sums(fracs, ROOTS) + __compute_partial_sums(fracs) }; // We split off the first term to check the initial sum @@ -339,11 +335,7 @@ fn compute_factor(z: F) -> F { factor } -unconstrained fn __compute_fracs( - z: F, - ys: [F; FIELDS_PER_BLOB], - ROOTS: [F; FIELDS_PER_BLOB], -) -> [F; FIELDS_PER_BLOB] { +unconstrained fn __compute_fracs(z: F, ys: [F; FIELDS_PER_BLOB]) -> [F; FIELDS_PER_BLOB] { let mut denoms = [BigNum::new(); FIELDS_PER_BLOB]; for i in 0..FIELDS_PER_BLOB { denoms[i] = z.__sub(ROOTS[i]); // (z - omega^i) @@ -361,14 +353,10 @@ unconstrained fn __compute_fracs( fracs } -fn compute_fracs( - z: F, - ys: [F; FIELDS_PER_BLOB], - ROOTS: [F; FIELDS_PER_BLOB], -) -> [F; FIELDS_PER_BLOB] { +fn compute_fracs(z: F, ys: [F; FIELDS_PER_BLOB]) -> [F; FIELDS_PER_BLOB] { let mut fracs: [F; FIELDS_PER_BLOB] = unsafe { // Safety: We immediately constrain these `fracs` to be correct in the following call to `BigNum::evaluate_quadratic_expression`. - __compute_fracs(z, ys, ROOTS) + __compute_fracs(z, ys) }; for i in 0..FIELDS_PER_BLOB { @@ -390,7 +378,6 @@ fn compute_fracs( // TODO: Clean me unconstrained fn __compute_partial_sums( fracs: [F; FIELDS_PER_BLOB], - ROOTS: [F; FIELDS_PER_BLOB], ) -> [F; FIELDS_PER_BLOB / 8] { let mut partial_sums: [F; FIELDS_PER_BLOB / 8] = std::mem::zeroed(); @@ -442,7 +429,7 @@ mod tests { field_to_bignum, }, blob_public_inputs::BlobCommitment, - unconstrained_config::{D, D_INV, F, LOG_FIELDS_PER_BLOB}, + config::{D, D_INV, F, LOG_FIELDS_PER_BLOB}, }; use bigint::{BigNum, fields::bls12_381Fr::BLS12_381_Fr_Params}; use types::{ diff --git a/noir-projects/noir-protocol-circuits/crates/blob/src/blob_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/blob/src/blob_public_inputs.nr index a318fd00ed9c..cbbe9f419482 100644 --- a/noir-projects/noir-protocol-circuits/crates/blob/src/blob_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/blob/src/blob_public_inputs.nr @@ -1,5 +1,4 @@ -use crate::unconstrained_config::F; -// TODO(#9982): Replace unconstrained_config with config. +use crate::config::F; use bigint::BigNum; use types::{ constants::{BLOB_PUBLIC_INPUTS, BLOBS_PER_BLOCK}, diff --git a/noir-projects/noir-protocol-circuits/crates/blob/src/config.nr b/noir-projects/noir-protocol-circuits/crates/blob/src/config.nr index 53f72447e2b1..a3a698e629b7 100644 --- a/noir-projects/noir-protocol-circuits/crates/blob/src/config.nr +++ b/noir-projects/noir-protocol-circuits/crates/blob/src/config.nr @@ -7,8 +7,8 @@ pub type F = BigNum<3, 255, BLS12_381_Fr_Params>; pub global LOG_FIELDS_PER_BLOB: u32 = 12; pub global EXTRA_FIELDS_PER_BLOB: u32 = 16; // 16 = floor(4096 FIELDS_PER_BLOB / 254 noir_field_bits), wasting only 32 bits. -pub global NOIR_FIELDS_PER_BLOB: u32 = FIELDS_PER_BLOB + EXTRA_FIELDS_PER_BLOB; -pub global FIELDS_CARRYING_AN_EXTRA_BIT_PER_BLOB: u32 = EXTRA_FIELDS_PER_BLOB * 254; // EXTRA_FIELDS_PER_BLOB * 254 = 4064. So the first 4064 bls Fr fields in the blob will carry an extra bit in their 255th bit position, that will be used to reconstitute 16 extra fields. +// pub global NOIR_FIELDS_PER_BLOB: u32 = FIELDS_PER_BLOB + EXTRA_FIELDS_PER_BLOB; +// pub global FIELDS_CARRYING_AN_EXTRA_BIT_PER_BLOB: u32 = EXTRA_FIELDS_PER_BLOB * 254; // EXTRA_FIELDS_PER_BLOB * 254 = 4064. So the first 4064 bls Fr fields in the blob will carry an extra bit in their 255th bit position, that will be used to reconstitute 16 extra fields. pub global D: F = BigNum { limbs: [4096, 0, 0] }; pub global D_INV: F = BigNum { limbs: [0x686828bfce5c19400fffff00100001, 0x6878b46ae3705eb6a46a89213de7d3, 0x73e6] }; diff --git a/noir-projects/noir-protocol-circuits/crates/blob/src/lib.nr b/noir-projects/noir-protocol-circuits/crates/blob/src/lib.nr index 1f83b3bb669f..da66b644cb7c 100644 --- a/noir-projects/noir-protocol-circuits/crates/blob/src/lib.nr +++ b/noir-projects/noir-protocol-circuits/crates/blob/src/lib.nr @@ -1,5 +1,4 @@ mod blob_public_inputs; mod blob; mod mock_blob_oracle; -mod unconstrained_config; -// TODO(#9982): Replace unconstrained_config with config and import ROOTS - calculating ROOTS in unconstrained is insecure. +mod config; From 24770cf1b271933c223f4c0f988cf9a6be1965d4 Mon Sep 17 00:00:00 2001 From: TomAFrench Date: Wed, 11 Dec 2024 03:02:31 +0000 Subject: [PATCH 02/14] here be dragons --- .../crates/blob/src/blob.nr | 71 +++++++++++-------- .../crates/blob/src/config.nr | 2 +- 2 files changed, 44 insertions(+), 29 deletions(-) diff --git a/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr b/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr index 35d2c2c664f7..5630dcc446ad 100644 --- a/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr +++ b/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr @@ -375,10 +375,8 @@ fn compute_fracs(z: F, ys: [F; FIELDS_PER_BLOB]) -> [F; FIELDS_PER_BLOB] { fracs } -// TODO: Clean me -unconstrained fn __compute_partial_sums( - fracs: [F; FIELDS_PER_BLOB], -) -> [F; FIELDS_PER_BLOB / 8] { +// TODO: Clean me ... edit: Kill me +unconstrained fn __compute_partial_sums(fracs: [F; FIELDS_PER_BLOB]) -> [F; FIELDS_PER_BLOB / 8] { let mut partial_sums: [F; FIELDS_PER_BLOB / 8] = std::mem::zeroed(); // Seeking: @@ -388,37 +386,54 @@ unconstrained fn __compute_partial_sums( // /____ z - omega^k // k=i*8 + 0 - // Need to split off the first iteration. let mut partial_sum: F = BigNum::new(); - for i in 0..8 { - // y_k * ( omega^k / (z - omega^k) ) - let summand = ROOTS[i].__mul(fracs[i]); + unroll_loop_inner!(0 as u32); + partial_sums[0] = partial_sum; + + unroll_loop_outer!(); + + partial_sums +} - // partial_sum + ( y_k * ( omega^k / (z - omega^k) ) -> partial_sum - partial_sum = partial_sum.__add(summand); +comptime fn unroll_loop_outer() -> Quoted { + let mut indices: [u32; 512] = [0; 512]; + for i in 1..512 { + indices[i] = i; } partial_sums[0] = partial_sum; - let NUM_PARTIAL_SUMS = FIELDS_PER_BLOB / 8; - for i in 1..NUM_PARTIAL_SUMS { - let mut partial_sum: F = partial_sums[i - 1]; - // Seeking: - // ___i*8 + 7 - // \ omega^k - // partial_sum = / y_k . --------- - // /____ z - omega^k - // k=i*8 + 0 - for j in 0..8 { - let k = i * 8 + j; - // y_k * ( omega^k / (z - omega^k) ) - let summand = ROOTS[k].__mul(fracs[k]); - // partial_sum + ( y_k * ( omega^k / (z - omega^k) ) -> partial_sum - partial_sum = partial_sum.__add(summand); - } - partial_sums[i] = partial_sum; + indices + .as_slice() + .map(|index: u32| { + quote { + let mut partial_sum: F = partial_sums[$index - (1 as u32)]; + + unroll_loop_inner!($index * (8 as u32)); + + partial_sums[$index] = partial_sum; + } + }) + .join(quote { }) +} + +comptime fn unroll_loop_inner(loop_index: u32) -> Quoted { + let mut indices: [u32; 8] = [0; 8]; + for i in 0..8 { + indices[i] = i; } - partial_sums + indices + .as_slice() + .map(|index: u32| { + let root = ROOTS[loop_index + index]; + quote { + // y_k * ( omega^k / (z - omega^k) ) + let summand = $root.__mul(fracs[$loop_index + $index]); + // partial_sum + ( y_k * ( omega^k / (z - omega^k) ) -> partial_sum + partial_sum = partial_sum.__add(summand); + } + }) + .join(quote { }) } mod tests { diff --git a/noir-projects/noir-protocol-circuits/crates/blob/src/config.nr b/noir-projects/noir-protocol-circuits/crates/blob/src/config.nr index a3a698e629b7..5bf9386757a6 100644 --- a/noir-projects/noir-protocol-circuits/crates/blob/src/config.nr +++ b/noir-projects/noir-protocol-circuits/crates/blob/src/config.nr @@ -13,7 +13,7 @@ pub global D: F = BigNum { limbs: [4096, 0, 0] }; pub global D_INV: F = BigNum { limbs: [0x686828bfce5c19400fffff00100001, 0x6878b46ae3705eb6a46a89213de7d3, 0x73e6] }; -pub global ROOTS: [F; FIELDS_PER_BLOB] = [ +pub comptime global ROOTS: [F; FIELDS_PER_BLOB] = [ BigNum { limbs: [0x000000000000000000000000000001, 0x000000000000000000000000000000, 0x000000], }, From a6a939f1669934610dddd287e1426c95225f1efa Mon Sep 17 00:00:00 2001 From: TomAFrench Date: Fri, 13 Dec 2024 21:58:43 +0000 Subject: [PATCH 03/14] . --- noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr | 1 - 1 file changed, 1 deletion(-) diff --git a/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr b/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr index 5630dcc446ad..2473e302cc5c 100644 --- a/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr +++ b/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr @@ -400,7 +400,6 @@ comptime fn unroll_loop_outer() -> Quoted { for i in 1..512 { indices[i] = i; } - partial_sums[0] = partial_sum; indices .as_slice() From 9edf47d9d8fed9dec49fa8699cbda65c4812ad04 Mon Sep 17 00:00:00 2001 From: TomAFrench Date: Sat, 11 Jan 2025 15:02:18 +0000 Subject: [PATCH 04/14] feat: short-circuit empty loop codegen --- .../noirc_evaluator/src/ssa/ssa_gen/mod.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs index 16b7b3ea01bc..1fdfb8dcf594 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs @@ -528,6 +528,19 @@ impl<'a> FunctionContext<'a> { /// ... This is the current insert point after codegen_for finishes ... /// ``` fn codegen_for(&mut self, for_expr: &ast::For) -> Result { + self.builder.set_location(for_expr.start_range_location); + let start_index = self.codegen_non_tuple_expression(&for_expr.start_range)?; + + self.builder.set_location(for_expr.end_range_location); + let end_index = self.codegen_non_tuple_expression(&for_expr.end_range)?; + + if let (Some(start_constant), Some(end_constant)) = (self.builder.current_function.dfg.get_numeric_constant(start_index), self.builder.current_function.dfg.get_numeric_constant(end_index)) { + // If we can determine that the loop contains zero iterations then we can short-circuit codegen. + if start_constant == end_constant { + return Ok(Self::unit_value()) + } + } + let loop_entry = self.builder.insert_block(); let loop_body = self.builder.insert_block(); let loop_end = self.builder.insert_block(); @@ -540,11 +553,6 @@ impl<'a> FunctionContext<'a> { // within the loop which need to jump to them. self.enter_loop(loop_entry, loop_index, loop_end); - self.builder.set_location(for_expr.start_range_location); - let start_index = self.codegen_non_tuple_expression(&for_expr.start_range)?; - - self.builder.set_location(for_expr.end_range_location); - let end_index = self.codegen_non_tuple_expression(&for_expr.end_range)?; // Set the location of the initial jmp instruction to the start range. This is the location // used to issue an error if the start range cannot be determined at compile-time. From db913f3533fc40adcd92a9f36410bac8e00fc46a Mon Sep 17 00:00:00 2001 From: TomAFrench Date: Sat, 11 Jan 2025 15:18:27 +0000 Subject: [PATCH 05/14] . --- .../compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs index 1fdfb8dcf594..9e7afa02a52e 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs @@ -534,10 +534,13 @@ impl<'a> FunctionContext<'a> { self.builder.set_location(for_expr.end_range_location); let end_index = self.codegen_non_tuple_expression(&for_expr.end_range)?; - if let (Some(start_constant), Some(end_constant)) = (self.builder.current_function.dfg.get_numeric_constant(start_index), self.builder.current_function.dfg.get_numeric_constant(end_index)) { + if let (Some(start_constant), Some(end_constant)) = ( + self.builder.current_function.dfg.get_numeric_constant(start_index), + self.builder.current_function.dfg.get_numeric_constant(end_index), + ) { // If we can determine that the loop contains zero iterations then we can short-circuit codegen. if start_constant == end_constant { - return Ok(Self::unit_value()) + return Ok(Self::unit_value()); } } @@ -553,7 +556,6 @@ impl<'a> FunctionContext<'a> { // within the loop which need to jump to them. self.enter_loop(loop_entry, loop_index, loop_end); - // Set the location of the initial jmp instruction to the start range. This is the location // used to issue an error if the start range cannot be determined at compile-time. self.builder.set_location(for_expr.start_range_location); From 1e22e11ccba795fcc871c0d3f2b2545c5c0864f0 Mon Sep 17 00:00:00 2001 From: TomAFrench Date: Sat, 11 Jan 2025 16:18:21 +0000 Subject: [PATCH 06/14] . --- .../crates/blob/src/blob.nr | 103 +++++++++--------- 1 file changed, 50 insertions(+), 53 deletions(-) diff --git a/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr b/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr index cff8276aa5f3..269e77774d1d 100644 --- a/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr +++ b/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr @@ -267,20 +267,30 @@ fn barycentric_evaluate_blob_at_z(z: F, ys: [F; FIELDS_PER_BLOB]) -> F { // partial_sums[i] <- partial_sums[i-1] + (lhs[8*i] * rhs[8*i] + ... + lhs[8*i + 7] * rhs[8*i + 7]) // => (lhs[8*i] * rhs[8*i] + ... + lhs[8*i + 7] * rhs[8*i + 7]) + partial_sums[i-1] - partial_sums[i] == 0 - let mut lhs: [[F; 1]; 8] = [std::mem::zeroed(); 8]; - let mut rhs: [[F; 1]; 8] = [std::mem::zeroed(); 8]; - for j in 0..8 { - let k = i * 8 + j; - lhs[j] = [ROOTS[k]]; // omega^k - rhs[j] = [fracs[k]]; // y_k / (z - omega^k) - } - let linear_terms = [partial_sums[i - 1], partial_sums[i]]; BigNum::evaluate_quadratic_expression( - lhs, + [ + [ROOTS[i * 8 + 0]], + [ROOTS[i * 8 + 1]], + [ROOTS[i * 8 + 2]], + [ROOTS[i * 8 + 3]], + [ROOTS[i * 8 + 4]], + [ROOTS[i * 8 + 5]], + [ROOTS[i * 8 + 6]], + [ROOTS[i * 8 + 7]], + ], [[false], [false], [false], [false], [false], [false], [false], [false]], - rhs, + [ + [fracs[i * 8 + 0]], + [fracs[i * 8 + 1]], + [fracs[i * 8 + 2]], + [fracs[i * 8 + 3]], + [fracs[i * 8 + 4]], + [fracs[i * 8 + 5]], + [fracs[i * 8 + 6]], + [fracs[i * 8 + 7]], + ], [[false], [false], [false], [false], [false], [false], [false], [false]], linear_terms, [false, true], @@ -381,8 +391,10 @@ fn compute_fracs(z: F, ys: [F; FIELDS_PER_BLOB]) -> [F; FIELDS_PER_BLOB] { fracs } -// TODO: Clean me ... edit: Kill me -unconstrained fn __compute_partial_sums(fracs: [F; FIELDS_PER_BLOB]) -> [F; FIELDS_PER_BLOB / 8] { +// TODO: Clean me +unconstrained fn __compute_partial_sums( + fracs: [F; FIELDS_PER_BLOB], +) -> [F; FIELDS_PER_BLOB / 8] { let mut partial_sums: [F; FIELDS_PER_BLOB / 8] = std::mem::zeroed(); // Seeking: @@ -392,55 +404,40 @@ unconstrained fn __compute_partial_sums(fracs: [F; FIELDS_PER_BLOB]) -> [F; FIEL // /____ z - omega^k // k=i*8 + 0 + // Need to split off the first iteration. let mut partial_sum: F = BigNum::new(); - unroll_loop_inner!(0 as u32); - partial_sums[0] = partial_sum; - - unroll_loop_outer!(); - - partial_sums -} + for i in 0..8 { + // y_k * ( omega^k / (z - omega^k) ) + let summand = ROOTS[i].__mul(fracs[i]); -comptime fn unroll_loop_outer() -> Quoted { - let mut indices: [u32; 512] = [0; 512]; - for i in 1..512 { - indices[i] = i; + // partial_sum + ( y_k * ( omega^k / (z - omega^k) ) -> partial_sum + partial_sum = partial_sum.__add(summand); } + partial_sums[0] = partial_sum; - indices - .as_slice() - .map(|index: u32| { - quote { - let mut partial_sum: F = partial_sums[$index - (1 as u32)]; - - unroll_loop_inner!($index * (8 as u32)); - - partial_sums[$index] = partial_sum; - } - }) - .join(quote { }) -} - -comptime fn unroll_loop_inner(loop_index: u32) -> Quoted { - let mut indices: [u32; 8] = [0; 8]; - for i in 0..8 { - indices[i] = i; + let NUM_PARTIAL_SUMS = FIELDS_PER_BLOB / 8; + for i in 1..NUM_PARTIAL_SUMS { + let mut partial_sum: F = partial_sums[i - 1]; + // Seeking: + // ___i*8 + 7 + // \ omega^k + // partial_sum = / y_k . --------- + // /____ z - omega^k + // k=i*8 + 0 + for j in 0..8 { + let k = i * 8 + j; + // y_k * ( omega^k / (z - omega^k) ) + let summand = ROOTS[k].__mul(fracs[k]); + // partial_sum + ( y_k * ( omega^k / (z - omega^k) ) -> partial_sum + partial_sum = partial_sum.__add(summand); + } + partial_sums[i] = partial_sum; } - indices - .as_slice() - .map(|index: u32| { - let root = ROOTS[loop_index + index]; - quote { - // y_k * ( omega^k / (z - omega^k) ) - let summand = $root.__mul(fracs[$loop_index + $index]); - // partial_sum + ( y_k * ( omega^k / (z - omega^k) ) -> partial_sum - partial_sum = partial_sum.__add(summand); - } - }) - .join(quote { }) + partial_sums } + mod tests { // TODO(#9982): Replace unconstrained_config with config and import ROOTS - calculating ROOTS in unconstrained is insecure. use crate::{ From fb7eadce8569482c3d8032cddd1d17e7c604dd44 Mon Sep 17 00:00:00 2001 From: Tom French Date: Wed, 15 Jan 2025 01:39:56 +0000 Subject: [PATCH 07/14] . --- noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr b/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr index f708f1d02aac..eaa0abdbfa7b 100644 --- a/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr +++ b/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr @@ -392,9 +392,7 @@ fn compute_fracs(z: F, ys: [F; FIELDS_PER_BLOB]) -> [F; FIELDS_PER_BLOB] { } // TODO: Clean me -unconstrained fn __compute_partial_sums( - fracs: [F; FIELDS_PER_BLOB], -) -> [F; FIELDS_PER_BLOB / 8] { +unconstrained fn __compute_partial_sums(fracs: [F; FIELDS_PER_BLOB]) -> [F; FIELDS_PER_BLOB / 8] { let mut partial_sums: [F; FIELDS_PER_BLOB / 8] = std::mem::zeroed(); // Seeking: @@ -437,7 +435,6 @@ unconstrained fn __compute_partial_sums( partial_sums } - mod tests { // TODO(#9982): Replace unconstrained_config with config and import ROOTS - calculating ROOTS in unconstrained is insecure. use crate::{ From f2d30ae081ae59d8cb8c15f4ae8bcc5d572a7ed1 Mon Sep 17 00:00:00 2001 From: TomAFrench Date: Wed, 15 Jan 2025 16:49:18 +0000 Subject: [PATCH 08/14] . --- noir-projects/noir-protocol-circuits/crates/blob/src/config.nr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir-projects/noir-protocol-circuits/crates/blob/src/config.nr b/noir-projects/noir-protocol-circuits/crates/blob/src/config.nr index 5bf9386757a6..a3a698e629b7 100644 --- a/noir-projects/noir-protocol-circuits/crates/blob/src/config.nr +++ b/noir-projects/noir-protocol-circuits/crates/blob/src/config.nr @@ -13,7 +13,7 @@ pub global D: F = BigNum { limbs: [4096, 0, 0] }; pub global D_INV: F = BigNum { limbs: [0x686828bfce5c19400fffff00100001, 0x6878b46ae3705eb6a46a89213de7d3, 0x73e6] }; -pub comptime global ROOTS: [F; FIELDS_PER_BLOB] = [ +pub global ROOTS: [F; FIELDS_PER_BLOB] = [ BigNum { limbs: [0x000000000000000000000000000001, 0x000000000000000000000000000000, 0x000000], }, From c548a8cf362e55f7f471ba10054780271512bfb2 Mon Sep 17 00:00:00 2001 From: TomAFrench Date: Thu, 16 Jan 2025 00:25:57 +0000 Subject: [PATCH 09/14] chore: weird hack --- .../crates/blob/src/blob.nr | 23 +++++++++++-------- .../crates/blob/src/lib.nr | 1 + 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr b/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr index 90d1b56fc772..e81208f4beb3 100644 --- a/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr +++ b/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr @@ -1,6 +1,6 @@ use crate::{ blob_public_inputs::{BlobCommitment, BlobPublicInputs, BlockBlobPublicInputs}, - config::{D_INV, F, LOG_FIELDS_PER_BLOB, ROOTS}, + config::{D_INV, F, LOG_FIELDS_PER_BLOB, ROOTS}, unconstrained_config::compute_roots_of_unity }; use bigint::{BigNum, BigNumTrait}; @@ -183,6 +183,9 @@ pub fn evaluate_blobs( * @return y = p(z) */ fn barycentric_evaluate_blob_at_z(z: F, ys: [F; FIELDS_PER_BLOB]) -> F { + // TODO(#9982): Delete below and go back to using config.nr - calculating ROOTS in unconstrained is insecure. + let UNCONSTRAINED_ROOTS = unsafe { compute_roots_of_unity() }; + // Note: it's more efficient (saving 30k constraints) to compute: // ___d-1 // \ / y_i \ @@ -201,7 +204,7 @@ fn barycentric_evaluate_blob_at_z(z: F, ys: [F; FIELDS_PER_BLOB]) -> F { // i=0 // // perhaps because all the omega^i terms are constant witnesses? - let fracs = compute_fracs(z, ys); + let fracs = compute_fracs(z, ys, UNCONSTRAINED_ROOTS); // OK so...we can add multiple product terms into a sum...but I am not sure how many! // we are computing 254 * 254 bit products and we need to ensure each product limb doesn't overflow @@ -220,7 +223,7 @@ fn barycentric_evaluate_blob_at_z(z: F, ys: [F; FIELDS_PER_BLOB]) -> F { let NUM_PARTIAL_SUMS = FIELDS_PER_BLOB / 8; let partial_sums: [F; FIELDS_PER_BLOB / 8] = unsafe { // Safety: This sum is checked by the following `BigNum::evaluate_quadratic_expression` calls. - __compute_partial_sums(fracs) + __compute_partial_sums(fracs, UNCONSTRAINED_ROOTS) }; if !std::runtime::is_unconstrained() { @@ -349,10 +352,10 @@ fn compute_factor(z: F) -> F { factor } -unconstrained fn __compute_fracs(z: F, ys: [F; FIELDS_PER_BLOB]) -> [F; FIELDS_PER_BLOB] { +unconstrained fn __compute_fracs(z: F, ys: [F; FIELDS_PER_BLOB], unconstrained_roots: [F; FIELDS_PER_BLOB],) -> [F; FIELDS_PER_BLOB] { let mut denoms = [BigNum::new(); FIELDS_PER_BLOB]; for i in 0..FIELDS_PER_BLOB { - denoms[i] = z.__sub(ROOTS[i]); // (z - omega^i) + denoms[i] = z.__sub(unconstrained_roots[i]); // (z - omega^i) } let inv_denoms = __batch_invert_impl(denoms); // 1 / (z - omega^i), for all i @@ -367,10 +370,10 @@ unconstrained fn __compute_fracs(z: F, ys: [F; FIELDS_PER_BLOB]) -> [F; FIELDS_P fracs } -fn compute_fracs(z: F, ys: [F; FIELDS_PER_BLOB]) -> [F; FIELDS_PER_BLOB] { +fn compute_fracs(z: F, ys: [F; FIELDS_PER_BLOB],unconstrained_roots: [F; FIELDS_PER_BLOB],) -> [F; FIELDS_PER_BLOB] { let mut fracs: [F; FIELDS_PER_BLOB] = unsafe { // Safety: We immediately constrain these `fracs` to be correct in the following call to `BigNum::evaluate_quadratic_expression`. - __compute_fracs(z, ys) + __compute_fracs(z, ys, unconstrained_roots ) }; if !std::runtime::is_unconstrained() { @@ -392,7 +395,7 @@ fn compute_fracs(z: F, ys: [F; FIELDS_PER_BLOB]) -> [F; FIELDS_PER_BLOB] { } // TODO: Clean me -unconstrained fn __compute_partial_sums(fracs: [F; FIELDS_PER_BLOB]) -> [F; FIELDS_PER_BLOB / 8] { +unconstrained fn __compute_partial_sums(fracs: [F; FIELDS_PER_BLOB], unconstrained_roots: [F; FIELDS_PER_BLOB],) -> [F; FIELDS_PER_BLOB / 8] { let mut partial_sums: [F; FIELDS_PER_BLOB / 8] = std::mem::zeroed(); // Seeking: @@ -406,7 +409,7 @@ unconstrained fn __compute_partial_sums(fracs: [F; FIELDS_PER_BLOB]) -> [F; FIEL let mut partial_sum: F = BigNum::new(); for i in 0..8 { // y_k * ( omega^k / (z - omega^k) ) - let summand = ROOTS[i].__mul(fracs[i]); + let summand = unconstrained_roots[i].__mul(fracs[i]); // partial_sum + ( y_k * ( omega^k / (z - omega^k) ) -> partial_sum partial_sum = partial_sum.__add(summand); @@ -425,7 +428,7 @@ unconstrained fn __compute_partial_sums(fracs: [F; FIELDS_PER_BLOB]) -> [F; FIEL for j in 0..8 { let k = i * 8 + j; // y_k * ( omega^k / (z - omega^k) ) - let summand = ROOTS[k].__mul(fracs[k]); + let summand = unconstrained_roots[k].__mul(fracs[k]); // partial_sum + ( y_k * ( omega^k / (z - omega^k) ) -> partial_sum partial_sum = partial_sum.__add(summand); } diff --git a/noir-projects/noir-protocol-circuits/crates/blob/src/lib.nr b/noir-projects/noir-protocol-circuits/crates/blob/src/lib.nr index da66b644cb7c..3d2845e05271 100644 --- a/noir-projects/noir-protocol-circuits/crates/blob/src/lib.nr +++ b/noir-projects/noir-protocol-circuits/crates/blob/src/lib.nr @@ -2,3 +2,4 @@ mod blob_public_inputs; mod blob; mod mock_blob_oracle; mod config; +mod unconstrained_config; \ No newline at end of file From 312b03decac810e4d0334acd710277a30adf6706 Mon Sep 17 00:00:00 2001 From: TomAFrench Date: Thu, 16 Jan 2025 00:26:30 +0000 Subject: [PATCH 10/14] . --- .../crates/blob/src/blob.nr | 22 ++++++++++++++----- .../crates/blob/src/lib.nr | 2 +- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr b/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr index e81208f4beb3..8b2f5a56367d 100644 --- a/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr +++ b/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr @@ -1,6 +1,7 @@ use crate::{ blob_public_inputs::{BlobCommitment, BlobPublicInputs, BlockBlobPublicInputs}, - config::{D_INV, F, LOG_FIELDS_PER_BLOB, ROOTS}, unconstrained_config::compute_roots_of_unity + config::{D_INV, F, LOG_FIELDS_PER_BLOB, ROOTS}, + unconstrained_config::compute_roots_of_unity, }; use bigint::{BigNum, BigNumTrait}; @@ -352,7 +353,11 @@ fn compute_factor(z: F) -> F { factor } -unconstrained fn __compute_fracs(z: F, ys: [F; FIELDS_PER_BLOB], unconstrained_roots: [F; FIELDS_PER_BLOB],) -> [F; FIELDS_PER_BLOB] { +unconstrained fn __compute_fracs( + z: F, + ys: [F; FIELDS_PER_BLOB], + unconstrained_roots: [F; FIELDS_PER_BLOB], +) -> [F; FIELDS_PER_BLOB] { let mut denoms = [BigNum::new(); FIELDS_PER_BLOB]; for i in 0..FIELDS_PER_BLOB { denoms[i] = z.__sub(unconstrained_roots[i]); // (z - omega^i) @@ -370,10 +375,14 @@ unconstrained fn __compute_fracs(z: F, ys: [F; FIELDS_PER_BLOB], unconstrained_r fracs } -fn compute_fracs(z: F, ys: [F; FIELDS_PER_BLOB],unconstrained_roots: [F; FIELDS_PER_BLOB],) -> [F; FIELDS_PER_BLOB] { +fn compute_fracs( + z: F, + ys: [F; FIELDS_PER_BLOB], + unconstrained_roots: [F; FIELDS_PER_BLOB], +) -> [F; FIELDS_PER_BLOB] { let mut fracs: [F; FIELDS_PER_BLOB] = unsafe { // Safety: We immediately constrain these `fracs` to be correct in the following call to `BigNum::evaluate_quadratic_expression`. - __compute_fracs(z, ys, unconstrained_roots ) + __compute_fracs(z, ys, unconstrained_roots) }; if !std::runtime::is_unconstrained() { @@ -395,7 +404,10 @@ fn compute_fracs(z: F, ys: [F; FIELDS_PER_BLOB],unconstrained_roots: [F; FIELDS_ } // TODO: Clean me -unconstrained fn __compute_partial_sums(fracs: [F; FIELDS_PER_BLOB], unconstrained_roots: [F; FIELDS_PER_BLOB],) -> [F; FIELDS_PER_BLOB / 8] { +unconstrained fn __compute_partial_sums( + fracs: [F; FIELDS_PER_BLOB], + unconstrained_roots: [F; FIELDS_PER_BLOB], +) -> [F; FIELDS_PER_BLOB / 8] { let mut partial_sums: [F; FIELDS_PER_BLOB / 8] = std::mem::zeroed(); // Seeking: diff --git a/noir-projects/noir-protocol-circuits/crates/blob/src/lib.nr b/noir-projects/noir-protocol-circuits/crates/blob/src/lib.nr index 3d2845e05271..560b6d8d4367 100644 --- a/noir-projects/noir-protocol-circuits/crates/blob/src/lib.nr +++ b/noir-projects/noir-protocol-circuits/crates/blob/src/lib.nr @@ -2,4 +2,4 @@ mod blob_public_inputs; mod blob; mod mock_blob_oracle; mod config; -mod unconstrained_config; \ No newline at end of file +mod unconstrained_config; From 5cf1fec4927f4457a018c0069eea315402f89130 Mon Sep 17 00:00:00 2001 From: TomAFrench Date: Thu, 16 Jan 2025 00:32:04 +0000 Subject: [PATCH 11/14] chore: import traits --- noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr | 3 +++ 1 file changed, 3 insertions(+) diff --git a/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr b/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr index 8b2f5a56367d..cf94f94b2654 100644 --- a/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr +++ b/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr @@ -14,6 +14,7 @@ use types::{ constants::{BLOBS_PER_BLOCK, FIELDS_PER_BLOB}, utils::arrays::array_splice, }; +use std::ops::{Neg, Mul}; global LIMB_MAX: Field = 0x1000000000000000000000000000000; // 2^120 global TWO_POW_56: u64 = 0x100000000000000; // u64 to aid integer only modulo in __field_to_bignum_limbs @@ -466,6 +467,8 @@ mod tests { constants::{BLOBS_PER_BLOCK, FIELDS_PER_BLOB}, tests::{fixture_builder::FixtureBuilder, utils::pad_end}, }; + use types::traits::Serialize; + use bigint::bignum::BigNumTrait; #[test] unconstrained fn test_one_note() { From c057a6f5f394e9e27e4c2be679e86de3c93a2ef2 Mon Sep 17 00:00:00 2001 From: Tom French Date: Thu, 16 Jan 2025 09:44:00 +0000 Subject: [PATCH 12/14] . --- .../noir-protocol-circuits/crates/blob/src/blob.nr | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr b/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr index 5d86fa3420e4..e6d92f9e3abb 100644 --- a/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr +++ b/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr @@ -9,12 +9,12 @@ use bigint::{BigNum, BigNumTrait}; use types::hash::poseidon2_hash_subarray; // Variable hash method: // use types::hash::poseidon2_cheaper_variable_hash; +use std::ops::{Mul, Neg}; use types::{ abis::sponge_blob::SpongeBlob, constants::{BLOBS_PER_BLOCK, FIELDS_PER_BLOB}, utils::arrays::array_splice, }; -use std::ops::{Neg, Mul}; global LIMB_MAX: Field = 0x1000000000000000000000000000000; // 2^120 global TWO_POW_56: u64 = 0x100000000000000; // u64 to aid integer only modulo in __field_to_bignum_limbs @@ -224,9 +224,8 @@ fn barycentric_evaluate_blob_at_z(z: F, ys: [F; FIELDS_PER_BLOB]) -> F { // i=0 let NUM_PARTIAL_SUMS = FIELDS_PER_BLOB / 8; /// Safety: This sum is checked by the following `BigNum::evaluate_quadratic_expression` calls. - let partial_sums: [F; FIELDS_PER_BLOB / 8] = unsafe { - __compute_partial_sums(fracs, UNCONSTRAINED_ROOTS) - }; + let partial_sums: [F; FIELDS_PER_BLOB / 8] = + unsafe { __compute_partial_sums(fracs, UNCONSTRAINED_ROOTS) }; if !std::runtime::is_unconstrained() { // We split off the first term to check the initial sum @@ -460,13 +459,13 @@ mod tests { config::{D, D_INV, F}, }; use bigint::{BigNum, fields::bls12_381Fr::BLS12_381_Fr_Params}; + use bigint::bignum::BigNumTrait; use types::{ abis::sponge_blob::SpongeBlob, constants::{BLOBS_PER_BLOCK, FIELDS_PER_BLOB}, tests::{fixture_builder::FixtureBuilder, utils::pad_end}, }; use types::traits::Serialize; - use bigint::bignum::BigNumTrait; #[test] unconstrained fn test_one_note() { From e3e2b4f454021195db1cbe35885f2c11244eac18 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Thu, 16 Jan 2025 11:19:25 +0000 Subject: [PATCH 13/14] Apply suggestions from code review Co-authored-by: Michael Connor --- noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr | 2 ++ 1 file changed, 2 insertions(+) diff --git a/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr b/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr index e6d92f9e3abb..e628465e420e 100644 --- a/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr +++ b/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr @@ -274,6 +274,7 @@ fn barycentric_evaluate_blob_at_z(z: F, ys: [F; FIELDS_PER_BLOB]) -> F { let linear_terms = [partial_sums[i - 1], partial_sums[i]]; BigNum::evaluate_quadratic_expression( + /* lhs */ [ [ROOTS[i * 8 + 0]], [ROOTS[i * 8 + 1]], @@ -285,6 +286,7 @@ fn barycentric_evaluate_blob_at_z(z: F, ys: [F; FIELDS_PER_BLOB]) -> F { [ROOTS[i * 8 + 7]], ], [[false], [false], [false], [false], [false], [false], [false], [false]], + /* rhs */ [ [fracs[i * 8 + 0]], [fracs[i * 8 + 1]], From 995b6ecc70ec24f0f25f01e685259caea9cbf0c2 Mon Sep 17 00:00:00 2001 From: Tom French Date: Thu, 16 Jan 2025 11:27:08 +0000 Subject: [PATCH 14/14] fmt --- noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr b/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr index e628465e420e..862dfad250c1 100644 --- a/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr +++ b/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr @@ -274,8 +274,7 @@ fn barycentric_evaluate_blob_at_z(z: F, ys: [F; FIELDS_PER_BLOB]) -> F { let linear_terms = [partial_sums[i - 1], partial_sums[i]]; BigNum::evaluate_quadratic_expression( - /* lhs */ - [ + /* lhs */ [ [ROOTS[i * 8 + 0]], [ROOTS[i * 8 + 1]], [ROOTS[i * 8 + 2]],