server.rs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691
  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,
  20. fs::File,
  21. io::{BufRead, BufReader},
  22. path::PathBuf,
  23. sync::Arc,
  24. };
  25. use darkfi::{
  26. event_graph::Event,
  27. system::{StoppableTask, StoppableTaskPtr, Subscription},
  28. util::path::expand_path,
  29. Error, Result,
  30. };
  31. use darkfi_serial::{deserialize_async, serialize_async};
  32. use futures_rustls::{
  33. rustls::{
  34. self,
  35. pki_types::{CertificateDer, PrivateKeyDer},
  36. },
  37. TlsAcceptor,
  38. };
  39. use sled_overlay::sled;
  40. use smol::{
  41. fs,
  42. lock::{Mutex, RwLock},
  43. net::{SocketAddr, TcpListener},
  44. prelude::{AsyncRead, AsyncWrite},
  45. Executor,
  46. };
  47. use tracing::{debug, error, info, warn};
  48. use url::Url;
  49. use super::{
  50. client::Client,
  51. services::nickserv::{ACCOUNTS_DB_PREFIX, ACCOUNTS_DEFAULT_TREE, ACCOUNTS_KEY_RLN_IDENTITY},
  52. IrcChannel, IrcContact,
  53. };
  54. use crate::{
  55. crypto::{rln::RlnIdentity, saltbox},
  56. pad,
  57. settings::{parse_autojoin_channels, parse_configured_channels, parse_configured_contacts},
  58. unpad, DarkIrc, Privmsg,
  59. };
  60. /// Max channel/nick length
  61. pub const MAX_NICK_LEN: usize = 24;
  62. /// Max message length
  63. pub const MAX_MSG_LEN: usize = 512;
  64. /// Result of attempting to reserve the next RLN message slot.
  65. pub enum RlnMessageReservation {
  66. /// No active RLN identity is configured.
  67. MissingIdentity,
  68. /// The active identity has already used its epoch budget.
  69. BudgetExhausted,
  70. /// A message slot was persisted and can be used to build a proof.
  71. Reserved { identity: RlnIdentity, message_id: u64 },
  72. }
  73. /// Persist the active RLN counter to the default mirror and matching account tree.
  74. async fn persist_rln_identity_counter(sled_db: &sled::Db, identity: &RlnIdentity) -> Result<()> {
  75. let encoded = serialize_async(identity).await;
  76. let active_commitment = identity.commitment();
  77. let mut updated_account = false;
  78. for raw in sled_db.tree_names() {
  79. let bytes: &[u8] = raw.as_ref();
  80. let Ok(name) = std::str::from_utf8(bytes) else { continue };
  81. let Some(account_name) = name.strip_prefix(ACCOUNTS_DB_PREFIX) else { continue };
  82. if account_name == "default" || account_name.is_empty() {
  83. continue
  84. }
  85. let tree = sled_db.open_tree(name)?;
  86. let Some(blob) = tree.get(ACCOUNTS_KEY_RLN_IDENTITY)? else { continue };
  87. let Ok(stored): std::result::Result<RlnIdentity, _> = deserialize_async(&blob).await else {
  88. continue
  89. };
  90. if stored.commitment() == active_commitment {
  91. tree.insert(ACCOUNTS_KEY_RLN_IDENTITY, encoded.clone())?;
  92. updated_account = true;
  93. }
  94. }
  95. if !updated_account {
  96. warn!(
  97. target: "darkirc::irc::server",
  98. "active RLN identity has no matching account tree; persisting default mirror only",
  99. );
  100. }
  101. let default_db = sled_db.open_tree(ACCOUNTS_DEFAULT_TREE)?;
  102. default_db.insert(ACCOUNTS_KEY_RLN_IDENTITY, encoded)?;
  103. sled_db.flush_async().await?;
  104. Ok(())
  105. }
  106. /// Reserve the next RLN message ID and persist it before proof creation.
  107. pub(crate) async fn reserve_rln_message_id_in_store(
  108. sled_db: &sled::Db,
  109. active: &mut Option<RlnIdentity>,
  110. now_millis: u64,
  111. ) -> Result<RlnMessageReservation> {
  112. let Some(current) = active else { return Ok(RlnMessageReservation::MissingIdentity) };
  113. let mut updated = *current;
  114. let Some(message_id) = updated.next_message_id(now_millis) else {
  115. return Ok(RlnMessageReservation::BudgetExhausted)
  116. };
  117. persist_rln_identity_counter(sled_db, &updated).await?;
  118. *current = updated;
  119. Ok(RlnMessageReservation::Reserved { identity: updated, message_id })
  120. }
  121. fn parse_tls_secret<R>(reader: &mut R) -> Result<PrivateKeyDer<'static>>
  122. where
  123. R: BufRead,
  124. {
  125. let key = rustls_pemfile::pkcs8_private_keys(reader)
  126. .next()
  127. .ok_or(Error::ParseFailed("TLS key missing PKCS#8 private key"))?
  128. .map_err(|_| Error::ParseFailed("TLS key contains invalid PKCS#8 private key"))?;
  129. Ok(PrivateKeyDer::Pkcs8(key))
  130. }
  131. fn parse_tls_cert<R>(reader: &mut R) -> Result<CertificateDer<'static>>
  132. where
  133. R: BufRead,
  134. {
  135. rustls_pemfile::certs(reader)
  136. .next()
  137. .ok_or(Error::ParseFailed("TLS certificate missing"))?
  138. .map_err(|_| Error::ParseFailed("TLS certificate contains invalid DER"))
  139. }
  140. fn tls_acceptor_from_pem<CR, KR>(
  141. cert_reader: &mut CR,
  142. secret_reader: &mut KR,
  143. ) -> Result<TlsAcceptor>
  144. where
  145. CR: BufRead,
  146. KR: BufRead,
  147. {
  148. let secret = parse_tls_secret(secret_reader)?;
  149. let cert = parse_tls_cert(cert_reader)?;
  150. let config = rustls::ServerConfig::builder()
  151. .with_no_client_auth()
  152. .with_single_cert(vec![cert], secret)
  153. .map_err(|_| Error::ParseFailed("TLS certificate and key are invalid"))?;
  154. Ok(TlsAcceptor::from(Arc::new(config)))
  155. }
  156. fn load_tls_acceptor(tls_cert: &str, tls_secret: &str) -> Result<TlsAcceptor> {
  157. let f = File::open(expand_path(tls_secret)?)?;
  158. let mut secret_reader = BufReader::new(f);
  159. let f = File::open(expand_path(tls_cert)?)?;
  160. let mut cert_reader = BufReader::new(f);
  161. tls_acceptor_from_pem(&mut cert_reader, &mut secret_reader)
  162. }
  163. async fn load_default_rln_identity(sled_db: &sled::Db) -> Result<Option<RlnIdentity>> {
  164. let default_db = sled_db.open_tree(ACCOUNTS_DEFAULT_TREE)?;
  165. let Some(blob) = default_db.get(ACCOUNTS_KEY_RLN_IDENTITY)? else {
  166. if default_db.is_empty() {
  167. return Ok(None)
  168. }
  169. return Err(Error::ParseFailed("Default RLN account is missing identity record"))
  170. };
  171. let identity: RlnIdentity = deserialize_async(&blob)
  172. .await
  173. .map_err(|_| Error::ParseFailed("Default RLN account identity is corrupted"))?;
  174. Ok(Some(identity))
  175. }
  176. /// IRC server instance
  177. pub struct IrcServer {
  178. /// DarkIrc instance
  179. pub darkirc: Arc<DarkIrc>,
  180. /// Path to the darkirc config file
  181. config_path: PathBuf,
  182. /// TCP listener
  183. listener: TcpListener,
  184. /// TLS acceptor
  185. acceptor: Option<TlsAcceptor>,
  186. /// Configured autojoin channels
  187. pub autojoin: RwLock<Vec<String>>,
  188. /// Configured IRC channels
  189. pub channels: RwLock<HashMap<String, IrcChannel>>,
  190. /// Configured IRC contacts
  191. pub contacts: RwLock<HashMap<String, IrcContact>>,
  192. /// Configured RLN identity
  193. pub rln_identity: RwLock<Option<RlnIdentity>>,
  194. /// Static-DAG events whose broadcast is deferred until the
  195. /// EventGraph is synced.
  196. pub pending_static_broadcasts: Mutex<Vec<(Event, Vec<u8>)>>,
  197. /// Active client connections
  198. clients: Mutex<HashMap<u16, StoppableTaskPtr>>,
  199. /// IRC server Password
  200. pub password: String,
  201. }
  202. impl IrcServer {
  203. /// Reserve and persist the next RLN message slot before proof creation.
  204. pub async fn reserve_rln_message_id(&self, now_millis: u64) -> Result<RlnMessageReservation> {
  205. let mut active = self.rln_identity.write().await;
  206. reserve_rln_message_id_in_store(&self.darkirc.sled, &mut active, now_millis).await
  207. }
  208. /// Instantiate a new IRC server. This function will try to bind a TCP socket,
  209. /// and optionally load a TLS certificate and key. To start the listening loop,
  210. /// call `IrcServer::listen()`.
  211. pub async fn new(
  212. darkirc: Arc<DarkIrc>,
  213. listen: Url,
  214. tls_cert: Option<String>,
  215. tls_secret: Option<String>,
  216. config_path: PathBuf,
  217. password: String,
  218. ) -> Result<Arc<Self>> {
  219. let scheme = listen.scheme();
  220. if scheme != "tcp" && scheme != "tcp+tls" {
  221. error!("IRC server supports listening only on tcp:// or tcp+tls://");
  222. return Err(Error::BindFailed(listen.to_string()))
  223. }
  224. if scheme == "tcp+tls" && (tls_cert.is_none() || tls_secret.is_none()) {
  225. error!("You must provide a TLS certificate and key if you want a TLS server");
  226. return Err(Error::BindFailed(listen.to_string()))
  227. }
  228. // Bind listener
  229. let listen_addr = listen.socket_addrs(|| None)?[0];
  230. let listener = TcpListener::bind(listen_addr).await?;
  231. let acceptor = match scheme {
  232. "tcp+tls" => {
  233. // openssl genpkey -algorithm ED25519 > example.com.key
  234. // openssl req -new -out example.com.csr -key example.com.key
  235. // openssl x509 -req -in example.com.csr -signkey example.com.key -out example.com.crt
  236. let (Some(tls_cert), Some(tls_secret)) = (tls_cert.as_ref(), tls_secret.as_ref())
  237. else {
  238. return Err(Error::ParseFailed("TLS certificate and key are required"))
  239. };
  240. Some(load_tls_acceptor(tls_cert, tls_secret)?)
  241. }
  242. _ => None,
  243. };
  244. // Set the default RLN account if any. When RLN is disabled, avoid
  245. // loading account state that cannot affect outbound messages.
  246. let rln_identity = if darkirc.event_graph.rln_enabled() {
  247. let rln_identity = load_default_rln_identity(&darkirc.sled).await?;
  248. if rln_identity.is_some() {
  249. info!("Default RLN account set");
  250. }
  251. rln_identity
  252. } else {
  253. info!("RLN disabled; skipping default RLN account load");
  254. None
  255. };
  256. let self_ = Arc::new(Self {
  257. darkirc,
  258. config_path,
  259. listener,
  260. acceptor,
  261. autojoin: RwLock::new(Vec::new()),
  262. channels: RwLock::new(HashMap::new()),
  263. contacts: RwLock::new(HashMap::new()),
  264. rln_identity: RwLock::new(rln_identity),
  265. pending_static_broadcasts: Mutex::new(Vec::new()),
  266. clients: Mutex::new(HashMap::new()),
  267. password,
  268. });
  269. // Load any channel/contact configuration.
  270. self_.rehash().await?;
  271. Ok(self_)
  272. }
  273. /// Drain `pending_static_broadcasts` and broadcast each entry.
  274. pub async fn drain_pending_static_broadcasts(&self) -> Result<usize> {
  275. let drained: Vec<(Event, Vec<u8>)> = {
  276. let mut guard = self.pending_static_broadcasts.lock().await;
  277. std::mem::take(&mut *guard)
  278. };
  279. let n = drained.len();
  280. for (event, blob) in drained {
  281. self.darkirc.event_graph.static_broadcast(event, blob).await?;
  282. }
  283. Ok(n)
  284. }
  285. /// Reload the darkirc configuration file and reconfigure channels and contacts.
  286. pub async fn rehash(&self) -> Result<()> {
  287. let contents = fs::read_to_string(&self.config_path).await?;
  288. let contents = match toml::from_str(&contents) {
  289. Ok(v) => v,
  290. Err(e) => {
  291. error!("Failed parsing TOML config: {e}");
  292. return Err(Error::ParseFailed("Failed parsing TOML config"))
  293. }
  294. };
  295. // Parse autojoin channels
  296. let autojoin = parse_autojoin_channels(&contents)?;
  297. // Parse configured channels
  298. let configured_channels = parse_configured_channels(&contents)?;
  299. // Parse configured contacts
  300. let contacts = parse_configured_contacts(&contents)?;
  301. // Persist unconfigured channels (joined from client, or autojoined without config)
  302. let channels = {
  303. let old_channels = self.channels.read().await.clone();
  304. let unconfigured_channels: HashMap<String, IrcChannel> = old_channels
  305. .into_iter()
  306. .filter(|(chan_str, _)| !configured_channels.contains_key(chan_str))
  307. .collect();
  308. configured_channels.into_iter().chain(unconfigured_channels).collect()
  309. };
  310. // Only if everything is fine, replace.
  311. *self.autojoin.write().await = autojoin;
  312. *self.channels.write().await = channels;
  313. *self.contacts.write().await = contacts;
  314. Ok(())
  315. }
  316. /// Start accepting new IRC connections.
  317. pub async fn listen(self: Arc<Self>, ex: Arc<Executor<'_>>) -> Result<()> {
  318. loop {
  319. let (stream, peer_addr) = match self.listener.accept().await {
  320. Ok((s, a)) => (s, a),
  321. // As per usual accept(2) recommendations
  322. Err(e)
  323. if matches!(
  324. e.raw_os_error(),
  325. Some(libc::EAGAIN | libc::ECONNABORTED | libc::EPROTO | libc::EINTR)
  326. ) =>
  327. {
  328. continue
  329. }
  330. Err(e) => {
  331. error!("[IRC SERVER] Failed accepting new connection: {e}");
  332. continue
  333. }
  334. };
  335. match &self.acceptor {
  336. // Expecting encrypted TLS connection
  337. Some(acceptor) => {
  338. let stream = match acceptor.accept(stream).await {
  339. Ok(s) => s,
  340. Err(e) => {
  341. error!("[IRC SERVER] Failed accepting new TLS connection: {e}");
  342. continue
  343. }
  344. };
  345. // Subscribe to incoming events and set up the connection.
  346. let incoming = self.darkirc.event_graph.event_pub.clone().subscribe().await;
  347. let incoming_st = self.darkirc.event_graph.static_pub.clone().subscribe().await;
  348. if let Err(e) = self
  349. .clone()
  350. .process_connection(stream, peer_addr, incoming, incoming_st, ex.clone())
  351. .await
  352. {
  353. error!("[IRC SERVER] Failed processing new connection: {e}");
  354. continue
  355. };
  356. }
  357. // Expecting plain TCP connection
  358. None => {
  359. // Subscribe to incoming events and set up the connection.
  360. let incoming = self.darkirc.event_graph.event_pub.clone().subscribe().await;
  361. let incoming_st = self.darkirc.event_graph.static_pub.clone().subscribe().await;
  362. if let Err(e) = self
  363. .clone()
  364. .process_connection(stream, peer_addr, incoming, incoming_st, ex.clone())
  365. .await
  366. {
  367. error!("[IRC SERVER] Failed processing new connection: {e}");
  368. continue
  369. };
  370. }
  371. }
  372. info!("[IRC SERVER] Accepted new client connection at: {peer_addr}");
  373. }
  374. }
  375. /// IRC client connection process.
  376. /// Sets up multiplexing between the server and client.
  377. /// Detaches the connection as a `StoppableTask`.
  378. async fn process_connection<C: AsyncRead + AsyncWrite + Send + Unpin + 'static>(
  379. self: Arc<Self>,
  380. stream: C,
  381. peer_addr: SocketAddr,
  382. incoming: Subscription<Event>,
  383. incoming_st: Subscription<Event>,
  384. ex: Arc<Executor<'_>>,
  385. ) -> Result<()> {
  386. let port = peer_addr.port();
  387. let client = Client::new(self.clone(), incoming, incoming_st, peer_addr).await?;
  388. let conn_task = StoppableTask::new();
  389. self.clients.lock().await.insert(port, conn_task.clone());
  390. conn_task.clone().start(
  391. async move { client.multiplex_connection(stream).await },
  392. move |res| async move {
  393. match res {
  394. Ok(()) => info!("[IRC SERVER] Disconnected client from {peer_addr}"),
  395. Err(e) => error!("[IRC SERVER] Disconnected client from {peer_addr}: {e}"),
  396. }
  397. self.clone().clients.lock().await.remove(&port);
  398. },
  399. Error::ChannelStopped,
  400. ex,
  401. );
  402. Ok(())
  403. }
  404. /// Try encrypting a given `Privmsg` if there is such a channel/contact.
  405. pub async fn try_encrypt(&self, privmsg: &mut Privmsg) {
  406. if let Some((name, channel)) = self.channels.read().await.get_key_value(&privmsg.channel) {
  407. if let Some(saltbox) = &channel.saltbox {
  408. // We will use a dummy channel value of MAX_NICK_LEN,
  409. // since its not used, so all encrypted messages look the same.
  410. privmsg.channel = saltbox::encrypt(saltbox, &[0x00; MAX_NICK_LEN]);
  411. // We will pad the name to MAX_NICK_LEN so they all look the same
  412. privmsg.nick = saltbox::encrypt(saltbox, &pad(&privmsg.nick));
  413. privmsg.msg = saltbox::encrypt(saltbox, privmsg.msg.as_bytes());
  414. debug!("Successfully encrypted message for {name}");
  415. return
  416. }
  417. };
  418. if let Some((name, contact)) = self.contacts.read().await.get_key_value(&privmsg.channel) {
  419. // We will use dummy channel and nick values of MAX_NICK_LEN,
  420. // since they are not used, so all encrypted messages look the same.
  421. privmsg.channel = saltbox::encrypt(&contact.saltbox, &[0x00; MAX_NICK_LEN]);
  422. // We will encrypt the dummy nick value using our own self saltbox,
  423. // so we can identify our messages.
  424. privmsg.nick = saltbox::encrypt(&contact.self_saltbox, &[0x00; MAX_NICK_LEN]);
  425. privmsg.msg = saltbox::encrypt(&contact.saltbox, privmsg.msg.as_bytes());
  426. debug!("Successfully encrypted message for {name}");
  427. };
  428. }
  429. /// Try decrypting a given potentially encrypted `Privmsg` object.
  430. pub async fn try_decrypt(&self, privmsg: &mut Privmsg, self_nickname: &str) {
  431. // If all fields have base58, then we can consider decrypting.
  432. let channel_ciphertext = match bs58::decode(&privmsg.channel).into_vec() {
  433. Ok(v) => v,
  434. Err(_) => return,
  435. };
  436. let nick_ciphertext = match bs58::decode(&privmsg.nick).into_vec() {
  437. Ok(v) => v,
  438. Err(_) => return,
  439. };
  440. let msg_ciphertext = match bs58::decode(&privmsg.msg).into_vec() {
  441. Ok(v) => v,
  442. Err(_) => return,
  443. };
  444. // Now go through all 3 ciphertexts. We'll use intermediate buffers
  445. // for decryption, iff all passes, we will return a modified
  446. // (i.e. decrypted) privmsg, otherwise we return the original.
  447. for (name, channel) in self.channels.read().await.iter() {
  448. let Some(saltbox) = &channel.saltbox else { continue };
  449. if saltbox::try_decrypt(saltbox, &channel_ciphertext).is_none() {
  450. continue
  451. };
  452. let Some(mut nick_dec) = saltbox::try_decrypt(saltbox, &nick_ciphertext) else {
  453. warn!(target: "darkirc::irc::server::try_decrypt", "Could not decrypt nick ciphertext for channel: {name}");
  454. continue
  455. };
  456. let Some(msg_dec) = saltbox::try_decrypt(saltbox, &msg_ciphertext) else {
  457. warn!(target: "darkirc::irc::server::try_decrypt", "Could not decrypt message ciphertext for channel: {name}");
  458. continue
  459. };
  460. unpad(&mut nick_dec);
  461. privmsg.channel = name.to_string();
  462. privmsg.nick = String::from_utf8_lossy(&nick_dec).into();
  463. privmsg.msg = String::from_utf8_lossy(&msg_dec).into();
  464. debug!("Successfully decrypted message for {name}");
  465. return
  466. }
  467. for (name, contact) in self.contacts.read().await.iter() {
  468. if saltbox::try_decrypt(&contact.saltbox, &channel_ciphertext).is_none() {
  469. continue
  470. };
  471. // Since everyone encrypts the dummy nick value with their self saltbox,
  472. // we try to decrypt using our, to identify our messages.
  473. let nick = if saltbox::try_decrypt(&contact.self_saltbox, &nick_ciphertext).is_some() {
  474. String::from(self_nickname)
  475. } else {
  476. name.to_string()
  477. };
  478. let Some(msg_dec) = saltbox::try_decrypt(&contact.saltbox, &msg_ciphertext) else {
  479. warn!(target: "darkirc::irc::server::try_decrypt", "Could not decrypt message ciphertext for contact: {name}");
  480. continue
  481. };
  482. privmsg.channel = name.to_string();
  483. privmsg.nick = nick;
  484. privmsg.msg = String::from_utf8_lossy(&msg_dec).into();
  485. debug!("Successfully decrypted message from {name}");
  486. return
  487. }
  488. }
  489. }
  490. #[cfg(test)]
  491. mod tests {
  492. use std::io::Cursor;
  493. use darkfi::{event_graph::rln::epoch_of, Error};
  494. use darkfi_sdk::pasta::pallas;
  495. use darkfi_serial::deserialize_async;
  496. use super::*;
  497. fn test_identity(limit: u64) -> RlnIdentity {
  498. RlnIdentity {
  499. nullifier: pallas::Base::from(0xabc_u64),
  500. trapdoor: pallas::Base::from(0xdef_u64),
  501. user_message_limit: limit,
  502. message_id: 0,
  503. last_epoch: 0,
  504. }
  505. }
  506. #[test]
  507. fn tls_secret_parser_rejects_malformed_key() {
  508. let mut reader = Cursor::new(b"not a private key".as_slice());
  509. assert!(matches!(parse_tls_secret(&mut reader), Err(Error::ParseFailed(_))));
  510. }
  511. #[test]
  512. fn tls_cert_parser_rejects_malformed_cert() {
  513. let mut reader = Cursor::new(b"not a certificate".as_slice());
  514. assert!(matches!(parse_tls_cert(&mut reader), Err(Error::ParseFailed(_))));
  515. }
  516. #[test]
  517. fn load_default_rln_identity_returns_none_for_empty_tree() {
  518. smol::block_on(async {
  519. let sled_db = sled::Config::new().temporary(true).open().unwrap();
  520. let identity = load_default_rln_identity(&sled_db).await.unwrap();
  521. assert!(identity.is_none());
  522. })
  523. }
  524. #[test]
  525. fn load_default_rln_identity_rejects_missing_identity_record() {
  526. smol::block_on(async {
  527. let sled_db = sled::Config::new().temporary(true).open().unwrap();
  528. let default = sled_db.open_tree(ACCOUNTS_DEFAULT_TREE).unwrap();
  529. default.insert(b"other", b"value").unwrap();
  530. let err = match load_default_rln_identity(&sled_db).await {
  531. Ok(_) => panic!("expected missing identity record error"),
  532. Err(e) => e,
  533. };
  534. assert!(matches!(
  535. err,
  536. Error::ParseFailed("Default RLN account is missing identity record")
  537. ));
  538. })
  539. }
  540. #[test]
  541. fn load_default_rln_identity_rejects_corrupted_identity_record() {
  542. smol::block_on(async {
  543. let sled_db = sled::Config::new().temporary(true).open().unwrap();
  544. let default = sled_db.open_tree(ACCOUNTS_DEFAULT_TREE).unwrap();
  545. default.insert(ACCOUNTS_KEY_RLN_IDENTITY, b"not an identity").unwrap();
  546. let err = match load_default_rln_identity(&sled_db).await {
  547. Ok(_) => panic!("expected corrupted identity record error"),
  548. Err(e) => e,
  549. };
  550. assert!(matches!(err, Error::ParseFailed("Default RLN account identity is corrupted")));
  551. })
  552. }
  553. #[test]
  554. fn rln_message_reservation_persists_default_and_account_counters() {
  555. smol::block_on(async {
  556. let sled_db = sled::Config::new().temporary(true).open().unwrap();
  557. let account = sled_db.open_tree(format!("{ACCOUNTS_DB_PREFIX}alice")).unwrap();
  558. let default = sled_db.open_tree(ACCOUNTS_DEFAULT_TREE).unwrap();
  559. let identity = test_identity(2);
  560. let encoded = serialize_async(&identity).await;
  561. account.insert(ACCOUNTS_KEY_RLN_IDENTITY, encoded.clone()).unwrap();
  562. default.insert(ACCOUNTS_KEY_RLN_IDENTITY, encoded).unwrap();
  563. let now = 1_704_067_800_000;
  564. let mut active = Some(identity);
  565. let reservation =
  566. reserve_rln_message_id_in_store(&sled_db, &mut active, now).await.unwrap();
  567. let RlnMessageReservation::Reserved { identity: reserved, message_id } = reservation
  568. else {
  569. panic!("expected reservation")
  570. };
  571. assert_eq!(message_id, 0);
  572. assert_eq!(reserved.message_id, 1);
  573. assert_eq!(reserved.last_epoch, epoch_of(now));
  574. let stored_default: RlnIdentity =
  575. deserialize_async(&default.get(ACCOUNTS_KEY_RLN_IDENTITY).unwrap().unwrap())
  576. .await
  577. .unwrap();
  578. let stored_account: RlnIdentity =
  579. deserialize_async(&account.get(ACCOUNTS_KEY_RLN_IDENTITY).unwrap().unwrap())
  580. .await
  581. .unwrap();
  582. assert_eq!(stored_default.message_id, 1);
  583. assert_eq!(stored_account.message_id, 1);
  584. assert_eq!(stored_default.last_epoch, epoch_of(now));
  585. assert_eq!(stored_account.last_epoch, epoch_of(now));
  586. let reservation =
  587. reserve_rln_message_id_in_store(&sled_db, &mut active, now).await.unwrap();
  588. let RlnMessageReservation::Reserved { message_id, .. } = reservation else {
  589. panic!("expected second reservation")
  590. };
  591. assert_eq!(message_id, 1);
  592. let exhausted =
  593. reserve_rln_message_id_in_store(&sled_db, &mut active, now).await.unwrap();
  594. assert!(matches!(exhausted, RlnMessageReservation::BudgetExhausted));
  595. })
  596. }
  597. }