vm.rs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. use bellman::{
  2. gadgets::{
  3. Assignment,
  4. },
  5. groth16, Circuit, ConstraintSystem, SynthesisError,
  6. };
  7. use bls12_381::Bls12;
  8. use bls12_381::Scalar;
  9. use ff::{Field, PrimeField};
  10. use rand::rngs::OsRng;
  11. use std::ops::{AddAssign, MulAssign, SubAssign};
  12. use std::time::Instant;
  13. use crate::error::Result;
  14. pub struct ZKVirtualMachine {
  15. pub constants: Vec<Scalar>,
  16. pub alloc: Vec<(AllocType, VariableIndex)>,
  17. pub ops: Vec<CryptoOperation>,
  18. pub constraints: Vec<ConstraintInstruction>,
  19. pub aux: Vec<Scalar>,
  20. pub params: Option<groth16::Parameters<Bls12>>,
  21. pub verifying_key: Option<groth16::PreparedVerifyingKey<Bls12>>,
  22. }
  23. pub type VariableIndex = usize;
  24. pub enum VariableRef {
  25. Aux(VariableIndex),
  26. Local(VariableIndex),
  27. }
  28. pub enum CryptoOperation {
  29. Set(VariableRef, VariableRef),
  30. Mul(VariableRef, VariableRef),
  31. Add(VariableRef, VariableRef),
  32. Sub(VariableRef, VariableRef),
  33. Load(VariableRef, VariableIndex),
  34. Divide(VariableRef, VariableRef),
  35. Double(VariableRef),
  36. Square(VariableRef),
  37. Invert(VariableRef),
  38. UnpackBits(VariableRef, VariableRef, VariableRef),
  39. Local,
  40. Debug(String, VariableRef),
  41. DumpAlloc,
  42. DumpLocal,
  43. }
  44. #[derive(Clone)]
  45. pub enum AllocType {
  46. Private,
  47. Public,
  48. }
  49. #[derive(Clone)]
  50. pub enum ConstraintInstruction {
  51. Lc0Add(VariableIndex),
  52. Lc1Add(VariableIndex),
  53. Lc2Add(VariableIndex),
  54. Lc0Sub(VariableIndex),
  55. Lc1Sub(VariableIndex),
  56. Lc2Sub(VariableIndex),
  57. Lc0AddOne,
  58. Lc1AddOne,
  59. Lc2AddOne,
  60. Lc0SubOne,
  61. Lc1SubOne,
  62. Lc2SubOne,
  63. Lc0AddCoeff(VariableIndex, VariableIndex),
  64. Lc1AddCoeff(VariableIndex, VariableIndex),
  65. Lc2AddCoeff(VariableIndex, VariableIndex),
  66. Lc0AddConstant(VariableIndex),
  67. Lc1AddConstant(VariableIndex),
  68. Lc2AddConstant(VariableIndex),
  69. Enforce,
  70. LcCoeffReset,
  71. LcCoeffDouble,
  72. }
  73. #[derive(Debug)]
  74. pub enum ZKVMError {
  75. DivisionByZero,
  76. MalformedRange,
  77. }
  78. impl ZKVirtualMachine {
  79. pub fn initialize(
  80. &mut self,
  81. params: &Vec<(VariableIndex, Scalar)>,
  82. ) -> std::result::Result<(), ZKVMError> {
  83. // Resize array
  84. self.aux = vec![Scalar::zero(); self.alloc.len()];
  85. // Copy over the parameters
  86. for (index, value) in params {
  87. //println!("Setting {} to {:?}", index, value);
  88. self.aux[*index] = *value;
  89. }
  90. let mut local_stack: Vec<Scalar> = Vec::new();
  91. for op in &self.ops {
  92. match op {
  93. CryptoOperation::Set(self_, other) => {
  94. let other = match other {
  95. VariableRef::Aux(index) => self.aux[*index].clone(),
  96. VariableRef::Local(index) => local_stack[*index].clone(),
  97. };
  98. let self_ = match self_ {
  99. VariableRef::Aux(index) => &mut self.aux[*index],
  100. VariableRef::Local(index) => &mut local_stack[*index],
  101. };
  102. *self_ = other;
  103. }
  104. CryptoOperation::Mul(self_, other) => {
  105. let other = match other {
  106. VariableRef::Aux(index) => self.aux[*index].clone(),
  107. VariableRef::Local(index) => local_stack[*index].clone(),
  108. };
  109. let self_ = match self_ {
  110. VariableRef::Aux(index) => &mut self.aux[*index],
  111. VariableRef::Local(index) => &mut local_stack[*index],
  112. };
  113. self_.mul_assign(other);
  114. }
  115. CryptoOperation::Add(self_, other) => {
  116. let other = match other {
  117. VariableRef::Aux(index) => self.aux[*index].clone(),
  118. VariableRef::Local(index) => local_stack[*index].clone(),
  119. };
  120. let self_ = match self_ {
  121. VariableRef::Aux(index) => &mut self.aux[*index],
  122. VariableRef::Local(index) => &mut local_stack[*index],
  123. };
  124. self_.add_assign(other);
  125. }
  126. CryptoOperation::Sub(self_, other) => {
  127. let other = match other {
  128. VariableRef::Aux(index) => self.aux[*index].clone(),
  129. VariableRef::Local(index) => local_stack[*index].clone(),
  130. };
  131. let self_ = match self_ {
  132. VariableRef::Aux(index) => &mut self.aux[*index],
  133. VariableRef::Local(index) => &mut local_stack[*index],
  134. };
  135. self_.sub_assign(other);
  136. }
  137. CryptoOperation::Load(self_, const_index) => {
  138. let self_ = match self_ {
  139. VariableRef::Aux(index) => &mut self.aux[*index],
  140. VariableRef::Local(index) => &mut local_stack[*index],
  141. };
  142. *self_ = self.constants[*const_index];
  143. }
  144. CryptoOperation::Divide(self_, other) => {
  145. let other = match other {
  146. VariableRef::Aux(index) => self.aux[*index].clone(),
  147. VariableRef::Local(index) => local_stack[*index].clone(),
  148. };
  149. let self_ = match self_ {
  150. VariableRef::Aux(index) => &mut self.aux[*index],
  151. VariableRef::Local(index) => &mut local_stack[*index],
  152. };
  153. let ret = other.invert().map(|other| *self_ * other);
  154. if bool::from(ret.is_some()) {
  155. *self_ = ret.unwrap();
  156. } else {
  157. return Err(ZKVMError::DivisionByZero);
  158. }
  159. }
  160. CryptoOperation::Double(self_) => {
  161. let self_ = match self_ {
  162. VariableRef::Aux(index) => &mut self.aux[*index],
  163. VariableRef::Local(index) => &mut local_stack[*index],
  164. };
  165. *self_ = self_.double();
  166. }
  167. CryptoOperation::Square(self_) => {
  168. let self_ = match self_ {
  169. VariableRef::Aux(index) => &mut self.aux[*index],
  170. VariableRef::Local(index) => &mut local_stack[*index],
  171. };
  172. *self_ = self_.square();
  173. }
  174. CryptoOperation::Invert(self_) => {
  175. let self_ = match self_ {
  176. VariableRef::Aux(index) => &mut self.aux[*index],
  177. VariableRef::Local(index) => &mut local_stack[*index],
  178. };
  179. if self_.is_zero() {
  180. return Err(ZKVMError::DivisionByZero);
  181. } else {
  182. *self_ = self_.invert().unwrap();
  183. }
  184. }
  185. CryptoOperation::UnpackBits(value, start, end) => {
  186. let value = match value {
  187. VariableRef::Aux(index) => self.aux[*index].clone(),
  188. VariableRef::Local(index) => local_stack[*index].clone(),
  189. };
  190. let (self_, start_index, end_index) = match start {
  191. VariableRef::Aux(start_index) => match end {
  192. VariableRef::Aux(end_index) => (&mut self.aux, start_index, end_index),
  193. VariableRef::Local(_) => {
  194. return Err(ZKVMError::MalformedRange);
  195. }
  196. },
  197. VariableRef::Local(start_index) => match end {
  198. VariableRef::Aux(_) => {
  199. return Err(ZKVMError::MalformedRange);
  200. }
  201. VariableRef::Local(end_index) => {
  202. (&mut local_stack, start_index, end_index)
  203. }
  204. },
  205. };
  206. if start_index > end_index {
  207. return Err(ZKVMError::MalformedRange);
  208. }
  209. if (end_index + 1) - start_index != 256 {
  210. return Err(ZKVMError::MalformedRange);
  211. }
  212. if *end_index >= self_.len() {
  213. return Err(ZKVMError::MalformedRange);
  214. }
  215. for (i, bit) in value.to_le_bits().into_iter().cloned().enumerate() {
  216. match bit {
  217. true => self_[start_index + i] = Scalar::one(),
  218. false => self_[start_index + i] = Scalar::zero(),
  219. }
  220. }
  221. }
  222. CryptoOperation::Local => {
  223. local_stack.push(Scalar::zero());
  224. }
  225. CryptoOperation::Debug(debug_str, self_) => {
  226. let self_ = match self_ {
  227. VariableRef::Aux(index) => &mut self.aux[*index],
  228. VariableRef::Local(index) => &mut local_stack[*index],
  229. };
  230. println!("{}", debug_str);
  231. println!("value = {:?}", self_);
  232. }
  233. CryptoOperation::DumpAlloc => {
  234. println!("-------------------");
  235. println!("alloc");
  236. println!("-------------------");
  237. for (i, value) in self.aux.iter().enumerate() {
  238. println!("{}: {:?}", i, value);
  239. }
  240. println!("-------------------");
  241. }
  242. CryptoOperation::DumpLocal => {
  243. println!("-------------------");
  244. println!("local");
  245. println!("-------------------");
  246. for (i, value) in local_stack.iter().enumerate() {
  247. println!("{}: {:?}", i, value);
  248. }
  249. println!("-------------------");
  250. }
  251. }
  252. }
  253. Ok(())
  254. }
  255. pub fn public(&self) -> Vec<(VariableIndex, Scalar)> {
  256. let mut publics = Vec::new();
  257. for (alloc_type, index) in &self.alloc {
  258. match alloc_type {
  259. AllocType::Private => {}
  260. AllocType::Public => {
  261. let scalar = self.aux[*index].clone();
  262. publics.push((*index, scalar));
  263. }
  264. }
  265. }
  266. publics
  267. }
  268. pub fn setup(&mut self) -> Result<()> {
  269. let start = Instant::now();
  270. // Create parameters for our circuit. In a production deployment these would
  271. // be generated securely using a multiparty computation.
  272. self.params = Some({
  273. let circuit = ZKVMCircuit {
  274. aux: vec![None; self.aux.len()],
  275. alloc: self.alloc.clone(),
  276. constraints: self.constraints.clone(),
  277. constants: self.constants.clone(),
  278. };
  279. groth16::generate_random_parameters::<Bls12, _, _>(circuit, &mut OsRng)?
  280. });
  281. println!("Setup: [{:?}]", start.elapsed());
  282. self.verifying_key = Some(groth16::prepare_verifying_key(
  283. &self.params.as_ref().unwrap().vk,
  284. ));
  285. Ok(())
  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. ) -> std::result::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::Lc0AddConstant(const_index) => {
  389. lc0 = lc0 + (self.constants[const_index], CS::one());
  390. }
  391. ConstraintInstruction::Lc1AddConstant(const_index) => {
  392. lc1 = lc1 + (self.constants[const_index], CS::one());
  393. }
  394. ConstraintInstruction::Lc2AddConstant(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. }