proto.rs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  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, HashSet},
  20. sync::{
  21. atomic::{AtomicUsize, Ordering::SeqCst},
  22. Arc,
  23. },
  24. time::Duration,
  25. };
  26. use darkfi_serial::{async_trait, SerialDecodable, SerialEncodable};
  27. use log::{debug, error, trace, warn};
  28. use smol::Executor;
  29. use super::{Event, EventGraphPtr, NULL_ID};
  30. use crate::{impl_p2p_message, net::*, system::timeout::timeout, Error, Result};
  31. /// Malicious behaviour threshold. If the threshold is reached, we will
  32. /// drop the peer from our P2P connection.
  33. const MALICIOUS_THRESHOLD: usize = 5;
  34. /// P2P protocol implementation for the Event Graph.
  35. pub struct ProtocolEventGraph {
  36. /// Pointer to the connected peer
  37. channel: ChannelPtr,
  38. /// Pointer to the Event Graph instance
  39. event_graph: EventGraphPtr,
  40. /// `MessageSubscriber` for `EventPut`
  41. ev_put_sub: MessageSubscription<EventPut>,
  42. /// `MessageSubscriber` for `EventReq`
  43. ev_req_sub: MessageSubscription<EventReq>,
  44. /// `MessageSubscriber` for `EventRep`
  45. ev_rep_sub: MessageSubscription<EventRep>,
  46. /// `MessageSubscriber` for `TipReq`
  47. tip_req_sub: MessageSubscription<TipReq>,
  48. /// `MessageSubscriber` for `TipRep`
  49. _tip_rep_sub: MessageSubscription<TipRep>,
  50. /// Peer malicious message count
  51. malicious_count: AtomicUsize,
  52. /// P2P jobs manager pointer
  53. jobsman: ProtocolJobsManagerPtr,
  54. }
  55. /// A P2P message representing publishing an event on the network
  56. #[derive(Clone, SerialEncodable, SerialDecodable)]
  57. pub struct EventPut(pub Event);
  58. impl_p2p_message!(EventPut, "EventGraph::EventPut");
  59. /// A P2P message representing an event request
  60. #[derive(Clone, SerialEncodable, SerialDecodable)]
  61. pub struct EventReq(pub Vec<blake3::Hash>);
  62. impl_p2p_message!(EventReq, "EventGraph::EventReq");
  63. /// A P2P message representing an event reply
  64. #[derive(Clone, SerialEncodable, SerialDecodable)]
  65. pub struct EventRep(pub Vec<Event>);
  66. impl_p2p_message!(EventRep, "EventGraph::EventRep");
  67. /// A P2P message representing a request for a peer's DAG tips
  68. #[derive(Clone, SerialEncodable, SerialDecodable)]
  69. pub struct TipReq {}
  70. impl_p2p_message!(TipReq, "EventGraph::TipReq");
  71. /// A P2P message representing a reply for the peer's DAG tips
  72. #[derive(Clone, SerialEncodable, SerialDecodable)]
  73. pub struct TipRep(pub BTreeMap<u64, HashSet<blake3::Hash>>);
  74. impl_p2p_message!(TipRep, "EventGraph::TipRep");
  75. #[async_trait]
  76. impl ProtocolBase for ProtocolEventGraph {
  77. async fn start(self: Arc<Self>, ex: Arc<Executor<'_>>) -> Result<()> {
  78. self.jobsman.clone().start(ex.clone());
  79. self.jobsman.clone().spawn(self.clone().handle_event_put(), ex.clone()).await;
  80. self.jobsman.clone().spawn(self.clone().handle_event_req(), ex.clone()).await;
  81. self.jobsman.clone().spawn(self.clone().handle_tip_req(), ex.clone()).await;
  82. Ok(())
  83. }
  84. fn name(&self) -> &'static str {
  85. "ProtocolEventGraph"
  86. }
  87. }
  88. impl ProtocolEventGraph {
  89. pub async fn init(event_graph: EventGraphPtr, channel: ChannelPtr) -> Result<ProtocolBasePtr> {
  90. let msg_subsystem = channel.message_subsystem();
  91. msg_subsystem.add_dispatch::<EventPut>().await;
  92. msg_subsystem.add_dispatch::<EventReq>().await;
  93. msg_subsystem.add_dispatch::<EventRep>().await;
  94. msg_subsystem.add_dispatch::<TipReq>().await;
  95. msg_subsystem.add_dispatch::<TipRep>().await;
  96. let ev_put_sub = channel.subscribe_msg::<EventPut>().await?;
  97. let ev_req_sub = channel.subscribe_msg::<EventReq>().await?;
  98. let ev_rep_sub = channel.subscribe_msg::<EventRep>().await?;
  99. let tip_req_sub = channel.subscribe_msg::<TipReq>().await?;
  100. let _tip_rep_sub = channel.subscribe_msg::<TipRep>().await?;
  101. Ok(Arc::new(Self {
  102. channel: channel.clone(),
  103. event_graph,
  104. ev_put_sub,
  105. ev_req_sub,
  106. ev_rep_sub,
  107. tip_req_sub,
  108. _tip_rep_sub,
  109. malicious_count: AtomicUsize::new(0),
  110. jobsman: ProtocolJobsManager::new("ProtocolEventGraph", channel.clone()),
  111. }))
  112. }
  113. async fn increase_malicious_count(self: Arc<Self>) -> Result<()> {
  114. let malicious_count = self.malicious_count.fetch_add(1, SeqCst);
  115. if malicious_count + 1 == MALICIOUS_THRESHOLD {
  116. error!(
  117. target: "event_graph::protocol::handle_event_put()",
  118. "[EVENTGRAPH] Peer {} reached malicious threshold. Dropping connection.",
  119. self.channel.address(),
  120. );
  121. self.channel.stop().await;
  122. return Err(Error::ChannelStopped)
  123. }
  124. warn!(
  125. target: "event_graph::protocol::handle_event_put()",
  126. "[EVENTGRAPH] Peer {} sent us a malicious event", self.channel.address(),
  127. );
  128. Ok(())
  129. }
  130. /// Protocol function handling `EventPut`.
  131. /// This is triggered whenever someone broadcasts (or relays) a new
  132. /// event on the network.
  133. async fn handle_event_put(self: Arc<Self>) -> Result<()> {
  134. loop {
  135. let event = match self.ev_put_sub.receive().await {
  136. Ok(v) => v.0.clone(),
  137. Err(_) => continue,
  138. };
  139. trace!(
  140. target: "event_graph::protocol::handle_event_put()",
  141. "Got EventPut: {} [{}]", event.id(), self.channel.address(),
  142. );
  143. // Check if node has finished syncing its DAG
  144. if !*self.event_graph.synced.read().await {
  145. debug!(
  146. target: "event_graph::protocol::handle_event_put",
  147. "DAG is still syncing, skipping..."
  148. );
  149. continue
  150. }
  151. // If we have already seen the event, we'll stay quiet.
  152. let event_id = event.id();
  153. if self.event_graph.dag.contains_key(event_id.as_bytes()).unwrap() {
  154. debug!(
  155. target: "event_graph::protocol::handle_event_put()",
  156. "Event {} is already known", event_id,
  157. );
  158. continue
  159. }
  160. // We received an event. Check if we already have it in our DAG.
  161. // Check event is not older that current genesis event timestamp.
  162. // Also check if we have the event's parents. In the case we do
  163. // not have the parents, we'll request them from the peer that has
  164. // sent this event to us. In case they do not reply in time, we drop
  165. // the event.
  166. // Check if the event is older than the genesis event. If so, we should
  167. // not include it in our Dag.
  168. // The genesis event marks the last time the Dag has been pruned of old
  169. // events. The pruning interval is defined by the days_rotation field
  170. // of [`EventGraph`].
  171. let genesis_timestamp = self.event_graph.current_genesis.read().await.timestamp;
  172. if event.timestamp < genesis_timestamp {
  173. debug!(
  174. target: "event_graph::protocol::handle_event_put()",
  175. "Event {} is older than genesis. Event timestamp: `{}`. Genesis timestamp: `{}`",
  176. event.id(), event.timestamp, genesis_timestamp
  177. );
  178. }
  179. // Validate the new event first. If we do not consider it valid, we
  180. // will just drop it and stay quiet. If the malicious threshold
  181. // is reached, we will stop the connection.
  182. if !event.validate_new() {
  183. self.clone().increase_malicious_count().await?;
  184. continue
  185. }
  186. // At this point, this is a new event to us. Let's see if we
  187. // have all of its parents.
  188. debug!(
  189. target: "event_graph::protocol::handle_event_put()",
  190. "Event {} is new", event_id,
  191. );
  192. let mut missing_parents = HashSet::new();
  193. for parent_id in event.parents.iter() {
  194. // `event.validate_new()` should have already made sure that
  195. // not all parents are NULL, and that there are no duplicates.
  196. if parent_id == &NULL_ID {
  197. continue
  198. }
  199. if !self.event_graph.dag.contains_key(parent_id.as_bytes()).unwrap() {
  200. missing_parents.insert(*parent_id);
  201. }
  202. }
  203. // If we have missing parents, then we have to attempt to
  204. // fetch them from this peer. Do this recursively until we
  205. // find all of them.
  206. if !missing_parents.is_empty() {
  207. // We track the received events mapped by their layer.
  208. // If/when we get all of them, we need to insert them in order so
  209. // the DAG state stays correct and unreferenced tips represent the
  210. // actual thing they should. If we insert them out of order, then
  211. // we might have wrong unreferenced tips.
  212. let mut received_events: BTreeMap<u64, Vec<Event>> = BTreeMap::new();
  213. let mut received_events_hashes = HashSet::new();
  214. debug!(
  215. target: "event_graph::protocol::handle_event_put()",
  216. "Event has {} missing parents. Requesting...", missing_parents.len(),
  217. );
  218. while !missing_parents.is_empty() {
  219. // for parent_id in missing_parents.clone().iter() {
  220. debug!(
  221. target: "event_graph::protocol::handle_event_put()",
  222. "Requesting {:?}...", missing_parents,
  223. );
  224. self.channel
  225. .send(&EventReq(missing_parents.clone().into_iter().collect()))
  226. .await?;
  227. let parents = match timeout(
  228. Duration::from_secs(
  229. self.event_graph.p2p.settings().outbound_connect_timeout,
  230. ),
  231. self.ev_rep_sub.receive(),
  232. )
  233. .await
  234. {
  235. Ok(parent) => parent?,
  236. Err(_) => {
  237. error!(
  238. target: "event_graph::protocol::handle_event_put()",
  239. "[EVENTGRAPH] Timeout while waiting for parents {:?} from {}",
  240. missing_parents, self.channel.address(),
  241. );
  242. self.channel.stop().await;
  243. return Err(Error::ChannelStopped)
  244. }
  245. };
  246. let parents = parents.0.clone();
  247. for parent in parents {
  248. let parent_id = parent.id();
  249. if !missing_parents.contains(&parent_id) {
  250. error!(
  251. target: "event_graph::protocol::handle_event_put()",
  252. "[EVENTGRAPH] Peer {} replied with a wrong event: {}",
  253. self.channel.address(), parent.id(),
  254. );
  255. self.channel.stop().await;
  256. return Err(Error::ChannelStopped)
  257. }
  258. debug!(
  259. target: "event_graph::protocol::handle_event_put()",
  260. "Got correct parent event {}", parent.id(),
  261. );
  262. if let Some(layer_events) = received_events.get_mut(&parent.layer) {
  263. layer_events.push(parent.clone());
  264. } else {
  265. let layer_events = vec![parent.clone()];
  266. received_events.insert(parent.layer, layer_events);
  267. }
  268. received_events_hashes.insert(parent_id);
  269. missing_parents.remove(&parent_id);
  270. // See if we have the upper parents
  271. for upper_parent in parent.parents.iter() {
  272. if upper_parent == &NULL_ID {
  273. continue
  274. }
  275. if !missing_parents.contains(upper_parent) &&
  276. !received_events_hashes.contains(upper_parent) &&
  277. !self
  278. .event_graph
  279. .dag
  280. .contains_key(upper_parent.as_bytes())
  281. .unwrap()
  282. {
  283. debug!(
  284. target: "event_graph::protocol::handle_event_put()",
  285. "Found upper missing parent event{}", upper_parent,
  286. );
  287. missing_parents.insert(*upper_parent);
  288. }
  289. }
  290. }
  291. } // <-- while !missing_parents.is_empty()
  292. // At this point we should've got all the events.
  293. // We should add them to the DAG.
  294. let mut events = vec![];
  295. for (_, tips) in received_events {
  296. for tip in tips {
  297. events.push(tip);
  298. }
  299. }
  300. if self.event_graph.dag_insert(&events).await.is_err() {
  301. self.clone().increase_malicious_count().await?;
  302. continue
  303. }
  304. } // <-- !missing_parents.is_empty()
  305. // If we're here, we have all the parents, and we can now
  306. // perform a full validation and add the actual event to
  307. // the DAG.
  308. debug!(
  309. target: "event_graph::protocol::handle_event_put()",
  310. "Got all parents necessary for insertion",
  311. );
  312. if self.event_graph.dag_insert(&[event.clone()]).await.is_err() {
  313. self.clone().increase_malicious_count().await?;
  314. continue
  315. }
  316. // Relay the event to other peers.
  317. self.event_graph
  318. .p2p
  319. .broadcast_with_exclude(&EventPut(event), &[self.channel.address().clone()])
  320. .await;
  321. }
  322. }
  323. /// Protocol function handling `EventReq`.
  324. /// This is triggered whenever someone requests an event from us.
  325. async fn handle_event_req(self: Arc<Self>) -> Result<()> {
  326. loop {
  327. let event_ids = match self.ev_req_sub.receive().await {
  328. Ok(v) => v.0.clone(),
  329. Err(_) => continue,
  330. };
  331. trace!(
  332. target: "event_graph::protocol::handle_event_req()",
  333. "Got EventReq: {:?} [{}]", event_ids, self.channel.address(),
  334. );
  335. // Check if node has finished syncing its DAG
  336. if !*self.event_graph.synced.read().await {
  337. debug!(
  338. target: "event_graph::protocol::handle_event_req()",
  339. "DAG is still syncing, skipping..."
  340. );
  341. continue
  342. }
  343. // We received an event request from somebody.
  344. // If we do have it, we will send it back to them as `EventRep`.
  345. // Otherwise, we'll stay quiet. An honest node should always have
  346. // something to reply with provided that the request is legitimate,
  347. // i.e. we've sent something to them and they did not have some of
  348. // the parents.
  349. // Check if we expected this request to come around.
  350. // I dunno if this is a good idea, but it seems it will help
  351. // against malicious event requests where they want us to keep
  352. // reading our db and steal our bandwidth.
  353. let mut events = vec![];
  354. for event_id in event_ids.iter() {
  355. if !self.event_graph.broadcasted_ids.read().await.contains(event_id) {
  356. let malicious_count = self.malicious_count.fetch_add(1, SeqCst);
  357. if malicious_count + 1 == MALICIOUS_THRESHOLD {
  358. error!(
  359. target: "event_graph::protocol::handle_event_req()",
  360. "[EVENTGRAPH] Peer {} reached malicious threshold. Dropping connection.",
  361. self.channel.address(),
  362. );
  363. self.channel.stop().await;
  364. return Err(Error::ChannelStopped)
  365. }
  366. warn!(
  367. target: "event_graph::protocol::handle_event_req()",
  368. "[EVENTGRAPH] Peer {} requested an unexpected event {:?}",
  369. self.channel.address(), event_id,
  370. );
  371. continue
  372. }
  373. // At this point we should have it in our DAG.
  374. // This code panics if this is not the case.
  375. debug!(
  376. target: "event_graph::protocol::handle_event_req()",
  377. "Fetching event {:?} from DAG", event_id,
  378. );
  379. events.push(self.event_graph.dag_get(event_id).await.unwrap().unwrap());
  380. }
  381. // Check if the incoming event is older than the genesis event. If so, something
  382. // has gone wrong. The event should have been pruned during the last
  383. // rotation.
  384. let genesis_timestamp = self.event_graph.current_genesis.read().await.timestamp;
  385. let mut bcast_ids = self.event_graph.broadcasted_ids.write().await;
  386. for event in events.iter() {
  387. if event.timestamp < genesis_timestamp {
  388. error!(
  389. target: "event_graph::protocol::handle_event_req()",
  390. "Requested event by peer {} is older than previous rotation period. It should have been pruned.
  391. Event timestamp: `{}`. Genesis timestamp: `{}`",
  392. event.id(), event.timestamp, genesis_timestamp
  393. );
  394. }
  395. // Now let's get the upper level of event IDs. When we reply, we could
  396. // get requests for those IDs as well.
  397. for parent_id in event.parents.iter() {
  398. if parent_id != &NULL_ID {
  399. bcast_ids.insert(*parent_id);
  400. }
  401. }
  402. }
  403. // TODO: We should remove the reply from the bcast IDs for this specific channel.
  404. // We can't remove them for everyone.
  405. //bcast_ids.remove(&event_id);
  406. drop(bcast_ids);
  407. // Reply with the event
  408. self.channel.send(&EventRep(events)).await?;
  409. }
  410. }
  411. /// Protocol function handling `TipReq`.
  412. /// This is triggered when someone requests the current unreferenced
  413. /// tips of our DAG.
  414. async fn handle_tip_req(self: Arc<Self>) -> Result<()> {
  415. loop {
  416. self.tip_req_sub.receive().await?;
  417. trace!(
  418. target: "event_graph::protocol::handle_tip_req()",
  419. "Got TipReq [{}]", self.channel.address(),
  420. );
  421. // Check if node has finished syncing its DAG
  422. if !*self.event_graph.synced.read().await {
  423. debug!(
  424. target: "event_graph::protocol::handle_tip_req()",
  425. "DAG is still syncing, skipping..."
  426. );
  427. continue
  428. }
  429. // TODO: Rate limit
  430. // We received a tip request. Let's find them, add them to
  431. // our bcast ids list, and reply with them.
  432. let layers = self.event_graph.unreferenced_tips.read().await.clone();
  433. let mut bcast_ids = self.event_graph.broadcasted_ids.write().await;
  434. for (_, tips) in layers.iter() {
  435. for tip in tips {
  436. bcast_ids.insert(*tip);
  437. }
  438. }
  439. drop(bcast_ids);
  440. self.channel.send(&TipRep(layers)).await?;
  441. }
  442. }
  443. }