Optimized new block processing. Added quick-ban for those, who send wrong blocks.
This commit is contained in:
@@ -611,6 +611,10 @@ impl Chain {
|
||||
|
||||
/// Check if this block can be added to our blockchain
|
||||
pub fn check_new_block(&self, block: &Block) -> BlockQuality {
|
||||
if block.version > CHAIN_VERSION {
|
||||
warn!("Ignoring block from unsupported version:\n{:?}", &block);
|
||||
return Bad;
|
||||
}
|
||||
let timestamp = Utc::now().timestamp();
|
||||
if block.timestamp > timestamp + 60 {
|
||||
warn!("Ignoring block from the future:\n{:?}", &block);
|
||||
|
||||
+57
-55
@@ -357,7 +357,6 @@ fn handle_message(context: Arc<Mutex<Context>>, message: Message, peers: &mut Pe
|
||||
};
|
||||
let answer = match message {
|
||||
Message::Hand { app_version, origin, version, public, rand} => {
|
||||
debug!("Hello from v{}", &app_version);
|
||||
if peers.is_our_own_connect(&rand) {
|
||||
warn!("Detected loop connect");
|
||||
State::Banned
|
||||
@@ -365,6 +364,7 @@ fn handle_message(context: Arc<Mutex<Context>>, message: Message, peers: &mut Pe
|
||||
if origin.eq(my_origin) && version == my_version {
|
||||
let peer = peers.get_mut_peer(token).unwrap();
|
||||
peer.set_public(public);
|
||||
debug!("Hello from v{} on {}", &app_version, peer.get_addr().ip());
|
||||
State::message(Message::shake(&origin, version, true, my_height))
|
||||
} else {
|
||||
warn!("Handshake from unsupported chain or version");
|
||||
@@ -453,65 +453,67 @@ fn handle_message(context: Arc<Mutex<Context>>, message: Message, peers: &mut Pe
|
||||
Ok(block) => block,
|
||||
Err(_) => return State::Error
|
||||
};
|
||||
let peer = peers.get_mut_peer(token).unwrap();
|
||||
peer.set_received_block(block.index);
|
||||
if let Some(transaction) = &block.transaction {
|
||||
if context.lock().unwrap().x_zones.has_hash(&transaction.identity.to_string()) {
|
||||
// This peer has mined some of the forbidden zones
|
||||
return State::Banned;
|
||||
}
|
||||
}
|
||||
let context = Arc::clone(&context);
|
||||
let peers_count = peers.get_peers_active_count();
|
||||
let _ = thread::Builder::new().name(String::from("Message::Block")).spawn(move || {
|
||||
let mut context = context.lock().unwrap();
|
||||
let max_height = context.chain.max_height();
|
||||
match context.chain.check_new_block(&block) {
|
||||
BlockQuality::Good => {
|
||||
context.chain.add_block(block);
|
||||
let keystore = context.keystore.clone();
|
||||
context.chain.update(&keystore);
|
||||
let my_height = context.chain.height();
|
||||
context.bus.post(crate::event::Event::BlockchainChanged { index: my_height });
|
||||
// If it was the last block to sync
|
||||
if my_height == max_height {
|
||||
context.bus.post(crate::event::Event::SyncFinished);
|
||||
} else {
|
||||
context.bus.post(crate::event::Event::Syncing { have: my_height, height: max_height});
|
||||
}
|
||||
context.bus.post(crate::event::Event::NetworkStatus { nodes: peers_count, blocks: my_height });
|
||||
}
|
||||
BlockQuality::Twin => { debug!("Ignoring duplicate block {}", block.index); }
|
||||
BlockQuality::Future => { debug!("Ignoring future block {}", block.index); }
|
||||
BlockQuality::Bad => {
|
||||
// TODO save bad public keys to banned table
|
||||
debug!("Ignoring bad block {} with hash {:?}", block.index, block.hash);
|
||||
let height = context.chain.height();
|
||||
context.chain.update_max_height(height);
|
||||
context.bus.post(crate::event::Event::SyncFinished);
|
||||
}
|
||||
BlockQuality::Fork => {
|
||||
debug!("Got forked block {} with hash {:?}", block.index, block.hash);
|
||||
let last_block = context.chain.last_block().unwrap();
|
||||
if block.is_better_than(&last_block) {
|
||||
context.chain.replace_block(block.index, block).expect("Error replacing block with fork");
|
||||
let keystore = context.keystore.clone();
|
||||
context.chain.update(&keystore);
|
||||
let index = context.chain.height();
|
||||
context.bus.post(crate::event::Event::BlockchainChanged { index });
|
||||
}
|
||||
let height = context.chain.height();
|
||||
context.chain.update_max_height(height);
|
||||
context.bus.post(crate::event::Event::SyncFinished);
|
||||
}
|
||||
}
|
||||
});
|
||||
State::idle()
|
||||
process_new_block(context, peers, token, block)
|
||||
}
|
||||
};
|
||||
answer
|
||||
}
|
||||
|
||||
fn process_new_block(context: Arc<Mutex<Context>>, peers: &mut Peers, token: &Token, block: Block) -> State {
|
||||
let peer = peers.get_mut_peer(token).unwrap();
|
||||
peer.set_received_block(block.index);
|
||||
if let Some(transaction) = &block.transaction {
|
||||
if context.lock().unwrap().x_zones.has_hash(&transaction.identity.to_string()) {
|
||||
// This peer has mined some of the forbidden zones
|
||||
return State::Banned;
|
||||
}
|
||||
}
|
||||
let peers_count = peers.get_peers_active_count();
|
||||
let mut context = context.lock().unwrap();
|
||||
let max_height = context.chain.max_height();
|
||||
match context.chain.check_new_block(&block) {
|
||||
BlockQuality::Good => {
|
||||
context.chain.add_block(block);
|
||||
let keystore = context.keystore.clone();
|
||||
context.chain.update(&keystore);
|
||||
let my_height = context.chain.height();
|
||||
context.bus.post(crate::event::Event::BlockchainChanged { index: my_height });
|
||||
// If it was the last block to sync
|
||||
if my_height == max_height {
|
||||
context.bus.post(crate::event::Event::SyncFinished);
|
||||
} else {
|
||||
context.bus.post(crate::event::Event::Syncing { have: my_height, height: max_height });
|
||||
}
|
||||
context.bus.post(crate::event::Event::NetworkStatus { nodes: peers_count, blocks: my_height });
|
||||
}
|
||||
BlockQuality::Twin => { debug!("Ignoring duplicate block {}", block.index); }
|
||||
BlockQuality::Future => { debug!("Ignoring future block {}", block.index); }
|
||||
BlockQuality::Bad => {
|
||||
// TODO save bad public keys to banned table
|
||||
debug!("Ignoring bad block {} with hash {:?}", block.index, block.hash);
|
||||
let height = context.chain.height();
|
||||
context.chain.update_max_height(height);
|
||||
context.bus.post(crate::event::Event::SyncFinished);
|
||||
return State::Banned;
|
||||
}
|
||||
BlockQuality::Fork => {
|
||||
debug!("Got forked block {} with hash {:?}", block.index, block.hash);
|
||||
let last_block = context.chain.last_block().unwrap();
|
||||
if block.is_better_than(&last_block) {
|
||||
context.chain.replace_block(block.index, block).expect("Error replacing block with fork");
|
||||
let keystore = context.keystore.clone();
|
||||
context.chain.update(&keystore);
|
||||
let index = context.chain.height();
|
||||
context.bus.post(crate::event::Event::BlockchainChanged { index });
|
||||
}
|
||||
let height = context.chain.height();
|
||||
context.chain.update_max_height(height);
|
||||
context.bus.post(crate::event::Event::SyncFinished);
|
||||
}
|
||||
}
|
||||
State::idle()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn deal_with_fork(context: MutexGuard<Context>, peer: &mut Peer, block: Block) {
|
||||
peer.add_fork_block(block);
|
||||
|
||||
+10
-1
@@ -79,7 +79,16 @@ impl Peer {
|
||||
}
|
||||
|
||||
pub fn has_more_blocks(&self, height: u64) -> bool {
|
||||
self.height > self.received_block && self.height > height && self.get_state().is_idle()
|
||||
if self.height <= height {
|
||||
return false;
|
||||
}
|
||||
if self.received_block > height {
|
||||
return false;
|
||||
}
|
||||
if !self.get_state().is_idle() {
|
||||
return false;
|
||||
}
|
||||
self.height > height
|
||||
}
|
||||
|
||||
pub fn is_public(&self) -> bool {
|
||||
|
||||
+1
-1
@@ -239,7 +239,7 @@ impl Peers {
|
||||
.choose(&mut rng) {
|
||||
None => {}
|
||||
Some((token, peer)) => {
|
||||
debug!("Found some peer higher than we are, requesting block {}", height + 1);
|
||||
debug!("Found some peer higher than we are, requesting block {}, from {}", height + 1, &peer.get_addr().ip());
|
||||
registry.reregister(peer.get_stream(), token.clone(), Interest::WRITABLE).unwrap();
|
||||
peer.set_state(State::message(Message::GetBlock { index: height + 1 }));
|
||||
ping_sent = true;
|
||||
|
||||
Reference in New Issue
Block a user