Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Commit

Permalink
Prepare the Runtime for asynchronous backing upgrade (#6287)
Browse files Browse the repository at this point in the history
* Introduce async backing params to runtime config

* fix cumulus config

* use config

* finish runtimes

* Introduce new staging API

* Update collator protocol

* Update provisioner

* Update prospective parachains

* Update backing

* Move async backing params lower in the config

* make naming consistent

* misc
  • Loading branch information
slumber authored Nov 30, 2022
1 parent aacb2b3 commit c41cbbe
Show file tree
Hide file tree
Showing 35 changed files with 500 additions and 332 deletions.
26 changes: 12 additions & 14 deletions node/core/backing/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -772,7 +772,7 @@ async fn handle_active_leaves_update<Context>(
state: &mut State,
) -> Result<(), Error> {
enum LeafHasProspectiveParachains {
Enabled(Result<Vec<ParaId>, ImplicitViewFetchError>),
Enabled(Result<ProspectiveParachainsMode, ImplicitViewFetchError>),
Disabled,
}

Expand All @@ -788,8 +788,8 @@ async fn handle_active_leaves_update<Context>(
leaf,
match mode {
ProspectiveParachainsMode::Disabled => LeafHasProspectiveParachains::Disabled,
ProspectiveParachainsMode::Enabled => LeafHasProspectiveParachains::Enabled(
state.implicit_view.activate_leaf(ctx.sender(), leaf_hash).await,
ProspectiveParachainsMode::Enabled { .. } => LeafHasProspectiveParachains::Enabled(
state.implicit_view.activate_leaf(ctx.sender(), leaf_hash).await.map(|_| mode),
),
},
))
Expand Down Expand Up @@ -824,7 +824,7 @@ async fn handle_active_leaves_update<Context>(

// Get relay parents which might be fresh but might be known already
// that are explicit or implicit from the new active leaf.
let fresh_relay_parents = match res {
let (fresh_relay_parents, leaf_mode) = match res {
None => return Ok(()),
Some((leaf, LeafHasProspectiveParachains::Disabled)) => {
// defensive in this case - for enabled, this manifests as an error.
Expand All @@ -844,9 +844,9 @@ async fn handle_active_leaves_update<Context>(
},
);

vec![leaf.hash]
(vec![leaf.hash], ProspectiveParachainsMode::Disabled)
},
Some((leaf, LeafHasProspectiveParachains::Enabled(Ok(_)))) => {
Some((leaf, LeafHasProspectiveParachains::Enabled(Ok(prospective_parachains_mode)))) => {
let fresh_relay_parents =
state.implicit_view.known_allowed_relay_parents_under(&leaf.hash, None);

Expand Down Expand Up @@ -907,13 +907,10 @@ async fn handle_active_leaves_update<Context>(

state.per_leaf.insert(
leaf.hash,
ActiveLeafState {
prospective_parachains_mode: ProspectiveParachainsMode::Enabled,
seconded_at_depth,
},
ActiveLeafState { prospective_parachains_mode, seconded_at_depth },
);

match fresh_relay_parents {
let fresh_relay_parent = match fresh_relay_parents {
Some(f) => f.to_vec(),
None => {
gum::warn!(
Expand All @@ -924,7 +921,8 @@ async fn handle_active_leaves_update<Context>(

vec![leaf.hash]
},
}
};
(fresh_relay_parent, prospective_parachains_mode)
},
Some((leaf, LeafHasProspectiveParachains::Enabled(Err(e)))) => {
gum::debug!(
Expand All @@ -951,7 +949,7 @@ async fn handle_active_leaves_update<Context>(
// subsystem that it is an ancestor of a leaf which
// has prospective parachains enabled and that the
// block itself did.
ProspectiveParachainsMode::Enabled
leaf_mode
},
Some(l) => l.prospective_parachains_mode,
};
Expand Down Expand Up @@ -1061,7 +1059,7 @@ async fn construct_per_relay_parent_state<Context>(
let table_context = TableContext { groups, validators, validator };
let table_config = TableConfig {
allow_multiple_seconded: match mode {
ProspectiveParachainsMode::Enabled => true,
ProspectiveParachainsMode::Enabled { .. } => true,
ProspectiveParachainsMode::Disabled => false,
},
};
Expand Down
10 changes: 5 additions & 5 deletions node/core/backing/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use assert_matches::assert_matches;
use futures::{future, Future};
use polkadot_node_primitives::{BlockData, InvalidCandidate, SignedFullStatement, Statement};
use polkadot_node_subsystem::{
errors::RuntimeApiError,
jaeger,
messages::{
AllMessages, CollatorProtocolMessage, RuntimeApiMessage, RuntimeApiRequest,
Expand All @@ -44,7 +45,8 @@ use std::collections::HashMap;

mod prospective_parachains;

const API_VERSION_PROSPECTIVE_DISABLED: u32 = 2;
const ASYNC_BACKING_DISABLED_ERROR: RuntimeApiError =
RuntimeApiError::NotSupported { runtime_api_name: "test-runtime" };

fn validator_pubkeys(val_ids: &[Sr25519Keyring]) -> Vec<ValidatorId> {
val_ids.iter().map(|v| v.public().into()).collect()
Expand Down Expand Up @@ -242,14 +244,12 @@ async fn test_startup(virtual_overseer: &mut VirtualOverseer, test_state: &TestS
))))
.await;

// Prospective parachains mode is temporarily defined by the Runtime API version.
// Disable it for the test leaf.
assert_matches!(
virtual_overseer.recv().await,
AllMessages::RuntimeApi(
RuntimeApiMessage::Request(parent, RuntimeApiRequest::Version(tx))
RuntimeApiMessage::Request(parent, RuntimeApiRequest::StagingAsyncBackingParameters(tx))
) if parent == test_state.relay_parent => {
tx.send(Ok(API_VERSION_PROSPECTIVE_DISABLED)).unwrap();
tx.send(Err(ASYNC_BACKING_DISABLED_ERROR)).unwrap();
}
);

Expand Down
12 changes: 8 additions & 4 deletions node/core/backing/src/tests/prospective_parachains.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,15 @@
//! Tests for the backing subsystem with enabled prospective parachains.
use polkadot_node_subsystem::{messages::ChainApiMessage, TimeoutExt};
use polkadot_primitives::v2::{BlockNumber, Header, OccupiedCore};
use polkadot_primitives::{
v2::{BlockNumber, Header, OccupiedCore},
vstaging as vstaging_primitives,
};

use super::*;

const API_VERSION_PROSPECTIVE_ENABLED: u32 = RuntimeApiRequest::VALIDITY_CONSTRAINTS;
const ASYNC_BACKING_PARAMETERS: vstaging_primitives::AsyncBackingParameters =
vstaging_primitives::AsyncBackingParameters { max_candidate_depth: 4, allowed_ancestry_len: 3 };

struct TestLeaf {
activated: ActivatedLeaf,
Expand Down Expand Up @@ -52,9 +56,9 @@ async fn activate_leaf(
assert_matches!(
virtual_overseer.recv().await,
AllMessages::RuntimeApi(
RuntimeApiMessage::Request(parent, RuntimeApiRequest::Version(tx))
RuntimeApiMessage::Request(parent, RuntimeApiRequest::StagingAsyncBackingParameters(tx))
) if parent == leaf_hash => {
tx.send(Ok(API_VERSION_PROSPECTIVE_ENABLED)).unwrap();
tx.send(Ok(ASYNC_BACKING_PARAMETERS)).unwrap();
}
);

Expand Down
27 changes: 10 additions & 17 deletions node/core/prospective-parachains/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ use polkadot_node_subsystem::{
};
use polkadot_node_subsystem_util::{
inclusion_emulator::staging::{Constraints, RelayChainBlockInfo},
runtime::prospective_parachains_mode,
runtime::{prospective_parachains_mode, ProspectiveParachainsMode},
};
use polkadot_primitives::vstaging::{
BlockNumber, CandidateHash, CommittedCandidateReceipt, CoreState, Hash, Id as ParaId,
Expand All @@ -58,18 +58,6 @@ mod fragment_tree;

const LOG_TARGET: &str = "parachain::prospective-parachains";

// The maximum depth the subsystem will allow. 'depth' is defined as the
// amount of blocks between the para head in a relay-chain block's state
// and a candidate with a particular relay-parent.
//
// This value is chosen mostly for reasons of resource-limitation.
// Without it, a malicious validator group could create arbitrarily long,
// useless prospective parachains and DoS honest nodes.
const MAX_DEPTH: usize = 4;

// The maximum ancestry we support.
const MAX_ANCESTRY: usize = 5;

struct RelayBlockViewData {
// Scheduling info for paras and upcoming paras.
fragment_trees: HashMap<ParaId, FragmentTree>,
Expand Down Expand Up @@ -171,7 +159,8 @@ async fn handle_active_leaves_update<Context>(
let mode = prospective_parachains_mode(ctx.sender(), hash)
.await
.map_err(JfyiError::Runtime)?;
if !mode.is_enabled() {

let ProspectiveParachainsMode::Enabled { max_candidate_depth, allowed_ancestry_len } = mode else {
gum::trace!(
target: LOG_TARGET,
block_hash = ?hash,
Expand All @@ -180,7 +169,7 @@ async fn handle_active_leaves_update<Context>(

// Not a part of any allowed ancestry.
return Ok(())
}
};

let scheduled_paras = fetch_upcoming_paras(&mut *ctx, hash).await?;

Expand All @@ -200,7 +189,7 @@ async fn handle_active_leaves_update<Context>(
Some(info) => info,
};

let ancestry = fetch_ancestry(&mut *ctx, hash, MAX_ANCESTRY).await?;
let ancestry = fetch_ancestry(&mut *ctx, hash, allowed_ancestry_len).await?;

// Find constraints.
let mut fragment_trees = HashMap::new();
Expand Down Expand Up @@ -230,7 +219,7 @@ async fn handle_active_leaves_update<Context>(
para,
block_info.clone(),
constraints,
MAX_DEPTH,
max_candidate_depth,
ancestry.iter().cloned(),
)
.expect("ancestors are provided in reverse order and correctly; qed");
Expand Down Expand Up @@ -627,6 +616,10 @@ async fn fetch_ancestry<Context>(
relay_hash: Hash,
ancestors: usize,
) -> JfyiErrorResult<Vec<RelayChainBlockInfo>> {
if ancestors == 0 {
return Ok(Vec::new())
}

let (tx, rx) = oneshot::channel();
ctx.send_message(ChainApiMessage::Ancestors {
hash: relay_hash,
Expand Down
2 changes: 1 addition & 1 deletion node/core/provisioner/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -692,7 +692,7 @@ async fn select_candidates(
sender: &mut impl overseer::ProvisionerSenderTrait,
) -> Result<Vec<BackedCandidate>, Error> {
let selected_candidates = match prospective_parachains_mode {
ProspectiveParachainsMode::Enabled =>
ProspectiveParachainsMode::Enabled { .. } =>
request_backable_candidates(availability_cores, bitfields, relay_parent, sender).await?,
ProspectiveParachainsMode::Disabled =>
select_candidate_hashes_from_tracked(
Expand Down
16 changes: 13 additions & 3 deletions node/core/provisioner/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ mod select_candidates {
AllMessages::ProspectiveParachains(
ProspectiveParachainsMessage::GetBackableCandidate(.., tx),
) => match prospective_parachains_mode {
ProspectiveParachainsMode::Enabled => {
ProspectiveParachainsMode::Enabled { .. } => {
let _ = tx.send(candidates.next());
},
ProspectiveParachainsMode::Disabled =>
Expand Down Expand Up @@ -572,7 +572,8 @@ mod select_candidates {
let expected_candidates: Vec<_> =
[1, 4, 7, 8, 10].iter().map(|&idx| candidates[idx].clone()).collect();
// Expect prospective parachains subsystem requests.
let prospective_parachains_mode = ProspectiveParachainsMode::Enabled;
let prospective_parachains_mode =
ProspectiveParachainsMode::Enabled { max_candidate_depth: 0, allowed_ancestry_len: 0 };

let expected_backed = expected_candidates
.iter()
Expand All @@ -587,7 +588,16 @@ mod select_candidates {
.collect();

test_harness(
|r| mock_overseer(r, expected_backed, ProspectiveParachainsMode::Enabled),
|r| {
mock_overseer(
r,
expected_backed,
ProspectiveParachainsMode::Enabled {
max_candidate_depth: 0,
allowed_ancestry_len: 0,
},
)
},
|mut tx: TestSubsystemSender| async move {
let result = select_candidates(
&mock_cores,
Expand Down
69 changes: 44 additions & 25 deletions node/core/runtime-api/src/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ const VERSION_CACHE_SIZE: usize = 4 * 1024;
const DISPUTES_CACHE_SIZE: usize = 64 * 1024;

const STAGING_VALIDITY_CONSTRAINTS_CACHE_SIZE: usize = 10 * 1024;
const STAGING_ASYNC_BACKING_PARAMETERS_CACHE_SIZE: usize = 10 * 1024;

struct ResidentSizeOf<T>(T);

Expand Down Expand Up @@ -120,15 +121,16 @@ pub(crate) struct RequestResultCache {
(Hash, ParaId, OccupiedCoreAssumption),
ResidentSizeOf<Option<ValidationCodeHash>>,
>,

staging_validity_constraints:
MemoryLruCache<(Hash, ParaId), ResidentSizeOf<Option<vstaging_primitives::Constraints>>>,

version: MemoryLruCache<Hash, ResidentSizeOf<u32>>,
disputes: MemoryLruCache<
Hash,
ResidentSizeOf<Vec<(SessionIndex, CandidateHash, DisputeState<BlockNumber>)>>,
>,

staging_validity_constraints:
MemoryLruCache<(Hash, ParaId), ResidentSizeOf<Option<vstaging_primitives::Constraints>>>,
staging_async_backing_parameters:
MemoryLruCache<Hash, ResidentSizeOf<vstaging_primitives::AsyncBackingParameters>>,
}

impl Default for RequestResultCache {
Expand All @@ -155,13 +157,15 @@ impl Default for RequestResultCache {
on_chain_votes: MemoryLruCache::new(ON_CHAIN_VOTES_CACHE_SIZE),
pvfs_require_precheck: MemoryLruCache::new(PVFS_REQUIRE_PRECHECK_SIZE),
validation_code_hash: MemoryLruCache::new(VALIDATION_CODE_HASH_CACHE_SIZE),
version: MemoryLruCache::new(VERSION_CACHE_SIZE),
disputes: MemoryLruCache::new(DISPUTES_CACHE_SIZE),

staging_validity_constraints: MemoryLruCache::new(
STAGING_VALIDITY_CONSTRAINTS_CACHE_SIZE,
),

version: MemoryLruCache::new(VERSION_CACHE_SIZE),
disputes: MemoryLruCache::new(DISPUTES_CACHE_SIZE),
staging_async_backing_parameters: MemoryLruCache::new(
STAGING_ASYNC_BACKING_PARAMETERS_CACHE_SIZE,
),
}
}
}
Expand Down Expand Up @@ -420,21 +424,6 @@ impl RequestResultCache {
self.validation_code_hash.insert(key, ResidentSizeOf(value));
}

pub(crate) fn staging_validity_constraints(
&mut self,
key: (Hash, ParaId),
) -> Option<&Option<vstaging_primitives::Constraints>> {
self.staging_validity_constraints.get(&key).map(|v| &v.0)
}

pub(crate) fn cache_staging_validity_constraints(
&mut self,
key: (Hash, ParaId),
value: Option<vstaging_primitives::Constraints>,
) {
self.staging_validity_constraints.insert(key, ResidentSizeOf(value));
}

pub(crate) fn version(&mut self, relay_parent: &Hash) -> Option<&u32> {
self.version.get(&relay_parent).map(|v| &v.0)
}
Expand All @@ -457,6 +446,36 @@ impl RequestResultCache {
) {
self.disputes.insert(relay_parent, ResidentSizeOf(value));
}

pub(crate) fn staging_validity_constraints(
&mut self,
key: (Hash, ParaId),
) -> Option<&Option<vstaging_primitives::Constraints>> {
self.staging_validity_constraints.get(&key).map(|v| &v.0)
}

pub(crate) fn cache_staging_validity_constraints(
&mut self,
key: (Hash, ParaId),
value: Option<vstaging_primitives::Constraints>,
) {
self.staging_validity_constraints.insert(key, ResidentSizeOf(value));
}

pub(crate) fn staging_async_backing_parameters(
&mut self,
key: &Hash,
) -> Option<&vstaging_primitives::AsyncBackingParameters> {
self.staging_async_backing_parameters.get(&key).map(|v| &v.0)
}

pub(crate) fn cache_staging_async_backing_parameters(
&mut self,
key: Hash,
value: vstaging_primitives::AsyncBackingParameters,
) {
self.staging_async_backing_parameters.insert(key, ResidentSizeOf(value));
}
}

pub(crate) enum RequestResult {
Expand Down Expand Up @@ -491,9 +510,9 @@ pub(crate) enum RequestResult {
// This is a request with side-effects and no result, hence ().
SubmitPvfCheckStatement(Hash, PvfCheckStatement, ValidatorSignature, ()),
ValidationCodeHash(Hash, ParaId, OccupiedCoreAssumption, Option<ValidationCodeHash>),

StagingValidityConstraints(Hash, ParaId, Option<vstaging_primitives::Constraints>),

Version(Hash, u32),
Disputes(Hash, Vec<(SessionIndex, CandidateHash, DisputeState<BlockNumber>)>),

StagingValidityConstraints(Hash, ParaId, Option<vstaging_primitives::Constraints>),
StagingAsyncBackingParameters(Hash, vstaging_primitives::AsyncBackingParameters),
}
Loading

0 comments on commit c41cbbe

Please sign in to comment.