From cc03f522aec6dbd30c39a15096b21ebddce268ee Mon Sep 17 00:00:00 2001 From: Uma Roy Date: Mon, 11 Sep 2023 17:25:14 -0700 Subject: [PATCH 1/8] Added initial starter template --- plonky2x/src/frontend/eth/mpt/rlc.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/plonky2x/src/frontend/eth/mpt/rlc.rs b/plonky2x/src/frontend/eth/mpt/rlc.rs index 4e3f650c4..4eefffe8a 100644 --- a/plonky2x/src/frontend/eth/mpt/rlc.rs +++ b/plonky2x/src/frontend/eth/mpt/rlc.rs @@ -1,5 +1,8 @@ use std::marker::PhantomData; +use plonky2::hash::poseidon::PoseidonHash; +use plonky2::iop::challenger::RecursiveChallenger; + use super::generators::SubarrayEqualGenerator; use crate::prelude::{BoolVariable, ByteVariable, CircuitBuilder, PlonkParameters, Variable}; @@ -35,7 +38,7 @@ impl, const D: usize> CircuitBuilder { b_offset: Variable, len: Variable, ) { - // TODO: implement + // TODO: instead of using the SubarrayEqualGenerator below that doesn't actually check anything, implement an RLC check here let generator: SubarrayEqualGenerator = SubarrayEqualGenerator { a: a.to_vec(), a_offset, @@ -45,6 +48,19 @@ impl, const D: usize> CircuitBuilder { _phantom: PhantomData::, }; self.add_simple_generator(generator); + + // The following methods might be helpful + let mut challenger = RecursiveChallenger::::new(&mut self.api); + let challenger_seed = Vec::new(); // TODO: have to "seed" the challenger with some random inputs from the circuit + challenger.observe_elements(&challenger_seed); + + let random_variables = challenger.get_n_challenges(&mut self.api, 1); + let random_variable = random_variables[0]; + + // To convert from a Target to a Variable, just use Variable(my_target) to get a Variable + + // TODO: now compute a commitment to a[a_offset:a_offset+len] + // TODO: now compute a commitment to b[b_offset:b_offset+len] } } From 22089cb1cdfa666a46b654e19fefae4f9818a454 Mon Sep 17 00:00:00 2001 From: Nikolay Kostadinov Date: Tue, 19 Sep 2023 18:07:43 +0300 Subject: [PATCH 2/8] feat: Implement subarray equality check using rlc --- plonky2x/src/frontend/builder/mod.rs | 9 ++ plonky2x/src/frontend/eth/mpt/rlc.rs | 158 +++++++++++++++++++++------ 2 files changed, 131 insertions(+), 36 deletions(-) diff --git a/plonky2x/src/frontend/builder/mod.rs b/plonky2x/src/frontend/builder/mod.rs index fbb7fd0c0..41e869a77 100644 --- a/plonky2x/src/frontend/builder/mod.rs +++ b/plonky2x/src/frontend/builder/mod.rs @@ -342,6 +342,15 @@ impl, const D: usize> CircuitBuilder { pub fn to_be_bits(&mut self, variable: V) -> Vec { variable.to_be_bits(self) } + + /// Takes a slice of bits and returns the number with little-endian bit representation as a Variable + pub fn le_sum(&mut self, bits: &[BoolVariable]) -> Variable { + let bits_in_booltarget = bits + .iter() + .map(|x| BoolTarget::new_unsafe(x.0.0)) + .collect_vec(); + Variable(self.api.le_sum(bits_in_booltarget.into_iter())) + } } impl, const D: usize> Default for CircuitBuilder { diff --git a/plonky2x/src/frontend/eth/mpt/rlc.rs b/plonky2x/src/frontend/eth/mpt/rlc.rs index 4eefffe8a..0b339f676 100644 --- a/plonky2x/src/frontend/eth/mpt/rlc.rs +++ b/plonky2x/src/frontend/eth/mpt/rlc.rs @@ -1,23 +1,45 @@ -use std::marker::PhantomData; - +use plonky2::field::types::Field; use plonky2::hash::poseidon::PoseidonHash; use plonky2::iop::challenger::RecursiveChallenger; -use super::generators::SubarrayEqualGenerator; use crate::prelude::{BoolVariable, ByteVariable, CircuitBuilder, PlonkParameters, Variable}; -// Checks that a[a_offset:a_offset+len] = b[b_offset:b_offset+len] -pub fn subarray_equal(a: &[u8], a_offset: usize, b: &[u8], b_offset: usize, len: usize) -> u8 { - for i in 0..len { - if a[a_offset + i] != b[b_offset + i] { - return 0; +impl, const D: usize> CircuitBuilder { + /// Generates a commitment for a subarray using RLC + fn commit_subarray( + &mut self, + arr: &[ByteVariable], + offset: Variable, + len: Variable, + random_value: Variable, + ) -> Variable { + let end_idx = self.add(offset, len); + let mut is_within_subarray: Variable = self.zero(); + let mut commitment = self.zero(); + + let _one: Variable = self.one(); + let mut current_multiplier = _one; + for idx in 0..arr.len() { + let idx_target = self.constant(L::Field::from_canonical_usize(idx)); + // is_within_subarray is one if idx is in the range [offset..offset+len] + let is_at_start_idx = self.is_equal(idx_target, offset); + is_within_subarray = self.add(is_within_subarray, is_at_start_idx.0); + let is_at_end_idx = self.is_equal(idx_target, end_idx); + is_within_subarray = self.sub(is_within_subarray, is_at_end_idx.0); + + let to_be_multiplied = self.select(BoolVariable(is_within_subarray), random_value, _one); + current_multiplier = self.mul(current_multiplier, to_be_multiplied); + + let le_value = arr[idx].to_variable(self); + let multiplied_value = self.mul(le_value, current_multiplier); + let random_value_if_in_range = self.mul(is_within_subarray, multiplied_value); + commitment = self.add(commitment, random_value_if_in_range); } + + commitment } - 1 -} -impl, const D: usize> CircuitBuilder { - #[allow(unused_variables, dead_code)] + /// Checks subarrays for equality using a random linear combination pub fn subarray_equal( &mut self, a: &[ByteVariable], @@ -26,7 +48,14 @@ impl, const D: usize> CircuitBuilder { b_offset: Variable, len: Variable, ) -> BoolVariable { - todo!(); + let mut challenger = RecursiveChallenger::::new(&mut self.api); + let challenger_seed = Vec::new(); + challenger.observe_elements(&challenger_seed); + let challenge = Variable(challenger.get_challenge(&mut self.api)); + + let commitment_for_a = self.commit_subarray(a, a_offset, len, challenge); + let commitment_for_b = self.commit_subarray(b, b_offset, len, challenge); + self.is_equal(commitment_for_a, commitment_for_b) } #[allow(unused_variables, dead_code)] @@ -38,32 +67,89 @@ impl, const D: usize> CircuitBuilder { b_offset: Variable, len: Variable, ) { - // TODO: instead of using the SubarrayEqualGenerator below that doesn't actually check anything, implement an RLC check here - let generator: SubarrayEqualGenerator = SubarrayEqualGenerator { - a: a.to_vec(), - a_offset, - b: b.to_vec(), - b_offset, - len, - _phantom: PhantomData::, - }; - self.add_simple_generator(generator); - - // The following methods might be helpful - let mut challenger = RecursiveChallenger::::new(&mut self.api); - let challenger_seed = Vec::new(); // TODO: have to "seed" the challenger with some random inputs from the circuit - challenger.observe_elements(&challenger_seed); + let subarrays_are_equal = self.subarray_equal(a, a_offset, b, b_offset, len); + let _true = self._true(); + self.assert_is_equal(subarrays_are_equal, _true); + } +} + +#[cfg(test)] +pub(crate) mod tests { + use anyhow::Result; + use plonky2::field::types::Field; + use plonky2::iop::witness::PartialWitness; + use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; - let random_variables = challenger.get_n_challenges(&mut self.api, 1); - let random_variable = random_variables[0]; + use crate::frontend::builder::DefaultBuilder; + use crate::prelude::{ByteVariable, CircuitVariable, Variable}; - // To convert from a Target to a Variable, just use Variable(my_target) to get a Variable + impl Default for ByteVariable { + fn default() -> ByteVariable { + unsafe { std::mem::zeroed() } + } + } + + #[test] + pub fn test_subarray_equal_should_succeed() -> Result<()> { + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type F = >::F; + let mut builder = DefaultBuilder::new(); + + const MAX_LEN: usize = 15; + let mut a: [ByteVariable; MAX_LEN] = Default::default(); + let mut b: [ByteVariable; MAX_LEN] = Default::default(); + + for i in 0..MAX_LEN { + a[i] = ByteVariable::constant(&mut builder, (i + 5) as u8); + } + + for i in 0..MAX_LEN { + b[i] = ByteVariable::constant(&mut builder, i as u8); + } - // TODO: now compute a commitment to a[a_offset:a_offset+len] - // TODO: now compute a commitment to b[b_offset:b_offset+len] + let a_offset = builder.constant(F::ZERO); + let b_offset = builder.constant(F::from_canonical_usize(5)); + let len: Variable = builder.constant(F::from_canonical_usize(5)); + builder.assert_subarray_equal(&a, a_offset, &b, b_offset, len); + + let pw = PartialWitness::new(); + let circuit = builder.build(); + let proof = circuit.data.prove(pw).unwrap(); + circuit.data.verify(proof) } -} -pub(crate) mod tests { - // TODO add a test for subarray_equal + #[test] + #[should_panic] + pub fn test_subarray_equal_should_fail() { + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type F = >::F; + let mut builder = DefaultBuilder::new(); + + const MAX_LEN: usize = 15; + let mut a: [ByteVariable; MAX_LEN] = Default::default(); + let mut b: [ByteVariable; MAX_LEN] = Default::default(); + + for i in 0..MAX_LEN { + a[i] = ByteVariable::constant(&mut builder, (i + 5) as u8); + } + + for i in 0..MAX_LEN { + b[i] = ByteVariable::constant(&mut builder, i as u8); + } + + // Modify 1 byte here + b[6] = ByteVariable::constant(&mut builder, 0); + + let a_offset = builder.constant(F::ZERO); + let b_offset = builder.constant(F::from_canonical_usize(5)); + let len: Variable = builder.constant(F::from_canonical_usize(5)); + builder.assert_subarray_equal(&a, a_offset, &b, b_offset, len); + + let pw = PartialWitness::new(); + let circuit = builder.build(); + let proof = circuit.data.prove(pw).unwrap(); + circuit.data.verify(proof).unwrap(); // panics + } } From 68cba40f51d68833cd8e3fde074c5b703172fcd0 Mon Sep 17 00:00:00 2001 From: Nikolay Kostadinov Date: Mon, 25 Sep 2023 15:21:28 +0300 Subject: [PATCH 3/8] refactor: Address the comments after opening the PR --- plonky2x/src/frontend/builder/mod.rs | 6 ++-- plonky2x/src/frontend/eth/mpt/rlc.rs | 46 ++++++++++++++++++---------- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/plonky2x/src/frontend/builder/mod.rs b/plonky2x/src/frontend/builder/mod.rs index 41e869a77..3a6d02c3d 100644 --- a/plonky2x/src/frontend/builder/mod.rs +++ b/plonky2x/src/frontend/builder/mod.rs @@ -343,13 +343,13 @@ impl, const D: usize> CircuitBuilder { variable.to_be_bits(self) } - /// Takes a slice of bits and returns the number with little-endian bit representation as a Variable + /// Takes a slice of bits and returns the number with little-endian bit representation as a Variable. pub fn le_sum(&mut self, bits: &[BoolVariable]) -> Variable { - let bits_in_booltarget = bits + let bits = bits .iter() .map(|x| BoolTarget::new_unsafe(x.0.0)) .collect_vec(); - Variable(self.api.le_sum(bits_in_booltarget.into_iter())) + Variable(self.api.le_sum(bits.into_iter())) } } diff --git a/plonky2x/src/frontend/eth/mpt/rlc.rs b/plonky2x/src/frontend/eth/mpt/rlc.rs index 0b339f676..46dcbecfa 100644 --- a/plonky2x/src/frontend/eth/mpt/rlc.rs +++ b/plonky2x/src/frontend/eth/mpt/rlc.rs @@ -5,7 +5,7 @@ use plonky2::iop::challenger::RecursiveChallenger; use crate::prelude::{BoolVariable, ByteVariable, CircuitBuilder, PlonkParameters, Variable}; impl, const D: usize> CircuitBuilder { - /// Generates a commitment for a subarray using RLC + /// Generates a commitment for a subarray using RLC. fn commit_subarray( &mut self, arr: &[ByteVariable], @@ -17,17 +17,17 @@ impl, const D: usize> CircuitBuilder { let mut is_within_subarray: Variable = self.zero(); let mut commitment = self.zero(); - let _one: Variable = self.one(); - let mut current_multiplier = _one; + let one: Variable = self.one(); + let mut current_multiplier = one; for idx in 0..arr.len() { let idx_target = self.constant(L::Field::from_canonical_usize(idx)); - // is_within_subarray is one if idx is in the range [offset..offset+len] + // is_within_subarray is one if idx is in the range [offset..offset+len]. let is_at_start_idx = self.is_equal(idx_target, offset); is_within_subarray = self.add(is_within_subarray, is_at_start_idx.0); let is_at_end_idx = self.is_equal(idx_target, end_idx); is_within_subarray = self.sub(is_within_subarray, is_at_end_idx.0); - let to_be_multiplied = self.select(BoolVariable(is_within_subarray), random_value, _one); + let to_be_multiplied = self.select(BoolVariable(is_within_subarray), random_value, one); current_multiplier = self.mul(current_multiplier, to_be_multiplied); let le_value = arr[idx].to_variable(self); @@ -39,7 +39,7 @@ impl, const D: usize> CircuitBuilder { commitment } - /// Checks subarrays for equality using a random linear combination + /// Checks subarrays for equality using a random linear combination. pub fn subarray_equal( &mut self, a: &[ByteVariable], @@ -75,9 +75,7 @@ impl, const D: usize> CircuitBuilder { #[cfg(test)] pub(crate) mod tests { - use anyhow::Result; use plonky2::field::types::Field; - use plonky2::iop::witness::PartialWitness; use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; use crate::frontend::builder::DefaultBuilder; @@ -90,7 +88,7 @@ pub(crate) mod tests { } #[test] - pub fn test_subarray_equal_should_succeed() -> Result<()> { + pub fn test_subarray_equal_should_succeed() { const D: usize = 2; type C = PoseidonGoldilocksConfig; type F = >::F; @@ -108,15 +106,22 @@ pub(crate) mod tests { b[i] = ByteVariable::constant(&mut builder, i as u8); } - let a_offset = builder.constant(F::ZERO); + let a_offset: Variable = builder.constant(F::ZERO); let b_offset = builder.constant(F::from_canonical_usize(5)); let len: Variable = builder.constant(F::from_canonical_usize(5)); builder.assert_subarray_equal(&a, a_offset, &b, b_offset, len); - let pw = PartialWitness::new(); + // Build your circuit. let circuit = builder.build(); - let proof = circuit.data.prove(pw).unwrap(); - circuit.data.verify(proof) + + // Write to the circuit input. + let input = circuit.input(); + + // Generate a proof. + let (proof, output) = circuit.prove(&input); + + // Verify proof. + circuit.verify(&proof, &input, &output) } #[test] @@ -139,7 +144,7 @@ pub(crate) mod tests { b[i] = ByteVariable::constant(&mut builder, i as u8); } - // Modify 1 byte here + // Modify 1 byte here. b[6] = ByteVariable::constant(&mut builder, 0); let a_offset = builder.constant(F::ZERO); @@ -147,9 +152,16 @@ pub(crate) mod tests { let len: Variable = builder.constant(F::from_canonical_usize(5)); builder.assert_subarray_equal(&a, a_offset, &b, b_offset, len); - let pw = PartialWitness::new(); + // Build your circuit. let circuit = builder.build(); - let proof = circuit.data.prove(pw).unwrap(); - circuit.data.verify(proof).unwrap(); // panics + + // Write to the circuit input. + let input = circuit.input(); + + // Generate a proof. + let (proof, output) = circuit.prove(&input); + + // Verify proof. + circuit.verify(&proof, &input, &output) } } From e543dd1572965e76ef7eafdb6ba9b1b22c1eea3e Mon Sep 17 00:00:00 2001 From: Xearty Date: Mon, 2 Oct 2023 19:05:54 +0300 Subject: [PATCH 4/8] refactor: Fix formatting and add comments --- plonky2x/src/frontend/builder/mod.rs | 6 +++--- plonky2x/src/frontend/eth/mpt/rlc.rs | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/plonky2x/src/frontend/builder/mod.rs b/plonky2x/src/frontend/builder/mod.rs index 3a6d02c3d..7e63cf4b3 100644 --- a/plonky2x/src/frontend/builder/mod.rs +++ b/plonky2x/src/frontend/builder/mod.rs @@ -346,9 +346,9 @@ impl, const D: usize> CircuitBuilder { /// Takes a slice of bits and returns the number with little-endian bit representation as a Variable. pub fn le_sum(&mut self, bits: &[BoolVariable]) -> Variable { let bits = bits - .iter() - .map(|x| BoolTarget::new_unsafe(x.0.0)) - .collect_vec(); + .iter() + .map(|x| BoolTarget::new_unsafe(x.0.0)) + .collect_vec(); Variable(self.api.le_sum(bits.into_iter())) } } diff --git a/plonky2x/src/frontend/eth/mpt/rlc.rs b/plonky2x/src/frontend/eth/mpt/rlc.rs index 46dcbecfa..b87370e58 100644 --- a/plonky2x/src/frontend/eth/mpt/rlc.rs +++ b/plonky2x/src/frontend/eth/mpt/rlc.rs @@ -14,8 +14,8 @@ impl, const D: usize> CircuitBuilder { random_value: Variable, ) -> Variable { let end_idx = self.add(offset, len); - let mut is_within_subarray: Variable = self.zero(); - let mut commitment = self.zero(); + let mut commitment: Variable = self.zero(); + let mut is_within_subarray = self.zero(); let one: Variable = self.one(); let mut current_multiplier = one; @@ -26,7 +26,7 @@ impl, const D: usize> CircuitBuilder { is_within_subarray = self.add(is_within_subarray, is_at_start_idx.0); let is_at_end_idx = self.is_equal(idx_target, end_idx); is_within_subarray = self.sub(is_within_subarray, is_at_end_idx.0); - + let to_be_multiplied = self.select(BoolVariable(is_within_subarray), random_value, one); current_multiplier = self.mul(current_multiplier, to_be_multiplied); @@ -58,7 +58,7 @@ impl, const D: usize> CircuitBuilder { self.is_equal(commitment_for_a, commitment_for_b) } - #[allow(unused_variables, dead_code)] + /// Asserts that subarrays are equal using a random linear combination. pub fn assert_subarray_equal( &mut self, a: &[ByteVariable], From 687abc7b287d78613bb99aaa92a5961091fb8b90 Mon Sep 17 00:00:00 2001 From: Xearty Date: Mon, 2 Oct 2023 19:18:17 +0300 Subject: [PATCH 5/8] feat: Implement assert_is_true method on the CircuitBuilder --- plonky2x/src/frontend/builder/mod.rs | 8 ++++++++ plonky2x/src/frontend/eth/mpt/rlc.rs | 3 +-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/plonky2x/src/frontend/builder/mod.rs b/plonky2x/src/frontend/builder/mod.rs index 7e63cf4b3..a17c3ebef 100644 --- a/plonky2x/src/frontend/builder/mod.rs +++ b/plonky2x/src/frontend/builder/mod.rs @@ -316,6 +316,14 @@ impl, const D: usize> CircuitBuilder { } } + /// Fails if i1 != true. + pub fn assert_is_true(&mut self, i1: V) { + let one = self.api.one(); + for t1 in i1.targets().iter() { + self.api.connect(*t1, one); + } + } + /// Returns 1 if i1 == i2 and 0 otherwise as a BoolVariable. pub fn is_equal(&mut self, i1: V, i2: V) -> BoolVariable { let mut result = self._true(); diff --git a/plonky2x/src/frontend/eth/mpt/rlc.rs b/plonky2x/src/frontend/eth/mpt/rlc.rs index b87370e58..c03229c9f 100644 --- a/plonky2x/src/frontend/eth/mpt/rlc.rs +++ b/plonky2x/src/frontend/eth/mpt/rlc.rs @@ -68,8 +68,7 @@ impl, const D: usize> CircuitBuilder { len: Variable, ) { let subarrays_are_equal = self.subarray_equal(a, a_offset, b, b_offset, len); - let _true = self._true(); - self.assert_is_equal(subarrays_are_equal, _true); + self.assert_is_true(subarrays_are_equal); } } From 7e373752778858dd9956572b6d954524b99de9bd Mon Sep 17 00:00:00 2001 From: Xearty Date: Mon, 2 Oct 2023 19:20:29 +0300 Subject: [PATCH 6/8] feat: Make challenger seed depend on the input arrays --- plonky2x/src/frontend/eth/mpt/rlc.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/plonky2x/src/frontend/eth/mpt/rlc.rs b/plonky2x/src/frontend/eth/mpt/rlc.rs index c03229c9f..7d4804e09 100644 --- a/plonky2x/src/frontend/eth/mpt/rlc.rs +++ b/plonky2x/src/frontend/eth/mpt/rlc.rs @@ -1,3 +1,4 @@ +use itertools::Itertools; use plonky2::field::types::Field; use plonky2::hash::poseidon::PoseidonHash; use plonky2::iop::challenger::RecursiveChallenger; @@ -49,7 +50,11 @@ impl, const D: usize> CircuitBuilder { len: Variable, ) -> BoolVariable { let mut challenger = RecursiveChallenger::::new(&mut self.api); - let challenger_seed = Vec::new(); + let challenger_seed = [a, b] + .concat() + .iter() + .map(|byte| byte.to_variable(self).0) + .collect_vec(); challenger.observe_elements(&challenger_seed); let challenge = Variable(challenger.get_challenge(&mut self.api)); From 95ed36262c05a52df8240d82cdcbdc0108c97968 Mon Sep 17 00:00:00 2001 From: Xearty Date: Mon, 2 Oct 2023 19:21:45 +0300 Subject: [PATCH 7/8] test: Add and mod RLC tests --- plonky2x/src/frontend/eth/mpt/rlc.rs | 90 +++++++++++++++++++++++++--- 1 file changed, 83 insertions(+), 7 deletions(-) diff --git a/plonky2x/src/frontend/eth/mpt/rlc.rs b/plonky2x/src/frontend/eth/mpt/rlc.rs index 7d4804e09..8589bc8d2 100644 --- a/plonky2x/src/frontend/eth/mpt/rlc.rs +++ b/plonky2x/src/frontend/eth/mpt/rlc.rs @@ -83,7 +83,7 @@ pub(crate) mod tests { use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; use crate::frontend::builder::DefaultBuilder; - use crate::prelude::{ByteVariable, CircuitVariable, Variable}; + use crate::prelude::{ByteVariable, Variable}; impl Default for ByteVariable { fn default() -> ByteVariable { @@ -103,11 +103,87 @@ pub(crate) mod tests { let mut b: [ByteVariable; MAX_LEN] = Default::default(); for i in 0..MAX_LEN { - a[i] = ByteVariable::constant(&mut builder, (i + 5) as u8); + a[i] = builder.constant::((i + 5) as u8); } for i in 0..MAX_LEN { - b[i] = ByteVariable::constant(&mut builder, i as u8); + b[i] = builder.constant::(i as u8); + } + + let a_offset: Variable = builder.constant(F::ZERO); + let b_offset = builder.constant(F::from_canonical_usize(5)); + let len: Variable = builder.constant(F::from_canonical_usize(5)); + builder.assert_subarray_equal(&a, a_offset, &b, b_offset, len); + + // Build your circuit. + let circuit = builder.build(); + + // Write to the circuit input. + let input = circuit.input(); + + // Generate a proof. + let (proof, output) = circuit.prove(&input); + + // Verify proof. + circuit.verify(&proof, &input, &output) + } + + #[test] + pub fn test_subarray_equal_diff_len_should_succeed() { + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type F = >::F; + let mut builder = DefaultBuilder::new(); + + const LEN_A: usize = 15; + const LEN_B: usize = 10; + let mut a: [ByteVariable; LEN_A] = Default::default(); + let mut b: [ByteVariable; LEN_B] = Default::default(); + + for i in 0..LEN_A { + a[i] = builder.constant::((i + 5) as u8); + } + + for i in 0..LEN_B { + b[i] = builder.constant::(i as u8); + } + + let a_offset: Variable = builder.constant(F::ZERO); + let b_offset = builder.constant(F::from_canonical_usize(5)); + let len: Variable = builder.constant(F::from_canonical_usize(5)); + builder.assert_subarray_equal(&a, a_offset, &b, b_offset, len); + + // Build your circuit. + let circuit = builder.build(); + + // Write to the circuit input. + let input = circuit.input(); + + // Generate a proof. + let (proof, output) = circuit.prove(&input); + + // Verify proof. + circuit.verify(&proof, &input, &output) + } + + #[test] + pub fn test_subarray_equal_diff_len_inverse_should_succeed() { + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type F = >::F; + let mut builder = DefaultBuilder::new(); + + const LEN_A: usize = 10; + const LEN_B: usize = 15; + let mut a: [ByteVariable; LEN_A] = Default::default(); + let mut b: [ByteVariable; LEN_B] = Default::default(); + + for i in 0..LEN_A { + a[i] = builder.constant::((i + 5) as u8); + } + + for i in 0..LEN_B { + b[i] = builder.constant::(i as u8); } let a_offset: Variable = builder.constant(F::ZERO); @@ -141,15 +217,15 @@ pub(crate) mod tests { let mut b: [ByteVariable; MAX_LEN] = Default::default(); for i in 0..MAX_LEN { - a[i] = ByteVariable::constant(&mut builder, (i + 5) as u8); + a[i] = builder.constant::((i + 5) as u8); } for i in 0..MAX_LEN { - b[i] = ByteVariable::constant(&mut builder, i as u8); + b[i] = builder.constant::(i as u8); } - + // Modify 1 byte here. - b[6] = ByteVariable::constant(&mut builder, 0); + b[6] = builder.constant::(0); let a_offset = builder.constant(F::ZERO); let b_offset = builder.constant(F::from_canonical_usize(5)); From 7dc11d802e4e580724f2a782b3412e9fdb0fd805 Mon Sep 17 00:00:00 2001 From: Xearty Date: Mon, 2 Oct 2023 21:14:01 +0300 Subject: [PATCH 8/8] refactor: Formatting --- plonky2x/src/frontend/eth/mpt/rlc.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plonky2x/src/frontend/eth/mpt/rlc.rs b/plonky2x/src/frontend/eth/mpt/rlc.rs index 8589bc8d2..e53cf1b8f 100644 --- a/plonky2x/src/frontend/eth/mpt/rlc.rs +++ b/plonky2x/src/frontend/eth/mpt/rlc.rs @@ -55,7 +55,9 @@ impl, const D: usize> CircuitBuilder { .iter() .map(|byte| byte.to_variable(self).0) .collect_vec(); + challenger.observe_elements(&challenger_seed); + let challenge = Variable(challenger.get_challenge(&mut self.api)); let commitment_for_a = self.commit_subarray(a, a_offset, len, challenge);