From 9554aadf052388745768aa535d5dcf6f17f77393 Mon Sep 17 00:00:00 2001
From: Peter Jankuliak
Date: Tue, 17 Oct 2023 11:17:19 +0200
Subject: [PATCH] Don't accept block by the same client who previously failed
---
lib/src/missing_parts/tracker.rs | 32 ++++++++++++++++++++++++--------
1 file changed, 24 insertions(+), 8 deletions(-)
diff --git a/lib/src/missing_parts/tracker.rs b/lib/src/missing_parts/tracker.rs
index 5114984db..4181c96e4 100644
--- a/lib/src/missing_parts/tracker.rs
+++ b/lib/src/missing_parts/tracker.rs
@@ -42,7 +42,8 @@ impl Tracker {
.entry(part_id)
.or_insert_with(|| MissingPartState {
offering_clients: HashSet::default(),
- accepted_by: None,
+ currently_accepted_by: None,
+ previously_accepted_by: Default::default(),
required: false,
approved: false,
});
@@ -149,13 +150,18 @@ impl TrackerClient {
.entry(part_id)
.or_insert_with(|| MissingPartState {
offering_clients: HashSet::default(),
- accepted_by: None,
+ currently_accepted_by: None,
+ previously_accepted_by: Default::default(),
required: false,
approved: false,
});
missing_part.offering_clients.insert(self.client_id);
+ // The peer could have previously lied about having the part (e.g. expired block). Now it's
+ // claiming to have it again so we need to reconsider loading from it again.
+ missing_part.previously_accepted_by.remove(&self.client_id);
+
match state {
OfferState::Approved => {
missing_part.approved = true;
@@ -184,6 +190,9 @@ impl Drop for TrackerClient {
notify = true;
}
+ // When the client reconnects, we allow it to accept the again.
+ missing_part.previously_accepted_by.remove(&self.client_id);
+
// TODO: if the block hasn't other offers and isn't required, remove it
}
@@ -233,9 +242,15 @@ impl PartPromiseAcceptor {
// unwrap is ok because of the invariant in `Inner`
let missing_part = inner.missing_parts.get_mut(part_id).unwrap();
- if missing_part.required && missing_part.approved && missing_part.accepted_by.is_none()
+ if missing_part.required
+ && missing_part.approved
+ && missing_part.currently_accepted_by.is_none()
+ && !missing_part
+ .previously_accepted_by
+ .contains(&self.client_id)
{
- missing_part.accepted_by = Some(self.client_id);
+ missing_part.currently_accepted_by = Some(self.client_id);
+ missing_part.previously_accepted_by.insert(self.client_id);
return Some(PartPromise {
shared: self.shared.clone(),
@@ -354,16 +369,17 @@ struct Inner {
#[derive(Debug)]
struct MissingPartState {
offering_clients: HashSet,
- accepted_by: Option,
+ currently_accepted_by: Option,
+ previously_accepted_by: HashSet,
required: bool,
approved: bool,
}
impl MissingPartState {
fn unaccept_by(&mut self, client_id: ClientId) -> bool {
- if let Some(accepted_by) = &self.accepted_by {
- if accepted_by == &client_id {
- self.accepted_by = None;
+ if let Some(currently_accepted_by) = &self.currently_accepted_by {
+ if currently_accepted_by == &client_id {
+ self.currently_accepted_by = None;
return true;
}
}