Use same fmt and clippy configs as in Substrate (#7611)

* Use same rustfmt.toml as Substrate

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* format format file

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Format with new config

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Add Substrate Clippy config

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Print Clippy version in CI

Otherwise its difficult to reproduce locally.

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Make fmt happy

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Update node/core/pvf/src/error.rs

Co-authored-by: Tsvetomir Dimitrov <tsvetomir@parity.io>

* Update node/core/pvf/src/error.rs

Co-authored-by: Tsvetomir Dimitrov <tsvetomir@parity.io>

---------

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Co-authored-by: Tsvetomir Dimitrov <tsvetomir@parity.io>
This commit is contained in:
Oliver Tale-Yazdi
2023-08-14 16:29:29 +02:00
committed by GitHub
parent ac435c96cf
commit 342d720573
203 changed files with 1880 additions and 1504 deletions
@@ -102,11 +102,13 @@ impl RecentlyOutdated {
// Aggression has 3 levels:
//
// * Aggression Level 0: The basic behaviors described above.
// * Aggression Level 1: The originator of a message sends to all peers. Other peers follow the rules above.
// * Aggression Level 2: All peers send all messages to all their row and column neighbors.
// This means that each validator will, on average, receive each message approximately `2*sqrt(n)` times.
// The aggression level of messages pertaining to a block increases when that block is unfinalized and
// is a child of the finalized block.
// * Aggression Level 1: The originator of a message sends to all peers. Other peers follow the
// rules above.
// * Aggression Level 2: All peers send all messages to all their row and column neighbors. This
// means that each validator will, on average, receive each message approximately `2*sqrt(n)`
// times.
// The aggression level of messages pertaining to a block increases when that block is unfinalized
// and is a child of the finalized block.
// This means that only one block at a time has its messages propagated with aggression > 0.
//
// A note on aggression thresholds: changes in propagation apply only to blocks which are the
@@ -120,7 +122,8 @@ impl RecentlyOutdated {
struct AggressionConfig {
/// Aggression level 1: all validators send all their own messages to all peers.
l1_threshold: Option<BlockNumber>,
/// Aggression level 2: level 1 + all validators send all messages to all peers in the X and Y dimensions.
/// Aggression level 2: level 1 + all validators send all messages to all peers in the X and Y
/// dimensions.
l2_threshold: Option<BlockNumber>,
/// How often to re-send messages to all targeted recipients.
/// This applies to all unfinalized blocks.
@@ -167,11 +170,12 @@ struct State {
blocks: HashMap<Hash, BlockEntry>,
/// Our view updates to our peers can race with `NewBlocks` updates. We store messages received
/// against the directly mentioned blocks in our view in this map until `NewBlocks` is received.
/// against the directly mentioned blocks in our view in this map until `NewBlocks` is
/// received.
///
/// As long as the parent is already in the `blocks` map and `NewBlocks` messages aren't delayed
/// by more than a block length, this strategy will work well for mitigating the race. This is
/// also a race that occurs typically on local networks.
/// As long as the parent is already in the `blocks` map and `NewBlocks` messages aren't
/// delayed by more than a block length, this strategy will work well for mitigating the race.
/// This is also a race that occurs typically on local networks.
pending_known: HashMap<Hash, Vec<(PeerId, PendingMessage)>>,
/// Peer data is partially stored here, and partially inline within the [`BlockEntry`]s
@@ -947,7 +951,8 @@ impl State {
}
}
// Invariant: to our knowledge, none of the peers except for the `source` know about the assignment.
// Invariant: to our knowledge, none of the peers except for the `source` know about the
// assignment.
metrics.on_assignment_imported();
let topology = self.topologies.get_topology(entry.session);
@@ -1239,7 +1244,8 @@ impl State {
}
}
// Invariant: to our knowledge, none of the peers except for the `source` know about the approval.
// Invariant: to our knowledge, none of the peers except for the `source` know about the
// approval.
metrics.on_approval_imported();
let required_routing = match entry.candidates.get_mut(candidate_index as usize) {
@@ -1925,9 +1931,9 @@ const fn ensure_size_not_zero(size: usize) -> usize {
}
/// The maximum amount of assignments per batch is 33% of maximum allowed by protocol.
/// This is an arbitrary value. Bumping this up increases the maximum amount of approvals or assignments
/// we send in a single message to peers. Exceeding `MAX_NOTIFICATION_SIZE` will violate the protocol
/// configuration.
/// This is an arbitrary value. Bumping this up increases the maximum amount of approvals or
/// assignments we send in a single message to peers. Exceeding `MAX_NOTIFICATION_SIZE` will violate
/// the protocol configuration.
pub const MAX_ASSIGNMENT_BATCH_SIZE: usize = ensure_size_not_zero(
MAX_NOTIFICATION_SIZE as usize /
std::mem::size_of::<(IndirectAssignmentCert, CandidateIndex)>() /
@@ -315,7 +315,8 @@ impl RunningTask {
continue
},
};
// We drop the span so that the span is not active whilst we validate and store the chunk.
// We drop the span so that the span is not active whilst we validate and store the
// chunk.
drop(_chunk_recombine_span);
let _chunk_validate_and_store_span = span
.child("validate-and-store-chunk")
@@ -114,8 +114,8 @@ impl Requester {
.with_string_tag("leaf", format!("{:?}", leaf.hash))
.with_stage(jaeger::Stage::AvailabilityDistribution);
// Order important! We need to handle activated, prior to deactivated, otherwise we might
// cancel still needed jobs.
// Order important! We need to handle activated, prior to deactivated, otherwise we
// might cancel still needed jobs.
self.start_requesting_chunks(ctx, runtime, leaf, &span).await?;
}
@@ -168,8 +168,8 @@ impl Requester {
// any tasks separately.
//
// The next time the subsystem receives leaf update, some of spawned task will be bumped
// to be live in fresh relay parent, while some might get dropped due to the current leaf
// being deactivated.
// to be live in fresh relay parent, while some might get dropped due to the current
// leaf being deactivated.
self.add_cores(ctx, runtime, leaf, leaf_session_index, cores, span).await?;
}
@@ -177,7 +177,6 @@ impl Requester {
}
/// Stop requesting chunks for obsolete heads.
///
fn stop_requesting_chunks(&mut self, obsolete_leaves: impl Iterator<Item = Hash>) {
let obsolete_leaves: HashSet<_> = obsolete_leaves.collect();
self.fetches.retain(|_, task| {
@@ -226,10 +225,10 @@ impl Requester {
.with_session_info(
context,
runtime,
// We use leaf here, the relay_parent must be in the same session as the
// leaf. This is guaranteed by runtime which ensures that cores are cleared
// at session boundaries. At the same time, only leaves are guaranteed to
// be fetchable by the state trie.
// We use leaf here, the relay_parent must be in the same session as
// the leaf. This is guaranteed by runtime which ensures that cores are
// cleared at session boundaries. At the same time, only leaves are
// guaranteed to be fetchable by the state trie.
leaf,
leaf_session_index,
|info| FetchTaskConfig::new(leaf, &core, tx, metrics, info, span),
@@ -23,7 +23,6 @@
//! was almost done, thus we would have wasted time with our impatience. By simply making them
//! not count towards length, we can make sure to have enough "live" requests ongoing, while at the
//! same time taking advantage of some maybe "late" response from the undead.
//!
use std::{
pin::Pin,
@@ -111,7 +111,8 @@ const SMALL_POV_LIMIT: usize = 128 * 1024;
pub enum RecoveryStrategy {
/// We always try the backing group first, then fallback to validator chunks.
BackersFirstAlways,
/// We try the backing group first if PoV size is lower than specified, then fallback to validator chunks.
/// We try the backing group first if PoV size is lower than specified, then fallback to
/// validator chunks.
BackersFirstIfSizeLower(usize),
/// We always recover using validator chunks.
ChunksAlways,
@@ -132,7 +133,8 @@ impl RecoveryStrategy {
}
}
/// Returns the PoV size limit in bytes for `BackersFirstIfSizeLower` strategy, otherwise `None`.
/// Returns the PoV size limit in bytes for `BackersFirstIfSizeLower` strategy, otherwise
/// `None`.
pub fn pov_size_limit(&self) -> Option<usize> {
match *self {
RecoveryStrategy::BackersFirstIfSizeLower(limit) => Some(limit),
@@ -165,8 +167,8 @@ struct RequestChunksFromValidators {
///
/// including failed ones.
total_received_responses: usize,
/// a random shuffling of the validators which indicates the order in which we connect to the validators and
/// request the chunk from them.
/// a random shuffling of the validators which indicates the order in which we connect to the
/// validators and request the chunk from them.
shuffling: VecDeque<ValidatorIndex>,
/// Chunks received so far.
received_chunks: HashMap<ValidatorIndex, ErasureChunk>,
@@ -215,7 +217,8 @@ enum ErasureTask {
HashMap<ValidatorIndex, ErasureChunk>,
oneshot::Sender<Result<AvailableData, ErasureEncodingError>>,
),
/// Re-encode `AvailableData` into erasure chunks in order to verify the provided root hash of the Merkle tree.
/// Re-encode `AvailableData` into erasure chunks in order to verify the provided root hash of
/// the Merkle tree.
Reencode(usize, Hash, AvailableData, oneshot::Sender<Option<AvailableData>>),
}
@@ -808,8 +811,8 @@ where
self.params.metrics.on_recovery_started();
loop {
// These only fail if we cannot reach the underlying subsystem, which case there is nothing
// meaningful we can do.
// These only fail if we cannot reach the underlying subsystem, which case there is
// nothing meaningful we can do.
match self.source {
Source::RequestFromBackers(ref mut from_backers) => {
match from_backers.run(&self.params, &mut self.sender).await {
@@ -1008,7 +1011,8 @@ async fn launch_recovery_task<Context>(
);
backing_group = backing_group.filter(|_| {
// We keep the backing group only if `1/3` of chunks sum up to less than `small_pov_limit`.
// We keep the backing group only if `1/3` of chunks sum up to less than
// `small_pov_limit`.
prefer_backing_group
});
}
@@ -1194,18 +1198,21 @@ impl AvailabilityRecoverySubsystem {
let (erasure_task_tx, erasure_task_rx) = futures::channel::mpsc::channel(16);
let mut erasure_task_rx = erasure_task_rx.fuse();
// `ThreadPoolBuilder` spawns the tasks using `spawn_blocking`. For each worker there will be a `mpsc` channel created.
// Each of these workers take the `Receiver` and poll it in an infinite loop.
// All of the sender ends of the channel are sent as a vec which we then use to create a `Cycle` iterator.
// We use this iterator to assign work in a round-robin fashion to the workers in the pool.
// `ThreadPoolBuilder` spawns the tasks using `spawn_blocking`. For each worker there will
// be a `mpsc` channel created. Each of these workers take the `Receiver` and poll it in an
// infinite loop. All of the sender ends of the channel are sent as a vec which we then use
// to create a `Cycle` iterator. We use this iterator to assign work in a round-robin
// fashion to the workers in the pool.
//
// How work is dispatched to the pool from the recovery tasks:
// - Once a recovery task finishes retrieving the availability data, it needs to reconstruct from chunks and/or
// - Once a recovery task finishes retrieving the availability data, it needs to reconstruct
// from chunks and/or
// re-encode the data which are heavy CPU computations.
// To do so it sends an `ErasureTask` to the main loop via the `erasure_task` channel, and waits for the results
// over a `oneshot` channel.
// To do so it sends an `ErasureTask` to the main loop via the `erasure_task` channel, and
// waits for the results over a `oneshot` channel.
// - In the subsystem main loop we poll the `erasure_task_rx` receiver.
// - We forward the received `ErasureTask` to the `next()` sender yielded by the `Cycle` iterator.
// - We forward the received `ErasureTask` to the `next()` sender yielded by the `Cycle`
// iterator.
// - Some worker thread handles it and sends the response over the `oneshot` channel.
// Create a thread pool with 2 workers.
@@ -1348,11 +1355,13 @@ impl ThreadPoolBuilder {
// Creates a pool of `size` workers, where 1 <= `size` <= `MAX_THREADS`.
//
// Each worker is created by `spawn_blocking` and takes the receiver side of a channel
// while all of the senders are returned to the caller. Each worker runs `erasure_task_thread` that
// polls the `Receiver` for an `ErasureTask` which is expected to be CPU intensive. The larger
// the input (more or larger chunks/availability data), the more CPU cycles will be spent.
// while all of the senders are returned to the caller. Each worker runs `erasure_task_thread`
// that polls the `Receiver` for an `ErasureTask` which is expected to be CPU intensive. The
// larger the input (more or larger chunks/availability data), the more CPU cycles will be
// spent.
//
// For example, for 32KB PoVs, we'd expect re-encode to eat as much as 90ms and 500ms for 2.5MiB.
// For example, for 32KB PoVs, we'd expect re-encode to eat as much as 90ms and 500ms for
// 2.5MiB.
//
// After executing such a task, the worker sends the response via a provided `oneshot` sender.
//
@@ -817,7 +817,8 @@ fn wrong_chunk_index_leads_to_recovery_error() {
let candidate_hash = test_state.candidate.hash();
// These chunks should fail the index check as they don't have the correct index for validator.
// These chunks should fail the index check as they don't have the correct index for
// validator.
test_state.chunks[1] = test_state.chunks[0].clone();
test_state.chunks[2] = test_state.chunks[0].clone();
test_state.chunks[3] = test_state.chunks[0].clone();
+4 -2
View File
@@ -14,7 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
//! The Network Bridge Subsystem - handles _incoming_ messages from the network, forwarded to the relevant subsystems.
//! The Network Bridge Subsystem - handles _incoming_ messages from the network, forwarded to the
//! relevant subsystems.
use super::*;
use always_assert::never;
@@ -86,7 +87,8 @@ pub struct NetworkBridgeRx<N, AD> {
}
impl<N, AD> NetworkBridgeRx<N, AD> {
/// Create a new network bridge subsystem with underlying network service and authority discovery service.
/// Create a new network bridge subsystem with underlying network service and authority
/// discovery service.
///
/// This assumes that the network service has had the notifications protocol for the network
/// bridge already registered. See [`peers_sets_info`](peers_sets_info).
+3 -2
View File
@@ -795,8 +795,9 @@ fn peer_messages_sent_via_overseer() {
network_handle.disconnect_peer(peer.clone(), PeerSet::Validation).await;
// Approval distribution message comes first, and the message is only sent to that subsystem.
// then a disconnection event arises that is sent to all validation networking subsystems.
// Approval distribution message comes first, and the message is only sent to that
// subsystem. then a disconnection event arises that is sent to all validation networking
// subsystems.
assert_matches!(
virtual_overseer.recv().await,
+2 -1
View File
@@ -61,7 +61,8 @@ pub struct NetworkBridgeTx<N, AD> {
}
impl<N, AD> NetworkBridgeTx<N, AD> {
/// Create a new network bridge subsystem with underlying network service and authority discovery service.
/// Create a new network bridge subsystem with underlying network service and authority
/// discovery service.
///
/// This assumes that the network service has had the notifications protocol for the network
/// bridge already registered. See [`peers_sets_info`](peers_sets_info).
@@ -106,9 +106,10 @@ impl<N: Network, AD: AuthorityDiscovery> Service<N, AD> {
/// It will ask the network to connect to the validators and not disconnect
/// from them at least until the next request is issued for the same peer set.
///
/// This method will also disconnect from previously connected validators not in the `validator_ids` set.
/// it takes `network_service` and `authority_discovery_service` by value
/// and returns them as a workaround for the Future: Send requirement imposed by async function implementation.
/// This method will also disconnect from previously connected validators not in the
/// `validator_ids` set. it takes `network_service` and `authority_discovery_service` by value
/// and returns them as a workaround for the Future: Send requirement imposed by async function
/// implementation.
pub async fn on_request(
&mut self,
validator_ids: Vec<AuthorityDiscoveryId>,
@@ -225,8 +225,8 @@ struct State {
/// Our validator groups per active leaf.
our_validators_groups: HashMap<Hash, ValidatorGroup>,
/// The mapping from [`PeerId`] to [`HashSet<AuthorityDiscoveryId>`]. This is filled over time as we learn the [`PeerId`]'s
/// by `PeerConnected` events.
/// The mapping from [`PeerId`] to [`HashSet<AuthorityDiscoveryId>`]. This is filled over time
/// as we learn the [`PeerId`]'s by `PeerConnected` events.
peer_ids: HashMap<PeerId, HashSet<AuthorityDiscoveryId>>,
/// Tracks which validators we want to stay connected to.
@@ -241,8 +241,8 @@ struct State {
/// All collation fetching requests that are still waiting to be answered.
///
/// They are stored per relay parent, when our view changes and the relay parent moves out, we will cancel the fetch
/// request.
/// They are stored per relay parent, when our view changes and the relay parent moves out, we
/// will cancel the fetch request.
waiting_collation_fetches: HashMap<Hash, WaitingCollationFetches>,
/// Active collation fetches.
@@ -526,8 +526,8 @@ async fn connect_to_validators<Context>(
/// Advertise collation to the given `peer`.
///
/// This will only advertise a collation if there exists one for the given `relay_parent` and the given `peer` is
/// set as validator for our para at the given `relay_parent`.
/// This will only advertise a collation if there exists one for the given `relay_parent` and the
/// given `peer` is set as validator for our para at the given `relay_parent`.
#[overseer::contextbounds(CollatorProtocol, prefix = self::overseer)]
async fn advertise_collation<Context>(
ctx: &mut Context,
@@ -638,7 +638,8 @@ async fn process_msg<Context>(
);
},
NetworkBridgeUpdate(event) => {
// We should count only this shoulder in the histogram, as other shoulders are just introducing noise
// We should count only this shoulder in the histogram, as other shoulders are just
// introducing noise
let _ = state.metrics.time_process_msg();
if let Err(e) = handle_network_msg(ctx, runtime, state, event).await {
@@ -160,8 +160,8 @@ impl TestState {
/// Generate a new relay parent and inform the subsystem about the new view.
///
/// If `merge_views == true` it means the subsystem will be informed that we are working on the old `relay_parent`
/// and the new one.
/// If `merge_views == true` it means the subsystem will be informed that we are working on the
/// old `relay_parent` and the new one.
async fn advance_to_new_round(
&mut self,
virtual_overseer: &mut VirtualOverseer,
@@ -901,7 +901,8 @@ fn collate_on_two_different_relay_chain_blocks() {
let old_relay_parent = test_state.relay_parent;
// Advance to a new round, while informing the subsystem that the old and the new relay parent are active.
// Advance to a new round, while informing the subsystem that the old and the new relay
// parent are active.
test_state.advance_to_new_round(virtual_overseer, true).await;
distribute_collation(virtual_overseer, &test_state, true).await;
@@ -1085,7 +1086,8 @@ where
.await
.unwrap();
// Keep the feedback channel alive because we need to use it to inform about the finished transfer.
// Keep the feedback channel alive because we need to use it to inform about the
// finished transfer.
let feedback_tx = assert_matches!(
rx.await,
Ok(full_response) => {
@@ -23,9 +23,9 @@
//! We keep a simple FIFO buffer of N validator groups and a bitvec for each advertisement,
//! 1 indicating we want to be connected to i-th validator in a buffer, 0 otherwise.
//!
//! The bit is set to 1 for the whole **group** whenever it's inserted into the buffer. Given a relay
//! parent, one can reset a bit back to 0 for particular **validator**. For example, if a collation
//! was fetched or some timeout has been hit.
//! The bit is set to 1 for the whole **group** whenever it's inserted into the buffer. Given a
//! relay parent, one can reset a bit back to 0 for particular **validator**. For example, if a
//! collation was fetched or some timeout has been hit.
//!
//! The bitwise OR over known advertisements gives us validators indices for connection request.
@@ -730,7 +730,8 @@ fn reject_connection_to_next_group() {
})
}
// Ensure that we fetch a second collation, after the first checked collation was found to be invalid.
// Ensure that we fetch a second collation, after the first checked collation was found to be
// invalid.
#[test]
fn fetch_next_collation_on_invalid_collation() {
let test_state = TestState::default();
@@ -60,8 +60,8 @@ use self::sender::{DisputeSender, DisputeSenderMessage};
/// ## The receiver [`DisputesReceiver`]
///
/// The receiving side is implemented as `DisputesReceiver` and is run as a separate long running task within
/// this subsystem ([`DisputesReceiver::run`]).
/// The receiving side is implemented as `DisputesReceiver` and is run as a separate long running
/// task within this subsystem ([`DisputesReceiver::run`]).
///
/// Conceptually all the receiver has to do, is waiting for incoming requests which are passed in
/// via a dedicated channel and forwarding them to the dispute coordinator via
@@ -101,8 +101,8 @@ const LOG_TARGET: &'static str = "parachain::dispute-distribution";
/// Rate limit on the `receiver` side.
///
/// If messages from one peer come in at a higher rate than every `RECEIVE_RATE_LIMIT` on average, we
/// start dropping messages from that peer to enforce that limit.
/// If messages from one peer come in at a higher rate than every `RECEIVE_RATE_LIMIT` on average,
/// we start dropping messages from that peer to enforce that limit.
pub const RECEIVE_RATE_LIMIT: Duration = Duration::from_millis(100);
/// Rate limit on the `sender` side.
@@ -192,8 +192,8 @@ impl Batch {
/// Calculate when the next tick should happen.
///
/// This will usually return `now + BATCH_COLLECTING_INTERVAL`, except if the lifetime of this batch
/// would exceed `MAX_BATCH_LIFETIME`.
/// This will usually return `now + BATCH_COLLECTING_INTERVAL`, except if the lifetime of this
/// batch would exceed `MAX_BATCH_LIFETIME`.
///
/// # Arguments
///
@@ -50,8 +50,8 @@ impl<Payload: Eq + Ord> WaitingQueue<Payload> {
/// Push a `PendingWake`.
///
/// The next call to `wait_ready` will make sure to wake soon enough to process that new event in a
/// timely manner.
/// The next call to `wait_ready` will make sure to wake soon enough to process that new event
/// in a timely manner.
pub fn push(&mut self, wake: PendingWake<Payload>) {
self.pending_wakes.push(wake);
// Reset timer as it is potentially obsolete now:
@@ -382,11 +382,11 @@ where
if let Err(pending_response) = batch_result {
// We don't expect honest peers to send redundant votes within a single batch,
// as the timeout for retry is much higher. Still we don't want to punish the
// node as it might not be the node's fault. Some other (malicious) node could have been
// faster sending the same votes in order to harm the reputation of that honest
// node. Given that we already have a rate limit, if a validator chooses to
// waste available rate with redundant votes - so be it. The actual dispute
// resolution is unaffected.
// node as it might not be the node's fault. Some other (malicious) node could
// have been faster sending the same votes in order to harm the reputation of
// that honest node. Given that we already have a rate limit, if a validator
// chooses to waste available rate with redundant votes - so be it. The actual
// dispute resolution is unaffected.
gum::debug!(
target: LOG_TARGET,
?peer,
@@ -45,8 +45,8 @@ use crate::{
///
/// The unit of work for a `SendTask` is an authority/validator.
pub struct SendTask<M> {
/// The request we are supposed to get out to all `parachain` validators of the dispute's session
/// and to all current authorities.
/// The request we are supposed to get out to all `parachain` validators of the dispute's
/// session and to all current authorities.
request: DisputeRequest,
/// The set of authorities we need to send our messages to. This set will change at session
@@ -185,7 +185,8 @@ impl<M: 'static + Send + Sync> SendTask<M> {
/// Handle a finished response waiting task.
///
/// Called by `DisputeSender` upon reception of the corresponding message from our spawned `wait_response_task`.
/// Called by `DisputeSender` upon reception of the corresponding message from our spawned
/// `wait_response_task`.
pub fn on_finished_send(&mut self, authority: &AuthorityDiscoveryId, result: TaskResult) {
match result {
TaskResult::Failed(err) => {
@@ -204,8 +205,8 @@ impl<M: 'static + Send + Sync> SendTask<M> {
TaskResult::Succeeded => {
let status = match self.deliveries.get_mut(&authority) {
None => {
// Can happen when a sending became irrelevant while the response was already
// queued.
// Can happen when a sending became irrelevant while the response was
// already queued.
gum::debug!(
target: LOG_TARGET,
candidate = ?self.request.0.candidate_receipt.hash(),
@@ -246,7 +246,8 @@ where
{
let mut connections = authorities_past_present_future(sender, leaf).await?;
// Remove all of our locally controlled validator indices so we don't connect to ourself.
// Remove all of our locally controlled validator indices so we don't connect to
// ourself.
let connections =
if remove_all_controlled(&self.keystore, &mut connections) != 0 {
connections
@@ -17,17 +17,20 @@
//! Grid topology support implementation
//! The basic operation of the 2D grid topology is that:
//! * A validator producing a message sends it to its row-neighbors and its column-neighbors
//! * A validator receiving a message originating from one of its row-neighbors sends it to its column-neighbors
//! * A validator receiving a message originating from one of its column-neighbors sends it to its row-neighbors
//! * A validator receiving a message originating from one of its row-neighbors sends it to its
//! column-neighbors
//! * A validator receiving a message originating from one of its column-neighbors sends it to its
//! row-neighbors
//!
//! This grid approach defines 2 unique paths for every validator to reach every other validator in at most 2 hops.
//! This grid approach defines 2 unique paths for every validator to reach every other validator in
//! at most 2 hops.
//!
//! However, we also supplement this with some degree of random propagation:
//! every validator, upon seeing a message for the first time, propagates it to 8 random peers.
//! This inserts some redundancy in case the grid topology isn't working or is being attacked -
//! an adversary doesn't know which peers a validator will send to.
//! This is combined with the property that the adversary doesn't know which validators will elect to check a block.
//!
//! This is combined with the property that the adversary doesn't know which validators will elect
//! to check a block.
use crate::PeerId;
use polkadot_primitives::{AuthorityDiscoveryId, SessionIndex, ValidatorIndex};
@@ -188,7 +191,8 @@ impl GridNeighbors {
(false, false) => RequiredRouting::None,
(true, false) => RequiredRouting::GridY, // messages from X go to Y
(false, true) => RequiredRouting::GridX, // messages from Y go to X
(true, true) => RequiredRouting::GridXY, // if the grid works as expected, this shouldn't happen.
(true, true) => RequiredRouting::GridXY, /* if the grid works as expected, this
* shouldn't happen. */
}
}
@@ -213,7 +217,8 @@ impl GridNeighbors {
"Grid topology is unexpected, play it safe and send to X AND Y"
);
RequiredRouting::GridXY
}, // if the grid works as expected, this shouldn't happen.
}, /* if the grid works as expected, this
* shouldn't happen. */
}
}
+4 -2
View File
@@ -91,7 +91,8 @@ impl Into<sc_network::ObservedRole> for ObservedRole {
/// Specialized wrapper around [`View`].
///
/// Besides the access to the view itself, it also gives access to the [`jaeger::Span`] per leave/head.
/// Besides the access to the view itself, it also gives access to the [`jaeger::Span`] per
/// leave/head.
#[derive(Debug, Clone, Default)]
pub struct OurView {
view: View,
@@ -131,7 +132,8 @@ impl std::ops::Deref for OurView {
}
}
/// Construct a new [`OurView`] with the given chain heads, finalized number 0 and disabled [`jaeger::Span`]'s.
/// Construct a new [`OurView`] with the given chain heads, finalized number 0 and disabled
/// [`jaeger::Span`]'s.
///
/// NOTE: Use for tests only.
///
@@ -98,7 +98,8 @@ impl PeerSet {
max_notification_size,
handshake: None,
set_config: SetConfig {
// Non-authority nodes don't need to accept incoming connections on this peer set:
// Non-authority nodes don't need to accept incoming connections on this peer
// set:
in_peers: if is_authority == IsAuthority::Yes { 100 } else { 0 },
out_peers: 0,
reserved_nodes: Vec::new(),
@@ -78,8 +78,8 @@ where
/// reputation changes in that case.
///
/// Params:
/// - The raw request to decode
/// - Reputation changes to apply for the peer in case decoding fails.
/// - The raw request to decode
/// - Reputation changes to apply for the peer in case decoding fails.
fn try_from_raw(
raw: sc_network::config::IncomingRequest,
reputation_changes: Vec<UnifiedReputationChange>,
@@ -110,9 +110,9 @@ pub const MAX_PARALLEL_STATEMENT_REQUESTS: u32 = 3;
/// Response size limit for responses of POV like data.
///
/// This is larger than `MAX_POV_SIZE` to account for protocol overhead and for additional data in
/// `CollationFetchingV1` or `AvailableDataFetchingV1` for example. We try to err on larger limits here
/// as a too large limit only allows an attacker to waste our bandwidth some more, a too low limit
/// might have more severe effects.
/// `CollationFetchingV1` or `AvailableDataFetchingV1` for example. We try to err on larger limits
/// here as a too large limit only allows an attacker to waste our bandwidth some more, a too low
/// limit might have more severe effects.
const POV_RESPONSE_SIZE: u64 = MAX_POV_SIZE as u64 + 10_000;
/// Maximum response sizes for `StatementFetchingV1`.
@@ -185,8 +185,8 @@ struct VcPerPeerTracker {
}
impl VcPerPeerTracker {
/// Note that the remote should now be aware that a validator has seconded a given candidate (by hash)
/// based on a message that we have sent it from our local pool.
/// Note that the remote should now be aware that a validator has seconded a given candidate (by
/// hash) based on a message that we have sent it from our local pool.
fn note_local(&mut self, h: CandidateHash) {
if !note_hash(&mut self.local_observed, h) {
gum::warn!(
@@ -198,8 +198,8 @@ impl VcPerPeerTracker {
}
}
/// Note that the remote should now be aware that a validator has seconded a given candidate (by hash)
/// based on a message that it has sent us.
/// Note that the remote should now be aware that a validator has seconded a given candidate (by
/// hash) based on a message that it has sent us.
///
/// Returns `true` if the peer was allowed to send us such a message, `false` otherwise.
fn note_remote(&mut self, h: CandidateHash) -> bool {
@@ -226,8 +226,8 @@ fn note_hash(
/// knowledge that a peer has about goings-on in a relay parent.
#[derive(Default)]
struct PeerRelayParentKnowledge {
/// candidates that the peer is aware of because we sent statements to it. This indicates that we can
/// send other statements pertaining to that candidate.
/// candidates that the peer is aware of because we sent statements to it. This indicates that
/// we can send other statements pertaining to that candidate.
sent_candidates: HashSet<CandidateHash>,
/// candidates that peer is aware of, because we received statements from it.
received_candidates: HashSet<CandidateHash>,
@@ -321,13 +321,13 @@ impl PeerRelayParentKnowledge {
}
}
/// Attempt to update our view of the peer's knowledge with this statement's fingerprint based on
/// a message we are receiving from the peer.
/// Attempt to update our view of the peer's knowledge with this statement's fingerprint based
/// on a message we are receiving from the peer.
///
/// Provide the maximum message count that we can receive per candidate. In practice we should
/// not receive more statements for any one candidate than there are members in the group assigned
/// to that para, but this maximum needs to be lenient to account for equivocations that may be
/// cross-group. As such, a maximum of 2 * `n_validators` is recommended.
/// not receive more statements for any one candidate than there are members in the group
/// assigned to that para, but this maximum needs to be lenient to account for equivocations
/// that may be cross-group. As such, a maximum of 2 * `n_validators` is recommended.
///
/// This returns an error if the peer should not have sent us this message according to protocol
/// rules for flood protection.
@@ -490,13 +490,13 @@ impl PeerData {
self.view_knowledge.get(relay_parent).map_or(false, |k| k.can_send(fingerprint))
}
/// Attempt to update our view of the peer's knowledge with this statement's fingerprint based on
/// a message we are receiving from the peer.
/// Attempt to update our view of the peer's knowledge with this statement's fingerprint based
/// on a message we are receiving from the peer.
///
/// Provide the maximum message count that we can receive per candidate. In practice we should
/// not receive more statements for any one candidate than there are members in the group assigned
/// to that para, but this maximum needs to be lenient to account for equivocations that may be
/// cross-group. As such, a maximum of 2 * `n_validators` is recommended.
/// not receive more statements for any one candidate than there are members in the group
/// assigned to that para, but this maximum needs to be lenient to account for equivocations
/// that may be cross-group. As such, a maximum of 2 * `n_validators` is recommended.
///
/// This returns an error if the peer should not have sent us this message according to protocol
/// rules for flood protection.
@@ -600,8 +600,8 @@ enum NotedStatement<'a> {
/// Large statement fetching status.
enum LargeStatementStatus {
/// We are currently fetching the statement data from a remote peer. We keep a list of other nodes
/// claiming to have that data and will fallback on them.
/// We are currently fetching the statement data from a remote peer. We keep a list of other
/// nodes claiming to have that data and will fallback on them.
Fetching(FetchingInfo),
/// Statement data is fetched or we got it locally via `StatementDistributionMessage::Share`.
FetchedOrShared(CommittedCandidateReceipt),
@@ -712,8 +712,8 @@ impl ActiveHeadData {
/// to have been checked, including that the validator index is not out-of-bounds and
/// the signature is valid.
///
/// Any other statements or those that reference a candidate we are not aware of cannot be accepted
/// and will return `NotedStatement::NotUseful`.
/// Any other statements or those that reference a candidate we are not aware of cannot be
/// accepted and will return `NotedStatement::NotUseful`.
fn note_statement(&mut self, statement: SignedFullStatement) -> NotedStatement {
let validator_index = statement.validator_index();
let comparator = StoredStatementComparator {
@@ -1272,9 +1272,9 @@ async fn retrieve_statement_from_message<'a, Context>(
}
},
protocol_v1::StatementDistributionMessage::Statement(_, s) => {
// No fetch in progress, safe to return any statement immediately (we don't bother
// about normal network jitter which might cause `Valid` statements to arrive early
// for now.).
// No fetch in progress, safe to return any statement immediately (we don't
// bother about normal network jitter which might cause `Valid` statements to
// arrive early for now.).
return Some(s)
},
}
@@ -1470,7 +1470,8 @@ async fn handle_incoming_message<'a, Context>(
);
match rep {
// This happens when a Valid statement has been received but there is no corresponding Seconded
// This happens when a Valid statement has been received but there is no corresponding
// Seconded
COST_UNEXPECTED_STATEMENT_UNKNOWN_CANDIDATE => {
metrics.on_unexpected_statement_valid();
// Report peer merely if this is not a duplicate out-of-view statement that
@@ -824,8 +824,8 @@ fn receiving_from_one_sends_to_another_and_to_candidate_backing() {
})
.await;
// receive a seconded statement from peer A. it should be propagated onwards to peer B and to
// candidate backing.
// receive a seconded statement from peer A. it should be propagated onwards to peer B and
// to candidate backing.
let statement = {
let signing_context = SigningContext { parent_hash: hash_a, session_index };
@@ -2536,8 +2536,8 @@ fn handle_multiple_seconded_statements() {
})
.await;
// receive a seconded statement from peer A. it should be propagated onwards to peer B and to
// candidate backing.
// receive a seconded statement from peer A. it should be propagated onwards to peer B and
// to candidate backing.
let statement = {
let signing_context = SigningContext { parent_hash: relay_parent_hash, session_index };