Speedup initial blockchain receiving.
This commit is contained in:
@@ -65,6 +65,15 @@ impl Blockchain {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_block(&mut self, block: Block) -> Result<(), &str> {
|
pub fn add_block(&mut self, block: Block) -> Result<(), &str> {
|
||||||
|
match &self.last_block {
|
||||||
|
None => {}
|
||||||
|
Some(last_block) => {
|
||||||
|
if last_block.index >= block.index && last_block.hash == block.hash {
|
||||||
|
info!("Ignoring block {}, we already have it", block.index);
|
||||||
|
return Err("Already have that block");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if !self.check_block(&block, &self.last_block) {
|
if !self.check_block(&block, &self.last_block) {
|
||||||
warn!("Bad block found, ignoring:\n{:?}", &block);
|
warn!("Bad block found, ignoring:\n{:?}", &block);
|
||||||
return Err("Bad block found, ignoring");
|
return Err("Bad block found, ignoring");
|
||||||
|
|||||||
+9
-3
@@ -273,7 +273,9 @@ fn handle_message(context: Arc<Mutex<Context>>, message: Message, peers: &mut Pe
|
|||||||
return State::Error;
|
return State::Error;
|
||||||
}
|
}
|
||||||
if ok {
|
if ok {
|
||||||
if height > my_height {
|
let peer = peers.get_mut_peer(token).unwrap();
|
||||||
|
peer.set_height(height);
|
||||||
|
if peer.is_higher(my_height) {
|
||||||
State::message(Message::GetBlock { index: my_height })
|
State::message(Message::GetBlock { index: my_height })
|
||||||
} else {
|
} else {
|
||||||
State::message(Message::GetPeers)
|
State::message(Message::GetPeers)
|
||||||
@@ -284,14 +286,18 @@ fn handle_message(context: Arc<Mutex<Context>>, message: Message, peers: &mut Pe
|
|||||||
}
|
}
|
||||||
Message::Error => { State::Error }
|
Message::Error => { State::Error }
|
||||||
Message::Ping { height } => {
|
Message::Ping { height } => {
|
||||||
if height > my_height {
|
let peer = peers.get_mut_peer(token).unwrap();
|
||||||
|
peer.set_height(height);
|
||||||
|
if peer.is_higher(my_height) {
|
||||||
State::message(Message::GetBlock { index: my_height })
|
State::message(Message::GetBlock { index: my_height })
|
||||||
} else {
|
} else {
|
||||||
State::message(Message::pong(my_height))
|
State::message(Message::pong(my_height))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Message::Pong { height } => {
|
Message::Pong { height } => {
|
||||||
if height > my_height {
|
let peer = peers.get_mut_peer(token).unwrap();
|
||||||
|
peer.set_height(height);
|
||||||
|
if peer.is_higher(my_height) {
|
||||||
State::message(Message::GetBlock { index: my_height })
|
State::message(Message::GetBlock { index: my_height })
|
||||||
} else {
|
} else {
|
||||||
State::idle()
|
State::idle()
|
||||||
|
|||||||
+10
-1
@@ -7,13 +7,14 @@ pub struct Peer {
|
|||||||
addr: SocketAddr,
|
addr: SocketAddr,
|
||||||
stream: TcpStream,
|
stream: TcpStream,
|
||||||
state: State,
|
state: State,
|
||||||
|
height: u64,
|
||||||
inbound: bool,
|
inbound: bool,
|
||||||
public: bool,
|
public: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Peer {
|
impl Peer {
|
||||||
pub fn new(addr: SocketAddr, stream: TcpStream, state: State, inbound: bool) -> Self {
|
pub fn new(addr: SocketAddr, stream: TcpStream, state: State, inbound: bool) -> Self {
|
||||||
Peer { addr, stream, state, inbound, public: false }
|
Peer { addr, stream, state, height: 0, inbound, public: false }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_addr(&self) -> SocketAddr {
|
pub fn get_addr(&self) -> SocketAddr {
|
||||||
@@ -36,6 +37,14 @@ impl Peer {
|
|||||||
self.state = state;
|
self.state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_height(&mut self, height: u64) {
|
||||||
|
self.height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_higher(&self, height: u64) -> bool {
|
||||||
|
self.height > height
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_public(&self) -> bool {
|
pub fn is_public(&self) -> bool {
|
||||||
self.public
|
self.public
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use crate::p2p::{Peer, State, Message};
|
|||||||
use crate::p2p::network::LISTEN_PORT;
|
use crate::p2p::network::LISTEN_PORT;
|
||||||
use crate::p2p::network::next;
|
use crate::p2p::network::next;
|
||||||
use rand::random;
|
use rand::random;
|
||||||
|
use rand::seq::IteratorRandom;
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use log::{trace, debug, info, warn, error};
|
use log::{trace, debug, info, warn, error};
|
||||||
|
|
||||||
@@ -98,6 +99,7 @@ impl Peers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_pings(&mut self, registry: &Registry, height: u64) {
|
pub fn send_pings(&mut self, registry: &Registry, height: u64) {
|
||||||
|
let mut ping_sent = false;
|
||||||
for (token, peer) in self.peers.iter_mut() {
|
for (token, peer) in self.peers.iter_mut() {
|
||||||
match peer.get_state() {
|
match peer.get_state() {
|
||||||
State::Idle { from } => {
|
State::Idle { from } => {
|
||||||
@@ -113,12 +115,28 @@ impl Peers {
|
|||||||
peer.set_state(State::message(message));
|
peer.set_state(State::message(message));
|
||||||
let stream = peer.get_stream();
|
let stream = peer.get_stream();
|
||||||
registry.reregister(stream, token.clone(), Interest::WRITABLE).unwrap();
|
registry.reregister(stream, token.clone(), Interest::WRITABLE).unwrap();
|
||||||
|
ping_sent = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !ping_sent {
|
||||||
|
let mut rng = rand::thread_rng();
|
||||||
|
match self.peers
|
||||||
|
.iter_mut()
|
||||||
|
.filter_map(|(token, peer)| if peer.get_state().is_idle() && peer.is_higher(height) { Some((token, peer)) } else { None })
|
||||||
|
.choose(&mut rng) {
|
||||||
|
None => {}
|
||||||
|
Some((token, peer)) => {
|
||||||
|
debug!("Found some peer higher than we are, sending block request");
|
||||||
|
registry.reregister(peer.get_stream(), token.clone(), Interest::WRITABLE).unwrap();
|
||||||
|
peer.set_state(State::message(Message::GetBlock { index: height }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (token, peer) in self.peers.iter_mut() {
|
for (token, peer) in self.peers.iter_mut() {
|
||||||
if peer.get_state().need_reconnect() {
|
if peer.get_state().need_reconnect() {
|
||||||
let addr = peer.get_addr();
|
let addr = peer.get_addr();
|
||||||
|
|||||||
Reference in New Issue
Block a user