vm.rs 17 KB

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