spend-classic.rs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. use bellman::gadgets::multipack;
  2. use bitvec::{order::Lsb0, view::AsBits};
  3. use blake2s_simd::Params as Blake2sParams;
  4. use ff::{Field, PrimeField};
  5. use group::{Curve, GroupEncoding};
  6. use drk::crypto::{
  7. create_spend_proof, load_params, save_params, setup_spend_prover, verify_spend_proof,
  8. };
  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. let value = 110;
  148. let randomness_value: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
  149. let serial: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
  150. let randomness_coin: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
  151. let secret: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
  152. let signature_secret: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
  153. let merkle_path = vec![
  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. {
  160. let params = setup_spend_prover();
  161. save_params("spend.params", &params);
  162. }
  163. let (params, pvk) = load_params("spend.params").expect("params should load");
  164. let signature_public = zcash_primitives::constants::SPENDING_KEY_GENERATOR * signature_secret;
  165. let (proof, revealed) = create_spend_proof(
  166. &params,
  167. value,
  168. randomness_value,
  169. serial,
  170. randomness_coin,
  171. secret,
  172. merkle_path,
  173. signature_secret,
  174. );
  175. assert!(verify_spend_proof(&pvk, &proof, &revealed));
  176. assert_eq!(revealed.signature_public, signature_public);
  177. }