protocol_sync.rs 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2025 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::sync::Arc;
  19. use async_trait::async_trait;
  20. use tracing::{debug, error};
  21. use darkfi::{
  22. blockchain::{BlockInfo, Header, HeaderHash},
  23. impl_p2p_message,
  24. net::{
  25. metering::MeteringConfiguration,
  26. protocol::protocol_generic::{
  27. ProtocolGenericAction, ProtocolGenericHandler, ProtocolGenericHandlerPtr,
  28. },
  29. session::SESSION_DEFAULT,
  30. Message, P2pPtr,
  31. },
  32. system::ExecutorPtr,
  33. util::time::NanoTimestamp,
  34. validator::{consensus::Proposal, ValidatorPtr},
  35. Error, Result,
  36. };
  37. use darkfi_serial::{SerialDecodable, SerialEncodable};
  38. // Constant defining max elements we send in vectors during syncing.
  39. pub const BATCH: usize = 20;
  40. // TODO: Fine tune
  41. // Protocol metering configuration.
  42. // Since all messages are synchronous(request -> response) we will define
  43. // strict rules to prevent spamming.
  44. // Each message score will be 1, with a threshold of 20 and expiry time of 5.
  45. // Check ../tests/metering.rs for each message max bytes definition.
  46. const PROTOCOL_SYNC_METERING_CONFIGURATION: MeteringConfiguration = MeteringConfiguration {
  47. threshold: 20,
  48. sleep_step: 500,
  49. expiry_time: NanoTimestamp::from_secs(5),
  50. };
  51. /// Structure represening a request to ask a node for their current
  52. /// canonical(confirmed) tip block hash, if they are synced. We also
  53. /// include our own tip, so they can verify we follow the same sequence.
  54. #[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
  55. pub struct TipRequest {
  56. /// Canonical(confirmed) tip block hash
  57. pub tip: HeaderHash,
  58. }
  59. impl_p2p_message!(TipRequest, "tiprequest", 32, 1, PROTOCOL_SYNC_METERING_CONFIGURATION);
  60. /// Structure representing the response to `TipRequest`,
  61. /// containing a boolean flag to indicate if we are synced,
  62. /// and our canonical(confirmed) tip block height and hash.
  63. #[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
  64. pub struct TipResponse {
  65. /// Flag indicating the node is synced
  66. pub synced: bool,
  67. /// Canonical(confirmed) tip block height
  68. pub height: Option<u32>,
  69. /// Canonical(confirmed) tip block hash
  70. pub hash: Option<HeaderHash>,
  71. }
  72. impl_p2p_message!(TipResponse, "tipresponse", 39, 1, PROTOCOL_SYNC_METERING_CONFIGURATION);
  73. /// Structure represening a request to ask a node for up to `BATCH` headers before
  74. /// the provided header height.
  75. #[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
  76. pub struct HeaderSyncRequest {
  77. /// Header height
  78. pub height: u32,
  79. }
  80. impl_p2p_message!(
  81. HeaderSyncRequest,
  82. "headersyncrequest",
  83. 4,
  84. 1,
  85. PROTOCOL_SYNC_METERING_CONFIGURATION
  86. );
  87. /// Structure representing the response to `HeaderSyncRequest`,
  88. /// containing up to `BATCH` headers before the requested block height.
  89. #[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
  90. pub struct HeaderSyncResponse {
  91. /// Response headers
  92. pub headers: Vec<Header>,
  93. }
  94. impl_p2p_message!(
  95. HeaderSyncResponse,
  96. "headersyncresponse",
  97. 8192, // We leave some headroom for merge mining data
  98. 1,
  99. PROTOCOL_SYNC_METERING_CONFIGURATION
  100. );
  101. /// Structure represening a request to ask a node for up to`BATCH` blocks
  102. /// of provided headers.
  103. #[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
  104. pub struct SyncRequest {
  105. /// Header hashes
  106. pub headers: Vec<HeaderHash>,
  107. }
  108. impl_p2p_message!(SyncRequest, "syncrequest", 641, 1, PROTOCOL_SYNC_METERING_CONFIGURATION);
  109. /// Structure representing the response to `SyncRequest`,
  110. /// containing up to `BATCH` blocks after the requested block height.
  111. #[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
  112. pub struct SyncResponse {
  113. /// Response blocks
  114. pub blocks: Vec<BlockInfo>,
  115. }
  116. impl_p2p_message!(SyncResponse, "syncresponse", 0, 1, PROTOCOL_SYNC_METERING_CONFIGURATION);
  117. /// Structure represening a request to ask a node a fork sequence.
  118. /// If we include a specific fork tip, they have to return its sequence,
  119. /// otherwise they respond with their best fork sequence.
  120. /// We also include our own canonical(confirmed) tip, so they can verify
  121. /// we follow the same sequence.
  122. #[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
  123. pub struct ForkSyncRequest {
  124. /// Canonical(confirmed) tip block hash
  125. pub tip: HeaderHash,
  126. /// Optional fork tip block hash
  127. pub fork_tip: Option<HeaderHash>,
  128. }
  129. impl_p2p_message!(ForkSyncRequest, "forksyncrequest", 65, 1, PROTOCOL_SYNC_METERING_CONFIGURATION);
  130. /// Structure representing the response to `ForkSyncRequest`,
  131. /// containing the requested fork sequence, up to `BATCH` proposals.
  132. #[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
  133. pub struct ForkSyncResponse {
  134. /// Response fork proposals
  135. pub proposals: Vec<Proposal>,
  136. }
  137. impl_p2p_message!(ForkSyncResponse, "forksyncresponse", 0, 1, PROTOCOL_SYNC_METERING_CONFIGURATION);
  138. /// Structure represening a request to ask a node a fork header for the
  139. /// requested height. The fork is identified by the provided header hash.
  140. #[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
  141. pub struct ForkHeaderHashRequest {
  142. /// Header height
  143. pub height: u32,
  144. /// Block header hash to identify the fork
  145. pub fork_header: HeaderHash,
  146. }
  147. impl_p2p_message!(
  148. ForkHeaderHashRequest,
  149. "forkheaderhashrequest",
  150. 36,
  151. 1,
  152. PROTOCOL_SYNC_METERING_CONFIGURATION
  153. );
  154. /// Structure representing the response to `ForkHeaderHashRequest`,
  155. /// containing the requested fork header hash, if it was found.
  156. #[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
  157. pub struct ForkHeaderHashResponse {
  158. /// Response fork block header hash
  159. pub fork_header: Option<HeaderHash>,
  160. }
  161. impl_p2p_message!(
  162. ForkHeaderHashResponse,
  163. "forkheaderhashresponse",
  164. 33,
  165. 1,
  166. PROTOCOL_SYNC_METERING_CONFIGURATION
  167. );
  168. /// Structure represening a request to ask a node for up to `BATCH`
  169. /// fork headers for provided header hashes. The fork is identified
  170. /// by the provided header hash.
  171. #[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
  172. pub struct ForkHeadersRequest {
  173. /// Header hashes
  174. pub headers: Vec<HeaderHash>,
  175. /// Block header hash to identify the fork
  176. pub fork_header: HeaderHash,
  177. }
  178. impl_p2p_message!(
  179. ForkHeadersRequest,
  180. "forkheadersrequest",
  181. 673,
  182. 1,
  183. PROTOCOL_SYNC_METERING_CONFIGURATION
  184. );
  185. /// Structure representing the response to `ForkHeadersRequest`,
  186. /// containing up to `BATCH` fork headers.
  187. #[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
  188. pub struct ForkHeadersResponse {
  189. /// Response headers
  190. pub headers: Vec<Header>,
  191. }
  192. impl_p2p_message!(
  193. ForkHeadersResponse,
  194. "forkheadersresponse",
  195. 8192, // We leave some headroom for merge mining data
  196. 1,
  197. PROTOCOL_SYNC_METERING_CONFIGURATION
  198. );
  199. /// Structure represening a request to ask a node for up to `BATCH`
  200. /// fork proposals for provided header hashes. The fork is identified
  201. /// by the provided header hash.
  202. #[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
  203. pub struct ForkProposalsRequest {
  204. /// Header hashes
  205. pub headers: Vec<HeaderHash>,
  206. /// Block header hash to identify the fork
  207. pub fork_header: HeaderHash,
  208. }
  209. impl_p2p_message!(
  210. ForkProposalsRequest,
  211. "forkproposalsrequest",
  212. 673,
  213. 1,
  214. PROTOCOL_SYNC_METERING_CONFIGURATION
  215. );
  216. /// Structure representing the response to `ForkProposalsRequest`,
  217. /// containing up to `BATCH` fork headers.
  218. #[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
  219. pub struct ForkProposalsResponse {
  220. /// Response proposals
  221. pub proposals: Vec<Proposal>,
  222. }
  223. impl_p2p_message!(
  224. ForkProposalsResponse,
  225. "forkproposalsresponse",
  226. 0,
  227. 1,
  228. PROTOCOL_SYNC_METERING_CONFIGURATION
  229. );
  230. /// Atomic pointer to the `ProtocolSync` handler.
  231. pub type ProtocolSyncHandlerPtr = Arc<ProtocolSyncHandler>;
  232. /// Handler managing all `ProtocolSync` messages, over generic P2P protocols.
  233. pub struct ProtocolSyncHandler {
  234. /// The generic handler for `TipRequest` messages.
  235. tip_handler: ProtocolGenericHandlerPtr<TipRequest, TipResponse>,
  236. /// The generic handler for `HeaderSyncRequest` messages.
  237. header_handler: ProtocolGenericHandlerPtr<HeaderSyncRequest, HeaderSyncResponse>,
  238. /// The generic handler for `SyncRequest` messages.
  239. sync_handler: ProtocolGenericHandlerPtr<SyncRequest, SyncResponse>,
  240. /// The generic handler for `ForkSyncRequest` messages.
  241. fork_sync_handler: ProtocolGenericHandlerPtr<ForkSyncRequest, ForkSyncResponse>,
  242. /// The generic handler for `ForkHeaderHashRequest` messages.
  243. fork_header_hash_handler:
  244. ProtocolGenericHandlerPtr<ForkHeaderHashRequest, ForkHeaderHashResponse>,
  245. /// The generic handler for `ForkHeadersRequest` messages.
  246. fork_headers_handler: ProtocolGenericHandlerPtr<ForkHeadersRequest, ForkHeadersResponse>,
  247. /// The generic handler for `ForkProposalsRequest` messages.
  248. fork_proposals_handler: ProtocolGenericHandlerPtr<ForkProposalsRequest, ForkProposalsResponse>,
  249. }
  250. impl ProtocolSyncHandler {
  251. /// Initialize the generic prototocol handlers for all `ProtocolSync` messages
  252. /// and register them to the provided P2P network, using the default session flag.
  253. pub async fn init(p2p: &P2pPtr) -> ProtocolSyncHandlerPtr {
  254. debug!(
  255. target: "darkfid::proto::protocol_sync::init",
  256. "Adding all sync protocols to the protocol registry"
  257. );
  258. let tip_handler =
  259. ProtocolGenericHandler::new(p2p, "ProtocolSyncTip", SESSION_DEFAULT).await;
  260. let header_handler =
  261. ProtocolGenericHandler::new(p2p, "ProtocolSyncHeader", SESSION_DEFAULT).await;
  262. let sync_handler = ProtocolGenericHandler::new(p2p, "ProtocolSync", SESSION_DEFAULT).await;
  263. let fork_sync_handler =
  264. ProtocolGenericHandler::new(p2p, "ProtocolSyncFork", SESSION_DEFAULT).await;
  265. let fork_header_hash_handler =
  266. ProtocolGenericHandler::new(p2p, "ProtocolSyncForkHeaderHash", SESSION_DEFAULT).await;
  267. let fork_headers_handler =
  268. ProtocolGenericHandler::new(p2p, "ProtocolSyncForkHeaders", SESSION_DEFAULT).await;
  269. let fork_proposals_handler =
  270. ProtocolGenericHandler::new(p2p, "ProtocolSyncForkProposals", SESSION_DEFAULT).await;
  271. Arc::new(Self {
  272. tip_handler,
  273. header_handler,
  274. sync_handler,
  275. fork_sync_handler,
  276. fork_header_hash_handler,
  277. fork_headers_handler,
  278. fork_proposals_handler,
  279. })
  280. }
  281. /// Start all `ProtocolSync` background tasks.
  282. pub async fn start(&self, executor: &ExecutorPtr, validator: &ValidatorPtr) -> Result<()> {
  283. debug!(
  284. target: "darkfid::proto::protocol_sync::start",
  285. "Starting sync protocols handlers tasks..."
  286. );
  287. self.tip_handler.task.clone().start(
  288. handle_receive_tip_request(self.tip_handler.clone(), validator.clone()),
  289. |res| async move {
  290. match res {
  291. Ok(()) | Err(Error::DetachedTaskStopped) => { /* Do nothing */ }
  292. Err(e) => error!(target: "darkfid::proto::protocol_sync::start", "Failed starting ProtocolSyncTip handler task: {e}"),
  293. }
  294. },
  295. Error::DetachedTaskStopped,
  296. executor.clone(),
  297. );
  298. self.header_handler.task.clone().start(
  299. handle_receive_header_request(self.header_handler.clone(), validator.clone()),
  300. |res| async move {
  301. match res {
  302. Ok(()) | Err(Error::DetachedTaskStopped) => { /* Do nothing */ }
  303. Err(e) => error!(target: "darkfid::proto::protocol_sync::start", "Failed starting ProtocolSyncHeader handler task: {e}"),
  304. }
  305. },
  306. Error::DetachedTaskStopped,
  307. executor.clone(),
  308. );
  309. self.sync_handler.task.clone().start(
  310. handle_receive_request(self.sync_handler.clone(), validator.clone()),
  311. |res| async move {
  312. match res {
  313. Ok(()) | Err(Error::DetachedTaskStopped) => { /* Do nothing */ }
  314. Err(e) => error!(target: "darkfid::proto::protocol_sync::start", "Failed starting ProtocolSync handler task: {e}"),
  315. }
  316. },
  317. Error::DetachedTaskStopped,
  318. executor.clone(),
  319. );
  320. self.fork_sync_handler.task.clone().start(
  321. handle_receive_fork_request(self.fork_sync_handler.clone(), validator.clone()),
  322. |res| async move {
  323. match res {
  324. Ok(()) | Err(Error::DetachedTaskStopped) => { /* Do nothing */ }
  325. Err(e) => error!(target: "darkfid::proto::protocol_sync::start", "Failed starting ProtocolSyncFork handler task: {e}"),
  326. }
  327. },
  328. Error::DetachedTaskStopped,
  329. executor.clone(),
  330. );
  331. self.fork_header_hash_handler.task.clone().start(
  332. handle_receive_fork_header_hash_request(self.fork_header_hash_handler.clone(), validator.clone()),
  333. |res| async move {
  334. match res {
  335. Ok(()) | Err(Error::DetachedTaskStopped) => { /* Do nothing */ }
  336. Err(e) => error!(target: "darkfid::proto::protocol_sync::start", "Failed starting ProtocolSyncForkHeaderHash handler task: {e}"),
  337. }
  338. },
  339. Error::DetachedTaskStopped,
  340. executor.clone(),
  341. );
  342. self.fork_headers_handler.task.clone().start(
  343. handle_receive_fork_headers_request(self.fork_headers_handler.clone(), validator.clone()),
  344. |res| async move {
  345. match res {
  346. Ok(()) | Err(Error::DetachedTaskStopped) => { /* Do nothing */ }
  347. Err(e) => error!(target: "darkfid::proto::protocol_sync::start", "Failed starting ProtocolSyncForkHeaders handler task: {e}"),
  348. }
  349. },
  350. Error::DetachedTaskStopped,
  351. executor.clone(),
  352. );
  353. self.fork_proposals_handler.task.clone().start(
  354. handle_receive_fork_proposals_request(self.fork_proposals_handler.clone(), validator.clone()),
  355. |res| async move {
  356. match res {
  357. Ok(()) | Err(Error::DetachedTaskStopped) => { /* Do nothing */ }
  358. Err(e) => error!(target: "darkfid::proto::protocol_sync::start", "Failed starting ProtocolSyncForkProposals handler task: {e}"),
  359. }
  360. },
  361. Error::DetachedTaskStopped,
  362. executor.clone(),
  363. );
  364. debug!(
  365. target: "darkfid::proto::protocol_sync::start",
  366. "Sync protocols handlers tasks started!"
  367. );
  368. Ok(())
  369. }
  370. /// Stop all `ProtocolSync` background tasks.
  371. pub async fn stop(&self) {
  372. debug!(target: "darkfid::proto::protocol_sync::stop", "Terminating sync protocols handlers tasks...");
  373. self.tip_handler.task.stop().await;
  374. self.header_handler.task.stop().await;
  375. self.sync_handler.task.stop().await;
  376. self.fork_sync_handler.task.stop().await;
  377. self.fork_header_hash_handler.task.stop().await;
  378. self.fork_headers_handler.task.stop().await;
  379. self.fork_proposals_handler.task.stop().await;
  380. debug!(target: "darkfid::proto::protocol_sync::stop", "Sync protocols handlers tasks terminated!");
  381. }
  382. }
  383. /// Background handler function for ProtocolSyncTip.
  384. async fn handle_receive_tip_request(
  385. handler: ProtocolGenericHandlerPtr<TipRequest, TipResponse>,
  386. validator: ValidatorPtr,
  387. ) -> Result<()> {
  388. debug!(target: "darkfid::proto::protocol_sync::handle_receive_tip_request", "START");
  389. loop {
  390. // Wait for a new tip request message
  391. let (channel, request) = match handler.receiver.recv().await {
  392. Ok(r) => r,
  393. Err(e) => {
  394. debug!(
  395. target: "darkfid::proto::protocol_sync::handle_receive_tip_request",
  396. "recv fail: {e}"
  397. );
  398. continue
  399. }
  400. };
  401. debug!(target: "darkfid::proto::protocol_sync::handle_receive_tip_request", "Received request: {request:?}");
  402. // Check if node has finished syncing its blockchain
  403. if !*validator.synced.read().await {
  404. debug!(
  405. target: "darkfid::proto::protocol_sync::handle_receive_tip_request",
  406. "Node still syncing blockchain"
  407. );
  408. handler
  409. .send_action(
  410. channel,
  411. ProtocolGenericAction::Response(TipResponse {
  412. synced: false,
  413. height: None,
  414. hash: None,
  415. }),
  416. )
  417. .await;
  418. continue
  419. }
  420. // Check we follow the same sequence
  421. match validator.blockchain.blocks.contains(&request.tip) {
  422. Ok(contains) => {
  423. if !contains {
  424. debug!(
  425. target: "darkfid::proto::protocol_sync::handle_receive_tip_request",
  426. "Node doesn't follow request sequence"
  427. );
  428. handler
  429. .send_action(
  430. channel,
  431. ProtocolGenericAction::Response(TipResponse {
  432. synced: true,
  433. height: None,
  434. hash: None,
  435. }),
  436. )
  437. .await;
  438. continue
  439. }
  440. }
  441. Err(e) => {
  442. error!(
  443. target: "darkfid::proto::protocol_sync::handle_receive_tip_request",
  444. "block_store.contains fail: {e}"
  445. );
  446. handler.send_action(channel, ProtocolGenericAction::Skip).await;
  447. continue
  448. }
  449. }
  450. // Grab our current tip and return it
  451. let tip = match validator.blockchain.last() {
  452. Ok(v) => v,
  453. Err(e) => {
  454. error!(
  455. target: "darkfid::proto::protocol_sync::handle_receive_tip_request",
  456. "blockchain.last fail: {e}"
  457. );
  458. handler.send_action(channel, ProtocolGenericAction::Skip).await;
  459. continue
  460. }
  461. };
  462. // Send response
  463. handler
  464. .send_action(
  465. channel,
  466. ProtocolGenericAction::Response(TipResponse {
  467. synced: true,
  468. height: Some(tip.0),
  469. hash: Some(tip.1),
  470. }),
  471. )
  472. .await;
  473. }
  474. }
  475. /// Background handler function for ProtocolSyncHeader.
  476. async fn handle_receive_header_request(
  477. handler: ProtocolGenericHandlerPtr<HeaderSyncRequest, HeaderSyncResponse>,
  478. validator: ValidatorPtr,
  479. ) -> Result<()> {
  480. debug!(target: "darkfid::proto::protocol_sync::handle_receive_header_request", "START");
  481. loop {
  482. // Wait for a new header request message
  483. let (channel, request) = match handler.receiver.recv().await {
  484. Ok(r) => r,
  485. Err(e) => {
  486. debug!(
  487. target: "darkfid::proto::protocol_sync::handle_receive_header_request",
  488. "recv fail: {e}"
  489. );
  490. continue
  491. }
  492. };
  493. // Check if node has finished syncing its blockchain
  494. if !*validator.synced.read().await {
  495. debug!(
  496. target: "darkfid::proto::protocol_sync::handle_receive_header_request",
  497. "Node still syncing blockchain, skipping..."
  498. );
  499. handler.send_action(channel, ProtocolGenericAction::Skip).await;
  500. continue
  501. }
  502. debug!(target: "darkfid::proto::protocol_sync::handle_receive_header_request", "Received request: {request:?}");
  503. // Grab the corresponding headers
  504. let headers = match validator.blockchain.get_headers_before(request.height, BATCH) {
  505. Ok(v) => v,
  506. Err(e) => {
  507. error!(
  508. target: "darkfid::proto::protocol_sync::handle_receive_header_request",
  509. "get_headers_before fail: {e}"
  510. );
  511. handler.send_action(channel, ProtocolGenericAction::Skip).await;
  512. continue
  513. }
  514. };
  515. // Send response
  516. handler
  517. .send_action(channel, ProtocolGenericAction::Response(HeaderSyncResponse { headers }))
  518. .await;
  519. }
  520. }
  521. /// Background handler function for ProtocolSync.
  522. async fn handle_receive_request(
  523. handler: ProtocolGenericHandlerPtr<SyncRequest, SyncResponse>,
  524. validator: ValidatorPtr,
  525. ) -> Result<()> {
  526. debug!(target: "darkfid::proto::protocol_sync::handle_receive_request", "START");
  527. loop {
  528. // Wait for a new sync request message
  529. let (channel, request) = match handler.receiver.recv().await {
  530. Ok(r) => r,
  531. Err(e) => {
  532. debug!(
  533. target: "darkfid::proto::protocol_sync::handle_receive_request",
  534. "recv fail: {e}"
  535. );
  536. continue
  537. }
  538. };
  539. // Check if node has finished syncing its blockchain
  540. if !*validator.synced.read().await {
  541. debug!(
  542. target: "darkfid::proto::protocol_sync::handle_receive_request",
  543. "Node still syncing blockchain, skipping..."
  544. );
  545. handler.send_action(channel, ProtocolGenericAction::Skip).await;
  546. continue
  547. }
  548. // Check if request exists the configured limit
  549. if request.headers.len() > BATCH {
  550. debug!(
  551. target: "darkfid::proto::protocol_sync::handle_receive_request",
  552. "Node requested more blocks than allowed."
  553. );
  554. handler.send_action(channel, ProtocolGenericAction::Skip).await;
  555. continue
  556. }
  557. debug!(target: "darkfid::proto::protocol_sync::handle_receive_request", "Received request: {request:?}");
  558. // Grab the corresponding blocks
  559. let blocks = match validator.blockchain.get_blocks_by_hash(&request.headers) {
  560. Ok(v) => v,
  561. Err(e) => {
  562. error!(
  563. target: "darkfid::proto::protocol_sync::handle_receive_request",
  564. "get_blocks_after fail: {e}"
  565. );
  566. handler.send_action(channel, ProtocolGenericAction::Skip).await;
  567. continue
  568. }
  569. };
  570. // Send response
  571. handler
  572. .send_action(channel, ProtocolGenericAction::Response(SyncResponse { blocks }))
  573. .await;
  574. }
  575. }
  576. /// Background handler function for ProtocolSyncFork.
  577. async fn handle_receive_fork_request(
  578. handler: ProtocolGenericHandlerPtr<ForkSyncRequest, ForkSyncResponse>,
  579. validator: ValidatorPtr,
  580. ) -> Result<()> {
  581. debug!(target: "darkfid::proto::protocol_sync::handle_receive_fork_request", "START");
  582. loop {
  583. // Wait for a new fork sync request message
  584. let (channel, request) = match handler.receiver.recv().await {
  585. Ok(r) => r,
  586. Err(e) => {
  587. debug!(
  588. target: "darkfid::proto::protocol_sync::handle_receive_fork_request",
  589. "recv fail: {e}"
  590. );
  591. continue
  592. }
  593. };
  594. // Check if node has finished syncing its blockchain
  595. if !*validator.synced.read().await {
  596. debug!(
  597. target: "darkfid::proto::protocol_sync::handle_receive_fork_request",
  598. "Node still syncing blockchain, skipping..."
  599. );
  600. handler.send_action(channel, ProtocolGenericAction::Skip).await;
  601. continue
  602. }
  603. debug!(target: "darkfid::proto::protocol_sync::handle_receive_fork_request", "Received request: {request:?}");
  604. // Retrieve proposals sequence
  605. let proposals = match validator
  606. .consensus
  607. .get_fork_proposals_after(request.tip, request.fork_tip, BATCH as u32)
  608. .await
  609. {
  610. Ok(p) => p,
  611. Err(e) => {
  612. debug!(
  613. target: "darkfid::proto::protocol_sync::handle_receive_fork_request",
  614. "Getting fork proposals failed: {e}"
  615. );
  616. handler.send_action(channel, ProtocolGenericAction::Skip).await;
  617. continue
  618. }
  619. };
  620. // Send response
  621. handler
  622. .send_action(channel, ProtocolGenericAction::Response(ForkSyncResponse { proposals }))
  623. .await;
  624. }
  625. }
  626. /// Background handler function for ProtocolSyncForkHeaderHash.
  627. async fn handle_receive_fork_header_hash_request(
  628. handler: ProtocolGenericHandlerPtr<ForkHeaderHashRequest, ForkHeaderHashResponse>,
  629. validator: ValidatorPtr,
  630. ) -> Result<()> {
  631. debug!(target: "darkfid::proto::protocol_sync::handle_receive_fork_header_hash_request", "START");
  632. loop {
  633. // Wait for a new fork header hash request message
  634. let (channel, request) = match handler.receiver.recv().await {
  635. Ok(r) => r,
  636. Err(e) => {
  637. debug!(
  638. target: "darkfid::proto::protocol_sync::handle_receive_fork_header_hash_request",
  639. "recv fail: {e}"
  640. );
  641. continue
  642. }
  643. };
  644. // Check if node has finished syncing its blockchain
  645. if !*validator.synced.read().await {
  646. debug!(
  647. target: "darkfid::proto::protocol_sync::handle_receive_fork_header_hash_request",
  648. "Node still syncing blockchain, skipping..."
  649. );
  650. handler.send_action(channel, ProtocolGenericAction::Skip).await;
  651. continue
  652. }
  653. debug!(target: "darkfid::proto::protocol_sync::handle_receive_fork_header_hash_request", "Received request: {request:?}");
  654. // Retrieve fork header
  655. let fork_header = match validator
  656. .consensus
  657. .get_fork_header_hash(request.height, &request.fork_header)
  658. .await
  659. {
  660. Ok(h) => h,
  661. Err(e) => {
  662. debug!(
  663. target: "darkfid::proto::protocol_sync::handle_receive_fork_header_hash_request",
  664. "Getting fork header hash failed: {e}"
  665. );
  666. handler.send_action(channel, ProtocolGenericAction::Skip).await;
  667. continue
  668. }
  669. };
  670. // Send response if header was found
  671. if fork_header.is_some() {
  672. handler
  673. .send_action(
  674. channel,
  675. ProtocolGenericAction::Response(ForkHeaderHashResponse { fork_header }),
  676. )
  677. .await;
  678. continue
  679. }
  680. // If header wasn't found in a fork, check canonical
  681. if let Err(e) = validator.blockchain.headers.get(&[request.fork_header], true) {
  682. debug!(
  683. target: "darkfid::proto::protocol_sync::handle_receive_fork_header_hash_request",
  684. "Getting fork header hash failed: {e}"
  685. );
  686. handler.send_action(channel, ProtocolGenericAction::Skip).await;
  687. continue
  688. };
  689. let response = match validator.blockchain.blocks.get_order(&[request.height], false) {
  690. Ok(h) => ProtocolGenericAction::Response(ForkHeaderHashResponse { fork_header: h[0] }),
  691. Err(e) => {
  692. debug!(
  693. target: "darkfid::proto::protocol_sync::handle_receive_fork_header_hash_request",
  694. "Getting fork header hash failed: {e}"
  695. );
  696. ProtocolGenericAction::Skip
  697. }
  698. };
  699. // Send response
  700. handler.send_action(channel, response).await;
  701. }
  702. }
  703. /// Background handler function for ProtocolSyncForkHeaders.
  704. async fn handle_receive_fork_headers_request(
  705. handler: ProtocolGenericHandlerPtr<ForkHeadersRequest, ForkHeadersResponse>,
  706. validator: ValidatorPtr,
  707. ) -> Result<()> {
  708. debug!(target: "darkfid::proto::protocol_sync::handle_receive_fork_headers_request", "START");
  709. loop {
  710. // Wait for a new fork header hash request message
  711. let (channel, request) = match handler.receiver.recv().await {
  712. Ok(r) => r,
  713. Err(e) => {
  714. debug!(
  715. target: "darkfid::proto::protocol_sync::handle_receive_fork_headers_request",
  716. "recv fail: {e}"
  717. );
  718. continue
  719. }
  720. };
  721. // Check if node has finished syncing its blockchain
  722. if !*validator.synced.read().await {
  723. debug!(
  724. target: "darkfid::proto::protocol_sync::handle_receive_fork_headers_request",
  725. "Node still syncing blockchain, skipping..."
  726. );
  727. handler.send_action(channel, ProtocolGenericAction::Skip).await;
  728. continue
  729. }
  730. // Check if request exists the configured limit
  731. if request.headers.len() > BATCH {
  732. debug!(
  733. target: "darkfid::proto::protocol_sync::handle_receive_fork_headers_request",
  734. "Node requested more headers than allowed."
  735. );
  736. handler.send_action(channel, ProtocolGenericAction::Skip).await;
  737. continue
  738. }
  739. debug!(target: "darkfid::proto::protocol_sync::handle_receive_fork_headers_request", "Received request: {request:?}");
  740. // Retrieve fork headers
  741. let headers = match validator
  742. .consensus
  743. .get_fork_headers(&request.headers, &request.fork_header)
  744. .await
  745. {
  746. Ok(h) => h,
  747. Err(e) => {
  748. debug!(
  749. target: "darkfid::proto::protocol_sync::handle_receive_fork_headers_request",
  750. "Getting fork headers failed: {e}"
  751. );
  752. handler.send_action(channel, ProtocolGenericAction::Skip).await;
  753. continue
  754. }
  755. };
  756. // Send response if headers were found
  757. if !headers.is_empty() {
  758. handler
  759. .send_action(
  760. channel,
  761. ProtocolGenericAction::Response(ForkHeadersResponse { headers }),
  762. )
  763. .await;
  764. continue
  765. }
  766. // If headers weren't found in a fork, check canonical
  767. if let Err(e) = validator.blockchain.headers.get(&[request.fork_header], true) {
  768. debug!(
  769. target: "darkfid::proto::protocol_sync::handle_receive_fork_headers_request",
  770. "Getting fork header hash failed: {e}"
  771. );
  772. handler.send_action(channel, ProtocolGenericAction::Skip).await;
  773. continue
  774. };
  775. let response = match validator.blockchain.headers.get(&request.headers, true) {
  776. Ok(h) => ProtocolGenericAction::Response(ForkHeadersResponse {
  777. headers: h.iter().map(|x| x.clone().unwrap()).collect(),
  778. }),
  779. Err(e) => {
  780. debug!(
  781. target: "darkfid::proto::protocol_sync::handle_receive_fork_headers_request",
  782. "Getting fork headers failed: {e}"
  783. );
  784. ProtocolGenericAction::Skip
  785. }
  786. };
  787. // Send response
  788. handler.send_action(channel, response).await;
  789. }
  790. }
  791. /// Background handler function for ProtocolSyncForkProposals.
  792. async fn handle_receive_fork_proposals_request(
  793. handler: ProtocolGenericHandlerPtr<ForkProposalsRequest, ForkProposalsResponse>,
  794. validator: ValidatorPtr,
  795. ) -> Result<()> {
  796. debug!(target: "darkfid::proto::protocol_sync::handle_receive_fork_proposals_request", "START");
  797. loop {
  798. // Wait for a new fork header hash request message
  799. let (channel, request) = match handler.receiver.recv().await {
  800. Ok(r) => r,
  801. Err(e) => {
  802. debug!(
  803. target: "darkfid::proto::protocol_sync::handle_receive_fork_proposals_request",
  804. "recv fail: {e}"
  805. );
  806. continue
  807. }
  808. };
  809. // Check if node has finished syncing its blockchain
  810. if !*validator.synced.read().await {
  811. debug!(
  812. target: "darkfid::proto::protocol_sync::handle_receive_fork_proposals_request",
  813. "Node still syncing blockchain, skipping..."
  814. );
  815. handler.send_action(channel, ProtocolGenericAction::Skip).await;
  816. continue
  817. }
  818. // Check if request exists the configured limit
  819. if request.headers.len() > BATCH {
  820. debug!(
  821. target: "darkfid::proto::protocol_sync::handle_receive_fork_proposals_request",
  822. "Node requested more proposals than allowed."
  823. );
  824. handler.send_action(channel, ProtocolGenericAction::Skip).await;
  825. continue
  826. }
  827. debug!(target: "darkfid::proto::protocol_sync::handle_receive_fork_proposals_request", "Received request: {request:?}");
  828. // Retrieve fork proposals
  829. let proposals = match validator
  830. .consensus
  831. .get_fork_proposals(&request.headers, &request.fork_header)
  832. .await
  833. {
  834. Ok(p) => p,
  835. Err(e) => {
  836. debug!(
  837. target: "darkfid::proto::protocol_sync::handle_receive_fork_proposals_request",
  838. "Getting fork proposals failed: {e}"
  839. );
  840. handler.send_action(channel, ProtocolGenericAction::Skip).await;
  841. continue
  842. }
  843. };
  844. // Send response if proposals were found
  845. if !proposals.is_empty() {
  846. handler
  847. .send_action(
  848. channel,
  849. ProtocolGenericAction::Response(ForkProposalsResponse { proposals }),
  850. )
  851. .await;
  852. continue
  853. }
  854. // If proposals weren't found in a fork, check canonical
  855. if let Err(e) = validator.blockchain.headers.get(&[request.fork_header], true) {
  856. debug!(
  857. target: "darkfid::proto::protocol_sync::handle_receive_fork_proposals_request",
  858. "Getting fork header hash failed: {e}"
  859. );
  860. handler.send_action(channel, ProtocolGenericAction::Skip).await;
  861. continue
  862. };
  863. let response = match validator.blockchain.get_blocks_by_hash(&request.headers) {
  864. Ok(blocks) => {
  865. let mut proposals = Vec::with_capacity(blocks.len());
  866. for block in blocks {
  867. proposals.push(Proposal::new(block));
  868. }
  869. ProtocolGenericAction::Response(ForkProposalsResponse { proposals })
  870. }
  871. Err(e) => {
  872. debug!(
  873. target: "darkfid::proto::protocol_sync::handle_receive_fork_proposals_request",
  874. "Getting fork proposals failed: {e}"
  875. );
  876. ProtocolGenericAction::Skip
  877. }
  878. };
  879. // Send response
  880. handler.send_action(channel, response).await;
  881. }
  882. }