proof.rs 4.4 KB

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