past-session validator discovery APIs (#2009)

* guide: fix formatting for SessionInfo module

* primitives: SessionInfo type

* punt on approval keys

* ah, revert the type alias

* session info runtime module skeleton

* update the guide

* runtime/configuration: sync with the guide

* runtime/configuration: setters for newly added fields

* runtime/configuration: set codec indexes

* runtime/configuration: update test

* primitives: fix SessionInfo definition

* runtime/session_info: initial impl

* runtime/session_info: use initializer for session handling (wip)

* runtime/session_info: mock authority discovery trait

* guide: update the initializer's order

* runtime/session_info: tests skeleton

* runtime/session_info: store n_delay_tranches in Configuration

* runtime/session_info: punt on approval keys

* runtime/session_info: add some basic tests

* Update primitives/src/v1.rs

* small fixes

* remove codec index annotation on structs

* fix off-by-one error

* validator_discovery: accept a session index

* runtime: replace validator_discovery api with session_info

* Update runtime/parachains/src/session_info.rs

Co-authored-by: Sergei Shulepov <sergei@parity.io>

* runtime/session_info: add a comment about missing entries

* runtime/session_info: define the keys

* util: expose connect_to_past_session_validators

* util: allow session_info requests for jobs

* runtime-api: add mock test for session_info

* collator-protocol: add session_index to test state

* util: fix error message for runtime error

* fix compilation

* fix tests after merge with master

Co-authored-by: Sergei Shulepov <sergei@parity.io>
This commit is contained in:
Andronik Ordian
2020-11-26 12:02:50 +01:00
committed by GitHub
parent 4ce744818c
commit 39a12b68f6
25 changed files with 696 additions and 213 deletions
+35 -7
View File
@@ -134,7 +134,7 @@ fn make_runtime_api_request<Client>(
Request::CandidatePendingAvailability(para, sender) => Request::CandidatePendingAvailability(para, sender) =>
query!(candidate_pending_availability(para), sender), query!(candidate_pending_availability(para), sender),
Request::CandidateEvents(sender) => query!(candidate_events(), sender), Request::CandidateEvents(sender) => query!(candidate_events(), sender),
Request::ValidatorDiscovery(ids, sender) => query!(validator_discovery(ids), sender), Request::SessionInfo(index, sender) => query!(session_info(index), sender),
Request::DmqContents(id, sender) => query!(dmq_contents(id), sender), Request::DmqContents(id, sender) => query!(dmq_contents(id), sender),
Request::InboundHrmpChannelsContents(id, sender) => query!(inbound_hrmp_channels_contents(id), sender), Request::InboundHrmpChannelsContents(id, sender) => query!(inbound_hrmp_channels_contents(id), sender),
} }
@@ -201,8 +201,8 @@ mod tests {
use polkadot_primitives::v1::{ use polkadot_primitives::v1::{
ValidatorId, ValidatorIndex, GroupRotationInfo, CoreState, PersistedValidationData, ValidatorId, ValidatorIndex, GroupRotationInfo, CoreState, PersistedValidationData,
Id as ParaId, OccupiedCoreAssumption, ValidationData, SessionIndex, ValidationCode, Id as ParaId, OccupiedCoreAssumption, ValidationData, SessionIndex, ValidationCode,
CommittedCandidateReceipt, CandidateEvent, AuthorityDiscoveryId, InboundDownwardMessage, CommittedCandidateReceipt, CandidateEvent, InboundDownwardMessage,
BlockNumber, InboundHrmpMessage, BlockNumber, InboundHrmpMessage, SessionInfo,
}; };
use polkadot_node_subsystem_test_helpers as test_helpers; use polkadot_node_subsystem_test_helpers as test_helpers;
use sp_core::testing::TaskExecutor; use sp_core::testing::TaskExecutor;
@@ -216,6 +216,7 @@ mod tests {
availability_cores: Vec<CoreState>, availability_cores: Vec<CoreState>,
validation_data: HashMap<ParaId, ValidationData>, validation_data: HashMap<ParaId, ValidationData>,
session_index_for_child: SessionIndex, session_index_for_child: SessionIndex,
session_info: HashMap<SessionIndex, SessionInfo>,
validation_code: HashMap<ParaId, ValidationCode>, validation_code: HashMap<ParaId, ValidationCode>,
historical_validation_code: HashMap<ParaId, Vec<(BlockNumber, ValidationCode)>>, historical_validation_code: HashMap<ParaId, Vec<(BlockNumber, ValidationCode)>>,
validation_outputs_results: HashMap<ParaId, bool>, validation_outputs_results: HashMap<ParaId, bool>,
@@ -289,6 +290,10 @@ mod tests {
self.session_index_for_child.clone() self.session_index_for_child.clone()
} }
fn session_info(&self, index: SessionIndex) -> Option<SessionInfo> {
self.session_info.get(&index).cloned()
}
fn validation_code( fn validation_code(
&self, &self,
para: ParaId, para: ParaId,
@@ -321,10 +326,6 @@ mod tests {
self.candidate_events.clone() self.candidate_events.clone()
} }
fn validator_discovery(ids: Vec<ValidatorId>) -> Vec<Option<AuthorityDiscoveryId>> {
vec![None; ids.len()]
}
fn dmq_contents( fn dmq_contents(
&self, &self,
recipient: ParaId, recipient: ParaId,
@@ -569,6 +570,33 @@ mod tests {
futures::executor::block_on(future::join(subsystem_task, test_task)); futures::executor::block_on(future::join(subsystem_task, test_task));
} }
#[test]
fn requests_session_info() {
let (ctx, mut ctx_handle) = test_helpers::make_subsystem_context(TaskExecutor::new());
let mut runtime_api = MockRuntimeApi::default();
let session_index = 1;
runtime_api.session_info.insert(session_index, Default::default());
let runtime_api = Arc::new(runtime_api);
let relay_parent = [1; 32].into();
let subsystem = RuntimeApiSubsystem::new(runtime_api.clone(), Metrics(None));
let subsystem_task = run(ctx, subsystem).map(|x| x.unwrap());
let test_task = async move {
let (tx, rx) = oneshot::channel();
ctx_handle.send(FromOverseer::Communication {
msg: RuntimeApiMessage::Request(relay_parent, Request::SessionInfo(session_index, tx))
}).await;
assert_eq!(rx.await.unwrap().unwrap(), Some(Default::default()));
ctx_handle.send(FromOverseer::Signal(OverseerSignal::Conclude)).await;
};
futures::executor::block_on(future::join(subsystem_task, test_task));
}
#[test] #[test]
fn requests_validation_code() { fn requests_validation_code() {
let (ctx, mut ctx_handle) = test_helpers::make_subsystem_context(TaskExecutor::new()); let (ctx, mut ctx_handle) = test_helpers::make_subsystem_context(TaskExecutor::new());
@@ -738,6 +738,7 @@ mod tests {
use polkadot_primitives::v1::{ use polkadot_primitives::v1::{
BlockData, CandidateDescriptor, CollatorPair, ScheduledCore, BlockData, CandidateDescriptor, CollatorPair, ScheduledCore,
ValidatorIndex, GroupRotationInfo, AuthorityDiscoveryId, ValidatorIndex, GroupRotationInfo, AuthorityDiscoveryId,
SessionIndex, SessionInfo,
}; };
use polkadot_subsystem::{ActiveLeavesUpdate, messages::{RuntimeApiMessage, RuntimeApiRequest}}; use polkadot_subsystem::{ActiveLeavesUpdate, messages::{RuntimeApiMessage, RuntimeApiRequest}};
use polkadot_node_subsystem_util::TimeoutExt; use polkadot_node_subsystem_util::TimeoutExt;
@@ -776,6 +777,7 @@ mod tests {
relay_parent: Hash, relay_parent: Hash,
availability_core: CoreState, availability_core: CoreState,
our_collator_pair: CollatorPair, our_collator_pair: CollatorPair,
session_index: SessionIndex,
} }
fn validator_pubkeys(val_ids: &[Sr25519Keyring]) -> Vec<ValidatorId> { fn validator_pubkeys(val_ids: &[Sr25519Keyring]) -> Vec<ValidatorId> {
@@ -832,6 +834,7 @@ mod tests {
relay_parent, relay_parent,
availability_core, availability_core,
our_collator_pair, our_collator_pair,
session_index: 1,
} }
} }
} }
@@ -841,6 +844,10 @@ mod tests {
&self.validator_groups.0[0] &self.validator_groups.0[0]
} }
fn current_session_index(&self) -> SessionIndex {
self.session_index
}
fn current_group_validator_peer_ids(&self) -> Vec<PeerId> { fn current_group_validator_peer_ids(&self) -> Vec<PeerId> {
self.current_group_validator_indices().iter().map(|i| self.validator_peer_id[*i as usize].clone()).collect() self.current_group_validator_indices().iter().map(|i| self.validator_peer_id[*i as usize].clone()).collect()
} }
@@ -870,20 +877,6 @@ mod tests {
.collect() .collect()
} }
fn next_group_validator_ids(&self) -> Vec<ValidatorId> {
self.next_group_validator_indices()
.iter()
.map(|i| self.validator_public[*i as usize].clone())
.collect()
}
/// Returns the unique count of validators in the current and next group.
fn current_and_next_group_unique_validator_count(&self) -> usize {
let mut indices = self.next_group_validator_indices().iter().collect::<HashSet<_>>();
indices.extend(self.current_group_validator_indices());
indices.len()
}
/// Generate a new relay parent and inform the subsystem about the new view. /// 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 working on the old `relay_parent` /// If `merge_views == true` it means the subsystem will be informed that we working on the old `relay_parent`
@@ -1090,20 +1083,33 @@ mod tests {
overseer_recv(virtual_overseer).await, overseer_recv(virtual_overseer).await,
AllMessages::RuntimeApi(RuntimeApiMessage::Request( AllMessages::RuntimeApi(RuntimeApiMessage::Request(
relay_parent, relay_parent,
RuntimeApiRequest::ValidatorDiscovery(validators, tx), RuntimeApiRequest::SessionIndexForChild(tx),
)) => { )) => {
assert_eq!(relay_parent, test_state.relay_parent); assert_eq!(relay_parent, test_state.relay_parent);
assert_eq!(validators.len(), test_state.current_and_next_group_unique_validator_count()); tx.send(Ok(test_state.current_session_index())).unwrap();
}
);
let current_validators = test_state.current_group_validator_ids(); assert_matches!(
let next_validators = test_state.next_group_validator_ids(); overseer_recv(virtual_overseer).await,
AllMessages::RuntimeApi(RuntimeApiMessage::Request(
relay_parent,
RuntimeApiRequest::SessionInfo(index, tx),
)) => {
assert_eq!(relay_parent, test_state.relay_parent);
assert_eq!(index, test_state.current_session_index());
assert!(validators.iter().all(|v| current_validators.contains(&v) || next_validators.contains(&v))); let validators = test_state.current_group_validator_ids();
let current_discovery_keys = test_state.current_group_validator_authority_ids();
let next_discovery_keys = test_state.next_group_validator_authority_ids();
let current_validators = test_state.current_group_validator_authority_ids(); let discovery_keys = [&current_discovery_keys[..], &next_discovery_keys[..]].concat();
let next_validators = test_state.next_group_validator_authority_ids();
tx.send(Ok(current_validators.into_iter().chain(next_validators).map(Some).collect())).unwrap(); tx.send(Ok(Some(SessionInfo {
validators,
discovery_keys,
..Default::default()
}))).unwrap();
} }
); );
@@ -60,16 +60,6 @@ enum Error {
Prometheus(#[from] prometheus::PrometheusError), Prometheus(#[from] prometheus::PrometheusError),
} }
impl From<util::validator_discovery::Error> for Error {
fn from(me: util::validator_discovery::Error) -> Self {
match me {
util::validator_discovery::Error::Subsystem(s) => Error::Subsystem(s),
util::validator_discovery::Error::RuntimeApi(ra) => Error::RuntimeApi(ra),
util::validator_discovery::Error::Oneshot(c) => Error::Oneshot(c),
}
}
}
type Result<T> = std::result::Result<T, Error>; type Result<T> = std::result::Result<T, Error>;
/// What side of the collator protocol is being engaged /// What side of the collator protocol is being engaged
@@ -27,8 +27,6 @@ pub enum Error {
#[error(transparent)] #[error(transparent)]
Runtime(#[from] polkadot_subsystem::errors::RuntimeApiError), Runtime(#[from] polkadot_subsystem::errors::RuntimeApiError),
#[error(transparent)] #[error(transparent)]
ValidatorDiscovery(#[from] polkadot_node_subsystem_util::validator_discovery::Error),
#[error(transparent)]
Util(#[from] polkadot_node_subsystem_util::Error), Util(#[from] polkadot_node_subsystem_util::Error),
} }
@@ -11,7 +11,7 @@ use sp_keyring::Sr25519Keyring;
use polkadot_primitives::v1::{ use polkadot_primitives::v1::{
AuthorityDiscoveryId, BlockData, CoreState, GroupRotationInfo, Id as ParaId, AuthorityDiscoveryId, BlockData, CoreState, GroupRotationInfo, Id as ParaId,
ScheduledCore, ValidatorIndex, ScheduledCore, ValidatorIndex, SessionIndex, SessionInfo,
}; };
use polkadot_subsystem::messages::{RuntimeApiMessage, RuntimeApiRequest}; use polkadot_subsystem::messages::{RuntimeApiMessage, RuntimeApiRequest};
use polkadot_node_subsystem_test_helpers as test_helpers; use polkadot_node_subsystem_test_helpers as test_helpers;
@@ -37,8 +37,10 @@ fn validator_authority_id(val_ids: &[Sr25519Keyring]) -> Vec<AuthorityDiscoveryI
val_ids.iter().map(|v| v.public().into()).collect() val_ids.iter().map(|v| v.public().into()).collect()
} }
type VirtualOverseer = test_helpers::TestSubsystemContextHandle<PoVDistributionMessage>;
struct TestHarness { struct TestHarness {
virtual_overseer: test_helpers::TestSubsystemContextHandle<PoVDistributionMessage>, virtual_overseer: VirtualOverseer,
} }
fn test_harness<T: Future<Output = ()>>( fn test_harness<T: Future<Output = ()>>(
@@ -75,7 +77,7 @@ fn test_harness<T: Future<Output = ()>>(
const TIMEOUT: Duration = Duration::from_millis(100); const TIMEOUT: Duration = Duration::from_millis(100);
async fn overseer_send( async fn overseer_send(
overseer: &mut test_helpers::TestSubsystemContextHandle<PoVDistributionMessage>, overseer: &mut VirtualOverseer,
msg: PoVDistributionMessage, msg: PoVDistributionMessage,
) { ) {
trace!("Sending message:\n{:?}", &msg); trace!("Sending message:\n{:?}", &msg);
@@ -87,7 +89,7 @@ async fn overseer_send(
} }
async fn overseer_recv( async fn overseer_recv(
overseer: &mut test_helpers::TestSubsystemContextHandle<PoVDistributionMessage>, overseer: &mut VirtualOverseer,
) -> AllMessages { ) -> AllMessages {
let msg = overseer_recv_with_timeout(overseer, TIMEOUT) let msg = overseer_recv_with_timeout(overseer, TIMEOUT)
.await .await
@@ -99,7 +101,7 @@ async fn overseer_recv(
} }
async fn overseer_recv_with_timeout( async fn overseer_recv_with_timeout(
overseer: &mut test_helpers::TestSubsystemContextHandle<PoVDistributionMessage>, overseer: &mut VirtualOverseer,
timeout: Duration, timeout: Duration,
) -> Option<AllMessages> { ) -> Option<AllMessages> {
trace!("Waiting for message..."); trace!("Waiting for message...");
@@ -110,7 +112,7 @@ async fn overseer_recv_with_timeout(
} }
async fn overseer_signal( async fn overseer_signal(
overseer: &mut test_helpers::TestSubsystemContextHandle<PoVDistributionMessage>, overseer: &mut VirtualOverseer,
signal: OverseerSignal, signal: OverseerSignal,
) { ) {
overseer overseer
@@ -130,6 +132,7 @@ struct TestState {
validator_groups: (Vec<Vec<ValidatorIndex>>, GroupRotationInfo), validator_groups: (Vec<Vec<ValidatorIndex>>, GroupRotationInfo),
relay_parent: Hash, relay_parent: Hash,
availability_cores: Vec<CoreState>, availability_cores: Vec<CoreState>,
session_index: SessionIndex,
} }
impl Default for TestState { impl Default for TestState {
@@ -184,10 +187,56 @@ impl Default for TestState {
validator_groups, validator_groups,
relay_parent, relay_parent,
availability_cores, availability_cores,
session_index: 1,
} }
} }
} }
async fn test_validator_discovery(
virtual_overseer: &mut VirtualOverseer,
expected_relay_parent: Hash,
session_index: SessionIndex,
validator_ids: &[ValidatorId],
discovery_ids: &[AuthorityDiscoveryId],
validator_group: &[ValidatorIndex],
) {
assert_matches!(
overseer_recv(virtual_overseer).await,
AllMessages::RuntimeApi(RuntimeApiMessage::Request(
relay_parent,
RuntimeApiRequest::SessionIndexForChild(tx),
)) => {
assert_eq!(relay_parent, expected_relay_parent);
tx.send(Ok(session_index)).unwrap();
}
);
assert_matches!(
overseer_recv(virtual_overseer).await,
AllMessages::RuntimeApi(RuntimeApiMessage::Request(
relay_parent,
RuntimeApiRequest::SessionInfo(index, tx),
)) => {
assert_eq!(relay_parent, expected_relay_parent);
assert_eq!(index, session_index);
let validators = validator_group.iter()
.map(|idx| validator_ids[*idx as usize].clone())
.collect();
let discovery_keys = validator_group.iter()
.map(|idx| discovery_ids[*idx as usize].clone())
.collect();
tx.send(Ok(Some(SessionInfo {
validators,
discovery_keys,
..Default::default()
}))).unwrap();
}
);
}
#[test] #[test]
fn ask_validators_for_povs() { fn ask_validators_for_povs() {
let test_state = TestState::default(); let test_state = TestState::default();
@@ -271,25 +320,14 @@ fn ask_validators_for_povs() {
} }
); );
// obtain the validator_id to authority_id mapping test_validator_discovery(
assert_matches!( &mut virtual_overseer,
overseer_recv(&mut virtual_overseer).await, current,
AllMessages::RuntimeApi(RuntimeApiMessage::Request( test_state.session_index,
relay_parent, &test_state.validator_public,
RuntimeApiRequest::ValidatorDiscovery(validators, tx), &test_state.validator_authority_id,
)) => { &test_state.validator_groups.0[0],
assert_eq!(relay_parent, current); ).await;
assert_eq!(validators.len(), 3);
assert!(validators.iter().all(|v| test_state.validator_public.contains(&v)));
let result = vec![
Some(test_state.validator_authority_id[2].clone()),
Some(test_state.validator_authority_id[0].clone()),
Some(test_state.validator_authority_id[4].clone()),
];
tx.send(Ok(result)).unwrap();
}
);
// We now should connect to our validator group. // We now should connect to our validator group.
assert_matches!( assert_matches!(
@@ -448,24 +486,14 @@ fn ask_validators_for_povs() {
); );
// obtain the validator_id to authority_id mapping // obtain the validator_id to authority_id mapping
assert_matches!( test_validator_discovery(
overseer_recv(&mut virtual_overseer).await, &mut virtual_overseer,
AllMessages::RuntimeApi(RuntimeApiMessage::Request( next_leaf,
relay_parent, test_state.session_index,
RuntimeApiRequest::ValidatorDiscovery(validators, tx), &test_state.validator_public,
)) => { &test_state.validator_authority_id,
assert_eq!(relay_parent, next_leaf); &test_state.validator_groups.0[0],
assert_eq!(validators.len(), 3); ).await;
assert!(validators.iter().all(|v| test_state.validator_public.contains(&v)));
let result = vec![
Some(test_state.validator_authority_id[2].clone()),
Some(test_state.validator_authority_id[0].clone()),
Some(test_state.validator_authority_id[4].clone()),
];
tx.send(Ok(result)).unwrap();
}
);
// We now should connect to our validator group. // We now should connect to our validator group.
assert_matches!( assert_matches!(
@@ -716,7 +744,7 @@ fn we_inform_peers_with_same_view_we_are_awaiting() {
RuntimeApiRequest::ValidatorGroups(tx) RuntimeApiRequest::ValidatorGroups(tx)
)) => { )) => {
assert_eq!(relay_parent, hash_a); assert_eq!(relay_parent, hash_a);
tx.send(Ok(validator_groups)).unwrap(); tx.send(Ok(validator_groups.clone())).unwrap();
} }
); );
@@ -731,25 +759,14 @@ fn we_inform_peers_with_same_view_we_are_awaiting() {
} }
); );
assert_matches!( test_validator_discovery(
handle.recv().await, &mut handle,
AllMessages::RuntimeApi(RuntimeApiMessage::Request( hash_a,
relay_parent, 1,
RuntimeApiRequest::ValidatorDiscovery(validators_res, tx), &validators,
)) => { &validator_authority_id,
assert_eq!(relay_parent, hash_a); &validator_groups.0[0],
assert_eq!(validators_res.len(), 3); ).await;
assert!(validators_res.iter().all(|v| validators.contains(&v)));
let result = vec![
Some(validator_authority_id[2].clone()),
Some(validator_authority_id[0].clone()),
Some(validator_authority_id[4].clone()),
];
tx.send(Ok(result)).unwrap();
}
);
assert_matches!( assert_matches!(
handle.recv().await, handle.recv().await,
+3
View File
@@ -37,6 +37,7 @@ use polkadot_primitives::v1::{
CandidateEvent, CommittedCandidateReceipt, CoreState, EncodeAs, PersistedValidationData, CandidateEvent, CommittedCandidateReceipt, CoreState, EncodeAs, PersistedValidationData,
GroupRotationInfo, Hash, Id as ParaId, ValidationData, OccupiedCoreAssumption, GroupRotationInfo, Hash, Id as ParaId, ValidationData, OccupiedCoreAssumption,
SessionIndex, Signed, SigningContext, ValidationCode, ValidatorId, ValidatorIndex, SessionIndex, Signed, SigningContext, ValidationCode, ValidatorId, ValidatorIndex,
SessionInfo,
}; };
use sp_core::{ use sp_core::{
traits::SpawnNamed, traits::SpawnNamed,
@@ -193,6 +194,7 @@ specialize_requests! {
fn request_validation_code(para_id: ParaId, assumption: OccupiedCoreAssumption) -> Option<ValidationCode>; ValidationCode; fn request_validation_code(para_id: ParaId, assumption: OccupiedCoreAssumption) -> Option<ValidationCode>; ValidationCode;
fn request_candidate_pending_availability(para_id: ParaId) -> Option<CommittedCandidateReceipt>; CandidatePendingAvailability; fn request_candidate_pending_availability(para_id: ParaId) -> Option<CommittedCandidateReceipt>; CandidatePendingAvailability;
fn request_candidate_events() -> Vec<CandidateEvent>; CandidateEvents; fn request_candidate_events() -> Vec<CandidateEvent>; CandidateEvents;
fn request_session_info(index: SessionIndex) -> Option<SessionInfo>; SessionInfo;
} }
/// Request some data from the `RuntimeApi` via a SubsystemContext. /// Request some data from the `RuntimeApi` via a SubsystemContext.
@@ -274,6 +276,7 @@ specialize_requests_ctx! {
fn request_validation_code_ctx(para_id: ParaId, assumption: OccupiedCoreAssumption) -> Option<ValidationCode>; ValidationCode; fn request_validation_code_ctx(para_id: ParaId, assumption: OccupiedCoreAssumption) -> Option<ValidationCode>; ValidationCode;
fn request_candidate_pending_availability_ctx(para_id: ParaId) -> Option<CommittedCandidateReceipt>; CandidatePendingAvailability; fn request_candidate_pending_availability_ctx(para_id: ParaId) -> Option<CommittedCandidateReceipt>; CandidatePendingAvailability;
fn request_candidate_events_ctx() -> Vec<CandidateEvent>; CandidateEvents; fn request_candidate_events_ctx() -> Vec<CandidateEvent>; CandidateEvents;
fn request_session_info_ctx(index: SessionIndex) -> Option<SessionInfo>; SessionInfo;
} }
/// From the given set of validators, find the first key we can sign with, if any. /// From the given set of validators, find the first key we can sign with, if any.
@@ -20,34 +20,20 @@ use std::collections::HashMap;
use std::pin::Pin; use std::pin::Pin;
use futures::{ use futures::{
channel::{mpsc, oneshot}, channel::mpsc,
task::{Poll, self}, task::{Poll, self},
stream, stream,
}; };
use streamunordered::{StreamUnordered, StreamYield}; use streamunordered::{StreamUnordered, StreamYield};
use thiserror::Error;
use polkadot_node_subsystem::{ use polkadot_node_subsystem::{
errors::RuntimeApiError, SubsystemError, errors::RuntimeApiError,
messages::{AllMessages, RuntimeApiMessage, RuntimeApiRequest, NetworkBridgeMessage}, messages::{AllMessages, NetworkBridgeMessage},
SubsystemContext, SubsystemContext,
}; };
use polkadot_primitives::v1::{Hash, ValidatorId, AuthorityDiscoveryId}; use polkadot_primitives::v1::{Hash, ValidatorId, AuthorityDiscoveryId, SessionIndex};
use sc_network::PeerId; use sc_network::PeerId;
use crate::Error;
/// Error when making a request to connect to validators.
#[derive(Debug, Error)]
pub enum Error {
/// Attempted to send or receive on a oneshot channel which had been canceled
#[error(transparent)]
Oneshot(#[from] oneshot::Canceled),
/// A subsystem error.
#[error(transparent)]
Subsystem(#[from] SubsystemError),
/// An error in the Runtime API.
#[error(transparent)]
RuntimeApi(#[from] RuntimeApiError),
}
/// Utility function to make it easier to connect to validators. /// Utility function to make it easier to connect to validators.
pub async fn connect_to_validators<Context: SubsystemContext>( pub async fn connect_to_validators<Context: SubsystemContext>(
@@ -55,17 +41,42 @@ pub async fn connect_to_validators<Context: SubsystemContext>(
relay_parent: Hash, relay_parent: Hash,
validators: Vec<ValidatorId>, validators: Vec<ValidatorId>,
) -> Result<ConnectionRequest, Error> { ) -> Result<ConnectionRequest, Error> {
// ValidatorId -> AuthorityDiscoveryId let current_index = crate::request_session_index_for_child_ctx(relay_parent, ctx).await?.await??;
let (tx, rx) = oneshot::channel(); connect_to_past_session_validators(ctx, relay_parent, validators, current_index).await
}
ctx.send_message(AllMessages::RuntimeApi( /// Utility function to make it easier to connect to validators in the past sessions.
RuntimeApiMessage::Request( pub async fn connect_to_past_session_validators<Context: SubsystemContext>(
relay_parent, ctx: &mut Context,
RuntimeApiRequest::ValidatorDiscovery(validators.clone(), tx), relay_parent: Hash,
) validators: Vec<ValidatorId>,
)).await; session_index: SessionIndex,
) -> Result<ConnectionRequest, Error> {
let session_info = crate::request_session_info_ctx(
relay_parent,
session_index,
ctx,
).await?.await??;
let (session_validators, discovery_keys) = match session_info {
Some(info) => (info.validators, info.discovery_keys),
None => return Err(RuntimeApiError::from(
format!("No SessionInfo found for the index {}", session_index)
).into()),
};
let id_to_index = session_validators.iter()
.zip(0usize..)
.collect::<HashMap<_, _>>();
// We assume the same ordering in authorities as in validators so we can do an index search
let maybe_authorities: Vec<_> = validators.iter()
.map(|id| {
let validator_index = id_to_index.get(&id);
validator_index.and_then(|i| discovery_keys.get(*i).cloned())
})
.collect();
let maybe_authorities = rx.await??;
let authorities: Vec<_> = maybe_authorities.iter() let authorities: Vec<_> = maybe_authorities.iter()
.cloned() .cloned()
.filter_map(|id| id) .filter_map(|id| id)
+3 -9
View File
@@ -31,7 +31,7 @@ use polkadot_node_primitives::{
CollationGenerationConfig, MisbehaviorReport, SignedFullStatement, ValidationResult, CollationGenerationConfig, MisbehaviorReport, SignedFullStatement, ValidationResult,
}; };
use polkadot_primitives::v1::{ use polkadot_primitives::v1::{
AuthorityDiscoveryId, AvailableData, BackedCandidate, BlockNumber, AuthorityDiscoveryId, AvailableData, BackedCandidate, BlockNumber, SessionInfo,
Header as BlockHeader, CandidateDescriptor, CandidateEvent, CandidateReceipt, Header as BlockHeader, CandidateDescriptor, CandidateEvent, CandidateReceipt,
CollatorId, CommittedCandidateReceipt, CoreState, ErasureChunk, CollatorId, CommittedCandidateReceipt, CoreState, ErasureChunk,
GroupRotationInfo, Hash, Id as ParaId, OccupiedCoreAssumption, GroupRotationInfo, Hash, Id as ParaId, OccupiedCoreAssumption,
@@ -434,14 +434,8 @@ pub enum RuntimeApiRequest {
/// Get all events concerning candidates (backing, inclusion, time-out) in the parent of /// Get all events concerning candidates (backing, inclusion, time-out) in the parent of
/// the block in whose state this request is executed. /// the block in whose state this request is executed.
CandidateEvents(RuntimeApiSender<Vec<CandidateEvent>>), CandidateEvents(RuntimeApiSender<Vec<CandidateEvent>>),
/// Get the `AuthorityDiscoveryId`s corresponding to the given `ValidatorId`s. /// Get the session info for the given session, if stored.
/// Currently this request is limited to validators in the current session. SessionInfo(SessionIndex, RuntimeApiSender<Option<SessionInfo>>),
///
/// Returns `None` for validators not found in the current session.
ValidatorDiscovery(
Vec<ValidatorId>,
RuntimeApiSender<Vec<Option<AuthorityDiscoveryId>>>,
),
/// Get all the pending inbound messages in the downward message queue for a para. /// Get all the pending inbound messages in the downward message queue for a para.
DmqContents( DmqContents(
ParaId, ParaId,
+61 -7
View File
@@ -25,6 +25,7 @@ use primitives::RuntimeDebug;
use runtime_primitives::traits::AppVerify; use runtime_primitives::traits::AppVerify;
use inherents::InherentIdentifier; use inherents::InherentIdentifier;
use sp_arithmetic::traits::{BaseArithmetic, Saturating, Zero}; use sp_arithmetic::traits::{BaseArithmetic, Saturating, Zero};
use application_crypto::KeyTypeId;
pub use runtime_primitives::traits::{BlakeTwo256, Hash as HashT}; pub use runtime_primitives::traits::{BlakeTwo256, Hash as HashT};
@@ -57,6 +58,34 @@ pub use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId;
/// Unique identifier for the Inclusion Inherent /// Unique identifier for the Inclusion Inherent
pub const INCLUSION_INHERENT_IDENTIFIER: InherentIdentifier = *b"inclusn0"; pub const INCLUSION_INHERENT_IDENTIFIER: InherentIdentifier = *b"inclusn0";
/// The key type ID for a parachain approval voting key.
pub const APPROVAL_KEY_TYPE_ID: KeyTypeId = KeyTypeId(*b"aprv");
mod approval_app {
use application_crypto::{app_crypto, sr25519};
app_crypto!(sr25519, super::APPROVAL_KEY_TYPE_ID);
}
/// The public key of a keypair used by a validator for approval voting
/// on included parachain candidates.
pub type ApprovalId = approval_app::Public;
/// The key type ID for parachain assignment key.
pub const ASSIGNMENT_KEY_TYPE_ID: KeyTypeId = KeyTypeId(*b"asgn");
// The public key of a keypair used by a validator for determining assignments
/// to approve included parachain candidates.
mod assigment_app {
use application_crypto::{app_crypto, sr25519};
app_crypto!(sr25519, super::ASSIGNMENT_KEY_TYPE_ID);
}
/// The public key of a keypair used by a validator for determining assignments
/// to approve included parachain candidates.
pub type AssignmentId = assigment_app::Public;
/// Get a collator signature payload on a relay-parent, block-data combo. /// Get a collator signature payload on a relay-parent, block-data combo.
pub fn collator_signature_payload<H: AsRef<[u8]>>( pub fn collator_signature_payload<H: AsRef<[u8]>>(
relay_parent: &H, relay_parent: &H,
@@ -671,6 +700,35 @@ pub enum CandidateEvent<H = Hash> {
CandidateTimedOut(CandidateReceipt<H>, HeadData), CandidateTimedOut(CandidateReceipt<H>, HeadData),
} }
/// Information about validator sets of a session.
#[derive(Clone, Encode, Decode, RuntimeDebug)]
#[cfg_attr(feature = "std", derive(PartialEq, Default))]
pub struct SessionInfo {
/// Validators in canonical ordering.
pub validators: Vec<ValidatorId>,
/// Validators' authority discovery keys for the session in canonical ordering.
pub discovery_keys: Vec<AuthorityDiscoveryId>,
/// The assignment and approval keys for validators.
pub approval_keys: Vec<(ApprovalId, AssignmentId)>,
/// Validators in shuffled ordering - these are the validator groups as produced
/// by the `Scheduler` module for the session and are typically referred to by
/// `GroupIndex`.
pub validator_groups: Vec<Vec<ValidatorIndex>>,
/// The number of availability cores used by the protocol during this session.
pub n_cores: u32,
/// The zeroth delay tranche width.
pub zeroth_delay_tranche_width: u32,
/// The number of samples we do of relay_vrf_modulo.
pub relay_vrf_modulo_samples: u32,
/// The number of delay tranches in total.
pub n_delay_tranches: u32,
/// How many slots (BABE / SASSAFRAS) must pass before an assignment is considered a
/// no-show.
pub no_show_slots: u32,
/// The number of validators needed to approve a block.
pub needed_approvals: u32,
}
sp_api::decl_runtime_apis! { sp_api::decl_runtime_apis! {
/// The API for querying the state of parachains on-chain. /// The API for querying the state of parachains on-chain.
pub trait ParachainHost<H: Decode = Hash, N: Encode + Decode = BlockNumber> { pub trait ParachainHost<H: Decode = Hash, N: Encode + Decode = BlockNumber> {
@@ -710,6 +768,9 @@ sp_api::decl_runtime_apis! {
/// This can be used to instantiate a `SigningContext`. /// This can be used to instantiate a `SigningContext`.
fn session_index_for_child() -> SessionIndex; fn session_index_for_child() -> SessionIndex;
/// Get the session info for the given session, if stored.
fn session_info(index: SessionIndex) -> Option<SessionInfo>;
/// Fetch the validation code used by a para, making the given `OccupiedCoreAssumption`. /// Fetch the validation code used by a para, making the given `OccupiedCoreAssumption`.
/// ///
/// Returns `None` if either the para is not registered or the assumption is `Freed` /// Returns `None` if either the para is not registered or the assumption is `Freed`
@@ -735,13 +796,6 @@ sp_api::decl_runtime_apis! {
#[skip_initialize_block] #[skip_initialize_block]
fn candidate_events() -> Vec<CandidateEvent<H>>; fn candidate_events() -> Vec<CandidateEvent<H>>;
/// Get the `AuthorityDiscoveryId`s corresponding to the given `ValidatorId`s.
/// Currently this request is limited to validators in the current session.
///
/// We assume that every validator runs authority discovery,
/// which would allow us to establish point-to-point connection to given validators.
fn validator_discovery(validators: Vec<ValidatorId>) -> Vec<Option<AuthorityDiscoveryId>>;
/// Get all the pending inbound messages in the downward message queue for a para. /// Get all the pending inbound messages in the downward message queue for a para.
fn dmq_contents( fn dmq_contents(
recipient: Id, recipient: Id,
@@ -23,7 +23,7 @@ The other parachains modules are initialized in this order:
1. Paras 1. Paras
1. Scheduler 1. Scheduler
1. Inclusion 1. Inclusion
1. Validity 1. SessionInfo
1. DMP 1. DMP
1. UMP 1. UMP
1. HRMP 1. HRMP
@@ -30,7 +30,7 @@ struct SessionInfo {
// no-show. // no-show.
no_show_slots: u32, no_show_slots: u32,
/// The number of validators needed to approve a block. /// The number of validators needed to approve a block.
needed_approvals: u32, needed_approvals: u32,
} }
``` ```
@@ -45,7 +45,6 @@ Sessions: map SessionIndex => Option<SessionInfo>,
## Session Change ## Session Change
1. Update the `CurrentSessionIndex`.
1. Update `EarliestStoredSession` based on `config.dispute_period` and remove all entries from `Sessions` from the previous value up to the new value. 1. Update `EarliestStoredSession` based on `config.dispute_period` and remove all entries from `Sessions` from the previous value up to the new value.
1. Create a new entry in `Sessions` with information about the current session. 1. Create a new entry in `Sessions` with information about the current session.
@@ -424,14 +424,8 @@ enum RuntimeApiRequest {
Validators(ResponseChannel<Vec<ValidatorId>>), Validators(ResponseChannel<Vec<ValidatorId>>),
/// Get the validator groups and rotation info. /// Get the validator groups and rotation info.
ValidatorGroups(ResponseChannel<(Vec<Vec<ValidatorIndex>>, GroupRotationInfo)>), ValidatorGroups(ResponseChannel<(Vec<Vec<ValidatorIndex>>, GroupRotationInfo)>),
/// Get the session index for children of the block. This can be used to construct a signing /// Get information about all availability cores.
/// context. AvailabilityCores(ResponseChannel<Vec<CoreState>>),
SessionIndex(ResponseChannel<SessionIndex>),
/// Get the validation code for a specific para, using the given occupied core assumption.
ValidationCode(ParaId, OccupiedCoreAssumption, ResponseChannel<Option<ValidationCode>>),
/// Fetch the historical validation code used by a para for candidates executed in
/// the context of a given block height in the current chain.
HistoricalValidationCode(ParaId, BlockNumber, ResponseChannel<Option<ValidationCode>>),
/// with the given occupied core assumption. /// with the given occupied core assumption.
PersistedValidationData( PersistedValidationData(
ParaId, ParaId,
@@ -450,12 +444,25 @@ enum RuntimeApiRequest {
CandidateCommitments, CandidateCommitments,
RuntimeApiSender<bool>, RuntimeApiSender<bool>,
), ),
/// Get information about all availability cores. /// Get the session index for children of the block. This can be used to construct a signing
AvailabilityCores(ResponseChannel<Vec<CoreState>>), /// context.
SessionIndexForChild(ResponseChannel<SessionIndex>),
/// Get the validation code for a specific para, using the given occupied core assumption.
ValidationCode(ParaId, OccupiedCoreAssumption, ResponseChannel<Option<ValidationCode>>),
/// Fetch the historical validation code used by a para for candidates executed in
/// the context of a given block height in the current chain.
HistoricalValidationCode(ParaId, BlockNumber, ResponseChannel<Option<ValidationCode>>),
/// Get a committed candidate receipt for all candidates pending availability. /// Get a committed candidate receipt for all candidates pending availability.
CandidatePendingAvailability(ParaId, ResponseChannel<Option<CommittedCandidateReceipt>>), CandidatePendingAvailability(ParaId, ResponseChannel<Option<CommittedCandidateReceipt>>),
/// Get all events concerning candidates in the last block. /// Get all events concerning candidates in the last block.
CandidateEvents(ResponseChannel<Vec<CandidateEvent>>), CandidateEvents(ResponseChannel<Vec<CandidateEvent>>),
/// Get the session info for the given session, if stored.
SessionInfo(SessionIndex, ResponseChannel<Option<SessionInfo>>),
/// Get all the pending inbound messages in the downward message queue for a para.
DmqContents(ParaId, ResponseChannel<Vec<InboundDownwardMessage<BlockNumber>>>),
/// Get the contents of all channels addressed to the given recipient. Channels that have no
/// messages in them are also included.
InboundHrmpChannelsContents(ParaId, ResponseChannel<BTreeMap<ParaId, Vec<InboundHrmpMessage<BlockNumber>>>>),
} }
enum RuntimeApiMessage { enum RuntimeApiMessage {
@@ -12,6 +12,9 @@ struct HostConfiguration {
pub validation_upgrade_frequency: BlockNumber, pub validation_upgrade_frequency: BlockNumber,
/// The delay, in blocks, before a validation upgrade is applied. /// The delay, in blocks, before a validation upgrade is applied.
pub validation_upgrade_delay: BlockNumber, pub validation_upgrade_delay: BlockNumber,
/// The acceptance period, in blocks. This is the amount of blocks after availability that validators
/// and fishermen have to perform secondary checks or issue reports.
pub acceptance_period: BlockNumber,
/// The maximum validation code size, in bytes. /// The maximum validation code size, in bytes.
pub max_code_size: u32, pub max_code_size: u32,
/// The maximum head-data size, in bytes. /// The maximum head-data size, in bytes.
@@ -37,6 +40,8 @@ struct HostConfiguration {
/// submitting an approval vote before a validator is considered a no-show. /// submitting an approval vote before a validator is considered a no-show.
/// Must be at least 1. /// Must be at least 1.
pub no_show_slots: u32, pub no_show_slots: u32,
/// The number of delay tranches in total.
pub n_delay_tranches: u32,
/// The width of the zeroth delay tranche for approval assignments. This many delay tranches /// The width of the zeroth delay tranche for approval assignments. This many delay tranches
/// beyond 0 are all consolidated to form a wide 0 tranche. /// beyond 0 are all consolidated to form a wide 0 tranche.
pub zeroth_delay_tranche_width: u32, pub zeroth_delay_tranche_width: u32,
+10 -2
View File
@@ -262,14 +262,14 @@ mod tests {
}, testing::{UintAuthorityId, TestXt}, Perbill, curve::PiecewiseLinear, }, testing::{UintAuthorityId, TestXt}, Perbill, curve::PiecewiseLinear,
}; };
use primitives::v1::{ use primitives::v1::{
Balance, BlockNumber, Header, Signature, Balance, BlockNumber, Header, Signature, AuthorityDiscoveryId,
}; };
use frame_support::{ use frame_support::{
traits::{Randomness, OnInitialize, OnFinalize}, traits::{Randomness, OnInitialize, OnFinalize},
impl_outer_origin, impl_outer_dispatch, assert_ok, parameter_types, impl_outer_origin, impl_outer_dispatch, assert_ok, parameter_types,
}; };
use keyring::Sr25519Keyring; use keyring::Sr25519Keyring;
use runtime_parachains::{initializer, configuration, inclusion, scheduler, dmp, ump, hrmp}; use runtime_parachains::{initializer, configuration, inclusion, session_info, scheduler, dmp, ump, hrmp};
use pallet_session::OneSessionHandler; use pallet_session::OneSessionHandler;
impl_outer_origin! { impl_outer_origin! {
@@ -477,6 +477,14 @@ mod tests {
type Event = (); type Event = ();
} }
impl session_info::AuthorityDiscoveryTrait for Test {
fn authorities() -> Vec<AuthorityDiscoveryId> {
Vec::new()
}
}
impl session_info::Trait for Test { }
pub struct TestRandomness; pub struct TestRandomness;
impl Randomness<H256> for TestRandomness { impl Randomness<H256> for TestRandomness {
+5 -5
View File
@@ -29,7 +29,7 @@ use primitives::v1::{
AccountId, AccountIndex, Balance, BlockNumber, CandidateEvent, CommittedCandidateReceipt, AccountId, AccountIndex, Balance, BlockNumber, CandidateEvent, CommittedCandidateReceipt,
CoreState, GroupRotationInfo, Hash, Id, Moment, Nonce, OccupiedCoreAssumption, CoreState, GroupRotationInfo, Hash, Id, Moment, Nonce, OccupiedCoreAssumption,
PersistedValidationData, Signature, ValidationCode, ValidationData, ValidatorId, ValidatorIndex, PersistedValidationData, Signature, ValidationCode, ValidationData, ValidatorId, ValidatorIndex,
InboundDownwardMessage, InboundHrmpMessage, InboundDownwardMessage, InboundHrmpMessage, SessionInfo,
}; };
use runtime_common::{ use runtime_common::{
claims, SlowAdjustingFeeUpdate, CurrencyToVote, claims, SlowAdjustingFeeUpdate, CurrencyToVote,
@@ -1092,6 +1092,10 @@ sp_api::impl_runtime_apis! {
0 0
} }
fn session_info(_: SessionIndex) -> Option<SessionInfo> {
None
}
fn validation_code(_: Id, _: OccupiedCoreAssumption) -> Option<ValidationCode> { fn validation_code(_: Id, _: OccupiedCoreAssumption) -> Option<ValidationCode> {
None None
} }
@@ -1108,10 +1112,6 @@ sp_api::impl_runtime_apis! {
Vec::new() Vec::new()
} }
fn validator_discovery(_: Vec<ValidatorId>) -> Vec<Option<AuthorityDiscoveryId>> {
Vec::new()
}
fn dmq_contents( fn dmq_contents(
_recipient: Id, _recipient: Id,
) -> Vec<InboundDownwardMessage<BlockNumber>> { ) -> Vec<InboundDownwardMessage<BlockNumber>> {
@@ -19,9 +19,10 @@
//! Configuration can change only at session boundaries and is buffered until then. //! Configuration can change only at session boundaries and is buffered until then.
use sp_std::prelude::*; use sp_std::prelude::*;
use primitives::v1::{Balance, ValidatorId}; use primitives::v1::{Balance, ValidatorId, SessionIndex};
use frame_support::{ use frame_support::{
decl_storage, decl_module, decl_error, decl_storage, decl_module, decl_error,
ensure,
dispatch::DispatchResult, dispatch::DispatchResult,
weights::{DispatchClass, Weight}, weights::{DispatchClass, Weight},
}; };
@@ -60,6 +61,21 @@ pub struct HostConfiguration<BlockNumber> {
pub thread_availability_period: BlockNumber, pub thread_availability_period: BlockNumber,
/// The amount of blocks ahead to schedule parachains and parathreads. /// The amount of blocks ahead to schedule parachains and parathreads.
pub scheduling_lookahead: u32, pub scheduling_lookahead: u32,
/// The amount of sessions to keep for disputes.
pub dispute_period: SessionIndex,
/// The amount of consensus slots that must pass between submitting an assignment and
/// submitting an approval vote before a validator is considered a no-show.
/// Must be at least 1.
pub no_show_slots: u32,
/// The number of delay tranches in total.
pub n_delay_tranches: u32,
/// The width of the zeroth delay tranche for approval assignments. This many delay tranches
/// beyond 0 are all consolidated to form a wide 0 tranche.
pub zeroth_delay_tranche_width: u32,
/// The number of validators needed to approve a block.
pub needed_approvals: u32,
/// The number of samples to do of the RelayVRFModulo approval assignment criterion.
pub relay_vrf_modulo_samples: u32,
/// Total number of individual messages allowed in the parachain -> relay-chain message queue. /// Total number of individual messages allowed in the parachain -> relay-chain message queue.
pub max_upward_queue_count: u32, pub max_upward_queue_count: u32,
/// Total size of messages allowed in the parachain -> relay-chain message queue before which /// Total size of messages allowed in the parachain -> relay-chain message queue before which
@@ -255,6 +271,68 @@ decl_module! {
Ok(()) Ok(())
} }
/// Set the dispute period, in number of sessions to keep for disputes.
#[weight = (1_000, DispatchClass::Operational)]
pub fn set_dispute_period(origin, new: SessionIndex) -> DispatchResult {
ensure_root(origin)?;
Self::update_config_member(|config| {
sp_std::mem::replace(&mut config.dispute_period, new) != new
});
Ok(())
}
/// Set the no show slots, in number of number of consensus slots.
/// Must be at least 1.
#[weight = (1_000, DispatchClass::Operational)]
pub fn set_no_show_slots(origin, new: u32) -> DispatchResult {
ensure_root(origin)?;
ensure!(new >= 1, "no_show_slots must be at least 1");
Self::update_config_member(|config| {
sp_std::mem::replace(&mut config.no_show_slots, new) != new
});
Ok(())
}
/// Set the total number of delay tranches.
#[weight = (1_000, DispatchClass::Operational)]
pub fn set_n_delay_tranches(origin, new: u32) -> DispatchResult {
ensure_root(origin)?;
Self::update_config_member(|config| {
sp_std::mem::replace(&mut config.n_delay_tranches, new) != new
});
Ok(())
}
/// Set the zeroth delay tranche width.
#[weight = (1_000, DispatchClass::Operational)]
pub fn set_zeroth_delay_tranche_width(origin, new: u32) -> DispatchResult {
ensure_root(origin)?;
Self::update_config_member(|config| {
sp_std::mem::replace(&mut config.zeroth_delay_tranche_width, new) != new
});
Ok(())
}
/// Set the number of validators needed to approve a block.
#[weight = (1_000, DispatchClass::Operational)]
pub fn set_needed_approvals(origin, new: u32) -> DispatchResult {
ensure_root(origin)?;
Self::update_config_member(|config| {
sp_std::mem::replace(&mut config.needed_approvals, new) != new
});
Ok(())
}
/// Set the number of samples to do of the RelayVRFModulo approval assignment criterion.
#[weight = (1_000, DispatchClass::Operational)]
pub fn set_relay_vrf_modulo_samples(origin, new: u32) -> DispatchResult {
ensure_root(origin)?;
Self::update_config_member(|config| {
sp_std::mem::replace(&mut config.relay_vrf_modulo_samples, new) != new
});
Ok(())
}
/// Sets the maximum items that can present in a upward dispatch queue at once. /// Sets the maximum items that can present in a upward dispatch queue at once.
#[weight = (1_000, DispatchClass::Operational)] #[weight = (1_000, DispatchClass::Operational)]
pub fn set_max_upward_queue_count(origin, new: u32) -> DispatchResult { pub fn set_max_upward_queue_count(origin, new: u32) -> DispatchResult {
@@ -504,6 +582,12 @@ mod tests {
chain_availability_period: 10, chain_availability_period: 10,
thread_availability_period: 8, thread_availability_period: 8,
scheduling_lookahead: 3, scheduling_lookahead: 3,
dispute_period: 239,
no_show_slots: 240,
n_delay_tranches: 241,
zeroth_delay_tranche_width: 242,
needed_approvals: 242,
relay_vrf_modulo_samples: 243,
max_upward_queue_count: 1337, max_upward_queue_count: 1337,
max_upward_queue_size: 228, max_upward_queue_size: 228,
max_downward_message_size: 2048, max_downward_message_size: 2048,
@@ -561,6 +645,24 @@ mod tests {
Configuration::set_scheduling_lookahead( Configuration::set_scheduling_lookahead(
Origin::root(), new_config.scheduling_lookahead, Origin::root(), new_config.scheduling_lookahead,
).unwrap(); ).unwrap();
Configuration::set_dispute_period(
Origin::root(), new_config.dispute_period,
).unwrap();
Configuration::set_no_show_slots(
Origin::root(), new_config.no_show_slots,
).unwrap();
Configuration::set_n_delay_tranches(
Origin::root(), new_config.n_delay_tranches,
).unwrap();
Configuration::set_zeroth_delay_tranche_width(
Origin::root(), new_config.zeroth_delay_tranche_width,
).unwrap();
Configuration::set_needed_approvals(
Origin::root(), new_config.needed_approvals,
).unwrap();
Configuration::set_relay_vrf_modulo_samples(
Origin::root(), new_config.relay_vrf_modulo_samples,
).unwrap();
Configuration::set_max_upward_queue_count( Configuration::set_max_upward_queue_count(
Origin::root(), new_config.max_upward_queue_count, Origin::root(), new_config.max_upward_queue_count,
).unwrap(); ).unwrap();
@@ -29,7 +29,7 @@ use sp_runtime::traits::One;
use parity_scale_codec::{Encode, Decode}; use parity_scale_codec::{Encode, Decode};
use crate::{ use crate::{
configuration::{self, HostConfiguration}, configuration::{self, HostConfiguration},
paras, scheduler, inclusion, dmp, ump, hrmp, paras, scheduler, inclusion, session_info, dmp, ump, hrmp,
}; };
/// Information about a session change that has just occurred. /// Information about a session change that has just occurred.
@@ -63,6 +63,7 @@ pub trait Trait:
+ paras::Trait + paras::Trait
+ scheduler::Trait + scheduler::Trait
+ inclusion::Trait + inclusion::Trait
+ session_info::Trait
+ dmp::Trait + dmp::Trait
+ ump::Trait + ump::Trait
+ hrmp::Trait + hrmp::Trait
@@ -123,6 +124,7 @@ decl_module! {
// - Paras // - Paras
// - Scheduler // - Scheduler
// - Inclusion // - Inclusion
// - SessionInfo
// - Validity // - Validity
// - DMP // - DMP
// - UMP // - UMP
@@ -131,6 +133,7 @@ decl_module! {
paras::Module::<T>::initializer_initialize(now) + paras::Module::<T>::initializer_initialize(now) +
scheduler::Module::<T>::initializer_initialize(now) + scheduler::Module::<T>::initializer_initialize(now) +
inclusion::Module::<T>::initializer_initialize(now) + inclusion::Module::<T>::initializer_initialize(now) +
session_info::Module::<T>::initializer_initialize(now) +
dmp::Module::<T>::initializer_initialize(now) + dmp::Module::<T>::initializer_initialize(now) +
ump::Module::<T>::initializer_initialize(now) + ump::Module::<T>::initializer_initialize(now) +
hrmp::Module::<T>::initializer_initialize(now); hrmp::Module::<T>::initializer_initialize(now);
@@ -146,6 +149,7 @@ decl_module! {
hrmp::Module::<T>::initializer_finalize(); hrmp::Module::<T>::initializer_finalize();
ump::Module::<T>::initializer_finalize(); ump::Module::<T>::initializer_finalize();
dmp::Module::<T>::initializer_finalize(); dmp::Module::<T>::initializer_finalize();
session_info::Module::<T>::initializer_finalize();
inclusion::Module::<T>::initializer_finalize(); inclusion::Module::<T>::initializer_finalize();
scheduler::Module::<T>::initializer_finalize(); scheduler::Module::<T>::initializer_finalize();
paras::Module::<T>::initializer_finalize(); paras::Module::<T>::initializer_finalize();
@@ -189,6 +193,7 @@ impl<T: Trait> Module<T> {
paras::Module::<T>::initializer_on_new_session(&notification); paras::Module::<T>::initializer_on_new_session(&notification);
scheduler::Module::<T>::initializer_on_new_session(&notification); scheduler::Module::<T>::initializer_on_new_session(&notification);
inclusion::Module::<T>::initializer_on_new_session(&notification); inclusion::Module::<T>::initializer_on_new_session(&notification);
session_info::Module::<T>::initializer_on_new_session(&notification);
dmp::Module::<T>::initializer_on_new_session(&notification); dmp::Module::<T>::initializer_on_new_session(&notification);
ump::Module::<T>::initializer_on_new_session(&notification); ump::Module::<T>::initializer_on_new_session(&notification);
hrmp::Module::<T>::initializer_on_new_session(&notification); hrmp::Module::<T>::initializer_on_new_session(&notification);
+1
View File
@@ -28,6 +28,7 @@ pub mod inclusion_inherent;
pub mod initializer; pub mod initializer;
pub mod paras; pub mod paras;
pub mod scheduler; pub mod scheduler;
pub mod session_info;
pub mod validity; pub mod validity;
pub mod origin; pub mod origin;
pub mod dmp; pub mod dmp;
+12 -1
View File
@@ -24,7 +24,7 @@ use sp_runtime::{
BlakeTwo256, IdentityLookup, BlakeTwo256, IdentityLookup,
}, },
}; };
use primitives::v1::{BlockNumber, Header}; use primitives::v1::{AuthorityDiscoveryId, BlockNumber, Header};
use frame_support::{ use frame_support::{
impl_outer_origin, impl_outer_dispatch, impl_outer_event, parameter_types, impl_outer_origin, impl_outer_dispatch, impl_outer_event, parameter_types,
weights::Weight, traits::Randomness as RandomnessT, weights::Weight, traits::Randomness as RandomnessT,
@@ -124,6 +124,14 @@ impl crate::inclusion::Trait for Test {
type Event = TestEvent; type Event = TestEvent;
} }
impl crate::session_info::Trait for Test { }
impl crate::session_info::AuthorityDiscoveryTrait for Test {
fn authorities() -> Vec<AuthorityDiscoveryId> {
Vec::new()
}
}
pub type System = frame_system::Module<Test>; pub type System = frame_system::Module<Test>;
/// Mocked initializer. /// Mocked initializer.
@@ -150,6 +158,9 @@ pub type Scheduler = crate::scheduler::Module<Test>;
/// Mocked inclusion module. /// Mocked inclusion module.
pub type Inclusion = crate::inclusion::Module<Test>; pub type Inclusion = crate::inclusion::Module<Test>;
/// Mocked session info module.
pub type SessionInfo = crate::session_info::Module<Test>;
/// Create a new set of test externalities. /// Create a new set of test externalities.
pub fn new_test_ext(state: GenesisConfig) -> TestExternalities { pub fn new_test_ext(state: GenesisConfig) -> TestExternalities {
let mut t = state.system.build_storage::<Test>().unwrap(); let mut t = state.system.build_storage::<Test>().unwrap();
@@ -23,12 +23,12 @@ use primitives::v1::{
ValidatorId, ValidatorIndex, GroupRotationInfo, CoreState, ValidationData, ValidatorId, ValidatorIndex, GroupRotationInfo, CoreState, ValidationData,
Id as ParaId, OccupiedCoreAssumption, SessionIndex, ValidationCode, Id as ParaId, OccupiedCoreAssumption, SessionIndex, ValidationCode,
CommittedCandidateReceipt, ScheduledCore, OccupiedCore, CoreOccupied, CoreIndex, CommittedCandidateReceipt, ScheduledCore, OccupiedCore, CoreOccupied, CoreIndex,
GroupIndex, CandidateEvent, PersistedValidationData, AuthorityDiscoveryId, GroupIndex, CandidateEvent, PersistedValidationData, SessionInfo,
InboundDownwardMessage, InboundHrmpMessage, InboundDownwardMessage, InboundHrmpMessage,
}; };
use sp_runtime::traits::Zero; use sp_runtime::traits::Zero;
use frame_support::debug; use frame_support::debug;
use crate::{initializer, inclusion, scheduler, configuration, paras, dmp, hrmp}; use crate::{initializer, inclusion, scheduler, configuration, paras, session_info, dmp, hrmp};
/// Implementation for the `validators` function of the runtime API. /// Implementation for the `validators` function of the runtime API.
pub fn validators<T: initializer::Trait>() -> Vec<ValidatorId> { pub fn validators<T: initializer::Trait>() -> Vec<ValidatorId> {
@@ -285,28 +285,9 @@ where
.collect() .collect()
} }
/// Get the `AuthorityDiscoveryId`s corresponding to the given `ValidatorId`s. /// Get the session info for the given session, if stored.
/// Currently this request is limited to validators in the current session. pub fn session_info<T: session_info::Trait>(index: SessionIndex) -> Option<SessionInfo> {
/// <session_info::Module<T>>::session_info(index)
/// We assume that every validator runs authority discovery,
/// which would allow us to establish point-to-point connection to given validators.
// FIXME: handle previous sessions:
// https://github.com/paritytech/polkadot/issues/1461
pub fn validator_discovery<T>(validators: Vec<ValidatorId>) -> Vec<Option<AuthorityDiscoveryId>>
where
T: initializer::Trait + pallet_authority_discovery::Trait,
{
// FIXME: the mapping might be invalid if a session change happens in between the calls
// use SessionInfo from https://github.com/paritytech/polkadot/pull/1691
let current_validators = <inclusion::Module<T>>::validators();
let authorities = <pallet_authority_discovery::Module<T>>::authorities();
// We assume the same ordering in authorities as in validators so we can do an index search
validators.iter().map(|id| {
// FIXME: linear search is slow O(n^2)
// use SessionInfo from https://github.com/paritytech/polkadot/pull/1691
let validator_index = current_validators.iter().position(|v| v == id);
validator_index.and_then(|i| authorities.get(i).cloned())
}).collect()
} }
/// Implementation for the `dmq_contents` function of the runtime API. /// Implementation for the `dmq_contents` function of the runtime API.
@@ -0,0 +1,256 @@
// Copyright 2020 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.
// Polkadot is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Polkadot is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
//! The session info module provides information about validator sets
//! from prior sessions needed for approvals and disputes.
//!
//! See https://w3f.github.io/parachain-implementers-guide/runtime/session_info.html.
use primitives::v1::{AuthorityDiscoveryId, SessionIndex, SessionInfo};
use frame_support::{
decl_storage, decl_module, decl_error,
weights::Weight,
};
use crate::{configuration, paras, scheduler};
use sp_std::{cmp, vec::Vec};
pub trait Trait:
frame_system::Trait
+ configuration::Trait
+ paras::Trait
+ scheduler::Trait
+ AuthorityDiscoveryTrait
{
}
decl_storage! {
trait Store for Module<T: Trait> as ParaSessionInfo {
/// The earliest session for which previous session info is stored.
EarliestStoredSession get(fn earliest_stored_session): SessionIndex;
/// Session information in a rolling window.
/// Should have an entry in range `EarliestStoredSession..=CurrentSessionIndex`.
/// Does not have any entries before the session index in the first session change notification.
Sessions get(fn session_info): map hasher(identity) SessionIndex => Option<SessionInfo>;
}
}
decl_error! {
pub enum Error for Module<T: Trait> { }
}
decl_module! {
/// The session info module.
pub struct Module<T: Trait> for enum Call where origin: <T as frame_system::Trait>::Origin {
type Error = Error<T>;
}
}
/// An abstraction for the authority discovery pallet
/// to help with mock testing.
pub trait AuthorityDiscoveryTrait {
/// Retrieve authority identifiers of the current and next authority set.
fn authorities() -> Vec<AuthorityDiscoveryId>;
}
impl<T: pallet_authority_discovery::Trait> AuthorityDiscoveryTrait for T {
fn authorities() -> Vec<AuthorityDiscoveryId> {
<pallet_authority_discovery::Module<T>>::authorities()
}
}
impl<T: Trait> Module<T> {
/// Handle an incoming session change.
pub(crate) fn initializer_on_new_session(
notification: &crate::initializer::SessionChangeNotification<T::BlockNumber>
) {
let config = <configuration::Module<T>>::config();
let dispute_period = config.dispute_period;
let n_parachains = <paras::Module<T>>::parachains().len() as u32;
let validators = notification.validators.clone();
let discovery_keys = <T as AuthorityDiscoveryTrait>::authorities();
// FIXME: once we store these keys: https://github.com/paritytech/polkadot/issues/1975
let approval_keys = Default::default();
let validator_groups = <scheduler::Module<T>>::validator_groups();
let n_cores = n_parachains + config.parathread_cores;
let zeroth_delay_tranche_width = config.zeroth_delay_tranche_width;
let relay_vrf_modulo_samples = config.relay_vrf_modulo_samples;
let n_delay_tranches = config.n_delay_tranches;
let no_show_slots = config.no_show_slots;
let needed_approvals = config.needed_approvals;
let new_session_index = notification.session_index;
let old_earliest_stored_session = EarliestStoredSession::get();
let dispute_period = cmp::max(1, dispute_period);
let new_earliest_stored_session = new_session_index.checked_sub(dispute_period - 1).unwrap_or(0);
let new_earliest_stored_session = cmp::max(new_earliest_stored_session, old_earliest_stored_session);
// update `EarliestStoredSession` based on `config.dispute_period`
EarliestStoredSession::set(new_earliest_stored_session);
// remove all entries from `Sessions` from the previous value up to the new value
for idx in old_earliest_stored_session..new_earliest_stored_session {
Sessions::remove(&idx);
}
// create a new entry in `Sessions` with information about the current session
let new_session_info = SessionInfo {
validators,
discovery_keys,
approval_keys,
validator_groups,
n_cores,
zeroth_delay_tranche_width,
relay_vrf_modulo_samples,
n_delay_tranches,
no_show_slots,
needed_approvals,
};
Sessions::insert(&new_session_index, &new_session_info);
}
/// Called by the initializer to initialize the session info module.
pub(crate) fn initializer_initialize(_now: T::BlockNumber) -> Weight {
0
}
/// Called by the initializer to finalize the session info module.
pub(crate) fn initializer_finalize() {}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::mock::{
new_test_ext, Configuration, SessionInfo, System, GenesisConfig as MockGenesisConfig,
Origin,
};
use crate::initializer::SessionChangeNotification;
use crate::configuration::HostConfiguration;
use frame_support::traits::{OnFinalize, OnInitialize};
use primitives::v1::BlockNumber;
fn run_to_block(
to: BlockNumber,
new_session: impl Fn(BlockNumber) -> Option<SessionChangeNotification<BlockNumber>>,
) {
while System::block_number() < to {
let b = System::block_number();
SessionInfo::initializer_finalize();
Configuration::initializer_finalize();
System::on_finalize(b);
System::on_initialize(b + 1);
System::set_block_number(b + 1);
if let Some(notification) = new_session(b + 1) {
Configuration::initializer_on_new_session(&notification.validators, &notification.queued);
SessionInfo::initializer_on_new_session(&notification);
}
Configuration::initializer_initialize(b + 1);
SessionInfo::initializer_initialize(b + 1);
}
}
fn default_config() -> HostConfiguration<BlockNumber> {
HostConfiguration {
parathread_cores: 1,
dispute_period: 2,
needed_approvals: 3,
..Default::default()
}
}
fn genesis_config() -> MockGenesisConfig {
MockGenesisConfig {
configuration: configuration::GenesisConfig {
config: default_config(),
..Default::default()
},
..Default::default()
}
}
fn session_changes(n: BlockNumber) -> Option<SessionChangeNotification<BlockNumber>> {
match n {
100 => Some(SessionChangeNotification {
session_index: 10,
..Default::default()
}),
200 => Some(SessionChangeNotification {
session_index: 20,
..Default::default()
}),
300 => Some(SessionChangeNotification {
session_index: 30,
..Default::default()
}),
400 => Some(SessionChangeNotification {
session_index: 40,
..Default::default()
}),
_ => None,
}
}
fn new_session_every_block(n: BlockNumber) -> Option<SessionChangeNotification<BlockNumber>> {
Some(SessionChangeNotification{
session_index: n,
..Default::default()
})
}
#[test]
fn session_pruning_is_based_on_dispute_deriod() {
new_test_ext(genesis_config()).execute_with(|| {
run_to_block(100, session_changes);
assert_eq!(EarliestStoredSession::get(), 9);
// changing dispute_period works
let dispute_period = 5;
Configuration::set_dispute_period(Origin::root(), dispute_period).unwrap();
run_to_block(200, session_changes);
assert_eq!(EarliestStoredSession::get(), 20 - dispute_period + 1);
// we don't have that many sessions stored
let new_dispute_period = 16;
Configuration::set_dispute_period(Origin::root(), new_dispute_period).unwrap();
run_to_block(300, session_changes);
assert_eq!(EarliestStoredSession::get(), 20 - dispute_period + 1);
// now we do
run_to_block(400, session_changes);
assert_eq!(EarliestStoredSession::get(), 40 - new_dispute_period + 1);
})
}
#[test]
fn session_info_is_based_on_config() {
new_test_ext(genesis_config()).execute_with(|| {
run_to_block(1, new_session_every_block);
let session = Sessions::get(&1).unwrap();
assert_eq!(session.needed_approvals, 3);
// change some param
Configuration::set_needed_approvals(Origin::root(), 42).unwrap();
run_to_block(2, new_session_every_block);
let session = Sessions::get(&2).unwrap();
assert_eq!(session.needed_approvals, 42);
})
}
}
+5 -5
View File
@@ -37,7 +37,7 @@ use primitives::v1::{
AccountId, AccountIndex, Balance, BlockNumber, CandidateEvent, CommittedCandidateReceipt, AccountId, AccountIndex, Balance, BlockNumber, CandidateEvent, CommittedCandidateReceipt,
CoreState, GroupRotationInfo, Hash, Id, Moment, Nonce, OccupiedCoreAssumption, CoreState, GroupRotationInfo, Hash, Id, Moment, Nonce, OccupiedCoreAssumption,
PersistedValidationData, Signature, ValidationCode, ValidationData, ValidatorId, ValidatorIndex, PersistedValidationData, Signature, ValidationCode, ValidationData, ValidatorId, ValidatorIndex,
InboundDownwardMessage, InboundHrmpMessage, InboundDownwardMessage, InboundHrmpMessage, SessionInfo,
}; };
use sp_runtime::{ use sp_runtime::{
create_runtime_str, generic, impl_opaque_keys, ModuleId, ApplyExtrinsicResult, create_runtime_str, generic, impl_opaque_keys, ModuleId, ApplyExtrinsicResult,
@@ -1086,6 +1086,10 @@ sp_api::impl_runtime_apis! {
0 0
} }
fn session_info(_: SessionIndex) -> Option<SessionInfo> {
None
}
fn validation_code(_: Id, _: OccupiedCoreAssumption) -> Option<ValidationCode> { fn validation_code(_: Id, _: OccupiedCoreAssumption) -> Option<ValidationCode> {
None None
} }
@@ -1102,10 +1106,6 @@ sp_api::impl_runtime_apis! {
Vec::new() Vec::new()
} }
fn validator_discovery(_: Vec<ValidatorId>) -> Vec<Option<AuthorityDiscoveryId>> {
Vec::new()
}
fn dmq_contents( fn dmq_contents(
_recipient: Id, _recipient: Id,
) -> Vec<InboundDownwardMessage<BlockNumber>> { ) -> Vec<InboundDownwardMessage<BlockNumber>> {
+7 -3
View File
@@ -28,7 +28,7 @@ use primitives::v1::{
AccountId, AccountIndex, Balance, BlockNumber, Hash, Nonce, Signature, Moment, AccountId, AccountIndex, Balance, BlockNumber, Hash, Nonce, Signature, Moment,
GroupRotationInfo, CoreState, Id, ValidationData, ValidationCode, CandidateEvent, GroupRotationInfo, CoreState, Id, ValidationData, ValidationCode, CandidateEvent,
ValidatorId, ValidatorIndex, CommittedCandidateReceipt, OccupiedCoreAssumption, ValidatorId, ValidatorIndex, CommittedCandidateReceipt, OccupiedCoreAssumption,
PersistedValidationData, InboundDownwardMessage, InboundHrmpMessage, PersistedValidationData, InboundDownwardMessage, InboundHrmpMessage, SessionInfo,
}; };
use runtime_common::{ use runtime_common::{
SlowAdjustingFeeUpdate, SlowAdjustingFeeUpdate,
@@ -72,6 +72,7 @@ use runtime_parachains::configuration as parachains_configuration;
use runtime_parachains::inclusion as parachains_inclusion; use runtime_parachains::inclusion as parachains_inclusion;
use runtime_parachains::inclusion_inherent as parachains_inclusion_inherent; use runtime_parachains::inclusion_inherent as parachains_inclusion_inherent;
use runtime_parachains::initializer as parachains_initializer; use runtime_parachains::initializer as parachains_initializer;
use runtime_parachains::session_info as parachains_session_info;
use runtime_parachains::paras as parachains_paras; use runtime_parachains::paras as parachains_paras;
use runtime_parachains::dmp as parachains_dmp; use runtime_parachains::dmp as parachains_dmp;
use runtime_parachains::ump as parachains_ump; use runtime_parachains::ump as parachains_ump;
@@ -536,6 +537,8 @@ impl parachains_paras::Trait for Runtime {
type Origin = Origin; type Origin = Origin;
} }
impl parachains_session_info::Trait for Runtime {}
impl parachains_ump::Trait for Runtime { impl parachains_ump::Trait for Runtime {
type UmpSink = (); // TODO: #1873 To be handled by the XCM receiver. type UmpSink = (); // TODO: #1873 To be handled by the XCM receiver.
} }
@@ -688,8 +691,9 @@ sp_api::impl_runtime_apis! {
} }
}) })
} }
fn validator_discovery(validators: Vec<ValidatorId>) -> Vec<Option<AuthorityDiscoveryId>> {
runtime_api_impl::validator_discovery::<Runtime>(validators) fn session_info(index: SessionIndex) -> Option<SessionInfo> {
runtime_api_impl::session_info::<Runtime>(index)
} }
fn dmq_contents(recipient: Id) -> Vec<InboundDownwardMessage<BlockNumber>> { fn dmq_contents(recipient: Id) -> Vec<InboundDownwardMessage<BlockNumber>> {
+6 -3
View File
@@ -29,6 +29,7 @@ use polkadot_runtime_parachains::configuration as parachains_configuration;
use polkadot_runtime_parachains::inclusion as parachains_inclusion; use polkadot_runtime_parachains::inclusion as parachains_inclusion;
use polkadot_runtime_parachains::inclusion_inherent as parachains_inclusion_inherent; use polkadot_runtime_parachains::inclusion_inherent as parachains_inclusion_inherent;
use polkadot_runtime_parachains::initializer as parachains_initializer; use polkadot_runtime_parachains::initializer as parachains_initializer;
use polkadot_runtime_parachains::session_info as parachains_session_info;
use polkadot_runtime_parachains::paras as parachains_paras; use polkadot_runtime_parachains::paras as parachains_paras;
use polkadot_runtime_parachains::dmp as parachains_dmp; use polkadot_runtime_parachains::dmp as parachains_dmp;
use polkadot_runtime_parachains::ump as parachains_ump; use polkadot_runtime_parachains::ump as parachains_ump;
@@ -40,7 +41,7 @@ use primitives::v1::{
AccountId, AccountIndex, Balance, BlockNumber, CandidateEvent, CommittedCandidateReceipt, AccountId, AccountIndex, Balance, BlockNumber, CandidateEvent, CommittedCandidateReceipt,
CoreState, GroupRotationInfo, Hash as HashT, Id as ParaId, Moment, Nonce, OccupiedCoreAssumption, CoreState, GroupRotationInfo, Hash as HashT, Id as ParaId, Moment, Nonce, OccupiedCoreAssumption,
PersistedValidationData, Signature, ValidationCode, ValidationData, ValidatorId, ValidatorIndex, PersistedValidationData, Signature, ValidationCode, ValidationData, ValidatorId, ValidatorIndex,
InboundDownwardMessage, InboundHrmpMessage, InboundDownwardMessage, InboundHrmpMessage, SessionInfo,
}; };
use runtime_common::{ use runtime_common::{
claims, SlowAdjustingFeeUpdate, paras_sudo_wrapper, claims, SlowAdjustingFeeUpdate, paras_sudo_wrapper,
@@ -457,6 +458,8 @@ impl parachains_initializer::Trait for Runtime {
type Randomness = RandomnessCollectiveFlip; type Randomness = RandomnessCollectiveFlip;
} }
impl parachains_session_info::Trait for Runtime {}
impl parachains_paras::Trait for Runtime { impl parachains_paras::Trait for Runtime {
type Origin = Origin; type Origin = Origin;
} }
@@ -678,8 +681,8 @@ sp_api::impl_runtime_apis! {
runtime_impl::candidate_events::<Runtime, _>(|trait_event| trait_event.try_into().ok()) runtime_impl::candidate_events::<Runtime, _>(|trait_event| trait_event.try_into().ok())
} }
fn validator_discovery(validators: Vec<ValidatorId>) -> Vec<Option<AuthorityDiscoveryId>> { fn session_info(index: SessionIndex) -> Option<SessionInfo> {
runtime_impl::validator_discovery::<Runtime>(validators) runtime_impl::session_info::<Runtime>(index)
} }
fn dmq_contents( fn dmq_contents(
+5 -5
View File
@@ -28,7 +28,7 @@ use primitives::v1::{
AccountId, AccountIndex, Balance, BlockNumber, CandidateEvent, CommittedCandidateReceipt, AccountId, AccountIndex, Balance, BlockNumber, CandidateEvent, CommittedCandidateReceipt,
CoreState, GroupRotationInfo, Hash, Id, Moment, Nonce, OccupiedCoreAssumption, CoreState, GroupRotationInfo, Hash, Id, Moment, Nonce, OccupiedCoreAssumption,
PersistedValidationData, Signature, ValidationCode, ValidationData, ValidatorId, ValidatorIndex, PersistedValidationData, Signature, ValidationCode, ValidationData, ValidatorId, ValidatorIndex,
InboundDownwardMessage, InboundHrmpMessage, InboundDownwardMessage, InboundHrmpMessage, SessionInfo,
}; };
use runtime_common::{ use runtime_common::{
SlowAdjustingFeeUpdate, CurrencyToVote, SlowAdjustingFeeUpdate, CurrencyToVote,
@@ -840,6 +840,10 @@ sp_api::impl_runtime_apis! {
0 0
} }
fn session_info(_: SessionIndex) -> Option<SessionInfo> {
None
}
fn validation_code(_: Id, _: OccupiedCoreAssumption) -> Option<ValidationCode> { fn validation_code(_: Id, _: OccupiedCoreAssumption) -> Option<ValidationCode> {
None None
} }
@@ -852,10 +856,6 @@ sp_api::impl_runtime_apis! {
Vec::new() Vec::new()
} }
fn validator_discovery(_: Vec<ValidatorId>) -> Vec<Option<AuthorityDiscoveryId>> {
Vec::new()
}
fn dmq_contents( fn dmq_contents(
_recipient: Id, _recipient: Id,
) -> Vec<InboundDownwardMessage<BlockNumber>> { ) -> Vec<InboundDownwardMessage<BlockNumber>> {