mint_proof.rs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. use std::time::Instant;
  2. use halo2_gadgets::poseidon::primitives as poseidon;
  3. use halo2_proofs::circuit::Value;
  4. use log::debug;
  5. use pasta_curves::{arithmetic::CurveAffine, group::Curve};
  6. use rand::rngs::OsRng;
  7. use crate::{
  8. crypto::{
  9. coin::Coin,
  10. keypair::PublicKey,
  11. proof::{Proof, ProvingKey, VerifyingKey},
  12. types::{
  13. DrkCircuitField, DrkCoinBlind, DrkSerial, DrkTokenId, DrkValue, DrkValueBlind,
  14. DrkValueCommit,
  15. },
  16. util::{pedersen_commitment_base, pedersen_commitment_u64},
  17. },
  18. util::serial::{SerialDecodable, SerialEncodable},
  19. zk::circuit::mint_contract::MintContract,
  20. Result,
  21. };
  22. #[derive(Debug, Clone, PartialEq, Eq, SerialEncodable, SerialDecodable)]
  23. pub struct MintRevealedValues {
  24. pub value_commit: DrkValueCommit,
  25. pub token_commit: DrkValueCommit,
  26. pub coin: Coin,
  27. }
  28. impl MintRevealedValues {
  29. pub fn compute(
  30. value: u64,
  31. token_id: DrkTokenId,
  32. value_blind: DrkValueBlind,
  33. token_blind: DrkValueBlind,
  34. serial: DrkSerial,
  35. coin_blind: DrkCoinBlind,
  36. public_key: PublicKey,
  37. ) -> Self {
  38. let value_commit = pedersen_commitment_u64(value, value_blind);
  39. let token_commit = pedersen_commitment_base(token_id, token_blind);
  40. let coords = public_key.0.to_affine().coordinates().unwrap();
  41. let messages =
  42. [*coords.x(), *coords.y(), DrkValue::from(value), token_id, serial, coin_blind];
  43. let coin =
  44. poseidon::Hash::<_, poseidon::P128Pow5T3, poseidon::ConstantLength<6>, 3, 2>::init()
  45. .hash(messages);
  46. MintRevealedValues { value_commit, token_commit, coin: Coin(coin) }
  47. }
  48. pub fn make_outputs(&self) -> Vec<DrkCircuitField> {
  49. let value_coords = self.value_commit.to_affine().coordinates().unwrap();
  50. let token_coords = self.token_commit.to_affine().coordinates().unwrap();
  51. vec![
  52. self.coin.0,
  53. *value_coords.x(),
  54. *value_coords.y(),
  55. *token_coords.x(),
  56. *token_coords.y(),
  57. ]
  58. .try_into()
  59. .unwrap()
  60. }
  61. }
  62. #[allow(clippy::too_many_arguments)]
  63. pub fn create_mint_proof(
  64. pk: &ProvingKey,
  65. value: u64,
  66. token_id: DrkTokenId,
  67. value_blind: DrkValueBlind,
  68. token_blind: DrkValueBlind,
  69. serial: DrkSerial,
  70. coin_blind: DrkCoinBlind,
  71. public_key: PublicKey,
  72. ) -> Result<(Proof, MintRevealedValues)> {
  73. let revealed = MintRevealedValues::compute(
  74. value,
  75. token_id,
  76. value_blind,
  77. token_blind,
  78. serial,
  79. coin_blind,
  80. public_key,
  81. );
  82. let coords = public_key.0.to_affine().coordinates().unwrap();
  83. let c = MintContract {
  84. pub_x: Value::known(*coords.x()),
  85. pub_y: Value::known(*coords.y()),
  86. value: Value::known(DrkValue::from(value)),
  87. token: Value::known(token_id),
  88. serial: Value::known(serial),
  89. coin_blind: Value::known(coin_blind),
  90. value_blind: Value::known(value_blind),
  91. token_blind: Value::known(token_blind),
  92. };
  93. let start = Instant::now();
  94. let public_inputs = revealed.make_outputs();
  95. let proof = Proof::create(pk, &[c], &public_inputs, &mut OsRng)?;
  96. debug!("Prove mint: [{:?}]", start.elapsed());
  97. Ok((proof, revealed))
  98. }
  99. pub fn verify_mint_proof(
  100. vk: &VerifyingKey,
  101. proof: &Proof,
  102. revealed: &MintRevealedValues,
  103. ) -> Result<()> {
  104. let start = Instant::now();
  105. let public_inputs = revealed.make_outputs();
  106. proof.verify(vk, &public_inputs)?;
  107. debug!("Verify mint: [{:?}]", start.elapsed());
  108. Ok(())
  109. }