diff --git a/node/core/backing/src/lib.rs b/node/core/backing/src/lib.rs index ea66c53bc892..5ed486e4ca64 100644 --- a/node/core/backing/src/lib.rs +++ b/node/core/backing/src/lib.rs @@ -1494,7 +1494,7 @@ async fn import_statement( // we need to create an entry in the `PerCandidateState` map. // // If the relay parent supports prospective parachains, we also need - // to inform the prospective parachains subsystem of the seconded candidate + // to inform the prospective parachains subsystem of the seconded candidate. // If `ProspectiveParachainsMessage::Second` fails, then we return // Error::RejectedByProspectiveParachains. // diff --git a/node/core/prospective-parachains/src/fragment_tree.rs b/node/core/prospective-parachains/src/fragment_tree.rs index c6f388f851b5..cbed7cf3f9dc 100644 --- a/node/core/prospective-parachains/src/fragment_tree.rs +++ b/node/core/prospective-parachains/src/fragment_tree.rs @@ -381,8 +381,8 @@ impl Scope { } } -// We use indices into a flat vector to refer to nodes in the tree. -// Every tree also has an implicit root. +/// We use indices into a flat vector to refer to nodes in the tree. +/// Every tree also has an implicit root. #[derive(Debug, Clone, Copy, PartialEq)] enum NodePointer { Root, @@ -618,7 +618,7 @@ impl FragmentTree { let max_depth = self.scope.max_depth; let mut depths = bitvec![u16, Msb0; 0; max_depth + 1]; - // iterate over all nodes < max_depth where parent head-data matches, + // iterate over all nodes where parent head-data matches, // relay-parent number is <= candidate, and depth < max_depth. let node_pointers = (0..self.nodes.len()).map(NodePointer::Storage); for parent_pointer in std::iter::once(NodePointer::Root).chain(node_pointers) { @@ -665,46 +665,46 @@ impl FragmentTree { }; let parent_head_hash = candidate.parent_head_data_hash(); - if parent_head_hash == child_constraints.required_parent.hash() { - // We do additional checks for complete candidates. - if let HypotheticalCandidate::Complete { - ref receipt, - ref persisted_validation_data, - } = candidate - { - let prospective_candidate = ProspectiveCandidate { - commitments: Cow::Borrowed(&receipt.commitments), - collator: receipt.descriptor().collator.clone(), - collator_signature: receipt.descriptor().signature.clone(), - persisted_validation_data: persisted_validation_data.as_ref().clone(), - pov_hash: receipt.descriptor().pov_hash, - validation_code_hash: receipt.descriptor().validation_code_hash, - }; + if parent_head_hash != child_constraints.required_parent.hash() { + continue + } - if Fragment::new( - candidate_relay_parent.clone(), - child_constraints, - prospective_candidate, - ) - .is_err() - { - continue - } - } + // We do additional checks for complete candidates. + if let HypotheticalCandidate::Complete { ref receipt, ref persisted_validation_data } = + candidate + { + let prospective_candidate = ProspectiveCandidate { + commitments: Cow::Borrowed(&receipt.commitments), + collator: receipt.descriptor().collator.clone(), + collator_signature: receipt.descriptor().signature.clone(), + persisted_validation_data: persisted_validation_data.as_ref().clone(), + pov_hash: receipt.descriptor().pov_hash, + validation_code_hash: receipt.descriptor().validation_code_hash, + }; - // Check that the path only contains backed candidates, if necessary. - if !backed_in_path_only || - self.path_contains_backed_only_candidates(parent_pointer, candidate_storage) + if Fragment::new( + candidate_relay_parent.clone(), + child_constraints, + prospective_candidate, + ) + .is_err() { - depths.set(child_depth, true); + continue } } + + // Check that the path only contains backed candidates, if necessary. + if !backed_in_path_only || + self.path_contains_backed_only_candidates(parent_pointer, candidate_storage) + { + depths.set(child_depth, true); + } } depths.iter_ones().collect() } - /// Select a candidate after the given `required_path` which pass + /// Select a candidate after the given `required_path` which passes /// the predicate. /// /// If there are multiple possibilities, this will select the first one. @@ -1160,6 +1160,7 @@ mod tests { assert!(storage.head_data_by_hash(&output_head_hash).is_none()); } + // [`FragmentTree::populate`] should pick up candidates that build on other candidates. #[test] fn populate_works_recursively() { let mut storage = CandidateStorage::new(); diff --git a/node/subsystem-types/src/messages.rs b/node/subsystem-types/src/messages.rs index bfe12981c30c..37a11ecbc949 100644 --- a/node/subsystem-types/src/messages.rs +++ b/node/subsystem-types/src/messages.rs @@ -529,7 +529,7 @@ pub enum ChainApiMessage { /// Request the last finalized block number. /// This request always succeeds. FinalizedBlockNumber(ChainApiResponseChannel), - /// Request the `k` ancestors block hashes of a block with the given hash. + /// Request the `k` ancestor block hashes of a block with the given hash. /// The response channel may return a `Vec` of size up to `k` /// filled with ancestors hashes with the following order: /// `parent`, `grandparent`, ... up to the hash of genesis block diff --git a/node/subsystem-util/src/backing_implicit_view.rs b/node/subsystem-util/src/backing_implicit_view.rs index 6fd273b1b212..e1966dddea9e 100644 --- a/node/subsystem-util/src/backing_implicit_view.rs +++ b/node/subsystem-util/src/backing_implicit_view.rs @@ -115,7 +115,7 @@ impl View { /// /// This returns a list of para-ids which are relevant to the leaf, /// and the allowed relay parents for these paras under this leaf can be - /// queried with [`known_allowed_relay_parents_under`]. + /// queried with [`View::known_allowed_relay_parents_under`]. /// /// No-op for known leaves. pub async fn activate_leaf( diff --git a/node/subsystem-util/src/inclusion_emulator/staging.rs b/node/subsystem-util/src/inclusion_emulator/staging.rs index 80ba0fb12eaf..66868f16925d 100644 --- a/node/subsystem-util/src/inclusion_emulator/staging.rs +++ b/node/subsystem-util/src/inclusion_emulator/staging.rs @@ -71,19 +71,20 @@ //! //! ### Pruning Fragment Trees //! -//! When the relay-chain advances, we want to compare the new constraints -//! of that relay-parent to the roots of the fragment trees we have. There are 3 cases. +//! When the relay-chain advances, we want to compare the new constraints of that relay-parent to +//! the roots of the fragment trees we have. There are 3 cases: //! -//! 1. The root fragment is still valid under the new constraints. In this case, we do nothing. -//! This is the "prediction still uncertain" case. -//! 2. The root fragment is invalid under the new constraints because it has been subsumed by the relay-chain. -//! in this case, we can discard the root and split & re-root the fragment tree -//! under its descendents and compare to the new constraints again. -//! This is the "prediction came true" case. -//! 3. The root fragment is invalid under the new constraints because a competing parachain block has been included -//! or it would never be accepted for some other reason. In this case we can discard the entire -//! fragment tree. -//! This is the "prediction came false" case. +//! 1. The root fragment is still valid under the new constraints. In this case, we do nothing. This +//! is the "prediction still uncertain" case. +//! +//! 2. The root fragment is invalid under the new constraints because it has been subsumed by the +//! relay-chain. In this case, we can discard the root and split & re-root the fragment tree under +//! its descendents and compare to the new constraints again. This is the "prediction came true" +//! case. +//! +//! 3. The root fragment is invalid under the new constraints because a competing parachain block +//! has been included or it would never be accepted for some other reason. In this case we can +//! discard the entire fragment tree. This is the "prediction came false" case. //! //! This is all a bit of a simplification because it assumes that the relay-chain advances without //! forks and is finalized instantly. In practice, the set of fragment-trees needs to be observable diff --git a/roadmap/implementers-guide/src/node/backing/statement-distribution-legacy.md b/roadmap/implementers-guide/src/node/backing/statement-distribution-legacy.md index 67dcaf9053a5..5cbc875d8a73 100644 --- a/roadmap/implementers-guide/src/node/backing/statement-distribution-legacy.md +++ b/roadmap/implementers-guide/src/node/backing/statement-distribution-legacy.md @@ -33,7 +33,7 @@ Output: Implemented as a gossip protocol. Handles updates to our view and peers' views. Neighbor packets are used to inform peers which chain heads we are interested in data for. -The Statement Distribution Subsystem is responsible for distributing signed statements that we have generated and for forwarding statements generated by other validators. It also detects a variety of Validator misbehaviors for reporting to [Misbehavior Arbitration](../utility/misbehavior-arbitration.md). During the Backing stage of the inclusion pipeline, Statement Distribution is the main point of contact with peer nodes. On receiving a signed statement from a peer in the same backing group, assuming the peer receipt state machine is in an appropriate state, it sends the Candidate Receipt to the [Candidate Backing subsystem](candidate-backing.md) to handle the validator's statement. On receiving `StatementDistributionMessage::Share` we make sure to send messages to our backing group in addition to random other peers, to ensure a fast backing process and getting all statements quickly for distribution. +The Statement Distribution Subsystem is responsible for distributing signed statements that we have generated and for forwarding statements generated by other validators. It also detects a variety of Validator misbehaviors for reporting to the [Provisioner Subsystem](../utility/provisioner.md). During the Backing stage of the inclusion pipeline, Statement Distribution is the main point of contact with peer nodes. On receiving a signed statement from a peer in the same backing group, assuming the peer receipt state machine is in an appropriate state, it sends the Candidate Receipt to the [Candidate Backing subsystem](candidate-backing.md) to handle the validator's statement. On receiving `StatementDistributionMessage::Share` we make sure to send messages to our backing group in addition to random other peers, to ensure a fast backing process and getting all statements quickly for distribution. This subsystem tracks equivocating validators and stops accepting information from them. It establishes a data-dependency order: diff --git a/roadmap/implementers-guide/src/node/backing/statement-distribution.md b/roadmap/implementers-guide/src/node/backing/statement-distribution.md index 3b1915052e4d..9259acf7387d 100644 --- a/roadmap/implementers-guide/src/node/backing/statement-distribution.md +++ b/roadmap/implementers-guide/src/node/backing/statement-distribution.md @@ -22,8 +22,7 @@ reasons. As a result, all validators must have a up to date view of all possible parachain candidates + backing statements that could be placed on-chain in the next block. -[This blog -post](https://polkadot.network/blog/polkadot-v1-0-sharding-and-economic-security) +[This blog post](https://polkadot.network/blog/polkadot-v1-0-sharding-and-economic-security) puts it another way: "Validators who aren't assigned to the parachain still listen for the attestations [statements] because whichever validator ends up being the author of the relay-chain block needs to bundle up attested parachain @@ -155,11 +154,11 @@ backing subsystem itself. - Note that requesting is not an implicit acknowledgement, and an explicit acknowledgement must be sent upon receipt. -## Statement distribution messages +## Messages -### Input +### Incoming -- `ActiveLeavesUpdate` +- `ActiveLeaves` - Notification of a change in the set of active leaves. - `StatementDistributionMessage::Share` - Notification of a locally-originating statement. That is, this statement @@ -186,7 +185,7 @@ backing subsystem itself. - Acknowledgement. - Handled by `handle_incoming_acknowledgement` -### Output +### Outgoing - `NetworkBridgeTxMessage::SendValidationMessages` - Sends a peer all pending messages / acknowledgements / statements for a @@ -202,7 +201,7 @@ backing subsystem itself. - Gets the hypothetical frontier membership of candidates under active leaves' fragment trees. - `NetworkBridgeTxMessage::SendRequests` - - Sends requests, initiating request/response protocol. + - Sends requests, initiating the request/response protocol. ## Request/Response