arith_chip.rs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. use halo2::{
  2. circuit::{Chip, Layouter},
  3. plonk::{Advice, Column, ConstraintSystem, Error, Selector},
  4. poly::Rotation,
  5. };
  6. use halo2_gadgets::utilities::{CellValue, Var};
  7. use pasta_curves::pallas;
  8. type Variable = CellValue<pallas::Base>;
  9. // Replace with use pasta::Fp and pasta::Fq
  10. type Fp = pallas::Base;
  11. //type Fq = pallas::Scalar;
  12. #[derive(Clone, Debug)]
  13. pub struct ArithmeticChipConfig {
  14. a_col: Column<Advice>,
  15. b_col: Column<Advice>,
  16. //permute: Permutation,
  17. s_add: Selector,
  18. s_mul: Selector,
  19. //s_pub: Selector,
  20. }
  21. pub struct ArithmeticChip {
  22. config: ArithmeticChipConfig,
  23. }
  24. impl Chip<Fp> for ArithmeticChip {
  25. type Config = ArithmeticChipConfig;
  26. type Loaded = ();
  27. fn config(&self) -> &Self::Config {
  28. &self.config
  29. }
  30. fn loaded(&self) -> &Self::Loaded {
  31. &()
  32. }
  33. }
  34. impl ArithmeticChip {
  35. pub fn construct(config: ArithmeticChipConfig) -> Self {
  36. Self { config }
  37. }
  38. pub fn configure(cs: &mut ConstraintSystem<Fp>) -> ArithmeticChipConfig {
  39. let a_col = cs.advice_column();
  40. let b_col = cs.advice_column();
  41. cs.enable_equality(a_col.into());
  42. cs.enable_equality(b_col.into());
  43. //let instance = cs.instance_column();
  44. /*let permute = {
  45. // Convert advice columns into an "any" columns.
  46. let cols: [Column<Any>; 2] = [a_col.into(), b_col.into()];
  47. Permutation::new(cs, &cols)
  48. };*/
  49. let s_add = cs.selector();
  50. let s_mul = cs.selector();
  51. //let s_pub = cs.selector();
  52. cs.create_gate("add", |cs| {
  53. let lhs = cs.query_advice(a_col, Rotation::cur());
  54. let rhs = cs.query_advice(b_col, Rotation::cur());
  55. let out = cs.query_advice(a_col, Rotation::next());
  56. let s_add = cs.query_selector(s_add);
  57. vec![s_add * (lhs + rhs - out)]
  58. });
  59. cs.create_gate("mul", |cs| {
  60. let lhs = cs.query_advice(a_col, Rotation::cur());
  61. let rhs = cs.query_advice(b_col, Rotation::cur());
  62. let out = cs.query_advice(a_col, Rotation::next());
  63. let s_mul = cs.query_selector(s_mul);
  64. vec![s_mul * (lhs * rhs - out)]
  65. });
  66. /*
  67. cs.create_gate("pub", |cs| {
  68. let a = cs.query_advice(a_col, Rotation::cur());
  69. let p = cs.query_instance(instance, Rotation::cur());
  70. let s_pub = cs.query_selector(s_pub);
  71. vec![s_pub * (p - a)]
  72. });
  73. */
  74. ArithmeticChipConfig {
  75. a_col,
  76. b_col,
  77. /*permute,*/ s_add,
  78. s_mul, /*, s_pub*/
  79. }
  80. }
  81. pub fn add(
  82. &self,
  83. mut layouter: impl Layouter<Fp>,
  84. a: Variable,
  85. b: Variable,
  86. ) -> Result<Variable, Error> {
  87. let mut out = None;
  88. layouter.assign_region(
  89. || "mul",
  90. |mut region| {
  91. self.config.s_add.enable(&mut region, 0)?;
  92. let lhs = region.assign_advice(
  93. || "lhs",
  94. self.config.a_col,
  95. 0,
  96. || a.value().ok_or(Error::SynthesisError),
  97. )?;
  98. let rhs = region.assign_advice(
  99. || "rhs",
  100. self.config.b_col,
  101. 0,
  102. || b.value().ok_or(Error::SynthesisError),
  103. )?;
  104. region.constrain_equal(a.cell(), lhs)?;
  105. region.constrain_equal(b.cell(), rhs)?;
  106. let value = a.value().and_then(|a| b.value().map(|b| a + b));
  107. let cell = region.assign_advice(
  108. || "lhs + rhs",
  109. self.config.a_col,
  110. 1,
  111. || value.ok_or(Error::SynthesisError),
  112. )?;
  113. out = Some(Var::new(cell, value));
  114. Ok(())
  115. },
  116. )?;
  117. Ok(out.unwrap())
  118. }
  119. pub fn mul(
  120. &self,
  121. mut layouter: impl Layouter<Fp>,
  122. a: Variable,
  123. b: Variable,
  124. ) -> Result<Variable, Error> {
  125. let mut out = None;
  126. layouter.assign_region(
  127. || "mul",
  128. |mut region| {
  129. self.config.s_mul.enable(&mut region, 0)?;
  130. let lhs = region.assign_advice(
  131. || "lhs",
  132. self.config.a_col,
  133. 0,
  134. || a.value().ok_or(Error::SynthesisError),
  135. )?;
  136. let rhs = region.assign_advice(
  137. || "rhs",
  138. self.config.b_col,
  139. 0,
  140. || b.value().ok_or(Error::SynthesisError),
  141. )?;
  142. region.constrain_equal(a.cell(), lhs)?;
  143. region.constrain_equal(b.cell(), rhs)?;
  144. let value = a.value().and_then(|a| b.value().map(|b| a * b));
  145. let cell = region.assign_advice(
  146. || "lhs * rhs",
  147. self.config.a_col,
  148. 1,
  149. || value.ok_or(Error::SynthesisError),
  150. )?;
  151. out = Some(Var::new(cell, value));
  152. Ok(())
  153. },
  154. )?;
  155. Ok(out.unwrap())
  156. }
  157. /*
  158. fn expose_public(&self, layouter: &mut impl Layouter<Fp>, num: Number) -> Result<(), Error> {
  159. layouter.assign_region(
  160. || "expose public",
  161. |mut region| {
  162. self.config.s_pub.enable(&mut region, 0)?;
  163. let out = region.assign_advice(
  164. || "public advice",
  165. self.config.b_col,
  166. 0,
  167. || num.value.ok_or(Error::SynthesisError),
  168. )?;
  169. region.constrain_equal(num.cell, out)?;
  170. Ok(())
  171. },
  172. )
  173. }
  174. */
  175. }