Unverified Commit cce0a950 authored by asynchronous rob's avatar asynchronous rob Committed by GitHub
Browse files

Include a reference to the validation data in the candidate descriptor (#1442)

* rename GlobalValidationSchedule to GlobalValidationData

* guide: update candidate descriptor to contain validation data hash

* guide: add note in inclusion module about checking validation data hash

* primitives: update CandidateDescriptor to contain new hash

* fix payload computation

* add helpers for computing validation data to runtime modules

* guide: note routines

* inclusion: check validation data hash and fix local_validation_data bug

* add a case to candidate_checks and improve that test substantially

* bump versions

* address review comments

* add a test for including code upgrade

* bump kusama version

* bump westend & polkadot versions
parent 9637baea
Pipeline #101533 passed with stages
in 25 minutes and 48 seconds
...@@ -58,7 +58,7 @@ use sp_core::Pair; ...@@ -58,7 +58,7 @@ use sp_core::Pair;
use polkadot_primitives::v0::{ use polkadot_primitives::v0::{
BlockId, Hash, Block, DownwardMessage, BlockId, Hash, Block, DownwardMessage,
BlockData, DutyRoster, HeadData, Id as ParaId, BlockData, DutyRoster, HeadData, Id as ParaId,
PoVBlock, ValidatorId, CollatorPair, LocalValidationData, GlobalValidationSchedule, PoVBlock, ValidatorId, CollatorPair, LocalValidationData, GlobalValidationData,
Collation, CollationInfo, collator_signature_payload, Collation, CollationInfo, collator_signature_payload,
}; };
use polkadot_cli::{ use polkadot_cli::{
...@@ -148,7 +148,7 @@ pub trait ParachainContext: Clone { ...@@ -148,7 +148,7 @@ pub trait ParachainContext: Clone {
fn produce_candidate( fn produce_candidate(
&mut self, &mut self,
relay_parent: Hash, relay_parent: Hash,
global_validation: GlobalValidationSchedule, global_validation: GlobalValidationData,
local_validation: LocalValidationData, local_validation: LocalValidationData,
downward_messages: Vec<DownwardMessage>, downward_messages: Vec<DownwardMessage>,
) -> Self::ProduceCandidate; ) -> Self::ProduceCandidate;
...@@ -158,7 +158,7 @@ pub trait ParachainContext: Clone { ...@@ -158,7 +158,7 @@ pub trait ParachainContext: Clone {
pub async fn collate<P>( pub async fn collate<P>(
relay_parent: Hash, relay_parent: Hash,
local_id: ParaId, local_id: ParaId,
global_validation: GlobalValidationSchedule, global_validation: GlobalValidationData,
local_validation_data: LocalValidationData, local_validation_data: LocalValidationData,
downward_messages: Vec<DownwardMessage>, downward_messages: Vec<DownwardMessage>,
mut para_context: P, mut para_context: P,
...@@ -315,7 +315,7 @@ fn build_collator_service<P, C, R, Extrinsic>( ...@@ -315,7 +315,7 @@ fn build_collator_service<P, C, R, Extrinsic>(
let work = future::lazy(move |_| { let work = future::lazy(move |_| {
let api = client.runtime_api(); let api = client.runtime_api();
let global_validation = try_fr!(api.global_validation_schedule(&id)); let global_validation = try_fr!(api.global_validation_data(&id));
let local_validation = match try_fr!(api.local_validation_data(&id, para_id)) { let local_validation = match try_fr!(api.local_validation_data(&id, para_id)) {
Some(local_validation) => local_validation, Some(local_validation) => local_validation,
None => return future::Either::Left(future::ok(())), None => return future::Either::Left(future::ok(())),
...@@ -477,7 +477,7 @@ mod tests { ...@@ -477,7 +477,7 @@ mod tests {
fn produce_candidate( fn produce_candidate(
&mut self, &mut self,
_relay_parent: Hash, _relay_parent: Hash,
_global: GlobalValidationSchedule, _global: GlobalValidationData,
_local_validation: LocalValidationData, _local_validation: LocalValidationData,
_: Vec<DownwardMessage>, _: Vec<DownwardMessage>,
) -> Self::ProduceCandidate { ) -> Self::ProduceCandidate {
......
...@@ -21,7 +21,7 @@ use polkadot_primitives::v0::{ ...@@ -21,7 +21,7 @@ use polkadot_primitives::v0::{
Block, Block,
Id as ParaId, Chain, DutyRoster, ParachainHost, ValidatorId, Id as ParaId, Chain, DutyRoster, ParachainHost, ValidatorId,
Retriable, CollatorId, AbridgedCandidateReceipt, Retriable, CollatorId, AbridgedCandidateReceipt,
GlobalValidationSchedule, LocalValidationData, ErasureChunk, SigningContext, GlobalValidationData, LocalValidationData, ErasureChunk, SigningContext,
PoVBlock, BlockData, ValidationCode, PoVBlock, BlockData, ValidationCode,
}; };
use polkadot_validation::{SharedTable, TableRouter}; use polkadot_validation::{SharedTable, TableRouter};
...@@ -180,7 +180,7 @@ sp_api::mock_impl_runtime_apis! { ...@@ -180,7 +180,7 @@ sp_api::mock_impl_runtime_apis! {
Some(ValidationCode(Vec::new())) Some(ValidationCode(Vec::new()))
} }
fn global_validation_schedule() -> GlobalValidationSchedule { fn global_validation_data() -> GlobalValidationData {
Default::default() Default::default()
} }
......
...@@ -606,7 +606,7 @@ impl CandidateBackingJob { ...@@ -606,7 +606,7 @@ impl CandidateBackingJob {
with_commitments: impl FnOnce(CandidateCommitments) -> Result<T, E>, with_commitments: impl FnOnce(CandidateCommitments) -> Result<T, E>,
) -> Result<Result<T, E>, Error> { ) -> Result<Result<T, E>, Error> {
let omitted_validation = OmittedValidationData { let omitted_validation = OmittedValidationData {
global_validation: outputs.global_validation_schedule, global_validation: outputs.global_validation_data,
local_validation: outputs.local_validation_data, local_validation: outputs.local_validation_data,
}; };
...@@ -773,7 +773,7 @@ mod tests { ...@@ -773,7 +773,7 @@ mod tests {
use futures::{executor, future, Future}; use futures::{executor, future, Future};
use polkadot_primitives::v1::{ use polkadot_primitives::v1::{
AssignmentKind, BlockData, CandidateCommitments, CollatorId, CoreAssignment, CoreIndex, AssignmentKind, BlockData, CandidateCommitments, CollatorId, CoreAssignment, CoreIndex,
LocalValidationData, GlobalValidationSchedule, GroupIndex, HeadData, LocalValidationData, GlobalValidationData, GroupIndex, HeadData,
ValidatorPair, ValidityAttestation, ValidatorPair, ValidityAttestation,
}; };
use polkadot_subsystem::{ use polkadot_subsystem::{
...@@ -792,7 +792,7 @@ mod tests { ...@@ -792,7 +792,7 @@ mod tests {
keystore: KeyStorePtr, keystore: KeyStorePtr,
validators: Vec<Sr25519Keyring>, validators: Vec<Sr25519Keyring>,
validator_public: Vec<ValidatorId>, validator_public: Vec<ValidatorId>,
global_validation_schedule: GlobalValidationSchedule, global_validation_data: GlobalValidationData,
local_validation_data: LocalValidationData, local_validation_data: LocalValidationData,
roster: SchedulerRoster, roster: SchedulerRoster,
head_data: HashMap<ParaId, HeadData>, head_data: HashMap<ParaId, HeadData>,
...@@ -877,7 +877,7 @@ mod tests { ...@@ -877,7 +877,7 @@ mod tests {
validation_code_hash: Default::default(), validation_code_hash: Default::default(),
}; };
let global_validation_schedule = GlobalValidationSchedule { let global_validation_data = GlobalValidationData {
max_code_size: 1000, max_code_size: 1000,
max_head_data_size: 1000, max_head_data_size: 1000,
block_number: Default::default(), block_number: Default::default(),
...@@ -891,7 +891,7 @@ mod tests { ...@@ -891,7 +891,7 @@ mod tests {
roster, roster,
head_data, head_data,
local_validation_data, local_validation_data,
global_validation_schedule, global_validation_data,
signing_context, signing_context,
relay_parent, relay_parent,
} }
...@@ -921,7 +921,7 @@ mod tests { ...@@ -921,7 +921,7 @@ mod tests {
fn make_erasure_root(test: &TestState, pov: PoV) -> Hash { fn make_erasure_root(test: &TestState, pov: PoV) -> Hash {
let omitted_validation = OmittedValidationData { let omitted_validation = OmittedValidationData {
global_validation: test.global_validation_schedule.clone(), global_validation: test.global_validation_data.clone(),
local_validation: test.local_validation_data.clone(), local_validation: test.local_validation_data.clone(),
}; };
...@@ -1048,7 +1048,7 @@ mod tests { ...@@ -1048,7 +1048,7 @@ mod tests {
) if pov == pov && &c == candidate.descriptor() => { ) if pov == pov && &c == candidate.descriptor() => {
tx.send(Ok( tx.send(Ok(
ValidationResult::Valid(ValidationOutputs { ValidationResult::Valid(ValidationOutputs {
global_validation_schedule: test_state.global_validation_schedule, global_validation_data: test_state.global_validation_data,
local_validation_data: test_state.local_validation_data, local_validation_data: test_state.local_validation_data,
head_data: expected_head_data.clone(), head_data: expected_head_data.clone(),
upward_messages: Vec::new(), upward_messages: Vec::new(),
...@@ -1160,7 +1160,7 @@ mod tests { ...@@ -1160,7 +1160,7 @@ mod tests {
) if pov == pov && &c == candidate_a.descriptor() => { ) if pov == pov && &c == candidate_a.descriptor() => {
tx.send(Ok( tx.send(Ok(
ValidationResult::Valid(ValidationOutputs { ValidationResult::Valid(ValidationOutputs {
global_validation_schedule: test_state.global_validation_schedule, global_validation_data: test_state.global_validation_data,
local_validation_data: test_state.local_validation_data, local_validation_data: test_state.local_validation_data,
head_data: expected_head_data.clone(), head_data: expected_head_data.clone(),
upward_messages: Vec::new(), upward_messages: Vec::new(),
...@@ -1281,7 +1281,7 @@ mod tests { ...@@ -1281,7 +1281,7 @@ mod tests {
) if pov == pov && &c == candidate_a.descriptor() => { ) if pov == pov && &c == candidate_a.descriptor() => {
tx.send(Ok( tx.send(Ok(
ValidationResult::Valid(ValidationOutputs { ValidationResult::Valid(ValidationOutputs {
global_validation_schedule: test_state.global_validation_schedule, global_validation_data: test_state.global_validation_data,
local_validation_data: test_state.local_validation_data, local_validation_data: test_state.local_validation_data,
head_data: expected_head_data.clone(), head_data: expected_head_data.clone(),
upward_messages: Vec::new(), upward_messages: Vec::new(),
...@@ -1438,7 +1438,7 @@ mod tests { ...@@ -1438,7 +1438,7 @@ mod tests {
) if pov == pov && &c == candidate_b.descriptor() => { ) if pov == pov && &c == candidate_b.descriptor() => {
tx.send(Ok( tx.send(Ok(
ValidationResult::Valid(ValidationOutputs { ValidationResult::Valid(ValidationOutputs {
global_validation_schedule: test_state.global_validation_schedule, global_validation_data: test_state.global_validation_data,
local_validation_data: test_state.local_validation_data, local_validation_data: test_state.local_validation_data,
head_data: expected_head_data.clone(), head_data: expected_head_data.clone(),
upward_messages: Vec::new(), upward_messages: Vec::new(),
......
...@@ -24,7 +24,7 @@ use parity_scale_codec::{Decode, Encode}; ...@@ -24,7 +24,7 @@ use parity_scale_codec::{Decode, Encode};
use polkadot_primitives::v1::{ use polkadot_primitives::v1::{
Hash, CommittedCandidateReceipt, CandidateReceipt, CompactStatement, Hash, CommittedCandidateReceipt, CandidateReceipt, CompactStatement,
EncodeAs, Signed, SigningContext, ValidatorIndex, ValidatorId, EncodeAs, Signed, SigningContext, ValidatorIndex, ValidatorId,
UpwardMessage, Balance, ValidationCode, GlobalValidationSchedule, LocalValidationData, UpwardMessage, Balance, ValidationCode, GlobalValidationData, LocalValidationData,
HeadData, HeadData,
}; };
use polkadot_statement_table::{ use polkadot_statement_table::{
...@@ -118,7 +118,7 @@ pub struct ValidationOutputs { ...@@ -118,7 +118,7 @@ pub struct ValidationOutputs {
/// The head-data produced by validation. /// The head-data produced by validation.
pub head_data: HeadData, pub head_data: HeadData,
/// The global validation schedule. /// The global validation schedule.
pub global_validation_schedule: GlobalValidationSchedule, pub global_validation_data: GlobalValidationData,
/// The local validation data. /// The local validation data.
pub local_validation_data: LocalValidationData, pub local_validation_data: LocalValidationData,
/// Upward messages to the relay chain. /// Upward messages to the relay chain.
......
...@@ -24,7 +24,7 @@ use sp_core::Pair; ...@@ -24,7 +24,7 @@ use sp_core::Pair;
use codec::{Encode, Decode}; use codec::{Encode, Decode};
use primitives::v0::{ use primitives::v0::{
Hash, DownwardMessage, Hash, DownwardMessage,
HeadData, BlockData, Id as ParaId, LocalValidationData, GlobalValidationSchedule, HeadData, BlockData, Id as ParaId, LocalValidationData, GlobalValidationData,
}; };
use collator::{ParachainContext, Network, BuildParachainContext, Cli, SubstrateCli}; use collator::{ParachainContext, Network, BuildParachainContext, Cli, SubstrateCli};
use parking_lot::Mutex; use parking_lot::Mutex;
...@@ -58,7 +58,7 @@ impl ParachainContext for AdderContext { ...@@ -58,7 +58,7 @@ impl ParachainContext for AdderContext {
fn produce_candidate( fn produce_candidate(
&mut self, &mut self,
_relay_parent: Hash, _relay_parent: Hash,
_global_validation: GlobalValidationSchedule, _global_validation: GlobalValidationData,
local_validation: LocalValidationData, local_validation: LocalValidationData,
_: Vec<DownwardMessage>, _: Vec<DownwardMessage>,
) -> Self::ProduceCandidate ) -> Self::ProduceCandidate
......
...@@ -179,7 +179,7 @@ pub struct DutyRoster { ...@@ -179,7 +179,7 @@ pub struct DutyRoster {
/// These are global parameters that apply to all parachain candidates in a block. /// These are global parameters that apply to all parachain candidates in a block.
#[derive(PartialEq, Eq, Clone, Encode, Decode)] #[derive(PartialEq, Eq, Clone, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug, Default))] #[cfg_attr(feature = "std", derive(Debug, Default))]
pub struct GlobalValidationSchedule<N = BlockNumber> { pub struct GlobalValidationData<N = BlockNumber> {
/// The maximum code size permitted, in bytes. /// The maximum code size permitted, in bytes.
pub max_code_size: u32, pub max_code_size: u32,
/// The maximum head-data size permitted, in bytes. /// The maximum head-data size permitted, in bytes.
...@@ -278,7 +278,7 @@ pub struct CandidateReceipt<H = Hash, N = BlockNumber> { ...@@ -278,7 +278,7 @@ pub struct CandidateReceipt<H = Hash, N = BlockNumber> {
/// The hash of the PoV-block. /// The hash of the PoV-block.
pub pov_block_hash: H, pub pov_block_hash: H,
/// The global validation schedule. /// The global validation schedule.
pub global_validation: GlobalValidationSchedule<N>, pub global_validation: GlobalValidationData<N>,
/// The local validation data. /// The local validation data.
pub local_validation: LocalValidationData<N>, pub local_validation: LocalValidationData<N>,
/// Commitments made as a result of validation. /// Commitments made as a result of validation.
...@@ -352,7 +352,7 @@ impl Ord for CandidateReceipt { ...@@ -352,7 +352,7 @@ impl Ord for CandidateReceipt {
#[cfg_attr(feature = "std", derive(Debug, Default))] #[cfg_attr(feature = "std", derive(Debug, Default))]
pub struct OmittedValidationData<N = BlockNumber> { pub struct OmittedValidationData<N = BlockNumber> {
/// The global validation schedule. /// The global validation schedule.
pub global_validation: GlobalValidationSchedule<N>, pub global_validation: GlobalValidationData<N>,
/// The local validation data. /// The local validation data.
pub local_validation: LocalValidationData<N>, pub local_validation: LocalValidationData<N>,
} }
...@@ -762,7 +762,7 @@ sp_api::decl_runtime_apis! { ...@@ -762,7 +762,7 @@ sp_api::decl_runtime_apis! {
fn active_parachains() -> Vec<(Id, Option<(CollatorId, Retriable)>)>; fn active_parachains() -> Vec<(Id, Option<(CollatorId, Retriable)>)>;
/// Get the global validation schedule that all parachains should /// Get the global validation schedule that all parachains should
/// be validated under. /// be validated under.
fn global_validation_schedule() -> GlobalValidationSchedule; fn global_validation_data() -> GlobalValidationData;
/// Get the local validation data for a particular parachain. /// Get the local validation data for a particular parachain.
fn local_validation_data(id: Id) -> Option<LocalValidationData>; fn local_validation_data(id: Id) -> Option<LocalValidationData>;
/// Get the given parachain's head code blob. /// Get the given parachain's head code blob.
......
...@@ -60,14 +60,16 @@ pub const INCLUSION_INHERENT_IDENTIFIER: InherentIdentifier = *b"inclusn0"; ...@@ -60,14 +60,16 @@ pub const INCLUSION_INHERENT_IDENTIFIER: InherentIdentifier = *b"inclusn0";
pub fn collator_signature_payload<H: AsRef<[u8]>>( pub fn collator_signature_payload<H: AsRef<[u8]>>(
relay_parent: &H, relay_parent: &H,
para_id: &Id, para_id: &Id,
validation_data_hash: &Hash,
pov_hash: &Hash, pov_hash: &Hash,
) -> [u8; 68] { ) -> [u8; 100] {
// 32-byte hash length is protected in a test below. // 32-byte hash length is protected in a test below.
let mut payload = [0u8; 68]; let mut payload = [0u8; 100];
payload[0..32].copy_from_slice(relay_parent.as_ref()); payload[0..32].copy_from_slice(relay_parent.as_ref());
u32::from(*para_id).using_encoded(|s| payload[32..32 + s.len()].copy_from_slice(s)); u32::from(*para_id).using_encoded(|s| payload[32..32 + s.len()].copy_from_slice(s));
payload[36..68].copy_from_slice(pov_hash.as_ref()); payload[36..68].copy_from_slice(validation_data_hash.as_ref());
payload[68..100].copy_from_slice(pov_hash.as_ref());
payload payload
} }
...@@ -75,11 +77,18 @@ pub fn collator_signature_payload<H: AsRef<[u8]>>( ...@@ -75,11 +77,18 @@ pub fn collator_signature_payload<H: AsRef<[u8]>>(
fn check_collator_signature<H: AsRef<[u8]>>( fn check_collator_signature<H: AsRef<[u8]>>(
relay_parent: &H, relay_parent: &H,
para_id: &Id, para_id: &Id,
validation_data_hash: &Hash,
pov_hash: &Hash, pov_hash: &Hash,
collator: &CollatorId, collator: &CollatorId,
signature: &CollatorSignature, signature: &CollatorSignature,
) -> Result<(),()> { ) -> Result<(),()> {
let payload = collator_signature_payload(relay_parent, para_id, pov_hash); let payload = collator_signature_payload(
relay_parent,
para_id,
validation_data_hash,
pov_hash,
);
if signature.verify(&payload[..], collator) { if signature.verify(&payload[..], collator) {
Ok(()) Ok(())
} else { } else {
...@@ -87,6 +96,14 @@ fn check_collator_signature<H: AsRef<[u8]>>( ...@@ -87,6 +96,14 @@ fn check_collator_signature<H: AsRef<[u8]>>(
} }
} }
/// Compute the `validation_data_hash` from global & local validation data.
pub fn validation_data_hash<N: Encode>(
global: &GlobalValidationData<N>,
local: &LocalValidationData<N>,
) -> Hash {
BlakeTwo256::hash_of(&(global, local))
}
/// A unique descriptor of the candidate receipt. /// A unique descriptor of the candidate receipt.
#[derive(PartialEq, Eq, Clone, Encode, Decode)] #[derive(PartialEq, Eq, Clone, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug, Default))] #[cfg_attr(feature = "std", derive(Debug, Default))]
...@@ -97,11 +114,16 @@ pub struct CandidateDescriptor<H = Hash> { ...@@ -97,11 +114,16 @@ pub struct CandidateDescriptor<H = Hash> {
pub relay_parent: H, pub relay_parent: H,
/// The collator's sr25519 public key. /// The collator's sr25519 public key.
pub collator: CollatorId, pub collator: CollatorId,
/// Signature on blake2-256 of components of this receipt: /// The blake2-256 hash of the validation data. This is extra data derived from
/// The parachain index, the relay parent, and the pov_hash. /// relay-chain state which may vary based on bitfields included before the candidate.
pub signature: CollatorSignature, /// Thus it cannot be derived entirely from the relay-parent.
pub validation_data_hash: Hash,
/// The blake2-256 hash of the pov. /// The blake2-256 hash of the pov.
pub pov_hash: Hash, pub pov_hash: Hash,
/// Signature on blake2-256 of components of this receipt:
/// The parachain index, the relay parent, the validation data hash, and the pov_hash.
pub signature: CollatorSignature,
} }
impl<H: AsRef<[u8]>> CandidateDescriptor<H> { impl<H: AsRef<[u8]>> CandidateDescriptor<H> {
...@@ -110,6 +132,7 @@ impl<H: AsRef<[u8]>> CandidateDescriptor<H> { ...@@ -110,6 +132,7 @@ impl<H: AsRef<[u8]>> CandidateDescriptor<H> {
check_collator_signature( check_collator_signature(
&self.relay_parent, &self.relay_parent,
&self.para_id, &self.para_id,
&self.validation_data_hash,
&self.pov_hash, &self.pov_hash,
&self.collator, &self.collator,
&self.signature, &self.signature,
...@@ -146,7 +169,7 @@ pub struct FullCandidateReceipt<H = Hash, N = BlockNumber> { ...@@ -146,7 +169,7 @@ pub struct FullCandidateReceipt<H = Hash, N = BlockNumber> {
/// The inner candidate receipt. /// The inner candidate receipt.
pub inner: CandidateReceipt<H>, pub inner: CandidateReceipt<H>,
/// The global validation schedule. /// The global validation schedule.
pub global_validation: GlobalValidationSchedule<N>, pub global_validation: GlobalValidationData<N>,
/// The local validation data. /// The local validation data.
pub local_validation: LocalValidationData<N>, pub local_validation: LocalValidationData<N>,
} }
...@@ -232,7 +255,7 @@ pub struct LocalValidationData<N = BlockNumber> { ...@@ -232,7 +255,7 @@ pub struct LocalValidationData<N = BlockNumber> {
/// These are global parameters that apply to all candidates in a block. /// These are global parameters that apply to all candidates in a block.
#[derive(PartialEq, Eq, Clone, Encode, Decode)] #[derive(PartialEq, Eq, Clone, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug, Default))] #[cfg_attr(feature = "std", derive(Debug, Default))]
pub struct GlobalValidationSchedule<N = BlockNumber> { pub struct GlobalValidationData<N = BlockNumber> {
/// The maximum code size permitted, in bytes. /// The maximum code size permitted, in bytes.
pub max_code_size: u32, pub max_code_size: u32,
/// The maximum head-data size permitted, in bytes. /// The maximum head-data size permitted, in bytes.
...@@ -465,7 +488,7 @@ impl CoreAssignment { ...@@ -465,7 +488,7 @@ impl CoreAssignment {
#[cfg_attr(feature = "std", derive(PartialEq, Debug))] #[cfg_attr(feature = "std", derive(PartialEq, Debug))]
pub struct OmittedValidationData { pub struct OmittedValidationData {
/// The global validation schedule. /// The global validation schedule.
pub global_validation: GlobalValidationSchedule, pub global_validation: GlobalValidationData,
/// The local validation data. /// The local validation data.
pub local_validation: LocalValidationData, pub local_validation: LocalValidationData,
} }
...@@ -636,9 +659,9 @@ sp_api::decl_runtime_apis! { ...@@ -636,9 +659,9 @@ sp_api::decl_runtime_apis! {
/// cores can have paras assigned to them. /// cores can have paras assigned to them.
fn availability_cores() -> Vec<CoreState<N>>; fn availability_cores() -> Vec<CoreState<N>>;
/// Yields the GlobalValidationSchedule. This applies to all para candidates with the /// Yields the GlobalValidationData. This applies to all para candidates with the
/// relay-parent equal to the block in which context this is invoked in. /// relay-parent equal to the block in which context this is invoked in.
fn global_validation_schedule() -> GlobalValidationSchedule<N>; fn global_validation_data() -> GlobalValidationData<N>;
/// Yields the LocalValidationData for the given ParaId along with an assumption that /// Yields the LocalValidationData for the given ParaId along with an assumption that
/// should be used if the para currently occupies a core. /// should be used if the para currently occupies a core.
...@@ -696,4 +719,18 @@ mod tests { ...@@ -696,4 +719,18 @@ mod tests {
assert_eq!(info.next_rotation_at(), 0); assert_eq!(info.next_rotation_at(), 0);
assert_eq!(info.last_rotation_at(), 0); assert_eq!(info.last_rotation_at(), 0);
} }
#[test]
fn collator_signature_payload_is_valid() {
// if this fails, collator signature verification code has to be updated.
let h = Hash::default();
assert_eq!(h.as_ref().len(), 32);
let _payload = collator_signature_payload(
&Hash::from([1; 32]),
&5u32.into(),
&Hash::from([2; 32]),
&Hash::from([3; 32]),
);
}
} }
...@@ -137,10 +137,10 @@ enum CoreState { ...@@ -137,10 +137,10 @@ enum CoreState {
## Global Validation Schedule ## Global Validation Schedule
Yields the [`GlobalValidationSchedule`](../types/candidate.md#globalvalidationschedule) at the state of a given block. This applies to all para candidates with the relay-parent equal to that block. Yields the [`GlobalValidationData`](../types/candidate.md#globalvalidationschedule) at the state of a given block. This applies to all para candidates with the relay-parent equal to that block.
```rust ```rust
fn global_validation_schedule(at: Block) -> GlobalValidationSchedule; fn global_validation_data(at: Block) -> GlobalValidationData;
``` ```
## Local Validation Data ## Local Validation Data
......
...@@ -35,6 +35,9 @@ fn update_configuration(f: impl FnOnce(&mut HostConfiguration)) { ...@@ -35,6 +35,9 @@ fn update_configuration(f: impl FnOnce(&mut HostConfiguration)) {
*pending = Some(x); *pending = Some(x);
}) })
} }
/// Get the GlobalValidationData, assuming the context is the parent block.
fn global_validation_data() -> GlobalValidationData;
``` ```
## Entry-points ## Entry-points
......
...@@ -62,6 +62,7 @@ All failed checks should lead to an unrecoverable error making the block invalid ...@@ -62,6 +62,7 @@ All failed checks should lead to an unrecoverable error making the block invalid
1. check that each candidate corresponds to a scheduled core and that they are ordered in the same order the cores appear in assignments in `scheduled`. 1. check that each candidate corresponds to a scheduled core and that they are ordered in the same order the cores appear in assignments in `scheduled`.
1. check that `scheduled` is sorted ascending by `CoreIndex`, without duplicates. 1. check that `scheduled` is sorted ascending by `CoreIndex`, without duplicates.
1. check that there is no candidate pending availability for any scheduled `ParaId`. 1. check that there is no candidate pending availability for any scheduled `ParaId`.
1. check that each candidate's `validation_data_hash` corresponds to a `(LocalValidationData, GlobalValidationData)` computed from the current state.
1. If the core assignment includes a specific collator, ensure the backed candidate is issued by that collator. 1. If the core assignment includes a specific collator, ensure the backed candidate is issued by that collator.
1. Ensure that any code upgrade scheduled by the candidate does not happen within `config.validation_upgrade_frequency` of `Paras::last_code_upgrade(para_id, true)`, if any, comparing against the value of `Paras::FutureCodeUpgrades` for the given para ID. 1. Ensure that any code upgrade scheduled by the candidate does not happen within `config.validation_upgrade_frequency` of `Paras::last_code_upgrade(para_id, true)`, if any, comparing against the value of `Paras::FutureCodeUpgrades` for the given para ID.
1. Check the collator's signature on the candidate data. 1. Check the collator's signature on the candidate data.
......
...@@ -112,6 +112,7 @@ OutgoingParas: Vec<ParaId>; ...@@ -112,6 +112,7 @@ OutgoingParas: Vec<ParaId>;
* `is_parathread(ParaId) -> bool`: Returns true if the para ID references any live parathread. * `is_parathread(ParaId) -> bool`: Returns true if the para ID references any live parathread.
* `last_code_upgrade(id: ParaId, include_future: bool) -> Option<BlockNumber>`: The block number of the last scheduled upgrade of the requested para. Includes future upgrades if the flag is set. This is the `expected_at` number, not the `activated_at` number. * `last_code_upgrade(id: ParaId, include_future: bool) -> Option<BlockNumber>`: The block number of the last scheduled upgrade of the requested para. Includes future upgrades if the flag is set. This is the `expected_at` number, not the `activated_at` number.
* `local_validation_data(id: ParaId) -> Option<LocalValidationData>`: Get the LocalValidationData of the given para, assuming the context is the parent block. Returns `None` if the para is not known.
## Finalization ## Finalization
......
...@@ -26,12 +26,12 @@ struct PoV(Vec<u8>); ...@@ -26,12 +26,12 @@ struct PoV(Vec<u8>);
Validation data that is often omitted from types describing candidates as it can be derived from the relay-parent of the candidate. However, with the expectation of state pruning, these are best kept available elsewhere as well. Validation data that is often omitted from types describing candidates as it can be derived from the relay-parent of the candidate. However, with the expectation of state pruning, these are best kept available elsewhere as well.
This contains the [`GlobalValidationSchedule`](candidate.md#globalvalidationschedule) and [`LocalValidationData`](candidate.md#localvalidationdata) This contains the [`GlobalValidationData`](candidate.md#globalvalidationschedule) and [`LocalValidationData`](candidate.md#localvalidationdata)