mint_proof.rs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. use bellman::gadgets::multipack;
  2. use bellman::groth16;
  3. use blake2s_simd::Params as Blake2sParams;
  4. use bls12_381::Bls12;
  5. use group::{Curve, GroupEncoding};
  6. use rand::rngs::OsRng;
  7. use std::io;
  8. use std::time::Instant;
  9. use crate::circuit::mint_contract::MintContract;
  10. use crate::error::Result;
  11. use crate::serial::{Decodable, Encodable};
  12. pub struct MintRevealedValues {
  13. pub value_commit: jubjub::SubgroupPoint,
  14. pub coin: [u8; 32],
  15. }
  16. impl MintRevealedValues {
  17. fn compute(
  18. value: u64,
  19. asset_id: u64,
  20. randomness_value: &jubjub::Fr,
  21. serial: &jubjub::Fr,
  22. randomness_coin: &jubjub::Fr,
  23. public: &jubjub::SubgroupPoint,
  24. ) -> Self {
  25. let value_commit = (zcash_primitives::constants::VALUE_COMMITMENT_VALUE_GENERATOR
  26. * jubjub::Fr::from(value))
  27. + (zcash_primitives::constants::VALUE_COMMITMENT_RANDOMNESS_GENERATOR
  28. * randomness_value);
  29. let mut coin = [0; 32];
  30. coin.copy_from_slice(
  31. Blake2sParams::new()
  32. .hash_length(32)
  33. .personal(zcash_primitives::constants::CRH_IVK_PERSONALIZATION)
  34. .to_state()
  35. .update(&public.to_bytes())
  36. .update(&value.to_le_bytes())
  37. .update(&asset_id.to_le_bytes())
  38. .update(&serial.to_bytes())
  39. .update(&randomness_coin.to_bytes())
  40. .finalize()
  41. .as_bytes(),
  42. );
  43. MintRevealedValues { value_commit, coin }
  44. }
  45. fn make_outputs(&self) -> [bls12_381::Scalar; 4] {
  46. let mut public_input = [bls12_381::Scalar::zero(); 4];
  47. {
  48. let result = jubjub::ExtendedPoint::from(self.value_commit);
  49. let affine = result.to_affine();
  50. //let (u, v) = (affine.get_u(), affine.get_v());
  51. let u = affine.get_u();
  52. let v = affine.get_v();
  53. public_input[0] = u;
  54. public_input[1] = v;
  55. }
  56. {
  57. // Pack the hash as inputs for proof verification.
  58. let hash = multipack::bytes_to_bits_le(&self.coin);
  59. let hash = multipack::compute_multipacking(&hash);
  60. // There are 2 chunks for a blake hash
  61. assert_eq!(hash.len(), 2);
  62. public_input[2] = hash[0];
  63. public_input[3] = hash[1];
  64. }
  65. public_input
  66. }
  67. }
  68. impl Encodable for MintRevealedValues {
  69. fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
  70. let mut len = 0;
  71. len += self.value_commit.encode(&mut s)?;
  72. len += self.coin.encode(&mut s)?;
  73. Ok(len)
  74. }
  75. }
  76. impl Decodable for MintRevealedValues {
  77. fn decode<D: io::Read>(mut d: D) -> Result<Self> {
  78. Ok(Self {
  79. value_commit: Decodable::decode(&mut d)?,
  80. coin: Decodable::decode(d)?,
  81. })
  82. }
  83. }
  84. pub fn setup_mint_prover() -> groth16::Parameters<Bls12> {
  85. println!("Making random params...");
  86. let start = Instant::now();
  87. let params = {
  88. let c = MintContract {
  89. value: None,
  90. asset_id: None,
  91. randomness_value: None,
  92. serial: None,
  93. randomness_coin: None,
  94. public: None,
  95. };
  96. groth16::generate_random_parameters::<Bls12, _, _>(c, &mut OsRng).unwrap()
  97. };
  98. println!("Setup: [{:?}]", start.elapsed());
  99. params
  100. }
  101. pub fn create_mint_proof(
  102. params: &groth16::Parameters<Bls12>,
  103. value: u64,
  104. asset_id: u64,
  105. randomness_value: jubjub::Fr,
  106. serial: jubjub::Fr,
  107. randomness_coin: jubjub::Fr,
  108. public: jubjub::SubgroupPoint,
  109. ) -> (groth16::Proof<Bls12>, MintRevealedValues) {
  110. let revealed =
  111. MintRevealedValues::compute(value, asset_id, &randomness_value, &serial, &randomness_coin, &public);
  112. let c = MintContract {
  113. value: Some(value),
  114. asset_id: Some(asset_id),
  115. randomness_value: Some(randomness_value),
  116. serial: Some(serial),
  117. randomness_coin: Some(randomness_coin),
  118. public: Some(public),
  119. };
  120. let start = Instant::now();
  121. let proof = groth16::create_random_proof(c, params, &mut OsRng).unwrap();
  122. println!("Prove: [{:?}]", start.elapsed());
  123. (proof, revealed)
  124. }
  125. pub fn verify_mint_proof(
  126. pvk: &groth16::PreparedVerifyingKey<Bls12>,
  127. proof: &groth16::Proof<Bls12>,
  128. revealed: &MintRevealedValues,
  129. ) -> bool {
  130. let public_input = revealed.make_outputs();
  131. let start = Instant::now();
  132. let result = groth16::verify_proof(pvk, proof, &public_input).is_ok();
  133. println!("Verify: [{:?}]", start.elapsed());
  134. result
  135. }