simple4.rs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. use halo2::{
  2. circuit::{SimpleFloorPlanner, Cell, Chip, Layouter},
  3. pasta::{EqAffine, Fp},
  4. plonk::{Advice, Any, Circuit, Column, ConstraintSystem, Error, Expression, Selector, create_proof, verify_proof, keygen_vk, keygen_pk, Permutation},
  5. poly::{commitment::{Blind, Params}, Rotation},
  6. transcript::{Blake2bRead, Blake2bWrite, Challenge255},
  7. };
  8. use group::Curve;
  9. use std::time::Instant;
  10. #[derive(Clone, Debug)]
  11. struct CoolConfig {
  12. a_col: Column<Advice>,
  13. b_col: Column<Advice>,
  14. permute: Permutation,
  15. s_range: Selector,
  16. s_mul: Selector,
  17. s_pub: Selector,
  18. }
  19. struct CoolChip {
  20. config: CoolConfig
  21. }
  22. impl Chip<Fp> for CoolChip {
  23. type Config = CoolConfig;
  24. type Loaded = ();
  25. fn config(&self) -> &Self::Config {
  26. &self.config
  27. }
  28. fn loaded(&self) -> &Self::Loaded {
  29. &()
  30. }
  31. }
  32. #[derive(Clone, Debug)]
  33. struct Number {
  34. cell: Cell,
  35. value: Option<Fp>,
  36. }
  37. impl CoolChip {
  38. fn construct(config: CoolConfig) -> Self {
  39. Self { config }
  40. }
  41. fn configure(cs: &mut ConstraintSystem<Fp>) -> CoolConfig {
  42. let a_col = cs.advice_column();
  43. let b_col = cs.advice_column();
  44. let instance = cs.instance_column();
  45. let permute = {
  46. // Convert advice columns into an "any" columns.
  47. let cols: [Column<Any>; 2] = [a_col.into(), b_col.into()];
  48. Permutation::new(cs, &cols)
  49. };
  50. let s_range = cs.selector();
  51. let s_mul = cs.selector();
  52. let s_pub = cs.selector();
  53. cs.create_gate("check", |cs| {
  54. let a = cs.query_advice(a_col, Rotation::cur());
  55. let s_range = cs.query_selector(s_range);
  56. vec![s_range * (a - Expression::Constant(Fp::from(2)))]
  57. });
  58. cs.create_gate("mul", |cs| {
  59. let lhs = cs.query_advice(a_col, Rotation::cur());
  60. let rhs = cs.query_advice(b_col, Rotation::cur());
  61. let out = cs.query_advice(a_col, Rotation::next());
  62. let s_mul = cs.query_selector(s_mul);
  63. vec![s_mul * (lhs * rhs + out * -Fp::one())]
  64. });
  65. cs.create_gate("public input", |cs| {
  66. let a = cs.query_advice(b_col, Rotation::cur());
  67. let p = cs.query_instance(instance, Rotation::cur());
  68. let s = cs.query_selector(s_pub);
  69. vec![s * (p + a * -Fp::one())]
  70. });
  71. CoolConfig { a_col, b_col, permute, s_range, s_mul, s_pub }
  72. }
  73. fn alloc_left(
  74. &self,
  75. layouter: &mut impl Layouter<Fp>,
  76. value: Option<Fp>
  77. ) -> Result<Number, Error> {
  78. layouter.assign_region(
  79. || "load left private input",
  80. |mut region| {
  81. let cell = region.assign_advice(
  82. || "private input 'a'",
  83. self.config.a_col,
  84. 0,
  85. || value.ok_or(Error::SynthesisError),
  86. )?;
  87. Ok(Number { cell, value })
  88. }
  89. )
  90. }
  91. fn check(
  92. &self,
  93. layouter: &mut impl Layouter<Fp>,
  94. number: Number
  95. ) -> Result<(), Error> {
  96. layouter.assign_region(
  97. || "load private inputs",
  98. |mut region| {
  99. self.config.s_range.enable(&mut region, 0)?;
  100. let a = region.assign_advice(
  101. || "lhs",
  102. self.config.a_col,
  103. 0,
  104. || number.value.ok_or(Error::SynthesisError),
  105. )?;
  106. region.constrain_equal(&self.config.permute, number.cell, a)?;
  107. Ok(())
  108. },
  109. )
  110. }
  111. fn mul(
  112. &self,
  113. layouter: &mut impl Layouter<Fp>,
  114. a: Number,
  115. b: Number
  116. ) -> Result<Number, Error> {
  117. let mut out = None;
  118. layouter.assign_region(
  119. || "mul",
  120. |mut region| {
  121. self.config.s_mul.enable(&mut region, 0)?;
  122. let lhs = region.assign_advice(
  123. || "lhs",
  124. self.config.a_col,
  125. 0,
  126. || a.value.ok_or(Error::SynthesisError),
  127. )?;
  128. let rhs = region.assign_advice(
  129. || "rhs",
  130. self.config.b_col,
  131. 0,
  132. || b.value.ok_or(Error::SynthesisError),
  133. )?;
  134. region.constrain_equal(&self.config.permute, a.cell, lhs)?;
  135. region.constrain_equal(&self.config.permute, b.cell, rhs)?;
  136. let value = a.value.and_then(|a| b.value.map(|b| a * b));
  137. let cell = region.assign_advice(
  138. || "lhs * rhs",
  139. self.config.a_col,
  140. 1,
  141. || value.ok_or(Error::SynthesisError),
  142. )?;
  143. out = Some(Number { cell, value });
  144. Ok(())
  145. },
  146. )?;
  147. Ok(out.unwrap())
  148. }
  149. fn expose_public(&self, layouter: &mut impl Layouter<Fp>, num: Number) -> Result<(), Error> {
  150. layouter.assign_region(
  151. || "expose public",
  152. |mut region| {
  153. self.config.s_pub.enable(&mut region, 0)?;
  154. let out = region.assign_advice(
  155. || "public advice",
  156. self.config.b_col,
  157. 0,
  158. || num.value.ok_or(Error::SynthesisError),
  159. )?;
  160. region.constrain_equal(&self.config.permute, num.cell, out)?;
  161. Ok(())
  162. },
  163. )
  164. }
  165. }
  166. #[derive(Clone)]
  167. struct CoolCircuit {
  168. // Private input.
  169. a: Option<Fp>,
  170. }
  171. impl Circuit<Fp> for CoolCircuit {
  172. type Config = CoolConfig;
  173. type FloorPlanner = SimpleFloorPlanner;
  174. fn without_witnesses(&self) -> Self {
  175. Self { a: None }
  176. }
  177. fn configure(cs: &mut ConstraintSystem<Fp>) -> Self::Config {
  178. CoolChip::configure(cs)
  179. }
  180. fn synthesize(&self, config: Self::Config, mut layouter: impl Layouter<Fp>) -> Result<(), Error> {
  181. let chip = CoolChip::construct(config);
  182. let a = chip.alloc_left(&mut layouter, self.a)?;
  183. chip.check(&mut layouter, a.clone())?;
  184. let a2 = chip.mul(&mut layouter, a.clone(), a)?;
  185. chip.expose_public(&mut layouter, a2)?;
  186. Ok(())
  187. }
  188. }
  189. fn main() {
  190. let k = 6;
  191. let start = Instant::now();
  192. let params: Params<EqAffine> = Params::new(k);
  193. let empty_circuit = CoolCircuit { a: None };
  194. let vk = keygen_vk(&params, &empty_circuit).expect("keygen_vk should not fail");
  195. let pk = keygen_pk(&params, vk, &empty_circuit).expect("keygen_pk should not fail");
  196. println!("Setup: [{:?}]", start.elapsed());
  197. let start = Instant::now();
  198. let circuit = CoolCircuit {
  199. a: Some(Fp::from(2)),
  200. };
  201. let mut public_inputs = pk.get_vk().get_domain().empty_lagrange();
  202. public_inputs[4] = Fp::from(4);
  203. // Create a proof
  204. let mut transcript = Blake2bWrite::<_, _, Challenge255<_>>::init(vec![]);
  205. create_proof(&params, &pk, &[circuit], &[&[public_inputs.clone()]], &mut transcript)
  206. .expect("proof generation should not fail");
  207. let proof = transcript.finalize();
  208. println!("Prove: [{:?}]", start.elapsed());
  209. let pubinput = params
  210. .commit_lagrange(&public_inputs, Blind::default())
  211. .to_affine();
  212. let pubinput_slice = &[pubinput];
  213. let start = Instant::now();
  214. let msm = params.empty_msm();
  215. let mut transcript = Blake2bRead::<_, _, Challenge255<_>>::init(&proof[..]);
  216. let verification = verify_proof(&params, pk.get_vk(), msm, &[pubinput_slice], &mut transcript);
  217. if let Err(err) = verification {
  218. panic!("error {:?}", err);
  219. }
  220. let guard = verification.unwrap();
  221. let msm = guard.clone().use_challenges();
  222. assert!(msm.eval());
  223. println!("Verify: [{:?}]", start.elapsed());
  224. }