client.rs 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2026 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::{HashMap, HashSet, VecDeque},
  20. io::Cursor,
  21. slice,
  22. sync::{
  23. atomic::{AtomicBool, AtomicUsize, Ordering::SeqCst},
  24. Arc,
  25. },
  26. };
  27. use darkfi::{
  28. event_graph::{proto::EventPut, Event, NULL_ID},
  29. system::Subscription,
  30. zk::{empty_witnesses, Proof, ProvingKey, ZkCircuit},
  31. zkas::ZkBinary,
  32. Error, Result,
  33. };
  34. use darkfi_sdk::{
  35. bridgetree::Position,
  36. crypto::{pasta_prelude::PrimeField, poseidon_hash, MerkleTree},
  37. pasta::pallas,
  38. };
  39. use darkfi_serial::{deserialize_async, serialize_async};
  40. use futures::FutureExt;
  41. use sled_overlay::sled;
  42. use smol::{
  43. io::{self, AsyncBufReadExt, AsyncWriteExt, BufReader},
  44. lock::{OnceCell, RwLock},
  45. net::SocketAddr,
  46. prelude::{AsyncRead, AsyncWrite},
  47. };
  48. use tracing::{debug, error, info, warn};
  49. use super::{
  50. server::{IrcServer, MAX_MSG_LEN},
  51. Msg, NickServ, OldPrivmsg, SERVER_NAME,
  52. };
  53. use crate::crypto::rln::{
  54. closest_epoch, hash_event, RlnIdentity, RLN2_SIGNAL_ZKBIN, RLN_APP_IDENTIFIER,
  55. };
  56. const PENALTY_LIMIT: usize = 5;
  57. /// Reply types, we can either send server replies, or client replies.
  58. pub enum ReplyType {
  59. /// Server reply, we have to use numerics
  60. Server((u16, String)),
  61. /// Client reply, message from someone to some{one,where}
  62. Client((String, String)),
  63. /// Pong reply, we just use server origin
  64. Pong(String),
  65. /// CAP reply
  66. Cap(String),
  67. /// NOTICE reply (from, to, what)
  68. Notice((String, String, String)),
  69. }
  70. /// Stateful IRC client handler, used for each client connection
  71. pub struct Client {
  72. /// Pointer to parent `IrcServer`
  73. pub server: Arc<IrcServer>,
  74. /// Subscription for incoming events
  75. pub incoming: Subscription<Event>,
  76. /// Client socket addr
  77. pub addr: SocketAddr,
  78. /// ID of the last sent event
  79. pub last_sent: RwLock<blake3::Hash>,
  80. /// Active (joined) channels for this client
  81. pub channels: RwLock<HashSet<String>>,
  82. /// Penalty counter, when limit is reached, disconnect client
  83. pub penalty: AtomicUsize,
  84. /// Registration marker
  85. pub registered: AtomicBool,
  86. /// Registration pause marker
  87. pub reg_paused: AtomicBool,
  88. /// CAP END marker
  89. pub is_cap_end: AtomicBool,
  90. /// Password setup marker
  91. pub is_pass_set: AtomicBool,
  92. /// Client username
  93. pub username: Arc<RwLock<String>>,
  94. /// Client nickname
  95. pub nickname: Arc<RwLock<String>>,
  96. /// Client realname
  97. pub realname: RwLock<String>,
  98. /// Client caps
  99. pub caps: RwLock<HashMap<String, bool>>,
  100. /// Set of seen messages for the user
  101. /// TODO: It grows indefinitely, needs to be pruned.
  102. pub seen: OnceCell<sled::Tree>,
  103. /// NickServ instance
  104. pub nickserv: Arc<NickServ>,
  105. }
  106. impl Client {
  107. /// Instantiate a new Client.
  108. pub async fn new(
  109. server: Arc<IrcServer>,
  110. incoming: Subscription<Event>,
  111. addr: SocketAddr,
  112. ) -> Result<Self> {
  113. let caps =
  114. HashMap::from([("no-history".to_string(), false), ("no-autojoin".to_string(), false)]);
  115. let username = Arc::new(RwLock::new(String::from("*")));
  116. let nickname = Arc::new(RwLock::new(String::from("*")));
  117. Ok(Self {
  118. server: server.clone(),
  119. incoming,
  120. addr,
  121. last_sent: RwLock::new(NULL_ID),
  122. channels: RwLock::new(HashSet::new()),
  123. penalty: AtomicUsize::new(0),
  124. registered: AtomicBool::new(false),
  125. reg_paused: AtomicBool::new(false),
  126. is_cap_end: AtomicBool::new(false),
  127. is_pass_set: AtomicBool::new(false),
  128. username: username.clone(),
  129. nickname: nickname.clone(),
  130. realname: RwLock::new(String::from("*")),
  131. caps: RwLock::new(caps),
  132. seen: OnceCell::new(),
  133. nickserv: Arc::new(
  134. NickServ::new(username.clone(), nickname.clone(), server.clone()).await?,
  135. ),
  136. })
  137. }
  138. /// This function handles a single IRC client. We listen to messages from the
  139. /// IRC client and relay them to the network, and we also get notified of
  140. /// incoming messages and relay them to the IRC client. The notifications come
  141. /// from events being inserted into the Event Graph.
  142. pub async fn multiplex_connection<S>(&self, stream: S) -> Result<()>
  143. where
  144. S: AsyncRead + AsyncWrite + Unpin + Send + 'static,
  145. {
  146. let (reader, mut writer) = io::split(stream);
  147. let mut reader = BufReader::new(reader);
  148. // Our buffer for the client line
  149. let mut line = String::new();
  150. let mut args_queue: VecDeque<_> = VecDeque::new();
  151. loop {
  152. futures::select! {
  153. // Process message from the IRC client
  154. r = reader.read_line(&mut line).fuse() => {
  155. // If client closed unexpectedly, we disconnect.
  156. if let Ok(0) = r {
  157. error!("[IRC CLIENT] Read failed for {}: Client disconnected", self.addr);
  158. self.incoming.unsubscribe().await;
  159. return Err(Error::ChannelStopped)
  160. }
  161. // If something failed during reading, we disconnect.
  162. if let Err(e) = r {
  163. error!("[IRC CLIENT] Read failed for {}: {e}", self.addr);
  164. self.incoming.unsubscribe().await;
  165. return Err(Error::ChannelStopped)
  166. }
  167. // If the penalty limit is reached, disconnect the client.
  168. if self.penalty.load(SeqCst) == PENALTY_LIMIT {
  169. self.incoming.unsubscribe().await;
  170. return Err(Error::ChannelStopped)
  171. }
  172. // We'll be strict here and disconnect the client
  173. // in case line processing failed in any way.
  174. match self.process_client_line(&line, &mut writer, &mut args_queue).await {
  175. // If we got an event back, we should broadcast it.
  176. // This means we add it to our DAG, and the DAG will
  177. // handle the rest of the propagation.
  178. Ok(Some(events)) => {
  179. for event in events {
  180. // Update the last sent event.
  181. let event_id = event.header.id();
  182. *self.last_sent.write().await = event_id;
  183. let current_genesis = self.server.darkirc.event_graph.current_genesis.read().await;
  184. let dag_name = current_genesis.header.timestamp.to_string();
  185. // If it fails for some reason, for now, we just note it and pass.
  186. if let Err(e) = self.server.darkirc.event_graph.header_dag_insert(vec![event.header.clone()], &dag_name).await {
  187. error!("[IRC CLIENT] Failed inserting new header to Header DAG: {}", e);
  188. }
  189. if let Err(e) = self.server.darkirc.event_graph.dag_insert(slice::from_ref(&event), &dag_name).await {
  190. error!("[IRC CLIENT] Failed inserting new event to DAG: {e}");
  191. } else {
  192. // We sent this, so it should be considered seen.
  193. if let Err(e) = self.mark_seen(&event_id).await {
  194. error!("[IRC CLIENT] (multiplex_connection) self.mark_seen({event_id}) failed: {e}");
  195. return Err(e)
  196. }
  197. // If we have a RLN identity, now we'll build a ZK proof.
  198. // Also I really want GOTO in Rust... Fags.
  199. if let Some(mut rln_identity) = *self.server.rln_identity.write().await {
  200. // If the current epoch is different, we can reset the message counter
  201. if rln_identity.last_epoch != closest_epoch(event.header.timestamp) {
  202. rln_identity.last_epoch = closest_epoch(event.header.timestamp);
  203. rln_identity.message_id = 0;
  204. }
  205. rln_identity.message_id += 1;
  206. let (_proof, _public_inputs) = match self.create_rln_signal_proof(&rln_identity, &event).await {
  207. Ok(v) => v,
  208. Err(e) => {
  209. // TODO: Send a message to the IRC client telling that sending went wrong
  210. error!("[IRC CLIENT] Failed creating RLN signal proof: {e}");
  211. // Just use an empty "proof"
  212. (Proof::new(vec![]), vec![])
  213. }
  214. };
  215. self.server.darkirc.p2p.broadcast(&EventPut(event)).await;
  216. } else {
  217. // Broadcast it
  218. self.server.darkirc.p2p.broadcast(&EventPut(event)).await;
  219. }
  220. }
  221. }
  222. }
  223. // If we got nothing, we just pass.
  224. Ok(None) => {}
  225. // If we got an error, we disconnect the client.
  226. Err(e) => {
  227. self.incoming.unsubscribe().await;
  228. return Err(e)
  229. }
  230. }
  231. // Clear the line buffer
  232. line = String::new();
  233. }
  234. // Process message from the network. These should only be PRIVMSG.
  235. //
  236. // N.b. handling "historical messages", i.e. outstanding messages
  237. // which have occured when darkirc is offline are handled in
  238. // <file:./command.rs::async fn get_history(&self, channels: &HashSet<String>) -> Result<Vec<ReplyType>> {>
  239. // for which the logic for delivery should be kept in sync
  240. r = self.incoming.receive().fuse() => {
  241. // We will skip this if it's our own message.
  242. let event_id = r.header.id();
  243. if *self.last_sent.read().await == event_id {
  244. continue
  245. }
  246. // If this event was seen, skip it
  247. match self.is_seen(&event_id).await {
  248. Ok(true) => continue,
  249. Ok(false) => {},
  250. Err(e) => {
  251. error!("[IRC CLIENT] (multiplex_connection) self.is_seen({event_id}) failed: {e}");
  252. return Err(e)
  253. }
  254. }
  255. // If the Event contains an appended blob of data, try to check if it's
  256. // a RLN Signal proof and verify it.
  257. //if false {
  258. let mut verification_failed = false;
  259. #[allow(clippy::never_loop)]
  260. loop {
  261. let (event, blob) = (r.clone(), vec![0,1,2]);
  262. let (proof, public_inputs): (Proof, Vec<pallas::Base>) = match deserialize_async(&blob).await {
  263. Ok(v) => v,
  264. Err(_) => {
  265. // TODO: FIXME: This logic should be better written.
  266. // Right now we don't enforce RLN so we can just fall-through.
  267. //error!("[IRC CLIENT] Failed deserializing event ephemeral data: {e}");
  268. break
  269. }
  270. };
  271. if public_inputs.len() != 2 {
  272. error!("[IRC CLIENT] Received event has the wrong number of public inputs");
  273. verification_failed = true;
  274. break
  275. }
  276. info!("[IRC CLIENT] Verifying incoming Event RLN proof");
  277. if self.verify_rln_signal_proof(
  278. &event,
  279. proof,
  280. [public_inputs[0], public_inputs[1]],
  281. ).await.is_err() {
  282. verification_failed = true;
  283. break
  284. }
  285. // TODO: Store for secret shares recovery
  286. info!("[IRC CLIENT] RLN verification successful");
  287. break
  288. }
  289. if verification_failed {
  290. error!("[IRC CLIENT] Incoming Event proof verification failed");
  291. continue
  292. }
  293. // Try to deserialize the `Event`'s content into a `Privmsg`
  294. let mut privmsg = match Msg::deserialize(r.content()).await {
  295. Ok(Msg::V1(old_msg)) => old_msg.into_new(),
  296. Ok(Msg::V2(new_msg)) => new_msg,
  297. Err(e) => {
  298. error!("[IRC CLIENT] Failed deserializing incoming Privmsg event: {e}");
  299. continue
  300. }
  301. };
  302. // If successful, potentially decrypt it:
  303. self.server.try_decrypt(&mut privmsg, self.nickname.read().await.as_ref()).await;
  304. // We should skip any attempts to contact services from the network.
  305. if ["nickserv", "chanserv"].contains(&privmsg.nick.to_lowercase().as_str()) {
  306. continue
  307. }
  308. // If the privmsg is not intented for any of the given
  309. // channels or contacts, ignore it
  310. // otherwise add it as a reply and mark it as seen
  311. // in the seen_events tree.
  312. let channels = self.channels.read().await;
  313. let contacts = self.server.contacts.read().await;
  314. if !channels.contains(&privmsg.channel) &&
  315. !contacts.contains_key(&privmsg.channel)
  316. {
  317. continue
  318. }
  319. // Add the nickname to the list of nicks on the channel, if it's a channel.
  320. let mut chans_lock = self.server.channels.write().await;
  321. if let Some(chan) = chans_lock.get_mut(&privmsg.channel) {
  322. chan.nicks.insert(privmsg.nick.clone());
  323. }
  324. drop(chans_lock);
  325. // Handle message lines individually
  326. for line in privmsg.msg.lines() {
  327. // Skip empty lines
  328. if line.is_empty() {
  329. continue
  330. }
  331. // Format the message
  332. let msg = format!("PRIVMSG {} :{line}", privmsg.channel);
  333. // Send it to the client
  334. let reply = ReplyType::Client((privmsg.nick.clone(), msg));
  335. if let Err(e) = self.reply(&mut writer, &reply).await {
  336. error!("[IRC CLIENT] Failed writing PRIVMSG to client: {e}");
  337. continue
  338. }
  339. }
  340. // Mark the message as seen for this USER
  341. if let Err(e) = self.mark_seen(&event_id).await {
  342. error!("[IRC CLIENT] (multiplex_connection) self.mark_seen({event_id}) failed: {e}");
  343. return Err(e)
  344. }
  345. }
  346. }
  347. }
  348. }
  349. /// Send a reply to the IRC client. Matches on the reply type.
  350. async fn reply<W>(&self, writer: &mut W, reply: &ReplyType) -> Result<()>
  351. where
  352. W: AsyncWrite + Unpin,
  353. {
  354. let r = match reply {
  355. ReplyType::Server((rpl, msg)) => format!(":{SERVER_NAME} {rpl:03} {msg}"),
  356. ReplyType::Client((nick, msg)) => format!(":{nick}!~anon@darkirc {msg}"),
  357. ReplyType::Pong(origin) => format!(":{SERVER_NAME} PONG :{origin}"),
  358. ReplyType::Cap(msg) => format!(":{SERVER_NAME} {msg}"),
  359. ReplyType::Notice((src, dst, msg)) => {
  360. format!(":{src}!~anon@darkirc NOTICE {dst} :{msg}")
  361. }
  362. };
  363. debug!("[{}] <-- {r}", self.addr);
  364. writer.write(r.as_bytes()).await?;
  365. writer.write(b"\r\n").await?;
  366. writer.flush().await?;
  367. Ok(())
  368. }
  369. /// Handle the incoming line given sent by the IRC client
  370. async fn process_client_line<W>(
  371. &self,
  372. line: &str,
  373. writer: &mut W,
  374. args_queue: &mut VecDeque<OldPrivmsg>,
  375. ) -> Result<Option<Vec<Event>>>
  376. where
  377. W: AsyncWrite + Unpin,
  378. {
  379. if line.trim().is_empty() {
  380. // Silently ignore empty commands
  381. return Ok(None)
  382. }
  383. let mut line = line.to_string();
  384. // Remove CRLF
  385. if line.ends_with("\r\n") {
  386. line.pop();
  387. line.pop();
  388. } else if line.ends_with("\n") {
  389. line.pop();
  390. } else {
  391. return Err(Error::ParseFailed("Line doesn't end with CR/LF"))
  392. }
  393. // Prefix the message part of PRIVMSG with ':' if is not already.
  394. // Or realname part of USER command.
  395. if let Some(index) = match line.split_whitespace().next() {
  396. Some("PRIVMSG") => Some(2),
  397. Some("USER") => Some(4),
  398. _ => None,
  399. } {
  400. let mut words: Vec<String> =
  401. line.splitn(index + 1, char::is_whitespace).map(|s| s.to_string()).collect();
  402. if words.len() > index && !words[index].starts_with(':') {
  403. words[index] = format!(":{}", words[index]);
  404. }
  405. line = words.join(" ");
  406. }
  407. // Parse the line
  408. let mut tokens = line.split_ascii_whitespace();
  409. // Commands can begin with :garbage, but we will reject clients
  410. // doing that for now to keep the protocol simple and focused.
  411. let cmd = tokens.next().ok_or(Error::ParseFailed("Invalid command line"))?;
  412. let args = line.replacen(cmd, "", 1);
  413. let cmd = cmd.to_uppercase();
  414. debug!("[{}] --> {cmd}{args}", self.addr);
  415. // Handle the command. These implementations are in `command.rs`.
  416. let replies: Vec<ReplyType> = match cmd.as_str() {
  417. "ADMIN" => self.handle_cmd_admin(&args).await?,
  418. "CAP" => self.handle_cmd_cap(&args).await?,
  419. "INFO" => self.handle_cmd_info(&args).await?,
  420. "JOIN" => self.handle_cmd_join(&args, true).await?,
  421. "LIST" => self.handle_cmd_list(&args).await?,
  422. "MODE" => self.handle_cmd_mode(&args).await?,
  423. "MOTD" => self.handle_cmd_motd(&args).await?,
  424. "NAMES" => self.handle_cmd_names(&args).await?,
  425. "NICK" => self.handle_cmd_nick(&args).await?,
  426. "PART" => self.handle_cmd_part(&args).await?,
  427. "PASS" => self.handle_cmd_pass(&args).await?,
  428. "PING" => self.handle_cmd_ping(&args).await?,
  429. "PRIVMSG" => self.handle_cmd_privmsg(&args).await?,
  430. "REHASH" => self.handle_cmd_rehash(&args).await?,
  431. "TOPIC" => self.handle_cmd_topic(&args).await?,
  432. "USER" => self.handle_cmd_user(&args).await?,
  433. "VERSION" => self.handle_cmd_version(&args).await?,
  434. "QUIT" => return Err(Error::ChannelStopped),
  435. _ => {
  436. warn!("[IRC CLIENT] Unimplemented \"{cmd}\" command");
  437. vec![]
  438. }
  439. };
  440. // Depending on the reply type, we send according messages.
  441. for reply in replies.iter() {
  442. self.reply(writer, reply).await?;
  443. }
  444. // If the command was a PRIVMSG the client sent, we need to encrypt it and
  445. // create an Event to broadcast and return it from this function. So let's try.
  446. // We also do not allow sending unencrypted DMs. In that case, we send a notice
  447. // to the client to inform them that the feature is not enabled.
  448. // NOTE: This is not the most performant way to do this, probably not even
  449. // TODO: the best place to do it. Patches welcome. It's also a bit fragile
  450. // since we assume that `handle_cmd_privmsg()` won't return any replies.
  451. if cmd.as_str() == "PRIVMSG" && replies.is_empty() {
  452. // If the DAG is not synced yet, queue client lines
  453. // Once synced, send queued lines and continue as normal
  454. if !*self.server.darkirc.event_graph.synced.read().await {
  455. debug!("DAG is still syncing, queuing and skipping...");
  456. let privmsg = self.args_to_privmsg(args).await;
  457. args_queue.push_back(privmsg);
  458. return Ok(None)
  459. }
  460. // Check if we have queued PRIVMSGs, if we do send all of them first.
  461. let mut pending_events = vec![];
  462. if !args_queue.is_empty() {
  463. for _ in 0..args_queue.len() {
  464. let privmsg = args_queue.pop_front().unwrap();
  465. pending_events.push(self.privmsg_to_event(privmsg).await);
  466. }
  467. return Ok(Some(pending_events))
  468. }
  469. // If queue is empty, create an event and return it
  470. let privmsg = self.args_to_privmsg(args).await;
  471. let event = self.privmsg_to_event(privmsg).await;
  472. return Ok(Some(vec![event]))
  473. }
  474. Ok(None)
  475. }
  476. // Internal helper function that creates a PRIVMSG from IRC client arguments
  477. async fn args_to_privmsg(&self, args: String) -> OldPrivmsg {
  478. let nick = self.nickname.read().await.to_string();
  479. let channel = args.split_ascii_whitespace().next().unwrap().to_string();
  480. let msg_offset = args.find(':').unwrap() + 1;
  481. let (_, msg) = args.split_at(msg_offset);
  482. // Truncate messages longer than MAX_MSG_LEN
  483. let msg = if msg.len() > MAX_MSG_LEN { msg.split_at(MAX_MSG_LEN).0 } else { msg };
  484. OldPrivmsg { channel, nick, msg: msg.to_string() }
  485. }
  486. // Internal helper function that creates an Event from PRIVMSG arguments
  487. async fn privmsg_to_event(&self, mut privmsg: OldPrivmsg) -> Event {
  488. // Encrypt the Privmsg if an encryption method is available.
  489. self.server.try_encrypt(&mut privmsg).await;
  490. // Build a DAG event and return it.
  491. Event::new(serialize_async(&privmsg).await, &self.server.darkirc.event_graph).await
  492. }
  493. /// Atomically mark a message as seen for this client.
  494. pub async fn mark_seen(&self, event_id: &blake3::Hash) -> Result<()> {
  495. let db = self
  496. .seen
  497. .get_or_init(|| async {
  498. let u = self.username.read().await.to_string();
  499. self.server.darkirc.sled.open_tree(format!("darkirc_user_{u}")).unwrap()
  500. })
  501. .await;
  502. debug!("Marking event {event_id} as seen");
  503. let mut batch = sled::Batch::default();
  504. batch.insert(event_id.as_bytes(), &[]);
  505. Ok(db.apply_batch(batch)?)
  506. }
  507. /// Check if a message was already marked seen for this client.
  508. pub async fn is_seen(&self, event_id: &blake3::Hash) -> Result<bool> {
  509. let db = self
  510. .seen
  511. .get_or_init(|| async {
  512. let u = self.username.read().await.to_string();
  513. self.server.darkirc.sled.open_tree(format!("darkirc_user_{u}")).unwrap()
  514. })
  515. .await;
  516. Ok(db.contains_key(event_id.as_bytes())?)
  517. }
  518. /// Abstraction for RLN signal proof creation
  519. async fn create_rln_signal_proof(
  520. &self,
  521. rln_identity: &RlnIdentity,
  522. event: &Event,
  523. ) -> Result<(Proof, Vec<pallas::Base>)> {
  524. let identity_commitment = rln_identity.commitment();
  525. // Fetch the commitment's leaf position in the Merkle tree
  526. let Some(identity_pos) =
  527. self.server.rln_identity_store.get(identity_commitment.to_repr())?
  528. else {
  529. return Err(Error::DatabaseError(
  530. "Identity not found in commitment tree store".to_string(),
  531. ))
  532. };
  533. let identity_pos: Position = deserialize_async(&identity_pos).await?;
  534. // Fetch the latest commitment Merkle tree
  535. let Some(identity_tree) = self.server.server_store.get("rln_identity_tree")? else {
  536. return Err(Error::DatabaseError(
  537. "RLN Identity tree not found in server store".to_string(),
  538. ))
  539. };
  540. let identity_tree: MerkleTree = deserialize_async(&identity_tree).await?;
  541. // Retrieve the ZK proving key from the db
  542. let signal_zkbin = ZkBinary::decode(RLN2_SIGNAL_ZKBIN, false)?;
  543. let signal_circuit = ZkCircuit::new(empty_witnesses(&signal_zkbin)?, &signal_zkbin);
  544. let Some(proving_key) = self.server.server_store.get("rlnv2-diff-signal-pk")? else {
  545. return Err(Error::DatabaseError(
  546. "RLN signal proving key not found in server store".to_string(),
  547. ))
  548. };
  549. let mut reader = Cursor::new(proving_key);
  550. let proving_key = ProvingKey::read(&mut reader, signal_circuit)?;
  551. rln_identity.create_signal_proof(event, &identity_tree, identity_pos, &proving_key)
  552. }
  553. /// Abstraction for RLN signal proof verification
  554. async fn verify_rln_signal_proof(
  555. &self,
  556. event: &Event,
  557. proof: Proof,
  558. public_inputs: [pallas::Base; 2],
  559. ) -> Result<()> {
  560. let epoch = pallas::Base::from(closest_epoch(event.header.timestamp));
  561. let external_nullifier = poseidon_hash([epoch, RLN_APP_IDENTIFIER]);
  562. let x = hash_event(event);
  563. let y = public_inputs[0];
  564. let internal_nullifier = public_inputs[1];
  565. // Fetch the latest commitment Merkle tree
  566. let Some(identity_tree) = self.server.server_store.get("rln_identity_tree")? else {
  567. return Err(Error::DatabaseError(
  568. "RLN Identity tree not found in server store".to_string(),
  569. ))
  570. };
  571. let identity_tree: MerkleTree = deserialize_async(&identity_tree).await?;
  572. let identity_root = identity_tree.root(0).unwrap();
  573. let public_inputs =
  574. vec![epoch, external_nullifier, x, y, internal_nullifier, identity_root.inner()];
  575. Ok(proof.verify(&self.server.rln_signal_vk, &public_inputs)?)
  576. }
  577. }