|
|
@@ -1,5 +1,5 @@
|
|
|
use async_executor::Executor;
|
|
|
-use async_std::sync::Arc;
|
|
|
+use async_std::sync::{Arc, Mutex};
|
|
|
use async_trait::async_trait;
|
|
|
use log::{debug, error, warn};
|
|
|
|
|
|
@@ -27,6 +27,7 @@ pub struct ProtocolSync {
|
|
|
state: ValidatorStatePtr,
|
|
|
p2p: P2pPtr,
|
|
|
consensus_mode: bool,
|
|
|
+ pending: Mutex<bool>,
|
|
|
}
|
|
|
|
|
|
impl ProtocolSync {
|
|
|
@@ -51,11 +52,12 @@ impl ProtocolSync {
|
|
|
state,
|
|
|
p2p,
|
|
|
consensus_mode,
|
|
|
+ pending: Mutex::new(false),
|
|
|
}))
|
|
|
}
|
|
|
|
|
|
async fn handle_receive_request(self: Arc<Self>) -> Result<()> {
|
|
|
- debug!("ProtocolSync::handle_receive_request() [START]");
|
|
|
+ debug!("handle_receive_request() [START]");
|
|
|
loop {
|
|
|
let order = match self.request_sub.receive().await {
|
|
|
Ok(v) => v,
|
|
|
@@ -65,7 +67,7 @@ impl ProtocolSync {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
- debug!("ProtocolSync::handle_receive_request() received {:?}", order);
|
|
|
+ debug!("handle_receive_request() received {:?}", order);
|
|
|
|
|
|
// Extra validations can be added here
|
|
|
let key = order.sl;
|
|
|
@@ -76,7 +78,7 @@ impl ProtocolSync {
|
|
|
continue
|
|
|
}
|
|
|
};
|
|
|
- debug!("ProtocolSync::handle_receive_request(): Found {} blocks", blocks.len());
|
|
|
+ debug!("handle_receive_request(): Found {} blocks", blocks.len());
|
|
|
|
|
|
let response = BlockResponse { blocks };
|
|
|
if let Err(e) = self.channel.send(response).await {
|
|
|
@@ -86,7 +88,7 @@ impl ProtocolSync {
|
|
|
}
|
|
|
|
|
|
async fn handle_receive_block(self: Arc<Self>) -> Result<()> {
|
|
|
- debug!("ProtocolSync::handle_receive_block() [START]");
|
|
|
+ debug!("handle_receive_block() [START]");
|
|
|
loop {
|
|
|
let info = match self.block_sub.receive().await {
|
|
|
Ok(v) => v,
|
|
|
@@ -96,7 +98,13 @@ impl ProtocolSync {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
- debug!("ProtocolSync::handle_receive_block() received block");
|
|
|
+ debug!("handle_receive_block() received block");
|
|
|
+
|
|
|
+ // We block here if there's a pending validation, otherwise we might
|
|
|
+ // apply the same block twice.
|
|
|
+ debug!("handle_receive_block(): Waiting for pending block to apply");
|
|
|
+ while *self.pending.lock().await {}
|
|
|
+ debug!("handle_receive_block(): Pending lock released");
|
|
|
|
|
|
// Node stores finalized block, if it doesn't exist (checking by slot),
|
|
|
// and removes its transactions from the unconfirmed_txs vector.
|
|
|
@@ -104,12 +112,14 @@ impl ProtocolSync {
|
|
|
// during proposal finalization.
|
|
|
// Extra validations can be added here.
|
|
|
if !self.consensus_mode {
|
|
|
+ *self.pending.lock().await = true;
|
|
|
let info_copy = (*info).clone();
|
|
|
|
|
|
let has_block = match self.state.read().await.blockchain.has_block(&info_copy) {
|
|
|
Ok(v) => v,
|
|
|
Err(e) => {
|
|
|
error!("handle_receive_block(): failed checking for has_block(): {}", e);
|
|
|
+ *self.pending.lock().await = false;
|
|
|
continue
|
|
|
}
|
|
|
};
|
|
|
@@ -124,35 +134,42 @@ impl ProtocolSync {
|
|
|
Ok(v) => v,
|
|
|
Err(e) => {
|
|
|
warn!("handle_receive_block(): State transition fail: {}", e);
|
|
|
+ *self.pending.lock().await = false;
|
|
|
continue
|
|
|
}
|
|
|
};
|
|
|
- debug!("ProtocolSync::handle_receive_block(): All state transitions passed");
|
|
|
+ debug!("handle_receive_block(): All state transitions passed");
|
|
|
|
|
|
- debug!("ProtocolSync::handle_receive_block(): Updating canon state machine");
|
|
|
+ debug!("handle_receive_block(): Updating canon state machine");
|
|
|
if let Err(e) =
|
|
|
self.state.write().await.update_canon_state(state_updates, None).await
|
|
|
{
|
|
|
error!("handle_receive_block(): Canon statemachine update fail: {}", e);
|
|
|
+ *self.pending.lock().await = false;
|
|
|
continue
|
|
|
};
|
|
|
|
|
|
- debug!("ProtocolSync::handle_receive_block(): Appending block to ledger");
|
|
|
+ debug!("handle_receive_block(): Appending block to ledger");
|
|
|
if let Err(e) = self.state.write().await.blockchain.add(&[info_copy.clone()]) {
|
|
|
error!("handle_receive_block(): blockchain.add() fail: {}", e);
|
|
|
+ *self.pending.lock().await = false;
|
|
|
continue
|
|
|
};
|
|
|
|
|
|
if let Err(e) = self.state.write().await.remove_txs(info_copy.txs.clone()) {
|
|
|
error!("handle_receive_block(): remove_txs() fail: {}", e);
|
|
|
+ *self.pending.lock().await = false;
|
|
|
continue
|
|
|
};
|
|
|
|
|
|
if let Err(e) = self.p2p.broadcast(info_copy).await {
|
|
|
error!("handle_receive_block(): p2p broadcast fail: {}", e);
|
|
|
+ *self.pending.lock().await = false;
|
|
|
continue
|
|
|
};
|
|
|
}
|
|
|
+
|
|
|
+ *self.pending.lock().await = false;
|
|
|
}
|
|
|
}
|
|
|
}
|