mint_proof.rs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2022 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use std::time::Instant;
  19. use darkfi_sdk::{
  20. crypto::{
  21. pedersen::{pedersen_commitment_base, pedersen_commitment_u64},
  22. PublicKey,
  23. },
  24. pasta::{arithmetic::CurveAffine, group::Curve},
  25. };
  26. use darkfi_serial::{SerialDecodable, SerialEncodable};
  27. use halo2_proofs::circuit::Value;
  28. use log::debug;
  29. use rand::rngs::OsRng;
  30. use crate::{
  31. crypto::{
  32. coin::Coin,
  33. proof::{Proof, ProvingKey, VerifyingKey},
  34. types::{
  35. DrkCircuitField, DrkCoinBlind, DrkSerial, DrkSpendHook, DrkTokenId, DrkUserData,
  36. DrkValue, DrkValueBlind, DrkValueCommit,
  37. },
  38. util::poseidon_hash,
  39. },
  40. zk::circuit::mint_contract::MintContract,
  41. Result,
  42. };
  43. #[derive(Debug, Clone, PartialEq, Eq, SerialEncodable, SerialDecodable)]
  44. pub struct MintRevealedValues {
  45. pub value_commit: DrkValueCommit,
  46. pub token_commit: DrkValueCommit,
  47. pub coin: Coin,
  48. }
  49. impl MintRevealedValues {
  50. #[allow(clippy::too_many_arguments)]
  51. pub fn compute(
  52. value: u64,
  53. token_id: DrkTokenId,
  54. value_blind: DrkValueBlind,
  55. token_blind: DrkValueBlind,
  56. serial: DrkSerial,
  57. spend_hook: DrkSpendHook,
  58. user_data: DrkUserData,
  59. coin_blind: DrkCoinBlind,
  60. public_key: PublicKey,
  61. ) -> Self {
  62. let value_commit = pedersen_commitment_u64(value, value_blind);
  63. let token_commit = pedersen_commitment_base(token_id, token_blind);
  64. let (pub_x, pub_y) = public_key.xy();
  65. let coin = poseidon_hash::<8>([
  66. pub_x,
  67. pub_y,
  68. DrkValue::from(value),
  69. token_id,
  70. serial,
  71. spend_hook,
  72. user_data,
  73. coin_blind,
  74. ]);
  75. MintRevealedValues { value_commit, token_commit, coin: Coin(coin) }
  76. }
  77. pub fn make_outputs(&self) -> Vec<DrkCircuitField> {
  78. let value_coords = self.value_commit.to_affine().coordinates().unwrap();
  79. let token_coords = self.token_commit.to_affine().coordinates().unwrap();
  80. vec![
  81. self.coin.0,
  82. *value_coords.x(),
  83. *value_coords.y(),
  84. *token_coords.x(),
  85. *token_coords.y(),
  86. ]
  87. }
  88. }
  89. #[allow(clippy::too_many_arguments)]
  90. pub fn create_mint_proof(
  91. pk: &ProvingKey,
  92. value: u64,
  93. token_id: DrkTokenId,
  94. value_blind: DrkValueBlind,
  95. token_blind: DrkValueBlind,
  96. serial: DrkSerial,
  97. spend_hook: DrkSpendHook,
  98. user_data: DrkUserData,
  99. coin_blind: DrkCoinBlind,
  100. public_key: PublicKey,
  101. ) -> Result<(Proof, MintRevealedValues)> {
  102. let revealed = MintRevealedValues::compute(
  103. value,
  104. token_id,
  105. value_blind,
  106. token_blind,
  107. serial,
  108. spend_hook,
  109. user_data,
  110. coin_blind,
  111. public_key,
  112. );
  113. let (pub_x, pub_y) = public_key.xy();
  114. let c = MintContract {
  115. pub_x: Value::known(pub_x),
  116. pub_y: Value::known(pub_y),
  117. value: Value::known(DrkValue::from(value)),
  118. token: Value::known(token_id),
  119. serial: Value::known(serial),
  120. coin_blind: Value::known(coin_blind),
  121. spend_hook: Value::known(spend_hook),
  122. user_data: Value::known(user_data),
  123. value_blind: Value::known(value_blind),
  124. token_blind: Value::known(token_blind),
  125. };
  126. let start = Instant::now();
  127. let public_inputs = revealed.make_outputs();
  128. let proof = Proof::create(pk, &[c], &public_inputs, &mut OsRng)?;
  129. debug!("Prove mint: [{:?}]", start.elapsed());
  130. Ok((proof, revealed))
  131. }
  132. pub fn verify_mint_proof(
  133. vk: &VerifyingKey,
  134. proof: &Proof,
  135. revealed: &MintRevealedValues,
  136. ) -> Result<()> {
  137. let start = Instant::now();
  138. let public_inputs = revealed.make_outputs();
  139. proof.verify(vk, &public_inputs)?;
  140. debug!("Verify mint: [{:?}]", start.elapsed());
  141. Ok(())
  142. }