arith_chip.rs 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. use halo2_proofs::{
  2. circuit::{AssignedCell, Chip, Layouter},
  3. plonk::{Advice, Column, ConstraintSystem, Error, Selector},
  4. poly::Rotation,
  5. };
  6. use pasta_curves::pallas;
  7. type Variable = AssignedCell<pallas::Base, pallas::Base>;
  8. // Replace with use pasta::Fp and pasta::Fq
  9. type Fp = pallas::Base;
  10. //type Fq = pallas::Scalar;
  11. #[derive(Clone, Debug)]
  12. pub struct ArithmeticChipConfig {
  13. a_col: Column<Advice>,
  14. b_col: Column<Advice>,
  15. //permute: Permutation,
  16. s_add: Selector,
  17. s_mul: Selector,
  18. s_sub: 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);
  42. cs.enable_equality(b_col);
  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_sub = cs.selector();
  52. //let s_pub = cs.selector();
  53. cs.create_gate("add", |cs| {
  54. let lhs = cs.query_advice(a_col, Rotation::cur());
  55. let rhs = cs.query_advice(b_col, Rotation::cur());
  56. let out = cs.query_advice(a_col, Rotation::next());
  57. let s_add = cs.query_selector(s_add);
  58. vec![s_add * (lhs + rhs - out)]
  59. });
  60. cs.create_gate("mul", |cs| {
  61. let lhs = cs.query_advice(a_col, Rotation::cur());
  62. let rhs = cs.query_advice(b_col, Rotation::cur());
  63. let out = cs.query_advice(a_col, Rotation::next());
  64. let s_mul = cs.query_selector(s_mul);
  65. vec![s_mul * (lhs * rhs - out)]
  66. });
  67. cs.create_gate("sub", |cs| {
  68. let lhs = cs.query_advice(a_col, Rotation::cur());
  69. let rhs = cs.query_advice(b_col, Rotation::cur());
  70. let out = cs.query_advice(a_col, Rotation::next());
  71. let s_sub = cs.query_selector(s_sub);
  72. vec![s_sub * (lhs - rhs - out)]
  73. });
  74. /*
  75. cs.create_gate("pub", |cs| {
  76. let a = cs.query_advice(a_col, Rotation::cur());
  77. let p = cs.query_instance(instance, Rotation::cur());
  78. let s_pub = cs.query_selector(s_pub);
  79. vec![s_pub * (p - a)]
  80. });
  81. */
  82. ArithmeticChipConfig {
  83. a_col,
  84. b_col,
  85. /* permute, */ s_add,
  86. s_mul,
  87. s_sub, /* , s_pub */
  88. }
  89. }
  90. pub fn add(
  91. &self,
  92. mut layouter: impl Layouter<Fp>,
  93. a: Variable,
  94. b: Variable,
  95. ) -> Result<Variable, Error> {
  96. let mut out = None;
  97. layouter.assign_region(
  98. || "mul",
  99. |mut region| {
  100. self.config.s_add.enable(&mut region, 0)?;
  101. let lhs = region.assign_advice(
  102. || "lhs",
  103. self.config.a_col,
  104. 0,
  105. || Ok(*a.value().ok_or(Error::Synthesis)?),
  106. )?;
  107. let rhs = region.assign_advice(
  108. || "rhs",
  109. self.config.b_col,
  110. 0,
  111. || Ok(*b.value().ok_or(Error::Synthesis)?),
  112. )?;
  113. region.constrain_equal(a.cell(), lhs.cell())?;
  114. region.constrain_equal(b.cell(), rhs.cell())?;
  115. let value = a.value().and_then(|a| b.value().map(|b| a + b));
  116. let cell = region.assign_advice(
  117. || "lhs + rhs",
  118. self.config.a_col,
  119. 1,
  120. || value.ok_or(Error::Synthesis),
  121. )?;
  122. out = Some(cell);
  123. Ok(())
  124. },
  125. )?;
  126. Ok(out.unwrap())
  127. }
  128. pub fn mul(
  129. &self,
  130. mut layouter: impl Layouter<Fp>,
  131. a: Variable,
  132. b: Variable,
  133. ) -> Result<Variable, Error> {
  134. let mut out = None;
  135. layouter.assign_region(
  136. || "mul",
  137. |mut region| {
  138. self.config.s_mul.enable(&mut region, 0)?;
  139. let lhs = region.assign_advice(
  140. || "lhs",
  141. self.config.a_col,
  142. 0,
  143. || Ok(*a.value().ok_or(Error::Synthesis)?),
  144. )?;
  145. let rhs = region.assign_advice(
  146. || "rhs",
  147. self.config.b_col,
  148. 0,
  149. || Ok(*b.value().ok_or(Error::Synthesis)?),
  150. )?;
  151. region.constrain_equal(a.cell(), lhs.cell())?;
  152. region.constrain_equal(b.cell(), rhs.cell())?;
  153. let value = a.value().and_then(|a| b.value().map(|b| a * b));
  154. let cell = region.assign_advice(
  155. || "lhs * rhs",
  156. self.config.a_col,
  157. 1,
  158. || value.ok_or(Error::Synthesis),
  159. )?;
  160. out = Some(cell);
  161. Ok(())
  162. },
  163. )?;
  164. Ok(out.unwrap())
  165. }
  166. pub fn sub(
  167. &self,
  168. mut layouter: impl Layouter<Fp>,
  169. a: Variable,
  170. b: Variable,
  171. ) -> Result<Variable, Error> {
  172. let mut out = None;
  173. layouter.assign_region(
  174. || "sub",
  175. |mut region| {
  176. self.config.s_sub.enable(&mut region, 0)?;
  177. let lhs = region.assign_advice(
  178. || "lhs",
  179. self.config.a_col,
  180. 0,
  181. || Ok(*a.value().ok_or(Error::Synthesis)?),
  182. )?;
  183. let rhs = region.assign_advice(
  184. || "rhs",
  185. self.config.b_col,
  186. 0,
  187. || Ok(*b.value().ok_or(Error::Synthesis)?),
  188. )?;
  189. region.constrain_equal(a.cell(), lhs.cell())?;
  190. region.constrain_equal(b.cell(), rhs.cell())?;
  191. let value = a.value().and_then(|a| b.value().map(|b| a - b));
  192. let cell = region.assign_advice(
  193. || "lhs * rhs",
  194. self.config.a_col,
  195. 1,
  196. || value.ok_or(Error::Synthesis),
  197. )?;
  198. out = Some(cell);
  199. Ok(())
  200. },
  201. )?;
  202. Ok(out.unwrap())
  203. }
  204. /*
  205. fn expose_public(&self, layouter: &mut impl Layouter<Fp>, num: Number) -> Result<(), Error> {
  206. layouter.assign_region(
  207. || "expose public",
  208. |mut region| {
  209. self.config.s_pub.enable(&mut region, 0)?;
  210. let out = region.assign_advice(
  211. || "public advice",
  212. self.config.b_col,
  213. 0,
  214. || num.value.ok_or(Error::SynthesisError),
  215. )?;
  216. region.constrain_equal(num.cell, out)?;
  217. Ok(())
  218. },
  219. )
  220. }
  221. */
  222. }