mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-08-11 20:30:58 +00:00
statement-distribution: Fix CostMinor("Unexpected Statement") (#3223)
On grid distribution messages have two paths of reaching a node, so there is the possiblity of a race when two peers send each other the same statement around the same time. Statement local_knowledge will tell us that the peer should have not send the statement because we sent it to it. Fix it by also keeping track only of the statement we received from a given peer and penalize it only if it sends it to us more than once. Fixes: https://github.com/paritytech/polkadot-sdk/issues/2346 Additionally, also use different Cost labels for different paths to make it easier to debug things. --------- Signed-off-by: Alexandru Gheorghe <alexandru.gheorghe@parity.io>
This commit is contained in:
committed by
GitHub
parent
c3489aaf2f
commit
8362a6810d
@@ -527,12 +527,16 @@ impl GridTracker {
|
||||
}
|
||||
|
||||
/// Determine the validators which can send a statement to us by direct broadcast.
|
||||
///
|
||||
/// Returns a list of tuples representing each potential sender(ValidatorIndex)
|
||||
/// and if the sender should already know about the statement, because we just
|
||||
/// sent it to it.
|
||||
pub fn direct_statement_providers(
|
||||
&self,
|
||||
groups: &Groups,
|
||||
originator: ValidatorIndex,
|
||||
statement: &CompactStatement,
|
||||
) -> Vec<ValidatorIndex> {
|
||||
) -> Vec<(ValidatorIndex, bool)> {
|
||||
let (g, c_h, kind, in_group) =
|
||||
match extract_statement_and_group_info(groups, originator, statement) {
|
||||
None => return Vec::new(),
|
||||
@@ -616,12 +620,13 @@ impl GridTracker {
|
||||
originator: ValidatorIndex,
|
||||
counterparty: ValidatorIndex,
|
||||
statement: &CompactStatement,
|
||||
received: bool,
|
||||
) {
|
||||
if let Some((_, c_h, kind, in_group)) =
|
||||
extract_statement_and_group_info(groups, originator, statement)
|
||||
{
|
||||
if let Some(known) = self.confirmed_backed.get_mut(&c_h) {
|
||||
known.sent_or_received_direct_statement(counterparty, in_group, kind);
|
||||
known.sent_or_received_direct_statement(counterparty, in_group, kind, received);
|
||||
|
||||
if let Some(pending) = self.pending_statements.get_mut(&counterparty) {
|
||||
pending.remove(&(originator, statement.clone()));
|
||||
@@ -908,6 +913,12 @@ struct MutualKnowledge {
|
||||
/// `Some` only if we have advertised, acknowledged, or requested the candidate
|
||||
/// from them.
|
||||
local_knowledge: Option<StatementFilter>,
|
||||
/// Knowledge peer circulated to us, this is different from `local_knowledge` and
|
||||
/// `remote_knowledge`, through the fact that includes only statements that we received from
|
||||
/// peer while the other two, after manifest exchange part will include both what we sent to
|
||||
/// the peer and what we received from peer, see `sent_or_received_direct_statement` for more
|
||||
/// details.
|
||||
received_knowledge: Option<StatementFilter>,
|
||||
}
|
||||
|
||||
// A utility struct for keeping track of metadata about candidates
|
||||
@@ -933,10 +944,13 @@ impl KnownBackedCandidate {
|
||||
}
|
||||
|
||||
fn manifest_sent_to(&mut self, validator: ValidatorIndex, local_knowledge: StatementFilter) {
|
||||
let k = self
|
||||
.mutual_knowledge
|
||||
.entry(validator)
|
||||
.or_insert_with(|| MutualKnowledge { remote_knowledge: None, local_knowledge: None });
|
||||
let k = self.mutual_knowledge.entry(validator).or_insert_with(|| MutualKnowledge {
|
||||
remote_knowledge: None,
|
||||
local_knowledge: None,
|
||||
received_knowledge: None,
|
||||
});
|
||||
k.received_knowledge =
|
||||
Some(StatementFilter::blank(local_knowledge.seconded_in_group.len()));
|
||||
|
||||
k.local_knowledge = Some(local_knowledge);
|
||||
}
|
||||
@@ -946,20 +960,24 @@ impl KnownBackedCandidate {
|
||||
validator: ValidatorIndex,
|
||||
remote_knowledge: StatementFilter,
|
||||
) {
|
||||
let k = self
|
||||
.mutual_knowledge
|
||||
.entry(validator)
|
||||
.or_insert_with(|| MutualKnowledge { remote_knowledge: None, local_knowledge: None });
|
||||
let k = self.mutual_knowledge.entry(validator).or_insert_with(|| MutualKnowledge {
|
||||
remote_knowledge: None,
|
||||
local_knowledge: None,
|
||||
received_knowledge: None,
|
||||
});
|
||||
|
||||
k.remote_knowledge = Some(remote_knowledge);
|
||||
}
|
||||
|
||||
/// Returns a list of tuples representing each potential sender(ValidatorIndex)
|
||||
/// and if the sender should already know about the statement, because we just
|
||||
/// sent it to it.
|
||||
fn direct_statement_senders(
|
||||
&self,
|
||||
group_index: GroupIndex,
|
||||
originator_index_in_group: usize,
|
||||
statement_kind: StatementKind,
|
||||
) -> Vec<ValidatorIndex> {
|
||||
) -> Vec<(ValidatorIndex, bool)> {
|
||||
if group_index != self.group_index {
|
||||
return Vec::new()
|
||||
}
|
||||
@@ -968,11 +986,18 @@ impl KnownBackedCandidate {
|
||||
.iter()
|
||||
.filter(|(_, k)| k.remote_knowledge.is_some())
|
||||
.filter(|(_, k)| {
|
||||
k.local_knowledge
|
||||
k.received_knowledge
|
||||
.as_ref()
|
||||
.map_or(false, |r| !r.contains(originator_index_in_group, statement_kind))
|
||||
})
|
||||
.map(|(v, _)| *v)
|
||||
.map(|(v, k)| {
|
||||
(
|
||||
*v,
|
||||
k.local_knowledge
|
||||
.as_ref()
|
||||
.map_or(false, |r| r.contains(originator_index_in_group, statement_kind)),
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
@@ -1014,12 +1039,19 @@ impl KnownBackedCandidate {
|
||||
validator: ValidatorIndex,
|
||||
statement_index_in_group: usize,
|
||||
statement_kind: StatementKind,
|
||||
received: bool,
|
||||
) {
|
||||
if let Some(k) = self.mutual_knowledge.get_mut(&validator) {
|
||||
if let (Some(r), Some(l)) = (k.remote_knowledge.as_mut(), k.local_knowledge.as_mut()) {
|
||||
r.set(statement_index_in_group, statement_kind);
|
||||
l.set(statement_index_in_group, statement_kind);
|
||||
}
|
||||
|
||||
if received {
|
||||
k.received_knowledge
|
||||
.as_mut()
|
||||
.map(|knowledge| knowledge.set(statement_index_in_group, statement_kind));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2238,6 +2270,7 @@ mod tests {
|
||||
validator_index,
|
||||
counterparty,
|
||||
&statement,
|
||||
false,
|
||||
);
|
||||
|
||||
// There should be no pending statements now (for the counterparty).
|
||||
|
||||
Reference in New Issue
Block a user