vm2.rs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. use halo2::{
  2. circuit::{Layouter, SimpleFloorPlanner},
  3. dev::MockProver,
  4. plonk::{
  5. Advice, Circuit, Column, ConstraintSystem, Error, Instance as InstanceColumn, Selector,
  6. },
  7. poly::Rotation,
  8. };
  9. use halo2_gadgets::{
  10. ecc::{
  11. chip::{EccChip, EccConfig},
  12. FixedPoint, FixedPoints,
  13. },
  14. poseidon::{
  15. Hash as PoseidonHash, Pow5T3Chip as PoseidonChip, Pow5T3Config as PoseidonConfig,
  16. StateWord, Word,
  17. },
  18. primitives,
  19. primitives::{
  20. poseidon::{ConstantLength, P128Pow5T3},
  21. sinsemilla::S_PERSONALIZATION,
  22. },
  23. sinsemilla::{
  24. chip::{SinsemillaChip, SinsemillaConfig},
  25. merkle::chip::{MerkleChip, MerkleConfig},
  26. merkle::MerklePath,
  27. },
  28. utilities::{
  29. lookup_range_check::LookupRangeCheckConfig, CellValue, UtilitiesInstructions, Var,
  30. },
  31. };
  32. use pasta_curves::{
  33. arithmetic::{CurveAffine, Field},
  34. group::{ff::PrimeFieldBits, Curve, Group},
  35. pallas,
  36. };
  37. use rand::rngs::OsRng;
  38. use std::{collections::HashMap, fs::File, time::Instant};
  39. use drk::{
  40. crypto::{
  41. constants::{
  42. sinsemilla::{OrchardCommitDomains, OrchardHashDomains, MERKLE_CRH_PERSONALIZATION},
  43. OrchardFixedBases,
  44. },
  45. proof::{Proof, ProvingKey, VerifyingKey},
  46. util::{pedersen_commitment_scalar, pedersen_commitment_u64},
  47. },
  48. serial::Decodable,
  49. vm2,
  50. };
  51. fn main() -> std::result::Result<(), failure::Error> {
  52. // The number of rows in our circuit cannot exceed 2^k
  53. let k: u32 = 11;
  54. let start = Instant::now();
  55. let file = File::open("proof/mint.zk.bin")?;
  56. let zkbin = vm2::ZkBinary::decode(file)?;
  57. for contract_name in zkbin.contracts.keys() {
  58. println!("Loaded '{}' contract.", contract_name);
  59. }
  60. println!("Load time: [{:?}]", start.elapsed());
  61. let contract = &zkbin.contracts["Mint"];
  62. //contract.witness_base(...);
  63. //contract.witness_base(...);
  64. //contract.witness_base(...);
  65. let pubkey = pallas::Point::random(&mut OsRng);
  66. let coords = pubkey.to_affine().coordinates().unwrap();
  67. let value = 110;
  68. let asset = 1;
  69. let value_blind = pallas::Scalar::random(&mut OsRng);
  70. let asset_blind = pallas::Scalar::random(&mut OsRng);
  71. let serial = pallas::Base::random(&mut OsRng);
  72. let coin_blind = pallas::Base::random(&mut OsRng);
  73. let mut coin = pallas::Base::zero();
  74. let messages = [
  75. [*coords.x(), *coords.y()],
  76. [pallas::Base::from(value), pallas::Base::from(asset)],
  77. [serial, coin_blind],
  78. ];
  79. for msg in messages.iter() {
  80. coin += primitives::poseidon::Hash::init(P128Pow5T3, ConstantLength::<2>).hash(*msg);
  81. }
  82. let coin2 = primitives::poseidon::Hash::init(P128Pow5T3, ConstantLength::<2>)
  83. .hash([*coords.x(), *coords.y()]);
  84. let value_commit = pedersen_commitment_u64(value, value_blind);
  85. let value_coords = value_commit.to_affine().coordinates().unwrap();
  86. let asset_commit = pedersen_commitment_u64(asset, asset_blind);
  87. let asset_coords = asset_commit.to_affine().coordinates().unwrap();
  88. let mut public_inputs = vec![
  89. coin,
  90. *value_coords.x(),
  91. *value_coords.y(),
  92. *asset_coords.x(),
  93. *asset_coords.y(),
  94. ];
  95. let mut const_fixed_points = HashMap::new();
  96. const_fixed_points.insert(
  97. "VALUE_COMMIT_VALUE".to_string(),
  98. OrchardFixedBases::ValueCommitV,
  99. );
  100. const_fixed_points.insert(
  101. "VALUE_COMMIT_RANDOM".to_string(),
  102. OrchardFixedBases::ValueCommitR,
  103. );
  104. let mut circuit = vm2::ZkCircuit::new(const_fixed_points, &zkbin.constants, contract);
  105. let empty_circuit = circuit.clone();
  106. circuit.witness_base("pub_x", *coords.x())?;
  107. circuit.witness_base("pub_y", *coords.y())?;
  108. circuit.witness_base("value", pallas::Base::from(value))?;
  109. circuit.witness_base("asset", pallas::Base::from(asset))?;
  110. circuit.witness_base("serial", serial)?;
  111. circuit.witness_base("coin_blind", coin_blind)?;
  112. circuit.witness_scalar("value_blind", value_blind)?;
  113. circuit.witness_scalar("asset_blind", asset_blind)?;
  114. // Valid MockProver
  115. let prover = MockProver::run(k, &circuit, vec![public_inputs.clone()]).unwrap();
  116. assert_eq!(prover.verify(), Ok(()));
  117. // Actual ZK proof
  118. let start = Instant::now();
  119. let vk = VerifyingKey::build(k, empty_circuit.clone());
  120. let pk = ProvingKey::build(k, empty_circuit.clone());
  121. println!("\nSetup: [{:?}]", start.elapsed());
  122. let start = Instant::now();
  123. let proof = Proof::create(&pk, &[circuit], &public_inputs).unwrap();
  124. println!("Prove: [{:?}]", start.elapsed());
  125. let start = Instant::now();
  126. assert!(proof.verify(&vk, &public_inputs).is_ok());
  127. println!("Verify: [{:?}]", start.elapsed());
  128. Ok(())
  129. }