|
|
@@ -29,7 +29,7 @@ use darkfi::{
|
|
|
ChannelPtr, Message, MessageSubscription, ProtocolBase, ProtocolBasePtr,
|
|
|
ProtocolJobsManager, ProtocolJobsManagerPtr,
|
|
|
},
|
|
|
- validator::ValidatorPtr,
|
|
|
+ validator::{consensus::Proposal, ValidatorPtr},
|
|
|
Result,
|
|
|
};
|
|
|
use darkfi_serial::{SerialDecodable, SerialEncodable};
|
|
|
@@ -55,8 +55,29 @@ pub struct SyncResponse {
|
|
|
|
|
|
impl_p2p_message!(SyncResponse, "syncresponse");
|
|
|
|
|
|
+/// Auxiliary structure used for fork chain syncing.
|
|
|
+#[derive(Debug, SerialEncodable, SerialDecodable)]
|
|
|
+pub struct ForkSyncRequest {
|
|
|
+ /// Canonical(finalized) tip block hash
|
|
|
+ pub tip: blake3::Hash,
|
|
|
+ /// Optional fork tip block hash
|
|
|
+ pub fork_tip: Option<blake3::Hash>,
|
|
|
+}
|
|
|
+
|
|
|
+impl_p2p_message!(ForkSyncRequest, "forksyncrequest");
|
|
|
+
|
|
|
+/// Auxiliary structure used for fork chain syncing.
|
|
|
+#[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
|
|
|
+pub struct ForkSyncResponse {
|
|
|
+ /// Response fork proposals
|
|
|
+ pub proposals: Vec<Proposal>,
|
|
|
+}
|
|
|
+
|
|
|
+impl_p2p_message!(ForkSyncResponse, "forksyncresponse");
|
|
|
+
|
|
|
pub struct ProtocolSync {
|
|
|
request_sub: MessageSubscription<SyncRequest>,
|
|
|
+ fork_request_sub: MessageSubscription<ForkSyncRequest>,
|
|
|
jobsman: ProtocolJobsManagerPtr,
|
|
|
validator: ValidatorPtr,
|
|
|
channel: ChannelPtr,
|
|
|
@@ -70,11 +91,14 @@ impl ProtocolSync {
|
|
|
);
|
|
|
let msg_subsystem = channel.message_subsystem();
|
|
|
msg_subsystem.add_dispatch::<SyncRequest>().await;
|
|
|
+ msg_subsystem.add_dispatch::<ForkSyncRequest>().await;
|
|
|
|
|
|
let request_sub = channel.subscribe_msg::<SyncRequest>().await?;
|
|
|
+ let fork_request_sub = channel.subscribe_msg::<ForkSyncRequest>().await?;
|
|
|
|
|
|
Ok(Arc::new(Self {
|
|
|
request_sub,
|
|
|
+ fork_request_sub,
|
|
|
jobsman: ProtocolJobsManager::new("SyncProtocol", channel.clone()),
|
|
|
validator,
|
|
|
channel,
|
|
|
@@ -127,6 +151,61 @@ impl ProtocolSync {
|
|
|
};
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ async fn handle_receive_fork_request(self: Arc<Self>) -> Result<()> {
|
|
|
+ debug!(target: "darkfid::proto::protocol_sync::handle_receive_fork_request", "START");
|
|
|
+ loop {
|
|
|
+ let request = match self.fork_request_sub.receive().await {
|
|
|
+ Ok(v) => v,
|
|
|
+ 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 !*self.validator.synced.read().await {
|
|
|
+ debug!(
|
|
|
+ target: "darkfid::proto::protocol_sync::handle_receive_fork_request",
|
|
|
+ "Node still syncing blockchain, skipping..."
|
|
|
+ );
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ // If a fork tip is provided, grab its fork proposals sequence.
|
|
|
+ // Otherwise, grab best fork proposals sequence.
|
|
|
+ let proposals = match request.fork_tip {
|
|
|
+ Some(fork_tip) => {
|
|
|
+ self.validator.consensus.get_fork_proposals(request.tip, fork_tip).await
|
|
|
+ }
|
|
|
+ None => self.validator.consensus.get_best_fork_proposals(request.tip).await,
|
|
|
+ };
|
|
|
+ let proposals = match proposals {
|
|
|
+ Ok(p) => p,
|
|
|
+ Err(e) => {
|
|
|
+ debug!(
|
|
|
+ target: "darkfid::proto::protocol_sync::handle_receive_request",
|
|
|
+ "Getting fork proposals failed: {}",
|
|
|
+ e
|
|
|
+ );
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ let response = ForkSyncResponse { proposals };
|
|
|
+ if let Err(e) = self.channel.send(&response).await {
|
|
|
+ debug!(
|
|
|
+ target: "darkfid::proto::protocol_sync::handle_receive_fork_request",
|
|
|
+ "channel send fail: {}",
|
|
|
+ e
|
|
|
+ )
|
|
|
+ };
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
#[async_trait]
|
|
|
@@ -135,6 +214,10 @@ impl ProtocolBase for ProtocolSync {
|
|
|
debug!(target: "darkfid::proto::protocol_sync::start", "START");
|
|
|
self.jobsman.clone().start(executor.clone());
|
|
|
self.jobsman.clone().spawn(self.clone().handle_receive_request(), executor.clone()).await;
|
|
|
+ self.jobsman
|
|
|
+ .clone()
|
|
|
+ .spawn(self.clone().handle_receive_fork_request(), executor.clone())
|
|
|
+ .await;
|
|
|
debug!(target: "darkfid::proto::protocol_sync::start", "END");
|
|
|
Ok(())
|
|
|
}
|