rln.rs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  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. //! <https://darkrenaissance.github.io/darkfi/crypto/rln.html>
  19. use darkfi::{
  20. zk::{empty_witnesses, halo2::Field, ProvingKey, VerifyingKey, ZkCircuit},
  21. zkas::ZkBinary,
  22. Result,
  23. };
  24. use darkfi_sdk::{crypto::MerkleTree, pasta::pallas};
  25. use darkfi_serial::serialize_async;
  26. use log::info;
  27. const RLN_IDENTIFIER: pallas::Base = pallas::Base::from_raw([0, 0, 42, 42]);
  28. const IDENTITY_DERIVATION_PATH: pallas::Base = pallas::Base::from_raw([0, 0, 42, 11]);
  29. const NULLIFIER_DERIVATION_PATH: pallas::Base = pallas::Base::from_raw([0, 0, 42, 12]);
  30. /// Rate-Limit-Nullifiers
  31. ///
  32. /// This mechanism is used for spam protection on the IRC network.
  33. pub struct Rln {
  34. /// DB holding identity commitments and the membership Merkle tree
  35. /// The scheme is `(k=identity_commitment, v=leaf_position)`
  36. identities: sled::Tree,
  37. /// DB holding identity roots
  38. identity_roots: sled::Tree,
  39. /// DB holding banned roots
  40. banned_roots: sled::Tree,
  41. /// Proving key for the signalling circuit
  42. signal_pk: ProvingKey,
  43. /// Verifying key for the signalling circuit
  44. signal_vk: VerifyingKey,
  45. /// Proving key for the slashing circuit
  46. slash_pk: ProvingKey,
  47. /// Verifying key for the slashing circuit
  48. slash_vk: VerifyingKey,
  49. }
  50. impl Rln {
  51. /// Create a new Rln instance
  52. pub async fn new(sled_db: &sled::Db) -> Result<Self> {
  53. let identities = sled_db.open_tree("identities")?;
  54. let identity_roots = sled_db.open_tree("identity_roots")?;
  55. let banned_roots = sled_db.open_tree("banned_roots")?;
  56. if !identities.contains_key(b"identity_tree")? {
  57. info!("Creating RLN membership tree");
  58. let membership_tree = MerkleTree::new(1);
  59. identities.insert(b"identity_tree", serialize_async(&membership_tree).await)?;
  60. }
  61. let signal_zkbin = include_bytes!("../proof/signal.zk.bin");
  62. let slash_zkbin = include_bytes!("../proof/slash.zk.bin");
  63. info!("Building RLN signal proving key");
  64. let signal_zkbin = ZkBinary::decode(signal_zkbin).unwrap();
  65. let signal_circuit = ZkCircuit::new(empty_witnesses(&signal_zkbin)?, &signal_zkbin);
  66. let signal_pk = ProvingKey::build(signal_zkbin.k, &signal_circuit);
  67. info!("Building RLN signal verifying key");
  68. let signal_vk = VerifyingKey::build(signal_zkbin.k, &signal_circuit);
  69. info!("Building RLN slash proving key");
  70. let slash_zkbin = ZkBinary::decode(slash_zkbin).unwrap();
  71. let slash_circuit = ZkCircuit::new(empty_witnesses(&slash_zkbin)?, &slash_zkbin);
  72. let slash_pk = ProvingKey::build(slash_zkbin.k, &slash_circuit);
  73. info!("Building RLN slash verifying key");
  74. let slash_vk = VerifyingKey::build(slash_zkbin.k, &slash_circuit);
  75. Ok(Self {
  76. identities,
  77. identity_roots,
  78. banned_roots,
  79. signal_pk,
  80. signal_vk,
  81. slash_pk,
  82. slash_vk,
  83. })
  84. }
  85. /// Recover a secret from given secret shares
  86. pub fn sss_recover(shares: &[(pallas::Base, pallas::Base)]) -> pallas::Base {
  87. let mut secret = pallas::Base::zero();
  88. for (j, share_j) in shares.iter().enumerate() {
  89. let mut prod = pallas::Base::one();
  90. for (i, share_i) in shares.iter().enumerate() {
  91. if i != j {
  92. prod *= share_i.0 * (share_i.0 - share_j.0).invert().unwrap();
  93. }
  94. }
  95. prod *= share_j.1;
  96. secret += prod;
  97. }
  98. secret
  99. }
  100. }