/ example / zk-inclusion-proof.rs
zk-inclusion-proof.rs
  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  
 19  // ../zkas simple.zk
 20  
 21  use darkfi::{
 22      zk::{
 23          proof::{Proof, ProvingKey, VerifyingKey},
 24          vm::{Witness, ZkCircuit},
 25          vm_heap::empty_witnesses,
 26      },
 27      zkas::decoder::ZkBinary,
 28      Result,
 29  };
 30  use darkfi_sdk::{
 31      bridgetree::Hashable,
 32      crypto::{poseidon_hash, MerkleNode, MerkleTree},
 33      pasta::{group::ff::Field, pallas},
 34  };
 35  use darkfi_serial::Encodable;
 36  use halo2_proofs::circuit::Value;
 37  use rand::rngs::OsRng;
 38  
 39  fn main() -> Result<()> {
 40      let mut tree = MerkleTree::new(1);
 41  
 42      // Add 10 random things to the tree
 43      for _ in 0..10 {
 44          let random_leaf = pallas::Base::random(&mut OsRng);
 45          let node = MerkleNode::from(random_leaf);
 46          tree.append(node);
 47      }
 48  
 49      let leaf = pallas::Base::random(&mut OsRng);
 50      let node = MerkleNode::from(leaf);
 51      tree.append(node);
 52  
 53      let leaf_position = tree.mark().unwrap();
 54  
 55      // Add 10 more random things to the tree
 56      for _ in 0..10 {
 57          let random_leaf = pallas::Base::random(&mut OsRng);
 58          let node = MerkleNode::from(random_leaf);
 59          tree.append(node);
 60      }
 61  
 62      // Now begin zk proof API
 63      let bincode = include_bytes!("../proof/inclusion_proof.zk.bin");
 64      let zkbin = ZkBinary::decode(bincode)?;
 65  
 66      // ======
 67      // Prover
 68      // ======
 69      // Bigger k = more rows, but slower circuit
 70      // Number of rows is 2^k
 71      let k = zkbin.k;
 72      println!("k = {}", k);
 73  
 74      // Witness values
 75      let merkle_path = tree.witness(leaf_position, 0).unwrap();
 76      let leaf_position: u64 = leaf_position.into();
 77      let blind = pallas::Base::random(&mut OsRng);
 78  
 79      let prover_witnesses = vec![
 80          Witness::Base(Value::known(leaf)),
 81          Witness::Uint32(Value::known(leaf_position.try_into().unwrap())),
 82          Witness::MerklePath(Value::known(merkle_path.clone().try_into().unwrap())),
 83          Witness::Base(Value::known(blind)),
 84      ];
 85  
 86      // Create the public inputs
 87      let merkle_root = {
 88          let position: u64 = leaf_position.into();
 89          let mut current = MerkleNode::from(leaf);
 90          for (level, sibling) in merkle_path.iter().enumerate() {
 91              let level = level as u8;
 92              current = if position & (1 << level) == 0 {
 93                  MerkleNode::combine(level.into(), &current, sibling)
 94              } else {
 95                  MerkleNode::combine(level.into(), sibling, &current)
 96              };
 97          }
 98          current
 99      };
100  
101      let enc_leaf = poseidon_hash([leaf, blind]);
102      let public_inputs = vec![merkle_root.inner(), enc_leaf];
103  
104      // Create the circuit
105      let circuit = ZkCircuit::new(prover_witnesses, &zkbin.clone());
106  
107      let now = std::time::Instant::now();
108      let proving_key = ProvingKey::build(k, &circuit);
109      println!("ProvingKey built [{} s]", now.elapsed().as_secs_f64());
110      let now = std::time::Instant::now();
111      let proof = Proof::create(&proving_key, &[circuit], &public_inputs, &mut OsRng)?;
112      println!("Proof created [{} s]", now.elapsed().as_secs_f64());
113  
114      // ========
115      // Verifier
116      // ========
117  
118      // Construct empty witnesses
119      let verifier_witnesses = empty_witnesses(&zkbin)?;
120  
121      // Create the circuit
122      let circuit = ZkCircuit::new(verifier_witnesses, &zkbin);
123  
124      let now = std::time::Instant::now();
125      let verifying_key = VerifyingKey::build(k, &circuit);
126      println!("VerifyingKey built [{} s]", now.elapsed().as_secs_f64());
127      let now = std::time::Instant::now();
128      proof.verify(&verifying_key, &public_inputs)?;
129      println!("proof verify [{} s]", now.elapsed().as_secs_f64());
130  
131      let mut data = vec![];
132      proof.encode(&mut data)?;
133      println!("proof size: {}", data.len());
134  
135      Ok(())
136  }