mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-14 13:21:10 +00:00
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:
committed by
GitHub
parent
ac435c96cf
commit
342d720573
@@ -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();
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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. */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 };
|
||||
|
||||
|
||||
Reference in New Issue
Block a user