mint_proof.rs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  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 token_commit: jubjub::SubgroupPoint,
  15. pub coin: [u8; 32],
  16. }
  17. impl MintRevealedValues {
  18. fn compute(
  19. value: u64,
  20. token_id: jubjub::Fr,
  21. randomness_value: &jubjub::Fr,
  22. randomness_token: &jubjub::Fr,
  23. serial: &jubjub::Fr,
  24. randomness_coin: &jubjub::Fr,
  25. public: &jubjub::SubgroupPoint,
  26. ) -> Self {
  27. let value_commit = (zcash_primitives::constants::VALUE_COMMITMENT_VALUE_GENERATOR
  28. * jubjub::Fr::from(value))
  29. + (zcash_primitives::constants::VALUE_COMMITMENT_RANDOMNESS_GENERATOR
  30. * randomness_value);
  31. let token_commit = (zcash_primitives::constants::VALUE_COMMITMENT_VALUE_GENERATOR
  32. * token_id)
  33. + (zcash_primitives::constants::VALUE_COMMITMENT_RANDOMNESS_GENERATOR
  34. * randomness_token);
  35. let mut coin = [0; 32];
  36. coin.copy_from_slice(
  37. Blake2sParams::new()
  38. .hash_length(32)
  39. .personal(zcash_primitives::constants::CRH_IVK_PERSONALIZATION)
  40. .to_state()
  41. .update(&public.to_bytes())
  42. .update(&value.to_le_bytes())
  43. .update(&token_id.to_bytes())
  44. .update(&serial.to_bytes())
  45. .update(&randomness_coin.to_bytes())
  46. .finalize()
  47. .as_bytes(),
  48. );
  49. MintRevealedValues {
  50. value_commit,
  51. token_commit,
  52. coin,
  53. }
  54. }
  55. fn make_outputs(&self) -> [bls12_381::Scalar; 6] {
  56. let mut public_input = [bls12_381::Scalar::zero(); 6];
  57. {
  58. let result = jubjub::ExtendedPoint::from(self.value_commit);
  59. let affine = result.to_affine();
  60. //let (u, v) = (affine.get_u(), affine.get_v());
  61. let u = affine.get_u();
  62. let v = affine.get_v();
  63. public_input[0] = u;
  64. public_input[1] = v;
  65. }
  66. {
  67. let result = jubjub::ExtendedPoint::from(self.token_commit);
  68. let affine = result.to_affine();
  69. let u = affine.get_u();
  70. let v = affine.get_v();
  71. public_input[2] = u;
  72. public_input[3] = v;
  73. }
  74. {
  75. // Pack the hash as inputs for proof verification.
  76. let hash = multipack::bytes_to_bits_le(&self.coin);
  77. let hash = multipack::compute_multipacking(&hash);
  78. // There are 2 chunks for a blake hash
  79. assert_eq!(hash.len(), 2);
  80. public_input[4] = hash[0];
  81. public_input[5] = hash[1];
  82. }
  83. public_input
  84. }
  85. }
  86. impl Encodable for MintRevealedValues {
  87. fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
  88. let mut len = 0;
  89. len += self.value_commit.encode(&mut s)?;
  90. len += self.token_commit.encode(&mut s)?;
  91. len += self.coin.encode(&mut s)?;
  92. Ok(len)
  93. }
  94. }
  95. impl Decodable for MintRevealedValues {
  96. fn decode<D: io::Read>(mut d: D) -> Result<Self> {
  97. Ok(Self {
  98. value_commit: Decodable::decode(&mut d)?,
  99. token_commit: Decodable::decode(&mut d)?,
  100. coin: Decodable::decode(d)?,
  101. })
  102. }
  103. }
  104. pub fn setup_mint_prover() -> groth16::Parameters<Bls12> {
  105. println!("Mint: Making random params...");
  106. let start = Instant::now();
  107. let params = {
  108. let c = MintContract {
  109. value: None,
  110. token_id: None,
  111. randomness_value: None,
  112. randomness_token: None,
  113. serial: None,
  114. randomness_coin: None,
  115. public: None,
  116. };
  117. groth16::generate_random_parameters::<Bls12, _, _>(c, &mut OsRng).unwrap()
  118. };
  119. println!("Setup: [{:?}]", start.elapsed());
  120. params
  121. }
  122. #[allow(clippy::too_many_arguments)]
  123. pub fn create_mint_proof(
  124. params: &groth16::Parameters<Bls12>,
  125. value: u64,
  126. token_id: jubjub::Fr,
  127. randomness_value: jubjub::Fr,
  128. randomness_token: jubjub::Fr,
  129. serial: jubjub::Fr,
  130. randomness_coin: jubjub::Fr,
  131. public: jubjub::SubgroupPoint,
  132. ) -> (groth16::Proof<Bls12>, MintRevealedValues) {
  133. let revealed = MintRevealedValues::compute(
  134. value,
  135. token_id,
  136. &randomness_value,
  137. &randomness_token,
  138. &serial,
  139. &randomness_coin,
  140. &public,
  141. );
  142. let c = MintContract {
  143. value: Some(value),
  144. token_id: Some(token_id),
  145. randomness_value: Some(randomness_value),
  146. randomness_token: Some(randomness_token),
  147. serial: Some(serial),
  148. randomness_coin: Some(randomness_coin),
  149. public: Some(public),
  150. };
  151. let start = Instant::now();
  152. let proof = groth16::create_random_proof(c, params, &mut OsRng).unwrap();
  153. println!("Prove: [{:?}]", start.elapsed());
  154. (proof, revealed)
  155. }
  156. pub fn verify_mint_proof(
  157. pvk: &groth16::PreparedVerifyingKey<Bls12>,
  158. proof: &groth16::Proof<Bls12>,
  159. revealed: &MintRevealedValues,
  160. ) -> bool {
  161. let public_input = revealed.make_outputs();
  162. let start = Instant::now();
  163. let result = groth16::verify_proof(pvk, proof, &public_input).is_ok();
  164. println!("Verify: [{:?}]", start.elapsed());
  165. result
  166. }