spend_proof.rs 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. use bellman::gadgets::multipack;
  2. use bellman::groth16;
  3. use bitvec::{order::Lsb0, view::AsBits};
  4. use blake2s_simd::Params as Blake2sParams;
  5. use bls12_381::Bls12;
  6. use ff::{Field, PrimeField};
  7. use group::{Curve, GroupEncoding};
  8. use rand::rngs::OsRng;
  9. use std::io;
  10. use std::time::Instant;
  11. use super::coin::merkle_hash;
  12. use crate::circuit::spend_contract::SpendContract;
  13. use crate::error::{Error, Result};
  14. use crate::serial::{Decodable, Encodable};
  15. pub struct SpendRevealedValues {
  16. pub value_commit: jubjub::SubgroupPoint,
  17. pub nullifier: [u8; 32],
  18. // This should not be here, we just have it for debugging
  19. //coin: [u8; 32],
  20. pub merkle_root: bls12_381::Scalar,
  21. pub signature_public: jubjub::SubgroupPoint,
  22. }
  23. impl SpendRevealedValues {
  24. fn compute(
  25. value: u64,
  26. randomness_value: &jubjub::Fr,
  27. serial: &jubjub::Fr,
  28. randomness_coin: &jubjub::Fr,
  29. secret: &jubjub::Fr,
  30. merkle_path: &[(bls12_381::Scalar, bool)],
  31. signature_secret: &jubjub::Fr,
  32. ) -> Self {
  33. let value_commit = (zcash_primitives::constants::VALUE_COMMITMENT_VALUE_GENERATOR
  34. * jubjub::Fr::from(value))
  35. + (zcash_primitives::constants::VALUE_COMMITMENT_RANDOMNESS_GENERATOR
  36. * randomness_value);
  37. let mut nullifier = [0; 32];
  38. nullifier.copy_from_slice(
  39. Blake2sParams::new()
  40. .hash_length(32)
  41. .personal(zcash_primitives::constants::PRF_NF_PERSONALIZATION)
  42. .to_state()
  43. .update(&secret.to_bytes())
  44. .update(&serial.to_bytes())
  45. .finalize()
  46. .as_bytes(),
  47. );
  48. let public = zcash_primitives::constants::SPENDING_KEY_GENERATOR * secret;
  49. let signature_public =
  50. zcash_primitives::constants::SPENDING_KEY_GENERATOR * signature_secret;
  51. let mut coin = [0; 32];
  52. coin.copy_from_slice(
  53. Blake2sParams::new()
  54. .hash_length(32)
  55. .personal(zcash_primitives::constants::CRH_IVK_PERSONALIZATION)
  56. .to_state()
  57. .update(&public.to_bytes())
  58. .update(&value.to_le_bytes())
  59. .update(&serial.to_bytes())
  60. .update(&randomness_coin.to_bytes())
  61. .finalize()
  62. .as_bytes(),
  63. );
  64. let merkle_root =
  65. jubjub::ExtendedPoint::from(zcash_primitives::pedersen_hash::pedersen_hash(
  66. zcash_primitives::pedersen_hash::Personalization::NoteCommitment,
  67. multipack::bytes_to_bits_le(&coin),
  68. ));
  69. let affine = merkle_root.to_affine();
  70. let mut merkle_root = affine.get_u();
  71. for (i, (right, is_right)) in merkle_path.iter().enumerate() {
  72. if *is_right {
  73. merkle_root = merkle_hash(i, &right.to_repr(), &merkle_root.to_repr());
  74. } else {
  75. merkle_root = merkle_hash(i, &merkle_root.to_repr(), &right.to_repr());
  76. }
  77. }
  78. SpendRevealedValues {
  79. value_commit,
  80. nullifier,
  81. merkle_root,
  82. signature_public,
  83. }
  84. }
  85. fn make_outputs(&self) -> [bls12_381::Scalar; 7] {
  86. let mut public_input = [bls12_381::Scalar::zero(); 7];
  87. // CV
  88. {
  89. let result = jubjub::ExtendedPoint::from(self.value_commit);
  90. let affine = result.to_affine();
  91. //let (u, v) = (affine.get_u(), affine.get_v());
  92. let u = affine.get_u();
  93. let v = affine.get_v();
  94. public_input[0] = u;
  95. public_input[1] = v;
  96. }
  97. // NF
  98. {
  99. // Pack the hash as inputs for proof verification.
  100. let hash = multipack::bytes_to_bits_le(&self.nullifier);
  101. let hash = multipack::compute_multipacking(&hash);
  102. // There are 2 chunks for a blake hash
  103. assert_eq!(hash.len(), 2);
  104. public_input[2] = hash[0];
  105. public_input[3] = hash[1];
  106. }
  107. // Not revealed. We leave this code here for debug
  108. // Coin
  109. /*{
  110. // Pack the hash as inputs for proof verification.
  111. let hash = multipack::bytes_to_bits_le(&self.coin);
  112. let hash = multipack::compute_multipacking(&hash);
  113. // There are 2 chunks for a blake hash
  114. assert_eq!(hash.len(), 2);
  115. public_input[4] = hash[0];
  116. public_input[5] = hash[1];
  117. }*/
  118. public_input[4] = self.merkle_root;
  119. {
  120. let result = jubjub::ExtendedPoint::from(self.signature_public);
  121. let affine = result.to_affine();
  122. //let (u, v) = (affine.get_u(), affine.get_v());
  123. let u = affine.get_u();
  124. let v = affine.get_v();
  125. public_input[5] = u;
  126. public_input[6] = v;
  127. }
  128. public_input
  129. }
  130. }
  131. impl Encodable for SpendRevealedValues {
  132. fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
  133. let mut len = 0;
  134. len += self.value_commit.encode(&mut s)?;
  135. len += self.nullifier.encode(&mut s)?;
  136. len += self.merkle_root.encode(&mut s)?;
  137. len += self.signature_public.encode(s)?;
  138. Ok(len)
  139. }
  140. }
  141. impl Decodable for SpendRevealedValues {
  142. fn decode<D: io::Read>(mut d: D) -> Result<Self> {
  143. Ok(Self {
  144. value_commit: Decodable::decode(&mut d)?,
  145. nullifier: Decodable::decode(&mut d)?,
  146. merkle_root: Decodable::decode(&mut d)?,
  147. signature_public: Decodable::decode(d)?,
  148. })
  149. }
  150. }
  151. pub fn setup_spend_prover() -> groth16::Parameters<Bls12> {
  152. println!("Making random params...");
  153. let start = Instant::now();
  154. let params = {
  155. let c = SpendContract {
  156. value: None,
  157. randomness_value: None,
  158. serial: None,
  159. randomness_coin: None,
  160. secret: None,
  161. branch_0: None,
  162. is_right_0: None,
  163. branch_1: None,
  164. is_right_1: None,
  165. branch_2: None,
  166. is_right_2: None,
  167. branch_3: None,
  168. is_right_3: None,
  169. signature_secret: None,
  170. };
  171. groth16::generate_random_parameters::<Bls12, _, _>(c, &mut OsRng).unwrap()
  172. };
  173. println!("Setup: [{:?}]", start.elapsed());
  174. params
  175. }
  176. pub fn create_spend_proof(
  177. params: &groth16::Parameters<Bls12>,
  178. value: u64,
  179. randomness_value: jubjub::Fr,
  180. serial: jubjub::Fr,
  181. randomness_coin: jubjub::Fr,
  182. secret: jubjub::Fr,
  183. merkle_path: Vec<(bls12_381::Scalar, bool)>,
  184. signature_secret: jubjub::Fr,
  185. ) -> (groth16::Proof<Bls12>, SpendRevealedValues) {
  186. assert_eq!(merkle_path.len(), 4);
  187. assert_eq!(
  188. merkle_path.len(),
  189. super::coin::SAPLING_COMMITMENT_TREE_DEPTH
  190. );
  191. let c = SpendContract {
  192. value: Some(value),
  193. randomness_value: Some(randomness_value),
  194. serial: Some(serial),
  195. randomness_coin: Some(randomness_coin),
  196. secret: Some(secret),
  197. branch_0: Some(merkle_path[0].0),
  198. is_right_0: Some(merkle_path[0].1),
  199. branch_1: Some(merkle_path[1].0),
  200. is_right_1: Some(merkle_path[1].1),
  201. branch_2: Some(merkle_path[2].0),
  202. is_right_2: Some(merkle_path[2].1),
  203. branch_3: Some(merkle_path[3].0),
  204. is_right_3: Some(merkle_path[3].1),
  205. signature_secret: Some(signature_secret),
  206. };
  207. let start = Instant::now();
  208. let proof = groth16::create_random_proof(c, params, &mut OsRng).unwrap();
  209. println!("Prove: [{:?}]", start.elapsed());
  210. let revealed = SpendRevealedValues::compute(
  211. value,
  212. &randomness_value,
  213. &serial,
  214. &randomness_coin,
  215. &secret,
  216. &merkle_path,
  217. &signature_secret,
  218. );
  219. (proof, revealed)
  220. }
  221. pub fn verify_spend_proof(
  222. pvk: &groth16::PreparedVerifyingKey<Bls12>,
  223. proof: &groth16::Proof<Bls12>,
  224. revealed: &SpendRevealedValues,
  225. ) -> bool {
  226. let public_input = revealed.make_outputs();
  227. let start = Instant::now();
  228. let result = groth16::verify_proof(pvk, proof, &public_input).is_ok();
  229. println!("Verify: [{:?}]", start.elapsed());
  230. result
  231. }