proto.rs 22 KB

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