| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979 |
- /* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2025 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
- use std::sync::Arc;
- use async_trait::async_trait;
- use tracing::{debug, error};
- use darkfi::{
- blockchain::{BlockInfo, Header, HeaderHash},
- impl_p2p_message,
- net::{
- metering::MeteringConfiguration,
- protocol::protocol_generic::{
- ProtocolGenericAction, ProtocolGenericHandler, ProtocolGenericHandlerPtr,
- },
- session::SESSION_DEFAULT,
- Message, P2pPtr,
- },
- system::ExecutorPtr,
- util::time::NanoTimestamp,
- validator::{consensus::Proposal, ValidatorPtr},
- Error, Result,
- };
- use darkfi_serial::{SerialDecodable, SerialEncodable};
- // Constant defining max elements we send in vectors during syncing.
- pub const BATCH: usize = 20;
- // TODO: Fine tune
- // Protocol metering configuration.
- // Since all messages are synchronous(request -> response) we will define
- // strict rules to prevent spamming.
- // Each message score will be 1, with a threshold of 20 and expiry time of 5.
- // Check ../tests/metering.rs for each message max bytes definition.
- const PROTOCOL_SYNC_METERING_CONFIGURATION: MeteringConfiguration = MeteringConfiguration {
- threshold: 20,
- sleep_step: 500,
- expiry_time: NanoTimestamp::from_secs(5),
- };
- /// Structure represening a request to ask a node for their current
- /// canonical(confirmed) tip block hash, if they are synced. We also
- /// include our own tip, so they can verify we follow the same sequence.
- #[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
- pub struct TipRequest {
- /// Canonical(confirmed) tip block hash
- pub tip: HeaderHash,
- }
- impl_p2p_message!(TipRequest, "tiprequest", 32, 1, PROTOCOL_SYNC_METERING_CONFIGURATION);
- /// Structure representing the response to `TipRequest`,
- /// containing a boolean flag to indicate if we are synced,
- /// and our canonical(confirmed) tip block height and hash.
- #[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
- pub struct TipResponse {
- /// Flag indicating the node is synced
- pub synced: bool,
- /// Canonical(confirmed) tip block height
- pub height: Option<u32>,
- /// Canonical(confirmed) tip block hash
- pub hash: Option<HeaderHash>,
- }
- impl_p2p_message!(TipResponse, "tipresponse", 39, 1, PROTOCOL_SYNC_METERING_CONFIGURATION);
- /// Structure represening a request to ask a node for up to `BATCH` headers before
- /// the provided header height.
- #[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
- pub struct HeaderSyncRequest {
- /// Header height
- pub height: u32,
- }
- impl_p2p_message!(
- HeaderSyncRequest,
- "headersyncrequest",
- 4,
- 1,
- PROTOCOL_SYNC_METERING_CONFIGURATION
- );
- /// Structure representing the response to `HeaderSyncRequest`,
- /// containing up to `BATCH` headers before the requested block height.
- #[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
- pub struct HeaderSyncResponse {
- /// Response headers
- pub headers: Vec<Header>,
- }
- impl_p2p_message!(
- HeaderSyncResponse,
- "headersyncresponse",
- 8192, // We leave some headroom for merge mining data
- 1,
- PROTOCOL_SYNC_METERING_CONFIGURATION
- );
- /// Structure represening a request to ask a node for up to`BATCH` blocks
- /// of provided headers.
- #[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
- pub struct SyncRequest {
- /// Header hashes
- pub headers: Vec<HeaderHash>,
- }
- impl_p2p_message!(SyncRequest, "syncrequest", 641, 1, PROTOCOL_SYNC_METERING_CONFIGURATION);
- /// Structure representing the response to `SyncRequest`,
- /// containing up to `BATCH` blocks after the requested block height.
- #[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
- pub struct SyncResponse {
- /// Response blocks
- pub blocks: Vec<BlockInfo>,
- }
- impl_p2p_message!(SyncResponse, "syncresponse", 0, 1, PROTOCOL_SYNC_METERING_CONFIGURATION);
- /// Structure represening a request to ask a node a fork sequence.
- /// If we include a specific fork tip, they have to return its sequence,
- /// otherwise they respond with their best fork sequence.
- /// We also include our own canonical(confirmed) tip, so they can verify
- /// we follow the same sequence.
- #[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
- pub struct ForkSyncRequest {
- /// Canonical(confirmed) tip block hash
- pub tip: HeaderHash,
- /// Optional fork tip block hash
- pub fork_tip: Option<HeaderHash>,
- }
- impl_p2p_message!(ForkSyncRequest, "forksyncrequest", 65, 1, PROTOCOL_SYNC_METERING_CONFIGURATION);
- /// Structure representing the response to `ForkSyncRequest`,
- /// containing the requested fork sequence, up to `BATCH` proposals.
- #[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
- pub struct ForkSyncResponse {
- /// Response fork proposals
- pub proposals: Vec<Proposal>,
- }
- impl_p2p_message!(ForkSyncResponse, "forksyncresponse", 0, 1, PROTOCOL_SYNC_METERING_CONFIGURATION);
- /// Structure represening a request to ask a node a fork header for the
- /// requested height. The fork is identified by the provided header hash.
- #[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
- pub struct ForkHeaderHashRequest {
- /// Header height
- pub height: u32,
- /// Block header hash to identify the fork
- pub fork_header: HeaderHash,
- }
- impl_p2p_message!(
- ForkHeaderHashRequest,
- "forkheaderhashrequest",
- 36,
- 1,
- PROTOCOL_SYNC_METERING_CONFIGURATION
- );
- /// Structure representing the response to `ForkHeaderHashRequest`,
- /// containing the requested fork header hash, if it was found.
- #[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
- pub struct ForkHeaderHashResponse {
- /// Response fork block header hash
- pub fork_header: Option<HeaderHash>,
- }
- impl_p2p_message!(
- ForkHeaderHashResponse,
- "forkheaderhashresponse",
- 33,
- 1,
- PROTOCOL_SYNC_METERING_CONFIGURATION
- );
- /// Structure represening a request to ask a node for up to `BATCH`
- /// fork headers for provided header hashes. The fork is identified
- /// by the provided header hash.
- #[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
- pub struct ForkHeadersRequest {
- /// Header hashes
- pub headers: Vec<HeaderHash>,
- /// Block header hash to identify the fork
- pub fork_header: HeaderHash,
- }
- impl_p2p_message!(
- ForkHeadersRequest,
- "forkheadersrequest",
- 673,
- 1,
- PROTOCOL_SYNC_METERING_CONFIGURATION
- );
- /// Structure representing the response to `ForkHeadersRequest`,
- /// containing up to `BATCH` fork headers.
- #[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
- pub struct ForkHeadersResponse {
- /// Response headers
- pub headers: Vec<Header>,
- }
- impl_p2p_message!(
- ForkHeadersResponse,
- "forkheadersresponse",
- 8192, // We leave some headroom for merge mining data
- 1,
- PROTOCOL_SYNC_METERING_CONFIGURATION
- );
- /// Structure represening a request to ask a node for up to `BATCH`
- /// fork proposals for provided header hashes. The fork is identified
- /// by the provided header hash.
- #[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
- pub struct ForkProposalsRequest {
- /// Header hashes
- pub headers: Vec<HeaderHash>,
- /// Block header hash to identify the fork
- pub fork_header: HeaderHash,
- }
- impl_p2p_message!(
- ForkProposalsRequest,
- "forkproposalsrequest",
- 673,
- 1,
- PROTOCOL_SYNC_METERING_CONFIGURATION
- );
- /// Structure representing the response to `ForkProposalsRequest`,
- /// containing up to `BATCH` fork headers.
- #[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
- pub struct ForkProposalsResponse {
- /// Response proposals
- pub proposals: Vec<Proposal>,
- }
- impl_p2p_message!(
- ForkProposalsResponse,
- "forkproposalsresponse",
- 0,
- 1,
- PROTOCOL_SYNC_METERING_CONFIGURATION
- );
- /// Atomic pointer to the `ProtocolSync` handler.
- pub type ProtocolSyncHandlerPtr = Arc<ProtocolSyncHandler>;
- /// Handler managing all `ProtocolSync` messages, over generic P2P protocols.
- pub struct ProtocolSyncHandler {
- /// The generic handler for `TipRequest` messages.
- tip_handler: ProtocolGenericHandlerPtr<TipRequest, TipResponse>,
- /// The generic handler for `HeaderSyncRequest` messages.
- header_handler: ProtocolGenericHandlerPtr<HeaderSyncRequest, HeaderSyncResponse>,
- /// The generic handler for `SyncRequest` messages.
- sync_handler: ProtocolGenericHandlerPtr<SyncRequest, SyncResponse>,
- /// The generic handler for `ForkSyncRequest` messages.
- fork_sync_handler: ProtocolGenericHandlerPtr<ForkSyncRequest, ForkSyncResponse>,
- /// The generic handler for `ForkHeaderHashRequest` messages.
- fork_header_hash_handler:
- ProtocolGenericHandlerPtr<ForkHeaderHashRequest, ForkHeaderHashResponse>,
- /// The generic handler for `ForkHeadersRequest` messages.
- fork_headers_handler: ProtocolGenericHandlerPtr<ForkHeadersRequest, ForkHeadersResponse>,
- /// The generic handler for `ForkProposalsRequest` messages.
- fork_proposals_handler: ProtocolGenericHandlerPtr<ForkProposalsRequest, ForkProposalsResponse>,
- }
- impl ProtocolSyncHandler {
- /// Initialize the generic prototocol handlers for all `ProtocolSync` messages
- /// and register them to the provided P2P network, using the default session flag.
- pub async fn init(p2p: &P2pPtr) -> ProtocolSyncHandlerPtr {
- debug!(
- target: "darkfid::proto::protocol_sync::init",
- "Adding all sync protocols to the protocol registry"
- );
- let tip_handler =
- ProtocolGenericHandler::new(p2p, "ProtocolSyncTip", SESSION_DEFAULT).await;
- let header_handler =
- ProtocolGenericHandler::new(p2p, "ProtocolSyncHeader", SESSION_DEFAULT).await;
- let sync_handler = ProtocolGenericHandler::new(p2p, "ProtocolSync", SESSION_DEFAULT).await;
- let fork_sync_handler =
- ProtocolGenericHandler::new(p2p, "ProtocolSyncFork", SESSION_DEFAULT).await;
- let fork_header_hash_handler =
- ProtocolGenericHandler::new(p2p, "ProtocolSyncForkHeaderHash", SESSION_DEFAULT).await;
- let fork_headers_handler =
- ProtocolGenericHandler::new(p2p, "ProtocolSyncForkHeaders", SESSION_DEFAULT).await;
- let fork_proposals_handler =
- ProtocolGenericHandler::new(p2p, "ProtocolSyncForkProposals", SESSION_DEFAULT).await;
- Arc::new(Self {
- tip_handler,
- header_handler,
- sync_handler,
- fork_sync_handler,
- fork_header_hash_handler,
- fork_headers_handler,
- fork_proposals_handler,
- })
- }
- /// Start all `ProtocolSync` background tasks.
- pub async fn start(&self, executor: &ExecutorPtr, validator: &ValidatorPtr) -> Result<()> {
- debug!(
- target: "darkfid::proto::protocol_sync::start",
- "Starting sync protocols handlers tasks..."
- );
- self.tip_handler.task.clone().start(
- handle_receive_tip_request(self.tip_handler.clone(), validator.clone()),
- |res| async move {
- match res {
- Ok(()) | Err(Error::DetachedTaskStopped) => { /* Do nothing */ }
- Err(e) => error!(target: "darkfid::proto::protocol_sync::start", "Failed starting ProtocolSyncTip handler task: {e}"),
- }
- },
- Error::DetachedTaskStopped,
- executor.clone(),
- );
- self.header_handler.task.clone().start(
- handle_receive_header_request(self.header_handler.clone(), validator.clone()),
- |res| async move {
- match res {
- Ok(()) | Err(Error::DetachedTaskStopped) => { /* Do nothing */ }
- Err(e) => error!(target: "darkfid::proto::protocol_sync::start", "Failed starting ProtocolSyncHeader handler task: {e}"),
- }
- },
- Error::DetachedTaskStopped,
- executor.clone(),
- );
- self.sync_handler.task.clone().start(
- handle_receive_request(self.sync_handler.clone(), validator.clone()),
- |res| async move {
- match res {
- Ok(()) | Err(Error::DetachedTaskStopped) => { /* Do nothing */ }
- Err(e) => error!(target: "darkfid::proto::protocol_sync::start", "Failed starting ProtocolSync handler task: {e}"),
- }
- },
- Error::DetachedTaskStopped,
- executor.clone(),
- );
- self.fork_sync_handler.task.clone().start(
- handle_receive_fork_request(self.fork_sync_handler.clone(), validator.clone()),
- |res| async move {
- match res {
- Ok(()) | Err(Error::DetachedTaskStopped) => { /* Do nothing */ }
- Err(e) => error!(target: "darkfid::proto::protocol_sync::start", "Failed starting ProtocolSyncFork handler task: {e}"),
- }
- },
- Error::DetachedTaskStopped,
- executor.clone(),
- );
- self.fork_header_hash_handler.task.clone().start(
- handle_receive_fork_header_hash_request(self.fork_header_hash_handler.clone(), validator.clone()),
- |res| async move {
- match res {
- Ok(()) | Err(Error::DetachedTaskStopped) => { /* Do nothing */ }
- Err(e) => error!(target: "darkfid::proto::protocol_sync::start", "Failed starting ProtocolSyncForkHeaderHash handler task: {e}"),
- }
- },
- Error::DetachedTaskStopped,
- executor.clone(),
- );
- self.fork_headers_handler.task.clone().start(
- handle_receive_fork_headers_request(self.fork_headers_handler.clone(), validator.clone()),
- |res| async move {
- match res {
- Ok(()) | Err(Error::DetachedTaskStopped) => { /* Do nothing */ }
- Err(e) => error!(target: "darkfid::proto::protocol_sync::start", "Failed starting ProtocolSyncForkHeaders handler task: {e}"),
- }
- },
- Error::DetachedTaskStopped,
- executor.clone(),
- );
- self.fork_proposals_handler.task.clone().start(
- handle_receive_fork_proposals_request(self.fork_proposals_handler.clone(), validator.clone()),
- |res| async move {
- match res {
- Ok(()) | Err(Error::DetachedTaskStopped) => { /* Do nothing */ }
- Err(e) => error!(target: "darkfid::proto::protocol_sync::start", "Failed starting ProtocolSyncForkProposals handler task: {e}"),
- }
- },
- Error::DetachedTaskStopped,
- executor.clone(),
- );
- debug!(
- target: "darkfid::proto::protocol_sync::start",
- "Sync protocols handlers tasks started!"
- );
- Ok(())
- }
- /// Stop all `ProtocolSync` background tasks.
- pub async fn stop(&self) {
- debug!(target: "darkfid::proto::protocol_sync::stop", "Terminating sync protocols handlers tasks...");
- self.tip_handler.task.stop().await;
- self.header_handler.task.stop().await;
- self.sync_handler.task.stop().await;
- self.fork_sync_handler.task.stop().await;
- self.fork_header_hash_handler.task.stop().await;
- self.fork_headers_handler.task.stop().await;
- self.fork_proposals_handler.task.stop().await;
- debug!(target: "darkfid::proto::protocol_sync::stop", "Sync protocols handlers tasks terminated!");
- }
- }
- /// Background handler function for ProtocolSyncTip.
- async fn handle_receive_tip_request(
- handler: ProtocolGenericHandlerPtr<TipRequest, TipResponse>,
- validator: ValidatorPtr,
- ) -> Result<()> {
- debug!(target: "darkfid::proto::protocol_sync::handle_receive_tip_request", "START");
- loop {
- // Wait for a new tip request message
- let (channel, request) = match handler.receiver.recv().await {
- Ok(r) => r,
- Err(e) => {
- debug!(
- target: "darkfid::proto::protocol_sync::handle_receive_tip_request",
- "recv fail: {e}"
- );
- continue
- }
- };
- debug!(target: "darkfid::proto::protocol_sync::handle_receive_tip_request", "Received request: {request:?}");
- // Check if node has finished syncing its blockchain
- if !*validator.synced.read().await {
- debug!(
- target: "darkfid::proto::protocol_sync::handle_receive_tip_request",
- "Node still syncing blockchain"
- );
- handler
- .send_action(
- channel,
- ProtocolGenericAction::Response(TipResponse {
- synced: false,
- height: None,
- hash: None,
- }),
- )
- .await;
- continue
- }
- // Check we follow the same sequence
- match validator.blockchain.blocks.contains(&request.tip) {
- Ok(contains) => {
- if !contains {
- debug!(
- target: "darkfid::proto::protocol_sync::handle_receive_tip_request",
- "Node doesn't follow request sequence"
- );
- handler
- .send_action(
- channel,
- ProtocolGenericAction::Response(TipResponse {
- synced: true,
- height: None,
- hash: None,
- }),
- )
- .await;
- continue
- }
- }
- Err(e) => {
- error!(
- target: "darkfid::proto::protocol_sync::handle_receive_tip_request",
- "block_store.contains fail: {e}"
- );
- handler.send_action(channel, ProtocolGenericAction::Skip).await;
- continue
- }
- }
- // Grab our current tip and return it
- let tip = match validator.blockchain.last() {
- Ok(v) => v,
- Err(e) => {
- error!(
- target: "darkfid::proto::protocol_sync::handle_receive_tip_request",
- "blockchain.last fail: {e}"
- );
- handler.send_action(channel, ProtocolGenericAction::Skip).await;
- continue
- }
- };
- // Send response
- handler
- .send_action(
- channel,
- ProtocolGenericAction::Response(TipResponse {
- synced: true,
- height: Some(tip.0),
- hash: Some(tip.1),
- }),
- )
- .await;
- }
- }
- /// Background handler function for ProtocolSyncHeader.
- async fn handle_receive_header_request(
- handler: ProtocolGenericHandlerPtr<HeaderSyncRequest, HeaderSyncResponse>,
- validator: ValidatorPtr,
- ) -> Result<()> {
- debug!(target: "darkfid::proto::protocol_sync::handle_receive_header_request", "START");
- loop {
- // Wait for a new header request message
- let (channel, request) = match handler.receiver.recv().await {
- Ok(r) => r,
- Err(e) => {
- debug!(
- target: "darkfid::proto::protocol_sync::handle_receive_header_request",
- "recv fail: {e}"
- );
- continue
- }
- };
- // Check if node has finished syncing its blockchain
- if !*validator.synced.read().await {
- debug!(
- target: "darkfid::proto::protocol_sync::handle_receive_header_request",
- "Node still syncing blockchain, skipping..."
- );
- handler.send_action(channel, ProtocolGenericAction::Skip).await;
- continue
- }
- debug!(target: "darkfid::proto::protocol_sync::handle_receive_header_request", "Received request: {request:?}");
- // Grab the corresponding headers
- let headers = match validator.blockchain.get_headers_before(request.height, BATCH) {
- Ok(v) => v,
- Err(e) => {
- error!(
- target: "darkfid::proto::protocol_sync::handle_receive_header_request",
- "get_headers_before fail: {e}"
- );
- handler.send_action(channel, ProtocolGenericAction::Skip).await;
- continue
- }
- };
- // Send response
- handler
- .send_action(channel, ProtocolGenericAction::Response(HeaderSyncResponse { headers }))
- .await;
- }
- }
- /// Background handler function for ProtocolSync.
- async fn handle_receive_request(
- handler: ProtocolGenericHandlerPtr<SyncRequest, SyncResponse>,
- validator: ValidatorPtr,
- ) -> Result<()> {
- debug!(target: "darkfid::proto::protocol_sync::handle_receive_request", "START");
- loop {
- // Wait for a new sync request message
- let (channel, request) = match handler.receiver.recv().await {
- Ok(r) => r,
- Err(e) => {
- debug!(
- target: "darkfid::proto::protocol_sync::handle_receive_request",
- "recv fail: {e}"
- );
- continue
- }
- };
- // Check if node has finished syncing its blockchain
- if !*validator.synced.read().await {
- debug!(
- target: "darkfid::proto::protocol_sync::handle_receive_request",
- "Node still syncing blockchain, skipping..."
- );
- handler.send_action(channel, ProtocolGenericAction::Skip).await;
- continue
- }
- // Check if request exists the configured limit
- if request.headers.len() > BATCH {
- debug!(
- target: "darkfid::proto::protocol_sync::handle_receive_request",
- "Node requested more blocks than allowed."
- );
- handler.send_action(channel, ProtocolGenericAction::Skip).await;
- continue
- }
- debug!(target: "darkfid::proto::protocol_sync::handle_receive_request", "Received request: {request:?}");
- // Grab the corresponding blocks
- let blocks = match validator.blockchain.get_blocks_by_hash(&request.headers) {
- Ok(v) => v,
- Err(e) => {
- error!(
- target: "darkfid::proto::protocol_sync::handle_receive_request",
- "get_blocks_after fail: {e}"
- );
- handler.send_action(channel, ProtocolGenericAction::Skip).await;
- continue
- }
- };
- // Send response
- handler
- .send_action(channel, ProtocolGenericAction::Response(SyncResponse { blocks }))
- .await;
- }
- }
- /// Background handler function for ProtocolSyncFork.
- async fn handle_receive_fork_request(
- handler: ProtocolGenericHandlerPtr<ForkSyncRequest, ForkSyncResponse>,
- validator: ValidatorPtr,
- ) -> Result<()> {
- debug!(target: "darkfid::proto::protocol_sync::handle_receive_fork_request", "START");
- loop {
- // Wait for a new fork sync request message
- let (channel, request) = match handler.receiver.recv().await {
- Ok(r) => r,
- Err(e) => {
- debug!(
- target: "darkfid::proto::protocol_sync::handle_receive_fork_request",
- "recv fail: {e}"
- );
- continue
- }
- };
- // Check if node has finished syncing its blockchain
- if !*validator.synced.read().await {
- debug!(
- target: "darkfid::proto::protocol_sync::handle_receive_fork_request",
- "Node still syncing blockchain, skipping..."
- );
- handler.send_action(channel, ProtocolGenericAction::Skip).await;
- continue
- }
- debug!(target: "darkfid::proto::protocol_sync::handle_receive_fork_request", "Received request: {request:?}");
- // Retrieve proposals sequence
- let proposals = match validator
- .consensus
- .get_fork_proposals_after(request.tip, request.fork_tip, BATCH as u32)
- .await
- {
- Ok(p) => p,
- Err(e) => {
- debug!(
- target: "darkfid::proto::protocol_sync::handle_receive_fork_request",
- "Getting fork proposals failed: {e}"
- );
- handler.send_action(channel, ProtocolGenericAction::Skip).await;
- continue
- }
- };
- // Send response
- handler
- .send_action(channel, ProtocolGenericAction::Response(ForkSyncResponse { proposals }))
- .await;
- }
- }
- /// Background handler function for ProtocolSyncForkHeaderHash.
- async fn handle_receive_fork_header_hash_request(
- handler: ProtocolGenericHandlerPtr<ForkHeaderHashRequest, ForkHeaderHashResponse>,
- validator: ValidatorPtr,
- ) -> Result<()> {
- debug!(target: "darkfid::proto::protocol_sync::handle_receive_fork_header_hash_request", "START");
- loop {
- // Wait for a new fork header hash request message
- let (channel, request) = match handler.receiver.recv().await {
- Ok(r) => r,
- Err(e) => {
- debug!(
- target: "darkfid::proto::protocol_sync::handle_receive_fork_header_hash_request",
- "recv fail: {e}"
- );
- continue
- }
- };
- // Check if node has finished syncing its blockchain
- if !*validator.synced.read().await {
- debug!(
- target: "darkfid::proto::protocol_sync::handle_receive_fork_header_hash_request",
- "Node still syncing blockchain, skipping..."
- );
- handler.send_action(channel, ProtocolGenericAction::Skip).await;
- continue
- }
- debug!(target: "darkfid::proto::protocol_sync::handle_receive_fork_header_hash_request", "Received request: {request:?}");
- // Retrieve fork header
- let fork_header = match validator
- .consensus
- .get_fork_header_hash(request.height, &request.fork_header)
- .await
- {
- Ok(h) => h,
- Err(e) => {
- debug!(
- target: "darkfid::proto::protocol_sync::handle_receive_fork_header_hash_request",
- "Getting fork header hash failed: {e}"
- );
- handler.send_action(channel, ProtocolGenericAction::Skip).await;
- continue
- }
- };
- // Send response if header was found
- if fork_header.is_some() {
- handler
- .send_action(
- channel,
- ProtocolGenericAction::Response(ForkHeaderHashResponse { fork_header }),
- )
- .await;
- continue
- }
- // If header wasn't found in a fork, check canonical
- if let Err(e) = validator.blockchain.headers.get(&[request.fork_header], true) {
- debug!(
- target: "darkfid::proto::protocol_sync::handle_receive_fork_header_hash_request",
- "Getting fork header hash failed: {e}"
- );
- handler.send_action(channel, ProtocolGenericAction::Skip).await;
- continue
- };
- let response = match validator.blockchain.blocks.get_order(&[request.height], false) {
- Ok(h) => ProtocolGenericAction::Response(ForkHeaderHashResponse { fork_header: h[0] }),
- Err(e) => {
- debug!(
- target: "darkfid::proto::protocol_sync::handle_receive_fork_header_hash_request",
- "Getting fork header hash failed: {e}"
- );
- ProtocolGenericAction::Skip
- }
- };
- // Send response
- handler.send_action(channel, response).await;
- }
- }
- /// Background handler function for ProtocolSyncForkHeaders.
- async fn handle_receive_fork_headers_request(
- handler: ProtocolGenericHandlerPtr<ForkHeadersRequest, ForkHeadersResponse>,
- validator: ValidatorPtr,
- ) -> Result<()> {
- debug!(target: "darkfid::proto::protocol_sync::handle_receive_fork_headers_request", "START");
- loop {
- // Wait for a new fork header hash request message
- let (channel, request) = match handler.receiver.recv().await {
- Ok(r) => r,
- Err(e) => {
- debug!(
- target: "darkfid::proto::protocol_sync::handle_receive_fork_headers_request",
- "recv fail: {e}"
- );
- continue
- }
- };
- // Check if node has finished syncing its blockchain
- if !*validator.synced.read().await {
- debug!(
- target: "darkfid::proto::protocol_sync::handle_receive_fork_headers_request",
- "Node still syncing blockchain, skipping..."
- );
- handler.send_action(channel, ProtocolGenericAction::Skip).await;
- continue
- }
- // Check if request exists the configured limit
- if request.headers.len() > BATCH {
- debug!(
- target: "darkfid::proto::protocol_sync::handle_receive_fork_headers_request",
- "Node requested more headers than allowed."
- );
- handler.send_action(channel, ProtocolGenericAction::Skip).await;
- continue
- }
- debug!(target: "darkfid::proto::protocol_sync::handle_receive_fork_headers_request", "Received request: {request:?}");
- // Retrieve fork headers
- let headers = match validator
- .consensus
- .get_fork_headers(&request.headers, &request.fork_header)
- .await
- {
- Ok(h) => h,
- Err(e) => {
- debug!(
- target: "darkfid::proto::protocol_sync::handle_receive_fork_headers_request",
- "Getting fork headers failed: {e}"
- );
- handler.send_action(channel, ProtocolGenericAction::Skip).await;
- continue
- }
- };
- // Send response if headers were found
- if !headers.is_empty() {
- handler
- .send_action(
- channel,
- ProtocolGenericAction::Response(ForkHeadersResponse { headers }),
- )
- .await;
- continue
- }
- // If headers weren't found in a fork, check canonical
- if let Err(e) = validator.blockchain.headers.get(&[request.fork_header], true) {
- debug!(
- target: "darkfid::proto::protocol_sync::handle_receive_fork_headers_request",
- "Getting fork header hash failed: {e}"
- );
- handler.send_action(channel, ProtocolGenericAction::Skip).await;
- continue
- };
- let response = match validator.blockchain.headers.get(&request.headers, true) {
- Ok(h) => ProtocolGenericAction::Response(ForkHeadersResponse {
- headers: h.iter().map(|x| x.clone().unwrap()).collect(),
- }),
- Err(e) => {
- debug!(
- target: "darkfid::proto::protocol_sync::handle_receive_fork_headers_request",
- "Getting fork headers failed: {e}"
- );
- ProtocolGenericAction::Skip
- }
- };
- // Send response
- handler.send_action(channel, response).await;
- }
- }
- /// Background handler function for ProtocolSyncForkProposals.
- async fn handle_receive_fork_proposals_request(
- handler: ProtocolGenericHandlerPtr<ForkProposalsRequest, ForkProposalsResponse>,
- validator: ValidatorPtr,
- ) -> Result<()> {
- debug!(target: "darkfid::proto::protocol_sync::handle_receive_fork_proposals_request", "START");
- loop {
- // Wait for a new fork header hash request message
- let (channel, request) = match handler.receiver.recv().await {
- Ok(r) => r,
- Err(e) => {
- debug!(
- target: "darkfid::proto::protocol_sync::handle_receive_fork_proposals_request",
- "recv fail: {e}"
- );
- continue
- }
- };
- // Check if node has finished syncing its blockchain
- if !*validator.synced.read().await {
- debug!(
- target: "darkfid::proto::protocol_sync::handle_receive_fork_proposals_request",
- "Node still syncing blockchain, skipping..."
- );
- handler.send_action(channel, ProtocolGenericAction::Skip).await;
- continue
- }
- // Check if request exists the configured limit
- if request.headers.len() > BATCH {
- debug!(
- target: "darkfid::proto::protocol_sync::handle_receive_fork_proposals_request",
- "Node requested more proposals than allowed."
- );
- handler.send_action(channel, ProtocolGenericAction::Skip).await;
- continue
- }
- debug!(target: "darkfid::proto::protocol_sync::handle_receive_fork_proposals_request", "Received request: {request:?}");
- // Retrieve fork proposals
- let proposals = match validator
- .consensus
- .get_fork_proposals(&request.headers, &request.fork_header)
- .await
- {
- Ok(p) => p,
- Err(e) => {
- debug!(
- target: "darkfid::proto::protocol_sync::handle_receive_fork_proposals_request",
- "Getting fork proposals failed: {e}"
- );
- handler.send_action(channel, ProtocolGenericAction::Skip).await;
- continue
- }
- };
- // Send response if proposals were found
- if !proposals.is_empty() {
- handler
- .send_action(
- channel,
- ProtocolGenericAction::Response(ForkProposalsResponse { proposals }),
- )
- .await;
- continue
- }
- // If proposals weren't found in a fork, check canonical
- if let Err(e) = validator.blockchain.headers.get(&[request.fork_header], true) {
- debug!(
- target: "darkfid::proto::protocol_sync::handle_receive_fork_proposals_request",
- "Getting fork header hash failed: {e}"
- );
- handler.send_action(channel, ProtocolGenericAction::Skip).await;
- continue
- };
- let response = match validator.blockchain.get_blocks_by_hash(&request.headers) {
- Ok(blocks) => {
- let mut proposals = Vec::with_capacity(blocks.len());
- for block in blocks {
- proposals.push(Proposal::new(block));
- }
- ProtocolGenericAction::Response(ForkProposalsResponse { proposals })
- }
- Err(e) => {
- debug!(
- target: "darkfid::proto::protocol_sync::handle_receive_fork_proposals_request",
- "Getting fork proposals failed: {e}"
- );
- ProtocolGenericAction::Skip
- }
- };
- // Send response
- handler.send_action(channel, response).await;
- }
- }
|