range_check.rs 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. use std::marker::PhantomData;
  2. use group::ff::PrimeFieldBits;
  3. use halo2_proofs::{
  4. arithmetic::FieldExt,
  5. circuit::{Chip, Layouter, Value},
  6. plonk::{Advice, Column, ConstraintSystem, Error, Selector, TableColumn},
  7. poly::Rotation,
  8. };
  9. #[derive(Clone, Debug)]
  10. pub struct RangeCheckConfig {
  11. pub z: Column<Advice>,
  12. pub s_rc: Selector,
  13. pub k_values_table: TableColumn,
  14. }
  15. pub struct RangeCheckChip<F: FieldExt + PrimeFieldBits, const WINDOW_SIZE: usize> {
  16. config: RangeCheckConfig,
  17. _marker: PhantomData<F>,
  18. }
  19. impl<F: FieldExt + PrimeFieldBits, const WINDOW_SIZE: usize> Chip<F>
  20. for RangeCheckChip<F, WINDOW_SIZE>
  21. {
  22. type Config = RangeCheckConfig;
  23. type Loaded = ();
  24. fn config(&self) -> &Self::Config {
  25. &self.config
  26. }
  27. fn loaded(&self) -> &Self::Loaded {
  28. &()
  29. }
  30. }
  31. impl<F: FieldExt + PrimeFieldBits, const WINDOW_SIZE: usize> RangeCheckChip<F, WINDOW_SIZE> {
  32. pub fn configure(
  33. meta: &mut ConstraintSystem<F>,
  34. k_values_table: TableColumn,
  35. ) -> <Self as Chip<F>>::Config {
  36. let z = meta.advice_column();
  37. let s_rc = meta.complex_selector();
  38. let config = RangeCheckConfig { z, s_rc, k_values_table };
  39. meta.lookup(|meta| {
  40. let s_rc = meta.query_selector(config.s_rc);
  41. let z_curr = meta.query_advice(config.z, Rotation::cur());
  42. let z_next = meta.query_advice(config.z, Rotation::next());
  43. // z_next = (z_curr - k_i) / 2^K
  44. // => k_i = z_curr - (z_next * 2^K)
  45. vec![(s_rc * (z_curr - z_next * F::from(1 << WINDOW_SIZE)), config.k_values_table)]
  46. });
  47. config
  48. }
  49. /// `k_values_table` should be reused across different chips
  50. /// which is why we don't limit it to a specific instance.
  51. pub fn load_k_table(
  52. layouter: &mut impl Layouter<F>,
  53. k_values_table: TableColumn,
  54. ) -> Result<(), Error> {
  55. layouter.assign_table(
  56. || format!("{} window table", WINDOW_SIZE),
  57. |mut table| {
  58. for index in 0..(1 << WINDOW_SIZE) {
  59. table.assign_cell(
  60. || "table",
  61. k_values_table,
  62. index,
  63. || Value::known(F::from(index as u64)),
  64. )?;
  65. }
  66. Ok(())
  67. },
  68. )
  69. }
  70. }