|
|
@@ -17,6 +17,7 @@
|
|
|
*/
|
|
|
|
|
|
use darkfi::{
|
|
|
+ util::async_util::sleep,
|
|
|
validator::proto::{SyncRequest, SyncResponse},
|
|
|
Result,
|
|
|
};
|
|
|
@@ -27,43 +28,55 @@ use crate::Darkfid;
|
|
|
/// async task used for block syncing
|
|
|
pub async fn sync_task(node: &Darkfid) -> Result<()> {
|
|
|
info!(target: "darkfid::task::sync_task", "Starting blockchain sync...");
|
|
|
+ // Block until at least node is connected to at least one peer
|
|
|
+ loop {
|
|
|
+ if !node.sync_p2p.channels().lock().await.is_empty() {
|
|
|
+ break
|
|
|
+ }
|
|
|
+ warn!(target: "darkfid::task::sync_task", "Node is not connected to other nodes, waiting to retry...");
|
|
|
+ sleep(10).await;
|
|
|
+ }
|
|
|
+
|
|
|
// Getting a random connected channel to ask from peers
|
|
|
- match node.sync_p2p.random_channel().await {
|
|
|
- Some(channel) => {
|
|
|
- // Communication setup
|
|
|
- let msg_subsystem = channel.message_subsystem();
|
|
|
- msg_subsystem.add_dispatch::<SyncResponse>().await;
|
|
|
- let block_response_sub = channel.subscribe_msg::<SyncResponse>().await?;
|
|
|
+ let channel = node.sync_p2p.random_channel().await.unwrap();
|
|
|
|
|
|
- // Node sends the last known block hash of the canonical blockchain
|
|
|
- // and loops until the response is the same block (used to utilize
|
|
|
- // batch requests).
|
|
|
- let mut last = node.validator.read().await.blockchain.last()?;
|
|
|
- info!(target: "darkfid::task::sync_task", "Last known block: {:?} - {:?}", last.0, last.1);
|
|
|
- loop {
|
|
|
- // Node creates a `SyncRequest` and sends it
|
|
|
- let request = SyncRequest { slot: last.0, block: last.1 };
|
|
|
- channel.send(&request).await?;
|
|
|
+ // Communication setup
|
|
|
+ let msg_subsystem = channel.message_subsystem();
|
|
|
+ msg_subsystem.add_dispatch::<SyncResponse>().await;
|
|
|
+ let block_response_sub = channel.subscribe_msg::<SyncResponse>().await?;
|
|
|
|
|
|
- // Node stores response data
|
|
|
- let response = block_response_sub.receive().await?;
|
|
|
+ // TODO: make this parallel and use a head selection method,
|
|
|
+ // for example use a manual known head and only connect to nodes
|
|
|
+ // that follow that. Also use a random peer on every block range
|
|
|
+ // we sync.
|
|
|
|
|
|
- // Verify and store retrieved blocks
|
|
|
- debug!(target: "darkfid::task::sync_task", "block_sync_task(): Processing received blocks");
|
|
|
- node.validator.write().await.add_blocks(&response.blocks).await?;
|
|
|
+ // Node sends the last known block hash of the canonical blockchain
|
|
|
+ // and loops until the response is the same block (used to utilize
|
|
|
+ // batch requests).
|
|
|
+ let mut last = node.validator.read().await.blockchain.last()?;
|
|
|
+ info!(target: "darkfid::task::sync_task", "Last known block: {:?} - {:?}", last.0, last.1);
|
|
|
+ loop {
|
|
|
+ // Node creates a `SyncRequest` and sends it
|
|
|
+ let request = SyncRequest { slot: last.0, block: last.1 };
|
|
|
+ channel.send(&request).await?;
|
|
|
|
|
|
- let last_received = node.validator.read().await.blockchain.last()?;
|
|
|
- info!(target: "darkfid::task::sync_task", "Last received block: {:?} - {:?}", last_received.0, last_received.1);
|
|
|
+ // TODO: add a timeout here to retry
|
|
|
+ // Node waits for response
|
|
|
+ let response = block_response_sub.receive().await?;
|
|
|
|
|
|
- if last == last_received {
|
|
|
- break
|
|
|
- }
|
|
|
+ // Verify and store retrieved blocks
|
|
|
+ debug!(target: "darkfid::task::sync_task", "Processing received blocks");
|
|
|
+ node.validator.read().await.add_blocks(&response.blocks).await?;
|
|
|
|
|
|
- last = last_received;
|
|
|
- }
|
|
|
+ let last_received = node.validator.read().await.blockchain.last()?;
|
|
|
+ info!(target: "darkfid::task::sync_task", "Last received block: {:?} - {:?}", last_received.0, last_received.1);
|
|
|
+
|
|
|
+ if last == last_received {
|
|
|
+ break
|
|
|
}
|
|
|
- None => warn!(target: "darkfid::task::sync_task", "Node is not connected to other nodes"),
|
|
|
- };
|
|
|
+
|
|
|
+ last = last_received;
|
|
|
+ }
|
|
|
|
|
|
node.validator.write().await.synced = true;
|
|
|
info!(target: "darkfid::task::sync_task", "Blockchain synced!");
|