vm.rs 17 KB

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