proof.rs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. use darkfi_serial::{SerialDecodable, SerialEncodable};
  2. use halo2_proofs::{
  3. plonk,
  4. plonk::{Circuit, SingleVerifier},
  5. poly::commitment::Params,
  6. transcript::{Blake2bRead, Blake2bWrite},
  7. };
  8. use pasta_curves::vesta;
  9. use rand::RngCore;
  10. use crate::crypto::types::DrkCircuitField;
  11. // TODO: this API needs rework. It's not very good.
  12. // keygen_pk() takes a VerifyingKey by value,
  13. // yet ProvingKey also provides get_vk() -> &VerifyingKey
  14. //
  15. // Maybe we should just use the native halo2 types instead of wrapping them.
  16. // We can avoid double creating the vk when we call VerifyingKey::build(), ProvingKey::build()
  17. #[derive(Clone, Debug)]
  18. pub struct VerifyingKey {
  19. pub params: Params<vesta::Affine>,
  20. pub vk: plonk::VerifyingKey<vesta::Affine>,
  21. }
  22. impl VerifyingKey {
  23. pub fn build(k: u32, c: &impl Circuit<DrkCircuitField>) -> Self {
  24. let params = Params::new(k);
  25. let vk = plonk::keygen_vk(&params, c).unwrap();
  26. VerifyingKey { params, vk }
  27. }
  28. }
  29. #[derive(Clone, Debug)]
  30. pub struct ProvingKey {
  31. pub params: Params<vesta::Affine>,
  32. pub pk: plonk::ProvingKey<vesta::Affine>,
  33. }
  34. impl ProvingKey {
  35. pub fn build(k: u32, c: &impl Circuit<DrkCircuitField>) -> Self {
  36. let params = Params::new(k);
  37. let vk = plonk::keygen_vk(&params, c).unwrap();
  38. let pk = plonk::keygen_pk(&params, vk, c).unwrap();
  39. ProvingKey { params, pk }
  40. }
  41. }
  42. #[derive(Clone, Default, Debug, PartialEq, Eq, SerialEncodable, SerialDecodable)]
  43. pub struct Proof(Vec<u8>);
  44. impl AsRef<[u8]> for Proof {
  45. fn as_ref(&self) -> &[u8] {
  46. &self.0
  47. }
  48. }
  49. impl Proof {
  50. pub fn create(
  51. pk: &ProvingKey,
  52. circuits: &[impl Circuit<DrkCircuitField>],
  53. instances: &[DrkCircuitField],
  54. mut rng: impl RngCore,
  55. ) -> std::result::Result<Self, plonk::Error> {
  56. let mut transcript = Blake2bWrite::<_, vesta::Affine, _>::init(vec![]);
  57. plonk::create_proof(
  58. &pk.params,
  59. &pk.pk,
  60. circuits,
  61. &[&[instances]],
  62. &mut rng,
  63. &mut transcript,
  64. )?;
  65. Ok(Proof(transcript.finalize()))
  66. }
  67. pub fn verify(
  68. &self,
  69. vk: &VerifyingKey,
  70. instances: &[DrkCircuitField],
  71. ) -> std::result::Result<(), plonk::Error> {
  72. let strategy = SingleVerifier::new(&vk.params);
  73. let mut transcript = Blake2bRead::init(&self.0[..]);
  74. plonk::verify_proof(&vk.params, &vk.vk, strategy, &[&[instances]], &mut transcript)
  75. }
  76. pub fn new(bytes: Vec<u8>) -> Self {
  77. Proof(bytes)
  78. }
  79. }
  80. #[cfg(test)]
  81. mod tests {
  82. use super::*;
  83. use crate::{
  84. crypto::{
  85. keypair::PublicKey,
  86. mint_proof::create_mint_proof,
  87. types::{
  88. DrkCoinBlind, DrkSerial, DrkSpendHook, DrkTokenId, DrkUserData, DrkValueBlind,
  89. },
  90. },
  91. zk::circuit::MintContract,
  92. Result,
  93. };
  94. use darkfi_serial::{Decodable, Encodable};
  95. use pasta_curves::group::ff::Field;
  96. use rand::rngs::OsRng;
  97. #[test]
  98. fn test_proof_serialization() -> Result<()> {
  99. let value = 110_u64;
  100. let token_id = DrkTokenId::random(&mut OsRng);
  101. let value_blind = DrkValueBlind::random(&mut OsRng);
  102. let token_blind = DrkValueBlind::random(&mut OsRng);
  103. let serial = DrkSerial::random(&mut OsRng);
  104. let spend_hook = DrkSpendHook::random(&mut OsRng);
  105. let user_data = DrkUserData::random(&mut OsRng);
  106. let coin_blind = DrkCoinBlind::random(&mut OsRng);
  107. let public_key = PublicKey::random(&mut OsRng);
  108. let pk = ProvingKey::build(11, &MintContract::default());
  109. let (proof, _) = create_mint_proof(
  110. &pk,
  111. value,
  112. token_id,
  113. value_blind,
  114. token_blind,
  115. serial,
  116. spend_hook,
  117. user_data,
  118. coin_blind,
  119. public_key,
  120. )?;
  121. let mut buf = vec![];
  122. proof.encode(&mut buf)?;
  123. let deserialized_proof: Proof = Decodable::decode(&mut buf.as_slice())?;
  124. assert_eq!(proof.as_ref(), deserialized_proof.as_ref());
  125. Ok(())
  126. }
  127. }