From 539513e5123a75966d06c12000b646cee6674768 Mon Sep 17 00:00:00 2001 From: Simon Masson Date: Thu, 8 Dec 2022 19:24:43 +0000 Subject: [PATCH 1/4] wip but still not working when I run it --- taiga_halo2/src/circuit/mod.rs | 1 + .../src/circuit/verification/compute_b.rs | 185 ++++++++++++++++++ 2 files changed, 186 insertions(+) create mode 100644 taiga_halo2/src/circuit/verification/compute_b.rs diff --git a/taiga_halo2/src/circuit/mod.rs b/taiga_halo2/src/circuit/mod.rs index d64422b6..7bb523b4 100644 --- a/taiga_halo2/src/circuit/mod.rs +++ b/taiga_halo2/src/circuit/mod.rs @@ -7,4 +7,5 @@ pub mod note_circuit; pub mod vp_circuit; pub mod curve; pub mod hash_to_curve; +pub mod verification; pub mod vp_examples; diff --git a/taiga_halo2/src/circuit/verification/compute_b.rs b/taiga_halo2/src/circuit/verification/compute_b.rs new file mode 100644 index 00000000..9d242096 --- /dev/null +++ b/taiga_halo2/src/circuit/verification/compute_b.rs @@ -0,0 +1,185 @@ +use halo2_proofs::{ + circuit::{AssignedCell, Region}, + plonk::{Advice, Column, ConstraintSystem, Constraints, Error, Expression, Selector}, + poly::Rotation, +}; +use pasta_curves::{pallas, Fp}; + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct ComputeBConfig { + q_compute_b: Selector, + x: Column, + u: [Column; 4], +} + +impl ComputeBConfig { + #[allow(clippy::too_many_arguments)] + pub fn configure( + meta: &mut ConstraintSystem, + x: Column, + u: [Column; 4], + ) -> Self { + meta.enable_equality(x); + for uu in u { + meta.enable_equality(uu); + } + + let config = Self { + q_compute_b: meta.selector(), + x, + u, + }; + + config.create_gate(meta); + + config + } + + fn create_gate(&self, meta: &mut ConstraintSystem) { + meta.create_gate("compute b", |meta| { + let q_compute_b = meta.query_selector(self.q_compute_b); + let x = meta.query_advice(self.x, Rotation::cur()); + let u: Vec> = self + .u + .iter() + .map(|uu| meta.query_advice(*uu, Rotation::cur())) + .collect(); + + let one = Expression::Constant(pallas::Base::one()); + let mut tmp = one.clone(); + let mut cur = x.clone(); + for u_j in u.iter().rev() { + tmp = tmp * one.clone() + u_j.clone() * cur.clone(); + cur = cur.clone() * cur.clone(); + } + meta.query_advice(self.x, Rotation::next()); + Constraints::with_selector( + q_compute_b, + [("", Expression::Constant(pallas::Base::zero()))], + ) + }); + } + + pub fn assign_region( + &self, + x: &AssignedCell, + u: &Vec>, + offset: usize, + region: &mut Region<'_, pallas::Base>, + ) -> Result, Error> { + // Enable `q_compute_b` selector + self.q_compute_b.enable(region, offset)?; + + // copy x and u_i into advice columns + let x_cell = x.copy_advice(|| "x", region, self.x, offset)?; + for (u_col, u_cell) in self.u.iter().zip(u) { + u_cell.copy_advice(|| "u_i", region, *u_col, offset)?; + } + Ok(x_cell) + } +} + +#[test] +fn test_compute_b_circuit() { + use crate::circuit::gadgets::assign_free_advice; + use ff::Field; + use halo2_proofs::{ + circuit::{Layouter, SimpleFloorPlanner, Value}, + dev::MockProver, + plonk::{Circuit, Instance}, + }; + use pallas::Base as Fp; + use rand::rngs::OsRng; + + #[derive(Default)] + struct MyCircuit { + x: Fp, + u: Vec, + } + + impl Circuit for MyCircuit { + type Config = ([Column; 10], Column, ComputeBConfig); + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + let advices = [ + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + ]; + let instance = meta.instance_column(); + + let lagrange_coeffs = [ + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + ]; + meta.enable_constant(lagrange_coeffs[0]); + + let compute_b_config = + ComputeBConfig::configure(meta, advices[0], advices[1..5].try_into().unwrap()); + + (advices, instance, compute_b_config) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + let (advices, instance, compute_b_config) = config; + + let x = + assign_free_advice(layouter.namespace(|| "x"), advices[0], Value::known(self.x))?; + let u: Vec> = self + .u + .iter() + .map(|uu| { + assign_free_advice(layouter.namespace(|| "u_i"), advices[1], Value::known(*uu)) + .unwrap() + }) + .collect(); + + let y = layouter.assign_region( + || "y in cirucit", + |mut region| compute_b_config.assign_region(&x, &u, 0, &mut region), + )?; + layouter.constrain_instance(y.cell(), instance, 0)?; + Ok(()) + } + } + + // we create random values for x, and u_i and check that the computation is okay. + let mut rng = OsRng; + let x = Fp::random(&mut rng); + let u: Vec = (0..12).map(|_| Fp::random(&mut rng)).collect(); + // compute y = $\prod\limits_{i=0}^{k-1} (1 + u_{k - 1 - i} x^{2^i})$ out-of-circuit + let mut tmp = Fp::one(); + let mut cur = x; + for u_j in u.iter().rev() { + tmp *= Fp::one() + &(*u_j * &cur); + cur *= cur; + } + let y = tmp; + + let circuit = MyCircuit { x, u }; + + let prover = MockProver::run(11, &circuit, vec![vec![y]]).unwrap(); + assert_eq!(prover.verify(), Ok(())) +} From 6273e13af6b8ccbc0584655786ff974136b943c3 Mon Sep 17 00:00:00 2001 From: Simon Masson Date: Fri, 9 Dec 2022 14:19:54 +0000 Subject: [PATCH 2/4] verification file --- taiga_halo2/src/circuit/verification.rs | 1 + 1 file changed, 1 insertion(+) create mode 100644 taiga_halo2/src/circuit/verification.rs diff --git a/taiga_halo2/src/circuit/verification.rs b/taiga_halo2/src/circuit/verification.rs new file mode 100644 index 00000000..b563298b --- /dev/null +++ b/taiga_halo2/src/circuit/verification.rs @@ -0,0 +1 @@ +pub mod compute_b; From 6264836728d6f7c62166b9a0d13597eb78fddc7d Mon Sep 17 00:00:00 2001 From: Simon Masson Date: Fri, 9 Dec 2022 16:19:36 +0000 Subject: [PATCH 3/4] wip but still not working --- .../src/circuit/verification/compute_b.rs | 104 ++++++++++-------- 1 file changed, 61 insertions(+), 43 deletions(-) diff --git a/taiga_halo2/src/circuit/verification/compute_b.rs b/taiga_halo2/src/circuit/verification/compute_b.rs index 9d242096..a5e539ea 100644 --- a/taiga_halo2/src/circuit/verification/compute_b.rs +++ b/taiga_halo2/src/circuit/verification/compute_b.rs @@ -10,6 +10,7 @@ pub struct ComputeBConfig { q_compute_b: Selector, x: Column, u: [Column; 4], + y: Column, } impl ComputeBConfig { @@ -18,16 +19,19 @@ impl ComputeBConfig { meta: &mut ConstraintSystem, x: Column, u: [Column; 4], + y: Column, ) -> Self { meta.enable_equality(x); for uu in u { meta.enable_equality(uu); } + meta.enable_equality(y); let config = Self { q_compute_b: meta.selector(), x, u, + y, }; config.create_gate(meta); @@ -44,6 +48,7 @@ impl ComputeBConfig { .iter() .map(|uu| meta.query_advice(*uu, Rotation::cur())) .collect(); + let y = meta.query_advice(self.y, Rotation::cur()); let one = Expression::Constant(pallas::Base::one()); let mut tmp = one.clone(); @@ -52,11 +57,8 @@ impl ComputeBConfig { tmp = tmp * one.clone() + u_j.clone() * cur.clone(); cur = cur.clone() * cur.clone(); } - meta.query_advice(self.x, Rotation::next()); - Constraints::with_selector( - q_compute_b, - [("", Expression::Constant(pallas::Base::zero()))], - ) + println!("tmp={:?}", tmp); + Constraints::with_selector(q_compute_b, [("y computation", tmp - y)]) }); } @@ -64,6 +66,7 @@ impl ComputeBConfig { &self, x: &AssignedCell, u: &Vec>, + y: &AssignedCell, offset: usize, region: &mut Region<'_, pallas::Base>, ) -> Result, Error> { @@ -71,11 +74,11 @@ impl ComputeBConfig { self.q_compute_b.enable(region, offset)?; // copy x and u_i into advice columns - let x_cell = x.copy_advice(|| "x", region, self.x, offset)?; + x.copy_advice(|| "x", region, self.x, offset)?; for (u_col, u_cell) in self.u.iter().zip(u) { u_cell.copy_advice(|| "u_i", region, *u_col, offset)?; } - Ok(x_cell) + Ok(y.copy_advice(|| "y", region, self.y, offset)?) } } @@ -94,11 +97,12 @@ fn test_compute_b_circuit() { #[derive(Default)] struct MyCircuit { x: Fp, - u: Vec, + u: [Fp; 4], + y: Fp, } impl Circuit for MyCircuit { - type Config = ([Column; 10], Column, ComputeBConfig); + type Config = ([Column; 10], ComputeBConfig); type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { @@ -118,24 +122,14 @@ fn test_compute_b_circuit() { meta.advice_column(), meta.advice_column(), ]; - let instance = meta.instance_column(); - - let lagrange_coeffs = [ - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - ]; - meta.enable_constant(lagrange_coeffs[0]); - - let compute_b_config = - ComputeBConfig::configure(meta, advices[0], advices[1..5].try_into().unwrap()); - (advices, instance, compute_b_config) + let compute_b_config = ComputeBConfig::configure( + meta, + advices[0], + advices[1..5].try_into().unwrap(), + advices[5], + ); + (advices, compute_b_config) } fn synthesize( @@ -143,33 +137,52 @@ fn test_compute_b_circuit() { config: Self::Config, mut layouter: impl Layouter, ) -> Result<(), Error> { - let (advices, instance, compute_b_config) = config; + let (advices, compute_b_config) = config; + println!("A"); let x = assign_free_advice(layouter.namespace(|| "x"), advices[0], Value::known(self.x))?; - let u: Vec> = self - .u - .iter() - .map(|uu| { - assign_free_advice(layouter.namespace(|| "u_i"), advices[1], Value::known(*uu)) - .unwrap() - }) - .collect(); + let mut i = 1; // advice columns are columns 1 to 5 + let mut u_vec: Vec> = vec![]; + for uu in self.u.iter() { + // assign a region for uu + let u_cell = assign_free_advice( + layouter.namespace(|| "u_i"), + advices[i], + Value::known(*uu), + )?; + u_vec.push(u_cell); + i = i + 1; + } + assert!(i < 6); + let y = + assign_free_advice(layouter.namespace(|| "y"), advices[i], Value::known(self.y))?; - let y = layouter.assign_region( + let y_in = layouter.assign_region( || "y in cirucit", - |mut region| compute_b_config.assign_region(&x, &u, 0, &mut region), + |mut region| compute_b_config.assign_region(&x, &u_vec, &y, 0, &mut region), )?; - layouter.constrain_instance(y.cell(), instance, 0)?; + + let y = + assign_free_advice(layouter.namespace(|| "y"), advices[6], Value::known(self.y))?; + // layouter.assign_region( + // || "equality constrain for y", + // |mut region| { + // region.constrain_equal( + // y_in.cell(), + // y.cell(), + // ) + // }, + // )?; Ok(()) } } // we create random values for x, and u_i and check that the computation is okay. let mut rng = OsRng; - let x = Fp::random(&mut rng); - let u: Vec = (0..12).map(|_| Fp::random(&mut rng)).collect(); - // compute y = $\prod\limits_{i=0}^{k-1} (1 + u_{k - 1 - i} x^{2^i})$ out-of-circuit + let x = Fp::one(); //random(&mut rng); + let u = [Fp::one(); 4]; //random(&mut rng);4]; + // compute y = $\prod\limits_{i=0}^{k-1} (1 + u_{k - 1 - i} x^{2^i})$ out-of-circuit let mut tmp = Fp::one(); let mut cur = x; for u_j in u.iter().rev() { @@ -178,8 +191,13 @@ fn test_compute_b_circuit() { } let y = tmp; - let circuit = MyCircuit { x, u }; + let circuit = MyCircuit { x, u, y }; - let prover = MockProver::run(11, &circuit, vec![vec![y]]).unwrap(); + let prover = MockProver::run(11, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())) + + /* + Seems that the circuit does not work.... I don't know how to check y == y_in + and even with x = u_i = 1, the polynomial condition is not satisfied and I don't know how to debug it... + */ } From 95fff133232606c3aab64073667e32d8bc55ffa1 Mon Sep 17 00:00:00 2001 From: Simon Masson Date: Fri, 16 Dec 2022 17:24:26 +0000 Subject: [PATCH 4/4] compute_b works for 16 u_is --- .../src/circuit/verification/compute_b.rs | 87 ++++++++++--------- 1 file changed, 48 insertions(+), 39 deletions(-) diff --git a/taiga_halo2/src/circuit/verification/compute_b.rs b/taiga_halo2/src/circuit/verification/compute_b.rs index a5e539ea..742e2cd1 100644 --- a/taiga_halo2/src/circuit/verification/compute_b.rs +++ b/taiga_halo2/src/circuit/verification/compute_b.rs @@ -43,22 +43,36 @@ impl ComputeBConfig { meta.create_gate("compute b", |meta| { let q_compute_b = meta.query_selector(self.q_compute_b); let x = meta.query_advice(self.x, Rotation::cur()); - let u: Vec> = self - .u - .iter() - .map(|uu| meta.query_advice(*uu, Rotation::cur())) - .collect(); + let mut u_array: Vec>> = vec![]; + /* + We collect the u values stored as follows: + u0 u4 u8 u12 + u1 u5 u9 u13 + u2 u6 u10 u14 + u3 u7 u11 u15 + */ + + for uu in self.u { + let mut u_col = vec![]; + u_col.push(meta.query_advice(uu, Rotation(0))); + u_col.push(meta.query_advice(uu, Rotation(1))); + u_col.push(meta.query_advice(uu, Rotation(2))); + u_col.push(meta.query_advice(uu, Rotation(3))); + u_array.push(u_col); + } let y = meta.query_advice(self.y, Rotation::cur()); let one = Expression::Constant(pallas::Base::one()); let mut tmp = one.clone(); let mut cur = x.clone(); - for u_j in u.iter().rev() { - tmp = tmp * one.clone() + u_j.clone() * cur.clone(); - cur = cur.clone() * cur.clone(); + for u_col in u_array.iter().rev() { + for u_j in u_col.iter().rev() { + tmp = tmp * (one.clone() + u_j.clone() * cur.clone()); + cur = cur.square(); + } } - println!("tmp={:?}", tmp); - Constraints::with_selector(q_compute_b, [("y computation", tmp - y)]) + + Constraints::with_selector(q_compute_b, [("y computation", tmp.clone() - y)]) }); } @@ -75,8 +89,13 @@ impl ComputeBConfig { // copy x and u_i into advice columns x.copy_advice(|| "x", region, self.x, offset)?; - for (u_col, u_cell) in self.u.iter().zip(u) { - u_cell.copy_advice(|| "u_i", region, *u_col, offset)?; + // we use four columns for the u_i, and store four in each (4 * 8 == 32) + for (u_col, u_4cells) in self.u.iter().zip(u.chunks(4)) { + let mut i = offset; + for u_cell in u_4cells { + u_cell.copy_advice(|| "u_i", region, *u_col, i)?; + i = i + 1; + } } Ok(y.copy_advice(|| "y", region, self.y, offset)?) } @@ -89,7 +108,7 @@ fn test_compute_b_circuit() { use halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner, Value}, dev::MockProver, - plonk::{Circuit, Instance}, + plonk::Circuit, }; use pallas::Base as Fp; use rand::rngs::OsRng; @@ -97,7 +116,7 @@ fn test_compute_b_circuit() { #[derive(Default)] struct MyCircuit { x: Fp, - u: [Fp; 4], + u: [Fp; 16], y: Fp, } @@ -122,7 +141,6 @@ fn test_compute_b_circuit() { meta.advice_column(), meta.advice_column(), ]; - let compute_b_config = ComputeBConfig::configure( meta, advices[0], @@ -139,10 +157,10 @@ fn test_compute_b_circuit() { ) -> Result<(), Error> { let (advices, compute_b_config) = config; - println!("A"); let x = assign_free_advice(layouter.namespace(|| "x"), advices[0], Value::known(self.x))?; - let mut i = 1; // advice columns are columns 1 to 5 + let mut i = 1; // advice columns are columns 1 to 4 + let mut cpt = 0; let mut u_vec: Vec> = vec![]; for uu in self.u.iter() { // assign a region for uu @@ -152,9 +170,12 @@ fn test_compute_b_circuit() { Value::known(*uu), )?; u_vec.push(u_cell); - i = i + 1; + cpt = cpt + 1; + if cpt == 4 { + i = i + 1; + cpt = 0; + } } - assert!(i < 6); let y = assign_free_advice(layouter.namespace(|| "y"), advices[i], Value::known(self.y))?; @@ -163,26 +184,19 @@ fn test_compute_b_circuit() { |mut region| compute_b_config.assign_region(&x, &u_vec, &y, 0, &mut region), )?; - let y = - assign_free_advice(layouter.namespace(|| "y"), advices[6], Value::known(self.y))?; - // layouter.assign_region( - // || "equality constrain for y", - // |mut region| { - // region.constrain_equal( - // y_in.cell(), - // y.cell(), - // ) - // }, - // )?; + layouter.assign_region( + || "equality constrain for y", + |mut region| region.constrain_equal(y_in.cell(), y.cell()), + )?; Ok(()) } } // we create random values for x, and u_i and check that the computation is okay. let mut rng = OsRng; - let x = Fp::one(); //random(&mut rng); - let u = [Fp::one(); 4]; //random(&mut rng);4]; - // compute y = $\prod\limits_{i=0}^{k-1} (1 + u_{k - 1 - i} x^{2^i})$ out-of-circuit + let x = Fp::random(&mut rng); + let u = [Fp::random(&mut rng); 16]; + // compute y = $\prod\limits_{i=0}^{k-1} (1 + u_{k - 1 - i} x^{2^i})$ out-of-circuit let mut tmp = Fp::one(); let mut cur = x; for u_j in u.iter().rev() { @@ -193,11 +207,6 @@ fn test_compute_b_circuit() { let circuit = MyCircuit { x, u, y }; - let prover = MockProver::run(11, &circuit, vec![]).unwrap(); + let prover = MockProver::run(6, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())) - - /* - Seems that the circuit does not work.... I don't know how to check y == y_in - and even with x = u_i = 1, the polynomial condition is not satisfied and I don't know how to debug it... - */ }