main.rs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2024 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::{
  19. collections::BTreeMap,
  20. time::{Instant, UNIX_EPOCH},
  21. };
  22. use darkfi::{
  23. zk::{empty_witnesses, halo2::Value, Proof, ProvingKey, VerifyingKey, Witness, ZkCircuit},
  24. zkas::ZkBinary,
  25. };
  26. use darkfi_sdk::{
  27. bridgetree::Position,
  28. crypto::{pasta_prelude::Field, poseidon_hash, MerkleNode, MerkleTree},
  29. pasta::{group::ff::FromUniformBytes, pallas},
  30. };
  31. use rand::rngs::OsRng;
  32. struct Account {
  33. identity_nullifier: pallas::Base,
  34. identity_trapdoor: pallas::Base,
  35. identity_leaf_pos: Position,
  36. msgid: pallas::Base,
  37. }
  38. impl Account {
  39. fn register(
  40. membership_tree: &mut MerkleTree,
  41. membership_map: &mut BTreeMap<Position, pallas::Base>,
  42. ) -> Self {
  43. let identity_nullifier = pallas::Base::random(&mut OsRng);
  44. let identity_trapdoor = pallas::Base::random(&mut OsRng);
  45. let identity_secret_hash = poseidon_hash([identity_nullifier, identity_trapdoor]);
  46. let identity_commitment = poseidon_hash([identity_secret_hash]);
  47. membership_tree.append(MerkleNode::from(identity_commitment));
  48. let identity_leaf_pos = membership_tree.mark().unwrap();
  49. membership_map.insert(identity_leaf_pos, identity_commitment);
  50. Self { identity_nullifier, identity_trapdoor, identity_leaf_pos }
  51. }
  52. }
  53. /// Hash message modulo Fp
  54. /// In DarkIRC/eventgraph this could be the event ID
  55. fn hash_message(msg: &str) -> pallas::Base {
  56. let message_hash = blake3::hash(msg.as_bytes());
  57. let mut buf = [0u8; 64];
  58. buf[..blake3::OUT_LEN].copy_from_slice(message_hash.as_bytes());
  59. pallas::Base::from_uniform_bytes(&buf)
  60. }
  61. fn main() {
  62. // There exists a Merkle tree of identity commitments that serves
  63. // as the user registry.
  64. let mut membership_tree = MerkleTree::new(1);
  65. // Since bridgetree is append-only, we'll maintain a BTreeMap of all the
  66. // identity commitments in their indexes and whenever some idenity is banned
  67. // we'll zero out that leaf and rebuild the bridgetree from the BTreeMap.
  68. let mut membership_map = BTreeMap::new();
  69. // The global message limit per-account per-epoch
  70. let message_limit = pallas::Base::from(3);
  71. // Per-app identifier
  72. let rln_identifier = pallas::Base::from(42);
  73. // Current epoch
  74. let epoch = pallas::Base::from(UNIX_EPOCH.elapsed().unwrap().as_secs() as u64);
  75. // Register three accounts
  76. let account0 = Account::register(&mut membership_tree, &mut membership_map);
  77. let account0_msgid = pallas::Base::from(0);
  78. /*
  79. let account1 = Account::register(&mut membership_tree, &mut membership_map);
  80. let account1_msgid = pallas::Base::from(0);
  81. let account2 = Account::register(&mut membership_tree, &mut membership_map);
  82. let account2_msgid = pallas::Base::from(0);
  83. */
  84. // ==========
  85. // Signalling
  86. // ==========
  87. let signal_zkbin = include_bytes!("../signal.zk.bin");
  88. let signal_zkbin = ZkBinary::decode(signal_zkbin).unwrap();
  89. let signal_empty_circuit =
  90. ZkCircuit::new(empty_witnesses(&signal_zkbin).unwrap(), &signal_zkbin);
  91. print!("[Signal] Building Proving key... ");
  92. let now = Instant::now();
  93. let signal_pk = ProvingKey::build(signal_zkbin.k, &signal_empty_circuit);
  94. println!("[{:?}]", now.elapsed());
  95. print!("[Signal] Building Verifying key... ");
  96. let now = Instant::now();
  97. let signal_vk = VerifyingKey::build(signal_zkbin.k, &signal_empty_circuit);
  98. println!("[{:?}]", now.elapsed());
  99. // =========================
  100. // Account 0 sends a message
  101. // =========================
  102. // 1. Construct share:
  103. let external_nullifier = poseidon_hash([epoch, rln_identifier]);
  104. let a_0 = poseidon_hash([account0.identity_nullifier, account0.identity_trapdoor]);
  105. let a_1 = poseidon_hash([a_0, external_nullifier, account0_msgid]);
  106. let internal_nullifier = poseidon_hash([a_1]);
  107. let x = hash_message("hello i wanna spam");
  108. let y = a_0 + x * a_1;
  109. // 2. Create Merkle proof:
  110. let identity_root = membership_tree.root(0).unwrap();
  111. let identity_path = membership_tree.witness(account0.identity_leaf_pos, 0).unwrap();
  112. // 3. Create ZK proof:
  113. let witnesses = vec![
  114. Witness::Base(Value::known(account0.identity_nullifier)),
  115. Witness::Base(Value::known(account0.identity_trapdoor)),
  116. Witness::MerklePath(Value::known(identity_path.clone().try_into().unwrap())),
  117. Witness::Uint32(Value::known(u64::from(account0.identity_leaf_pos).try_into().unwrap())),
  118. Witness::Base(Value::known(x)),
  119. Witness::Base(Value::known(account0_msgid)),
  120. Witness::Base(Value::known(message_limit)),
  121. Witness::Base(Value::known(epoch)),
  122. Witness::Base(Value::known(rln_identifier)),
  123. ];
  124. let public_inputs = vec![
  125. message_limit,
  126. epoch,
  127. external_nullifier,
  128. internal_nullifier,
  129. x,
  130. y,
  131. identity_root.inner(),
  132. ];
  133. print!("[Signal] Creating ZK proof for 0:0...");
  134. let now = Instant::now();
  135. let signal_circuit = ZkCircuit::new(witnesses, &signal_zkbin);
  136. let proof = Proof::create(&signal_pk, &[signal_circuit], &public_inputs, &mut OsRng).unwrap();
  137. println!("[{:?}]", now.elapsed());
  138. // ============
  139. // Verification
  140. // ============
  141. print!("[Signal] Verifying ZK proof... ");
  142. let now = Instant::now();
  143. assert!(proof.verify(&signal_vk, &public_inputs).is_ok());
  144. println!("[{:?}]", now.elapsed());
  145. }