vm.rs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. use bellman::{
  2. gadgets::{
  3. boolean::{AllocatedBit, Boolean},
  4. multipack, num, Assignment,
  5. },
  6. groth16, Circuit, ConstraintSystem, SynthesisError,
  7. };
  8. use bls12_381::Bls12;
  9. use bls12_381::Scalar;
  10. use ff::{Field, PrimeField};
  11. use group::Curve;
  12. use rand::rngs::OsRng;
  13. use std::ops::{Add, AddAssign, MulAssign, Neg, SubAssign};
  14. use std::time::Instant;
  15. pub struct ZKVirtualMachine {
  16. pub ops: Vec<CryptoOperation>,
  17. pub aux: Vec<Scalar>,
  18. pub alloc: Vec<(AllocType, VariableIndex)>,
  19. pub constraints: Vec<ConstraintInstruction>,
  20. pub params: Option<groth16::Parameters<Bls12>>,
  21. pub verifying_key: Option<groth16::PreparedVerifyingKey<Bls12>>,
  22. pub constants: Vec<Scalar>,
  23. }
  24. pub type VariableIndex = usize;
  25. pub enum VariableRef {
  26. Aux(VariableIndex),
  27. Local(VariableIndex),
  28. }
  29. pub enum CryptoOperation {
  30. Set(VariableRef, VariableRef),
  31. Mul(VariableRef, VariableRef),
  32. Add(VariableRef, VariableRef),
  33. Sub(VariableRef, VariableRef),
  34. Load(VariableRef, VariableIndex),
  35. Divide(VariableRef, VariableRef),
  36. Double(VariableRef),
  37. Square(VariableRef),
  38. Invert(VariableRef),
  39. UnpackBits(VariableRef, VariableRef, VariableRef),
  40. Local,
  41. Debug(String, VariableRef),
  42. DumpAlloc,
  43. DumpLocal,
  44. }
  45. #[derive(Clone)]
  46. pub enum AllocType {
  47. Private,
  48. Public,
  49. }
  50. #[derive(Clone)]
  51. pub enum ConstraintInstruction {
  52. Lc0Add(VariableIndex),
  53. Lc1Add(VariableIndex),
  54. Lc2Add(VariableIndex),
  55. Lc0Sub(VariableIndex),
  56. Lc1Sub(VariableIndex),
  57. Lc2Sub(VariableIndex),
  58. Lc0AddOne,
  59. Lc1AddOne,
  60. Lc2AddOne,
  61. Lc0SubOne,
  62. Lc1SubOne,
  63. Lc2SubOne,
  64. Lc0AddCoeff(VariableIndex, VariableIndex),
  65. Lc1AddCoeff(VariableIndex, VariableIndex),
  66. Lc2AddCoeff(VariableIndex, VariableIndex),
  67. Lc0AddOneCoeff(VariableIndex),
  68. Lc1AddOneCoeff(VariableIndex),
  69. Lc2AddOneCoeff(VariableIndex),
  70. Enforce,
  71. LcCoeffReset,
  72. LcCoeffDouble,
  73. }
  74. #[derive(Debug)]
  75. pub enum ZKVMError {
  76. DivisionByZero,
  77. MalformedRange,
  78. }
  79. impl ZKVirtualMachine {
  80. pub fn initialize(
  81. &mut self,
  82. params: &Vec<(VariableIndex, Scalar)>,
  83. ) -> std::result::Result<(), ZKVMError> {
  84. // Resize array
  85. self.aux = vec![Scalar::zero(); self.alloc.len()];
  86. // Copy over the parameters
  87. for (index, value) in params {
  88. //println!("Setting {} to {:?}", index, value);
  89. self.aux[*index] = *value;
  90. }
  91. let mut local_stack: Vec<Scalar> = Vec::new();
  92. for op in &self.ops {
  93. match op {
  94. CryptoOperation::Set(self_, other) => {
  95. let other = match other {
  96. VariableRef::Aux(index) => self.aux[*index].clone(),
  97. VariableRef::Local(index) => local_stack[*index].clone(),
  98. };
  99. let self_ = match self_ {
  100. VariableRef::Aux(index) => &mut self.aux[*index],
  101. VariableRef::Local(index) => &mut local_stack[*index],
  102. };
  103. *self_ = other;
  104. }
  105. CryptoOperation::Mul(self_, other) => {
  106. let other = match other {
  107. VariableRef::Aux(index) => self.aux[*index].clone(),
  108. VariableRef::Local(index) => local_stack[*index].clone(),
  109. };
  110. let self_ = match self_ {
  111. VariableRef::Aux(index) => &mut self.aux[*index],
  112. VariableRef::Local(index) => &mut local_stack[*index],
  113. };
  114. self_.mul_assign(other);
  115. }
  116. CryptoOperation::Add(self_, other) => {
  117. let other = match other {
  118. VariableRef::Aux(index) => self.aux[*index].clone(),
  119. VariableRef::Local(index) => local_stack[*index].clone(),
  120. };
  121. let self_ = match self_ {
  122. VariableRef::Aux(index) => &mut self.aux[*index],
  123. VariableRef::Local(index) => &mut local_stack[*index],
  124. };
  125. self_.add_assign(other);
  126. }
  127. CryptoOperation::Sub(self_, other) => {
  128. let other = match other {
  129. VariableRef::Aux(index) => self.aux[*index].clone(),
  130. VariableRef::Local(index) => local_stack[*index].clone(),
  131. };
  132. let self_ = match self_ {
  133. VariableRef::Aux(index) => &mut self.aux[*index],
  134. VariableRef::Local(index) => &mut local_stack[*index],
  135. };
  136. self_.sub_assign(other);
  137. }
  138. CryptoOperation::Load(self_, const_index) => {
  139. let self_ = match self_ {
  140. VariableRef::Aux(index) => &mut self.aux[*index],
  141. VariableRef::Local(index) => &mut local_stack[*index],
  142. };
  143. *self_ = self.constants[*const_index];
  144. }
  145. CryptoOperation::Divide(self_, other) => {
  146. let other = match other {
  147. VariableRef::Aux(index) => self.aux[*index].clone(),
  148. VariableRef::Local(index) => local_stack[*index].clone(),
  149. };
  150. let self_ = match self_ {
  151. VariableRef::Aux(index) => &mut self.aux[*index],
  152. VariableRef::Local(index) => &mut local_stack[*index],
  153. };
  154. let ret = other.invert().map(|other| *self_ * other);
  155. if bool::from(ret.is_some()) {
  156. *self_ = ret.unwrap();
  157. } else {
  158. return Err(ZKVMError::DivisionByZero);
  159. }
  160. }
  161. CryptoOperation::Double(self_) => {
  162. let self_ = match self_ {
  163. VariableRef::Aux(index) => &mut self.aux[*index],
  164. VariableRef::Local(index) => &mut local_stack[*index],
  165. };
  166. *self_ = self_.double();
  167. }
  168. CryptoOperation::Square(self_) => {
  169. let self_ = match self_ {
  170. VariableRef::Aux(index) => &mut self.aux[*index],
  171. VariableRef::Local(index) => &mut local_stack[*index],
  172. };
  173. *self_ = self_.square();
  174. }
  175. CryptoOperation::Invert(self_) => {
  176. let self_ = match self_ {
  177. VariableRef::Aux(index) => &mut self.aux[*index],
  178. VariableRef::Local(index) => &mut local_stack[*index],
  179. };
  180. if self_.is_zero() {
  181. return Err(ZKVMError::DivisionByZero);
  182. } else {
  183. *self_ = self_.invert().unwrap();
  184. }
  185. }
  186. CryptoOperation::UnpackBits(value, start, end) => {
  187. let value = match value {
  188. VariableRef::Aux(index) => self.aux[*index].clone(),
  189. VariableRef::Local(index) => local_stack[*index].clone(),
  190. };
  191. let (self_, start_index, end_index) = match start {
  192. VariableRef::Aux(start_index) => match end {
  193. VariableRef::Aux(end_index) => (&mut self.aux, start_index, end_index),
  194. VariableRef::Local(end_index) => {
  195. return Err(ZKVMError::MalformedRange);
  196. }
  197. },
  198. VariableRef::Local(start_index) => match end {
  199. VariableRef::Aux(end_index) => {
  200. return Err(ZKVMError::MalformedRange);
  201. }
  202. VariableRef::Local(end_index) => {
  203. (&mut local_stack, start_index, end_index)
  204. }
  205. },
  206. };
  207. if start_index > end_index {
  208. return Err(ZKVMError::MalformedRange);
  209. }
  210. if (end_index + 1) - start_index != 256 {
  211. return Err(ZKVMError::MalformedRange);
  212. }
  213. if *end_index >= self_.len() {
  214. return Err(ZKVMError::MalformedRange);
  215. }
  216. for (i, bit) in value.to_le_bits().into_iter().cloned().enumerate() {
  217. match bit {
  218. true => self_[start_index + i] = Scalar::one(),
  219. false => self_[start_index + i] = Scalar::zero(),
  220. }
  221. }
  222. }
  223. CryptoOperation::Local => {
  224. local_stack.push(Scalar::zero());
  225. }
  226. CryptoOperation::Debug(debug_str, self_) => {
  227. let self_ = match self_ {
  228. VariableRef::Aux(index) => &mut self.aux[*index],
  229. VariableRef::Local(index) => &mut local_stack[*index],
  230. };
  231. println!("{}", debug_str);
  232. println!("value = {:?}", self_);
  233. }
  234. CryptoOperation::DumpAlloc => {
  235. println!("-------------------");
  236. println!("alloc");
  237. println!("-------------------");
  238. for (i, value) in self.aux.iter().enumerate() {
  239. println!("{}: {:?}", i, value);
  240. }
  241. println!("-------------------");
  242. }
  243. CryptoOperation::DumpLocal => {
  244. println!("-------------------");
  245. println!("local");
  246. println!("-------------------");
  247. for (i, value) in local_stack.iter().enumerate() {
  248. println!("{}: {:?}", i, value);
  249. }
  250. println!("-------------------");
  251. }
  252. }
  253. }
  254. Ok(())
  255. }
  256. pub fn public(&self) -> Vec<Scalar> {
  257. let mut publics = Vec::new();
  258. for (alloc_type, index) in &self.alloc {
  259. match alloc_type {
  260. AllocType::Private => {}
  261. AllocType::Public => {
  262. let scalar = self.aux[*index].clone();
  263. publics.push(scalar);
  264. }
  265. }
  266. }
  267. publics
  268. }
  269. pub fn setup(&mut self) {
  270. let start = Instant::now();
  271. // Create parameters for our circuit. In a production deployment these would
  272. // be generated securely using a multiparty computation.
  273. self.params = Some({
  274. let circuit = ZKVMCircuit {
  275. aux: vec![None; self.aux.len()],
  276. alloc: self.alloc.clone(),
  277. constraints: self.constraints.clone(),
  278. constants: self.constants.clone(),
  279. };
  280. groth16::generate_random_parameters::<Bls12, _, _>(circuit, &mut OsRng).unwrap()
  281. });
  282. println!("Setup: [{:?}]", start.elapsed());
  283. self.verifying_key = Some(groth16::prepare_verifying_key(
  284. &self.params.as_ref().unwrap().vk,
  285. ))
  286. }
  287. pub fn prove(&self) -> groth16::Proof<Bls12> {
  288. let aux = self.aux.iter().map(|scalar| Some(scalar.clone())).collect();
  289. // Create an instance of our circuit (with the preimage as a witness).
  290. let circuit = ZKVMCircuit {
  291. aux,
  292. alloc: self.alloc.clone(),
  293. constraints: self.constraints.clone(),
  294. constants: self.constants.clone(),
  295. };
  296. let start = Instant::now();
  297. // Create a Groth16 proof with our parameters.
  298. let proof =
  299. groth16::create_random_proof(circuit, self.params.as_ref().unwrap(), &mut OsRng)
  300. .unwrap();
  301. println!("Prove: [{:?}]", start.elapsed());
  302. proof
  303. }
  304. pub fn verify(&self, proof: &groth16::Proof<Bls12>, public_values: &Vec<Scalar>) -> bool {
  305. let start = Instant::now();
  306. let is_passed =
  307. groth16::verify_proof(self.verifying_key.as_ref().unwrap(), proof, public_values)
  308. .is_ok();
  309. println!("Verify: [{:?}]", start.elapsed());
  310. is_passed
  311. }
  312. }
  313. pub struct ZKVMCircuit {
  314. aux: Vec<Option<bls12_381::Scalar>>,
  315. alloc: Vec<(AllocType, VariableIndex)>,
  316. constraints: Vec<ConstraintInstruction>,
  317. constants: Vec<Scalar>,
  318. }
  319. impl Circuit<bls12_381::Scalar> for ZKVMCircuit {
  320. fn synthesize<CS: ConstraintSystem<bls12_381::Scalar>>(
  321. self,
  322. cs: &mut CS,
  323. ) -> Result<(), SynthesisError> {
  324. let mut variables = Vec::new();
  325. for (alloc_type, index) in &self.alloc {
  326. match alloc_type {
  327. AllocType::Private => {
  328. let var = cs.alloc(|| "private alloc", || Ok(*self.aux[*index].get()?))?;
  329. variables.push(var);
  330. }
  331. AllocType::Public => {
  332. let var = cs.alloc_input(|| "public alloc", || Ok(*self.aux[*index].get()?))?;
  333. variables.push(var);
  334. }
  335. }
  336. }
  337. let mut coeff = bls12_381::Scalar::one();
  338. let mut lc0 = bellman::LinearCombination::<Scalar>::zero();
  339. let mut lc1 = bellman::LinearCombination::<Scalar>::zero();
  340. let mut lc2 = bellman::LinearCombination::<Scalar>::zero();
  341. for constraint in self.constraints {
  342. match constraint {
  343. ConstraintInstruction::Lc0Add(index) => {
  344. lc0 = lc0 + (coeff, variables[index]);
  345. }
  346. ConstraintInstruction::Lc1Add(index) => {
  347. lc1 = lc1 + (coeff, variables[index]);
  348. }
  349. ConstraintInstruction::Lc2Add(index) => {
  350. lc2 = lc2 + (coeff, variables[index]);
  351. }
  352. ConstraintInstruction::Lc0Sub(index) => {
  353. lc0 = lc0 - (coeff, variables[index]);
  354. }
  355. ConstraintInstruction::Lc1Sub(index) => {
  356. lc1 = lc1 - (coeff, variables[index]);
  357. }
  358. ConstraintInstruction::Lc2Sub(index) => {
  359. lc2 = lc2 - (coeff, variables[index]);
  360. }
  361. ConstraintInstruction::Lc0AddOne => {
  362. lc0 = lc0 + CS::one();
  363. }
  364. ConstraintInstruction::Lc1AddOne => {
  365. lc1 = lc1 + CS::one();
  366. }
  367. ConstraintInstruction::Lc2AddOne => {
  368. lc2 = lc2 + CS::one();
  369. }
  370. ConstraintInstruction::Lc0SubOne => {
  371. lc0 = lc0 - CS::one();
  372. }
  373. ConstraintInstruction::Lc1SubOne => {
  374. lc1 = lc1 - CS::one();
  375. }
  376. ConstraintInstruction::Lc2SubOne => {
  377. lc2 = lc2 - CS::one();
  378. }
  379. ConstraintInstruction::Lc0AddCoeff(const_index, index) => {
  380. lc0 = lc0 + (self.constants[const_index], variables[index]);
  381. }
  382. ConstraintInstruction::Lc1AddCoeff(const_index, index) => {
  383. lc1 = lc1 + (self.constants[const_index], variables[index]);
  384. }
  385. ConstraintInstruction::Lc2AddCoeff(const_index, index) => {
  386. lc2 = lc2 + (self.constants[const_index], variables[index]);
  387. }
  388. ConstraintInstruction::Lc0AddOneCoeff(const_index) => {
  389. lc0 = lc0 + (self.constants[const_index], CS::one());
  390. }
  391. ConstraintInstruction::Lc1AddOneCoeff(const_index) => {
  392. lc1 = lc1 + (self.constants[const_index], CS::one());
  393. }
  394. ConstraintInstruction::Lc2AddOneCoeff(const_index) => {
  395. lc2 = lc2 + (self.constants[const_index], CS::one());
  396. }
  397. ConstraintInstruction::Enforce => {
  398. cs.enforce(
  399. || "constraint",
  400. |_| lc0.clone(),
  401. |_| lc1.clone(),
  402. |_| lc2.clone(),
  403. );
  404. coeff = bls12_381::Scalar::one();
  405. lc0 = bellman::LinearCombination::<Scalar>::zero();
  406. lc1 = bellman::LinearCombination::<Scalar>::zero();
  407. lc2 = bellman::LinearCombination::<Scalar>::zero();
  408. }
  409. ConstraintInstruction::LcCoeffReset => {
  410. coeff = bls12_381::Scalar::one();
  411. }
  412. ConstraintInstruction::LcCoeffDouble => {
  413. coeff = coeff.double();
  414. }
  415. }
  416. }
  417. Ok(())
  418. }
  419. }