spend_proof.rs 9.2 KB

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