Check for block parent before verification. (#1714)

* Treat verification errors more seriously

* Track obsolete requests

* Check block parent before verification

* Style
This commit is contained in:
Arkadiy Paronyan
2019-02-07 11:58:27 +01:00
committed by GitHub
parent fb0f4dfb03
commit 1dc15be5bd
8 changed files with 117 additions and 135 deletions
+32 -102
View File
@@ -91,14 +91,10 @@ struct Peer<B: BlockT, H: ExHashT> {
best_hash: B::Hash,
/// Peer best block number
best_number: <B::Header as HeaderT>::Number,
/// Pending block request if any
block_request: Option<message::BlockRequest<B>>,
/// Pending block request timestamp
block_request_timestamp: Option<time::Instant>,
/// Pending block justification request if any
justification_request: Option<message::BlockRequest<B>>,
/// Pending block justification request timestamp
justification_request_timestamp: Option<time::Instant>,
/// Current block request, if any.
block_request: Option<(time::Instant, message::BlockRequest<B>)>,
/// Requests we are no longer insterested in.
obsolete_requests: HashMap<message::RequestId, time::Instant>,
/// Holds a set of transactions known to this peer.
known_extrinsics: HashSet<H>,
/// Holds a set of blocks known to this peer.
@@ -107,18 +103,6 @@ struct Peer<B: BlockT, H: ExHashT> {
next_request_id: message::RequestId,
}
impl<B: BlockT, H: ExHashT> Peer<B, H> {
fn min_request_timestamp(&self) -> Option<&time::Instant> {
match (self.block_request_timestamp, self.justification_request_timestamp) {
(Some(t1), Some(t2)) if t1 < t2 => self.block_request_timestamp.as_ref(),
(Some(_), Some(_)) => self.justification_request_timestamp.as_ref(),
(Some(_), None) => self.block_request_timestamp.as_ref(),
(None, Some(_)) => self.justification_request_timestamp.as_ref(),
_ => None,
}
}
}
/// Info about a peer's known state.
#[derive(Clone, Debug)]
pub struct PeerInfo<B: BlockT> {
@@ -433,72 +417,22 @@ impl<B: BlockT, S: NetworkSpecialization<B>, H: ExHashT> Protocol<B, S, H> {
}
fn handle_response(&mut self, who: NodeIndex, response: &message::BlockResponse<B>) -> Option<message::BlockRequest<B>> {
let request = if let Some(ref mut peer) = self.context_data.peers.get_mut(&who) {
match (peer.block_request.take(), peer.justification_request.take()) {
(Some(block_request), Some(justification_request)) => {
if block_request.id == response.id {
peer.block_request_timestamp = None;
peer.justification_request = Some(justification_request);
block_request
} else if justification_request.id == response.id {
peer.justification_request_timestamp = None;
peer.block_request = Some(block_request);
justification_request
} else {
peer.justification_request_timestamp = None;
peer.block_request_timestamp = None;
trace!(target: "sync", "Ignoring mismatched response packet from {} (expected {} or {} got {})",
who,
block_request.id,
justification_request.id,
response.id,
);
return None;
}
},
(Some(block_request), None) => {
if block_request.id == response.id {
peer.block_request_timestamp = None;
block_request
} else {
peer.block_request_timestamp = None;
trace!(target: "sync", "Ignoring mismatched response packet from {} (expected {} got {})",
who,
block_request.id,
response.id,
);
return None;
}
},
(None, Some(justification_request)) => {
if justification_request.id == response.id {
peer.justification_request_timestamp = None;
justification_request
} else {
peer.justification_request_timestamp = None;
trace!(target: "sync", "Ignoring mismatched response packet from {} (expected {} got {})",
who,
justification_request.id,
response.id,
);
return None;
}
},
(None, None) => {
let _ = self
.network_chan
.send(NetworkMsg::ReportPeer(who, Severity::Bad("Unexpected response packet received from peer".to_string())));
return None;
},
if let Some(ref mut peer) = self.context_data.peers.get_mut(&who) {
if let Some(_) = peer.obsolete_requests.remove(&response.id) {
trace!(target: "sync", "Ignoring obsolete block response packet from {} ({})", who, response.id,);
return None;
}
} else {
// Clear the request. If the response is invalid peer will be disconnected anyway.
let request = peer.block_request.take();
if request.as_ref().map_or(false, |(_, r)| r.id == response.id) {
return request.map(|(_, r)| r)
}
trace!(target: "sync", "Unexpected response packet from {} ({})", who, response.id,);
let _ = self
.network_chan
.send(NetworkMsg::ReportPeer(who, Severity::Bad("Unexpected packet received from peer".to_string())));
return None;
};
Some(request)
.send(NetworkMsg::ReportPeer(who, Severity::Bad("Unexpected response packet received from peer".to_string())));
}
None
}
/// Returns protocol status
@@ -726,18 +660,19 @@ impl<B: BlockT, S: NetworkSpecialization<B>, H: ExHashT> Protocol<B, S, H> {
let tick = time::Instant::now();
let mut aborting = Vec::new();
{
for (who, timestamp) in self
.context_data
.peers
.iter()
.filter_map(|(id, peer)| peer.min_request_timestamp().map(|r| (id, r)))
.chain(self.handshaking_peers.iter())
{
if (tick - *timestamp).as_secs() > REQUEST_TIMEOUT_SEC {
trace!(target: "sync", "Timeout {}", who);
for (who, peer) in self.context_data.peers.iter() {
if peer.block_request.as_ref().map_or(false, |(t, _)| (tick - *t).as_secs() > REQUEST_TIMEOUT_SEC) {
trace!(target: "sync", "Reqeust timeout {}", who);
aborting.push(*who);
} else if peer.obsolete_requests.values().any(|t| (tick - *t).as_secs() > REQUEST_TIMEOUT_SEC) {
trace!(target: "sync", "Obsolete timeout {}", who);
aborting.push(*who);
}
}
for (who, _) in self.handshaking_peers.iter().filter(|(_, t)| (tick - **t).as_secs() > REQUEST_TIMEOUT_SEC) {
trace!(target: "sync", "Handshake timeout {}", who);
aborting.push(*who);
}
}
self.specialization
@@ -819,12 +754,10 @@ impl<B: BlockT, S: NetworkSpecialization<B>, H: ExHashT> Protocol<B, S, H> {
best_hash: status.best_hash,
best_number: status.best_number,
block_request: None,
block_request_timestamp: None,
justification_request: None,
justification_request_timestamp: None,
known_extrinsics: HashSet::new(),
known_blocks: HashSet::new(),
next_request_id: 0,
obsolete_requests: HashMap::new(),
};
self.context_data.peers.insert(who.clone(), peer);
self.handshaking_peers.remove(&who);
@@ -1182,14 +1115,11 @@ fn send_message<B: BlockT, H: ExHashT>(
if let Some(ref mut peer) = peers.get_mut(&who) {
r.id = peer.next_request_id;
peer.next_request_id = peer.next_request_id + 1;
if r.fields == message::BlockAttributes::JUSTIFICATION {
peer.justification_request = Some(r.clone());
peer.justification_request_timestamp = Some(time::Instant::now());
} else {
peer.block_request = Some(r.clone());
peer.block_request_timestamp = Some(time::Instant::now());
if let Some((timestamp, request)) = peer.block_request.take() {
trace!(target: "sync", "Request {} for {} is now obsolete.", request.id, who);
peer.obsolete_requests.insert(request.id, timestamp);
}
peer.block_request = Some((time::Instant::now(), r.clone()));
}
}
_ => (),