chains.rs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. use async_std::sync::Mutex;
  2. use std::collections::VecDeque;
  3. use chrono::Utc;
  4. use fxhash::FxHashMap;
  5. use ripemd::{Digest, Ripemd256};
  6. use darkfi::serial::{SerialDecodable, SerialEncodable};
  7. const MAX_CHAIN_SIZE: usize = 4096;
  8. pub type PrivmsgId = String;
  9. #[derive(Debug, Clone, SerialEncodable, SerialDecodable, Eq, PartialEq)]
  10. pub struct Privmsg {
  11. pub id: PrivmsgId,
  12. pub nickname: String,
  13. pub target: String,
  14. pub message: String,
  15. pub timestamp: i64,
  16. pub read_confirms: u8,
  17. pub prev_msg_id: String,
  18. }
  19. impl Privmsg {
  20. pub fn new(nickname: &str, target: &str, message: &str, prev_msg_id: &str) -> Self {
  21. let timestamp = Utc::now().timestamp();
  22. let id = Self::hash(nickname, target, message, prev_msg_id, timestamp);
  23. let read_confirms = 0;
  24. Self {
  25. id,
  26. nickname: nickname.to_string(),
  27. target: target.to_string(),
  28. message: message.to_string(),
  29. timestamp,
  30. read_confirms,
  31. prev_msg_id: prev_msg_id.to_string(),
  32. }
  33. }
  34. pub fn hash(
  35. nickname: &str,
  36. target: &str,
  37. message: &str,
  38. prev_msg_id: &str,
  39. timestamp: i64,
  40. ) -> String {
  41. let mut hasher = Ripemd256::new();
  42. hasher.update(format!("{nickname}{target}{message}{timestamp}{prev_msg_id}"));
  43. hex::encode(hasher.finalize())
  44. }
  45. }
  46. impl std::string::ToString for Privmsg {
  47. fn to_string(&self) -> String {
  48. format!(":{}!anon@dark.fi PRIVMSG {} :{}\r\n", self.nickname, self.target, self.message)
  49. }
  50. }
  51. pub struct Chain {
  52. buffer: VecDeque<Privmsg>,
  53. hashes: Vec<String>,
  54. }
  55. impl Chain {
  56. pub fn new() -> Self {
  57. Self { buffer: VecDeque::new(), hashes: Vec::new() }
  58. }
  59. pub fn push_hashes(&mut self, hashes: Vec<String>) {
  60. self.hashes.extend(hashes);
  61. }
  62. pub fn push_msg(&mut self, msg: &Privmsg) -> bool {
  63. // Rehash the msg to check if it's valid
  64. let hash = Privmsg::hash(
  65. &msg.nickname,
  66. &msg.target,
  67. &msg.message,
  68. &msg.prev_msg_id,
  69. msg.timestamp,
  70. );
  71. if hash != msg.id {
  72. return false
  73. }
  74. // Prune last messages from the buffer if it has exceeded the MAX_CHAIN_SIZE
  75. if self.buffer.len() >= MAX_CHAIN_SIZE {
  76. self.buffer.pop_front();
  77. }
  78. // Check if the hashes already has the msg id, if so add the msg to the buffer
  79. if self.hashes.contains(&msg.id) {
  80. // TODO: it should do sorting by the msg id in this step
  81. self.buffer.push_back(msg.clone());
  82. return true
  83. }
  84. // Check if the last msg in the chains is equal to the previous_msg_id in privmsg,
  85. // if not and both the chain and previous_msg_id are empty,
  86. // then it will be add it as genesis msg
  87. if let Some(last_hash) = self.last_hash() {
  88. if last_hash != msg.prev_msg_id {
  89. return false
  90. }
  91. } else if !msg.prev_msg_id.is_empty() && !self.hashes.is_empty() {
  92. return false
  93. }
  94. // Push the msg to the chain
  95. self.buffer.push_back(msg.clone());
  96. self.hashes.push(msg.id.clone());
  97. true
  98. }
  99. pub fn last_msg(&self) -> Option<Privmsg> {
  100. self.buffer.iter().last().cloned()
  101. }
  102. pub fn last_hash(&self) -> Option<String> {
  103. self.hashes.iter().last().cloned()
  104. }
  105. pub fn height(&self) -> usize {
  106. self.hashes.len()
  107. }
  108. pub fn get_msgs(&self, hashes: &[String]) -> Vec<Privmsg> {
  109. self.buffer.iter().filter(|m| hashes.contains(&m.id)).cloned().collect()
  110. }
  111. pub fn get_hashes(&self, height: usize) -> Vec<String> {
  112. if height >= self.height() {
  113. return vec![]
  114. }
  115. self.hashes[height..].to_vec()
  116. }
  117. }
  118. pub struct Chains {
  119. chains: Mutex<FxHashMap<String, Chain>>,
  120. }
  121. impl Chains {
  122. pub fn new(targets: Vec<String>) -> Self {
  123. let mut map = FxHashMap::default();
  124. for target in targets {
  125. map.insert(target, Chain::new());
  126. }
  127. Self { chains: Mutex::new(map) }
  128. }
  129. pub async fn push_hashes(&self, target: String, height: usize, hashes: Vec<String>) -> bool {
  130. let mut chains = self.chains.lock().await;
  131. if !chains.contains_key(&target) {
  132. return false
  133. }
  134. let chain = chains.get_mut(&target).unwrap();
  135. if chain.height() + 1 != height {
  136. return false
  137. }
  138. chain.push_hashes(hashes);
  139. true
  140. }
  141. pub async fn push_msg(&self, msg: &Privmsg) -> bool {
  142. let mut chains = self.chains.lock().await;
  143. if !chains.contains_key(&msg.target) {
  144. return false
  145. }
  146. chains.get_mut(&msg.target).unwrap().push_msg(msg);
  147. true
  148. }
  149. pub async fn get_msgs(&self, target: &str, hashes: &[String]) -> Vec<Privmsg> {
  150. let chains = self.chains.lock().await;
  151. if !chains.contains_key(target) {
  152. return vec![]
  153. }
  154. chains.get(target).unwrap().get_msgs(hashes)
  155. }
  156. pub async fn get_hashes(&self, target: &str, height: usize) -> Vec<String> {
  157. let chains = self.chains.lock().await;
  158. if !chains.contains_key(target) {
  159. return vec![]
  160. }
  161. chains.get(target).unwrap().get_hashes(height)
  162. }
  163. pub async fn get_height(&self, target: &str) -> usize {
  164. let chains = self.chains.lock().await;
  165. if !chains.contains_key(target) {
  166. return 0
  167. }
  168. chains.get(target).unwrap().height()
  169. }
  170. }