spend-classic.rs 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  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 sapvi::circuit::spend_contract::SpendContract;
  9. // This thing is nasty lol
  10. pub fn merkle_hash(
  11. depth: usize,
  12. lhs: &bls12_381::Scalar,
  13. rhs: &bls12_381::Scalar,
  14. ) -> bls12_381::Scalar {
  15. let lhs = {
  16. let mut tmp = [false; 256];
  17. for (a, b) in tmp.iter_mut().zip(lhs.to_repr().as_bits::<Lsb0>()) {
  18. *a = *b;
  19. }
  20. tmp
  21. };
  22. let rhs = {
  23. let mut tmp = [false; 256];
  24. for (a, b) in tmp.iter_mut().zip(rhs.to_repr().as_bits::<Lsb0>()) {
  25. *a = *b;
  26. }
  27. tmp
  28. };
  29. jubjub::ExtendedPoint::from(zcash_primitives::pedersen_hash::pedersen_hash(
  30. zcash_primitives::pedersen_hash::Personalization::MerkleTree(depth),
  31. lhs.iter()
  32. .copied()
  33. .take(bls12_381::Scalar::NUM_BITS as usize)
  34. .chain(
  35. rhs.iter()
  36. .copied()
  37. .take(bls12_381::Scalar::NUM_BITS as usize),
  38. ),
  39. ))
  40. .to_affine()
  41. .get_u()
  42. }
  43. struct SpendRevealedValues {
  44. value_commit: jubjub::SubgroupPoint,
  45. nullifier: [u8; 32],
  46. // This should not be here, we just have it for debugging
  47. //coin: [u8; 32],
  48. merkle_root: bls12_381::Scalar,
  49. }
  50. impl SpendRevealedValues {
  51. fn compute(
  52. value: u64,
  53. randomness_value: &jubjub::Fr,
  54. serial: &jubjub::Fr,
  55. randomness_coin: &jubjub::Fr,
  56. secret: &jubjub::Fr,
  57. merkle_path: &[(bls12_381::Scalar, bool)],
  58. ) -> Self {
  59. let value_commit = (zcash_primitives::constants::VALUE_COMMITMENT_VALUE_GENERATOR
  60. * jubjub::Fr::from(value))
  61. + (zcash_primitives::constants::VALUE_COMMITMENT_RANDOMNESS_GENERATOR
  62. * randomness_value);
  63. let mut nullifier = [0; 32];
  64. nullifier.copy_from_slice(
  65. Blake2sParams::new()
  66. .hash_length(32)
  67. .personal(zcash_primitives::constants::PRF_NF_PERSONALIZATION)
  68. .to_state()
  69. .update(&secret.to_bytes())
  70. .update(&serial.to_bytes())
  71. .finalize()
  72. .as_bytes(),
  73. );
  74. let public = zcash_primitives::constants::SPENDING_KEY_GENERATOR * secret;
  75. let mut coin = [0; 32];
  76. coin.copy_from_slice(
  77. Blake2sParams::new()
  78. .hash_length(32)
  79. .personal(zcash_primitives::constants::CRH_IVK_PERSONALIZATION)
  80. .to_state()
  81. .update(&public.to_bytes())
  82. .update(&value.to_le_bytes())
  83. .update(&serial.to_bytes())
  84. .update(&randomness_coin.to_bytes())
  85. .finalize()
  86. .as_bytes(),
  87. );
  88. let merkle_root =
  89. jubjub::ExtendedPoint::from(zcash_primitives::pedersen_hash::pedersen_hash(
  90. zcash_primitives::pedersen_hash::Personalization::NoteCommitment,
  91. multipack::bytes_to_bits_le(&coin),
  92. ));
  93. let affine = merkle_root.to_affine();
  94. let mut merkle_root = affine.get_u();
  95. for (i, (right, is_right)) in merkle_path.iter().enumerate() {
  96. if *is_right {
  97. merkle_root = merkle_hash(i, &right, &merkle_root);
  98. } else {
  99. merkle_root = merkle_hash(i, &merkle_root, &right);
  100. }
  101. }
  102. SpendRevealedValues {
  103. value_commit,
  104. nullifier,
  105. merkle_root,
  106. }
  107. }
  108. fn make_outputs(&self) -> [bls12_381::Scalar; 5] {
  109. let mut public_input = [bls12_381::Scalar::zero(); 5];
  110. // CV
  111. {
  112. let result = jubjub::ExtendedPoint::from(self.value_commit);
  113. let affine = result.to_affine();
  114. //let (u, v) = (affine.get_u(), affine.get_v());
  115. let u = affine.get_u();
  116. let v = affine.get_v();
  117. public_input[0] = u;
  118. public_input[1] = v;
  119. }
  120. // NF
  121. {
  122. // Pack the hash as inputs for proof verification.
  123. let hash = multipack::bytes_to_bits_le(&self.nullifier);
  124. let hash = multipack::compute_multipacking(&hash);
  125. // There are 2 chunks for a blake hash
  126. assert_eq!(hash.len(), 2);
  127. public_input[2] = hash[0];
  128. public_input[3] = hash[1];
  129. }
  130. // Not revealed. We leave this code here for debug
  131. // Coin
  132. /*{
  133. // Pack the hash as inputs for proof verification.
  134. let hash = multipack::bytes_to_bits_le(&self.coin);
  135. let hash = multipack::compute_multipacking(&hash);
  136. // There are 2 chunks for a blake hash
  137. assert_eq!(hash.len(), 2);
  138. public_input[4] = hash[0];
  139. public_input[5] = hash[1];
  140. }*/
  141. public_input[4] = self.merkle_root;
  142. public_input
  143. }
  144. }
  145. fn main() {
  146. use rand::rngs::OsRng;
  147. use std::time::Instant;
  148. let value = 110;
  149. let randomness_value: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
  150. let serial: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
  151. let randomness_coin: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
  152. let secret: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
  153. let merkle_path = [
  154. (bls12_381::Scalar::random(&mut OsRng), true),
  155. (bls12_381::Scalar::random(&mut OsRng), false),
  156. (bls12_381::Scalar::random(&mut OsRng), true),
  157. (bls12_381::Scalar::random(&mut OsRng), true),
  158. ];
  159. let revealed = SpendRevealedValues::compute(
  160. value,
  161. &randomness_value,
  162. &serial,
  163. &randomness_coin,
  164. &secret,
  165. &merkle_path,
  166. );
  167. let start = Instant::now();
  168. let params = {
  169. let c = SpendContract {
  170. value: None,
  171. randomness_value: None,
  172. serial: None,
  173. randomness_coin: None,
  174. secret: None,
  175. branch_0: None,
  176. is_right_0: None,
  177. branch_1: None,
  178. is_right_1: None,
  179. branch_2: None,
  180. is_right_2: None,
  181. branch_3: None,
  182. is_right_3: None,
  183. };
  184. groth16::generate_random_parameters::<Bls12, _, _>(c, &mut OsRng).unwrap()
  185. };
  186. let pvk = groth16::prepare_verifying_key(&params.vk);
  187. println!("Setup: [{:?}]", start.elapsed());
  188. let c = SpendContract {
  189. value: Some(value),
  190. randomness_value: Some(randomness_value),
  191. serial: Some(serial),
  192. randomness_coin: Some(randomness_coin),
  193. secret: Some(secret),
  194. branch_0: Some(merkle_path[0].0),
  195. is_right_0: Some(merkle_path[0].1),
  196. branch_1: Some(merkle_path[1].0),
  197. is_right_1: Some(merkle_path[1].1),
  198. branch_2: Some(merkle_path[2].0),
  199. is_right_2: Some(merkle_path[2].1),
  200. branch_3: Some(merkle_path[3].0),
  201. is_right_3: Some(merkle_path[3].1),
  202. };
  203. let start = Instant::now();
  204. let proof = groth16::create_random_proof(c, &params, &mut OsRng).unwrap();
  205. println!("Prove: [{:?}]", start.elapsed());
  206. let public_input = revealed.make_outputs();
  207. let start = Instant::now();
  208. assert!(groth16::verify_proof(&pvk, &proof, &public_input).is_ok());
  209. println!("Verify: [{:?}]", start.elapsed());
  210. }