diff --git a/availability-store/src/lib.rs b/availability-store/src/lib.rs
index 7abc444758f7..4b973c7d0271 100644
--- a/availability-store/src/lib.rs
+++ b/availability-store/src/lib.rs
@@ -25,12 +25,10 @@
use futures::prelude::*;
use futures::channel::{mpsc, oneshot};
use keystore::KeyStorePtr;
-use polkadot_primitives::{
+use polkadot_primitives::v0::{
Hash, Block,
- parachain::{
- PoVBlock, AbridgedCandidateReceipt, ErasureChunk,
- ParachainHost, AvailableData, OmittedValidationData,
- },
+ PoVBlock, AbridgedCandidateReceipt, ErasureChunk,
+ ParachainHost, AvailableData, OmittedValidationData,
};
use sp_runtime::traits::HashFor;
use sp_blockchain::Result as ClientResult;
diff --git a/availability-store/src/store.rs b/availability-store/src/store.rs
index 851beabc6ac8..cd76de5d44ad 100644
--- a/availability-store/src/store.rs
+++ b/availability-store/src/store.rs
@@ -19,11 +19,8 @@ use kvdb_rocksdb::{Database, DatabaseConfig};
use kvdb::{KeyValueDB, DBTransaction};
use codec::{Encode, Decode};
use polkadot_erasure_coding as erasure;
-use polkadot_primitives::{
- Hash,
- parachain::{
- ErasureChunk, AvailableData, AbridgedCandidateReceipt,
- },
+use polkadot_primitives::v0::{
+ Hash, ErasureChunk, AvailableData, AbridgedCandidateReceipt,
};
use parking_lot::Mutex;
@@ -273,7 +270,7 @@ impl Store {
// If there are no block data in the store at this point,
// check that they can be reconstructed now and add them to store if they can.
if self.execution_data(&candidate_hash).is_none() {
- if let Ok(available_data) = erasure::reconstruct(
+ if let Ok(available_data) = erasure::reconstruct_v0(
n_validators as usize,
v.iter().map(|chunk| (chunk.chunk.as_ref(), chunk.index as usize)),
)
@@ -390,7 +387,7 @@ impl Store {
mod tests {
use super::*;
use polkadot_erasure_coding::{self as erasure};
- use polkadot_primitives::parachain::{
+ use polkadot_primitives::v0::{
Id as ParaId, BlockData, AvailableData, PoVBlock, OmittedValidationData,
};
@@ -489,7 +486,7 @@ mod tests {
let available_data = available_data(&[42; 8]);
let n_validators = 5;
- let erasure_chunks = erasure::obtain_chunks(
+ let erasure_chunks = erasure::obtain_chunks_v0(
n_validators,
&available_data,
).unwrap();
diff --git a/availability-store/src/worker.rs b/availability-store/src/worker.rs
index 8a3898579f54..a7cf7ec41dae 100644
--- a/availability-store/src/worker.rs
+++ b/availability-store/src/worker.rs
@@ -33,8 +33,8 @@ use consensus_common::{
import_queue::CacheKeyId,
};
use sp_core::traits::SpawnNamed;
-use polkadot_primitives::{Block, BlockId, Hash};
-use polkadot_primitives::parachain::{
+use polkadot_primitives::v0::{
+ Block, BlockId, Hash,
ParachainHost, ValidatorId, AbridgedCandidateReceipt, AvailableData,
ValidatorPair, ErasureChunk,
};
diff --git a/collator/src/lib.rs b/collator/src/lib.rs
index 0215b33ee6a1..663cb825bfc1 100644
--- a/collator/src/lib.rs
+++ b/collator/src/lib.rs
@@ -55,12 +55,11 @@ use log::warn;
use sc_client_api::{StateBackend, BlockchainEvents};
use sp_blockchain::HeaderBackend;
use sp_core::Pair;
-use polkadot_primitives::{
+use polkadot_primitives::v0::{
BlockId, Hash, Block, DownwardMessage,
- parachain::{
- self, BlockData, DutyRoster, HeadData, Id as ParaId,
- PoVBlock, ValidatorId, CollatorPair, LocalValidationData, GlobalValidationSchedule,
- }
+ BlockData, DutyRoster, HeadData, Id as ParaId,
+ PoVBlock, ValidatorId, CollatorPair, LocalValidationData, GlobalValidationSchedule,
+ Collation, CollationInfo, collator_signature_payload,
};
use polkadot_cli::{
ProvideRuntimeApi, ParachainHost, IdentifyVariant,
@@ -69,7 +68,7 @@ use polkadot_cli::{
pub use polkadot_cli::service::Configuration;
pub use polkadot_cli::Cli;
pub use polkadot_validation::SignedStatement;
-pub use polkadot_primitives::parachain::CollatorId;
+pub use polkadot_primitives::v0::CollatorId;
pub use sc_network::PeerId;
pub use service::RuntimeApiCollection;
pub use sc_cli::SubstrateCli;
@@ -164,7 +163,7 @@ pub async fn collate
(
downward_messages: Vec,
mut para_context: P,
key: Arc,
-) -> Option
+) -> Option
where
P: ParachainContext,
P::ProduceCandidate: Send,
@@ -181,13 +180,13 @@ pub async fn collate(
};
let pov_block_hash = pov_block.hash();
- let signature = key.sign(¶chain::collator_signature_payload(
+ let signature = key.sign(&collator_signature_payload(
&relay_parent,
&local_id,
&pov_block_hash,
));
- let info = parachain::CollationInfo {
+ let info = CollationInfo {
parachain_index: local_id,
relay_parent,
collator: key.public(),
@@ -196,7 +195,7 @@ pub async fn collate
(
pov_block_hash,
};
- let collation = parachain::Collation {
+ let collation = Collation {
info,
pov: pov_block,
};
@@ -456,7 +455,7 @@ where
#[cfg(not(feature = "service-rewr"))]
fn compute_targets(para_id: ParaId, session_keys: &[ValidatorId], roster: DutyRoster) -> HashSet {
- use polkadot_primitives::parachain::Chain;
+ use polkadot_primitives::v0::Chain;
roster.validator_duty.iter().enumerate()
.filter(|&(_, c)| c == &Chain::Parachain(para_id))
diff --git a/core-primitives/src/lib.rs b/core-primitives/src/lib.rs
index d91ed3cfc197..ffb346467d9e 100644
--- a/core-primitives/src/lib.rs
+++ b/core-primitives/src/lib.rs
@@ -94,3 +94,8 @@ pub enum DownwardMessage {
/// XCMP message for the Parachain.
XCMPMessage(sp_std::vec::Vec),
}
+
+/// V1 primitives.
+pub mod v1 {
+ pub use super::*;
+}
diff --git a/erasure-coding/src/lib.rs b/erasure-coding/src/lib.rs
index 98a2776d8848..708a167d6276 100644
--- a/erasure-coding/src/lib.rs
+++ b/erasure-coding/src/lib.rs
@@ -26,8 +26,8 @@
use codec::{Encode, Decode};
use reed_solomon::galois_16::{self, ReedSolomon};
-use primitives::{Hash as H256, BlakeTwo256, HashT};
-use primitives::parachain::AvailableData;
+use primitives::v0::{self, Hash as H256, BlakeTwo256, HashT};
+use primitives::v1;
use sp_core::Blake2Hasher;
use trie::{EMPTY_PREFIX, MemoryDB, Trie, TrieMut, trie_types::{TrieDBMut, TrieDB}};
@@ -124,14 +124,32 @@ fn code_params(n_validators: usize) -> Result {
})
}
+/// Obtain erasure-coded chunks for v0 `AvailableData`, one for each validator.
+///
+/// Works only up to 65536 validators, and `n_validators` must be non-zero.
+pub fn obtain_chunks_v0(n_validators: usize, data: &v0::AvailableData)
+ -> Result>, Error>
+{
+ obtain_chunks(n_validators, data)
+}
+
+/// Obtain erasure-coded chunks for v1 `AvailableData`, one for each validator.
+///
+/// Works only up to 65536 validators, and `n_validators` must be non-zero.
+pub fn obtain_chunks_v1(n_validators: usize, data: &v1::AvailableData)
+ -> Result>, Error>
+{
+ obtain_chunks(n_validators, data)
+}
+
/// Obtain erasure-coded chunks, one for each validator.
///
/// Works only up to 65536 validators, and `n_validators` must be non-zero.
-pub fn obtain_chunks(n_validators: usize, available_data: &AvailableData)
+fn obtain_chunks(n_validators: usize, data: &T)
-> Result>, Error>
{
let params = code_params(n_validators)?;
- let encoded = available_data.encode();
+ let encoded = data.encode();
if encoded.is_empty() {
return Err(Error::BadPayload);
@@ -145,15 +163,42 @@ pub fn obtain_chunks(n_validators: usize, available_data: &AvailableData)
Ok(shards.into_iter().map(|w| w.into_inner()).collect())
}
-/// Reconstruct the block data from a set of chunks.
+/// Reconstruct the v0 available data from a set of chunks.
+///
+/// Provide an iterator containing chunk data and the corresponding index.
+/// The indices of the present chunks must be indicated. If too few chunks
+/// are provided, recovery is not possible.
+///
+/// Works only up to 65536 validators, and `n_validators` must be non-zero.
+pub fn reconstruct_v0<'a, I: 'a>(n_validators: usize, chunks: I)
+ -> Result
+ where I: IntoIterator-
+{
+ reconstruct(n_validators, chunks)
+}
+
+/// Reconstruct the v1 available data from a set of chunks.
+///
+/// Provide an iterator containing chunk data and the corresponding index.
+/// The indices of the present chunks must be indicated. If too few chunks
+/// are provided, recovery is not possible.
+///
+/// Works only up to 65536 validators, and `n_validators` must be non-zero.
+pub fn reconstruct_v1<'a, I: 'a>(n_validators: usize, chunks: I)
+ -> Result
+ where I: IntoIterator-
+{
+ reconstruct(n_validators, chunks)
+}
+
+/// Reconstruct decodable data from a set of chunks.
///
/// Provide an iterator containing chunk data and the corresponding index.
/// The indices of the present chunks must be indicated. If too few chunks
/// are provided, recovery is not possible.
///
/// Works only up to 65536 validators, and `n_validators` must be non-zero.
-pub fn reconstruct<'a, I: 'a>(n_validators: usize, chunks: I)
- -> Result
+fn reconstruct<'a, I: 'a, T: Decode>(n_validators: usize, chunks: I) -> Result
where I: IntoIterator-
{
let params = code_params(n_validators)?;
@@ -343,7 +388,7 @@ impl<'a, I: Iterator
- > codec::Input for ShardInput<'a, I> {
#[cfg(test)]
mod tests {
use super::*;
- use primitives::parachain::{BlockData, PoVBlock};
+ use primitives::v0::{AvailableData, BlockData, PoVBlock};
#[test]
fn field_order_is_right_size() {
@@ -420,7 +465,7 @@ mod tests {
assert_eq!(chunks.len(), 10);
// any 4 chunks should work.
- let reconstructed = reconstruct(
+ let reconstructed: AvailableData = reconstruct(
10,
[
(&*chunks[1], 1),
diff --git a/network/src/legacy/collator_pool.rs b/network/src/legacy/collator_pool.rs
index a0c0a0458e90..f2b168e0f592 100644
--- a/network/src/legacy/collator_pool.rs
+++ b/network/src/legacy/collator_pool.rs
@@ -17,8 +17,7 @@
//! Bridge between the network and consensus service for getting collations to it.
use codec::{Encode, Decode};
-use polkadot_primitives::Hash;
-use polkadot_primitives::parachain::{CollatorId, Id as ParaId, Collation};
+use polkadot_primitives::v0::{Hash, CollatorId, Id as ParaId, Collation};
use sc_network::PeerId;
use futures::channel::oneshot;
@@ -236,7 +235,7 @@ impl CollatorPool {
mod tests {
use super::*;
use sp_core::crypto::UncheckedInto;
- use polkadot_primitives::parachain::{CollationInfo, BlockData, PoVBlock};
+ use polkadot_primitives::v0::{CollationInfo, BlockData, PoVBlock};
use futures::executor::block_on;
fn make_pov(block_data: Vec
) -> PoVBlock {
diff --git a/network/src/legacy/gossip/attestation.rs b/network/src/legacy/gossip/attestation.rs
index a47f75288bf4..2d20ce63b995 100644
--- a/network/src/legacy/gossip/attestation.rs
+++ b/network/src/legacy/gossip/attestation.rs
@@ -33,7 +33,7 @@
use sc_network_gossip::{ValidationResult as GossipValidationResult};
use sc_network::ReputationChange;
use polkadot_validation::GenericStatement;
-use polkadot_primitives::Hash;
+use polkadot_primitives::v0::Hash;
use std::collections::HashMap;
diff --git a/network/src/legacy/gossip/mod.rs b/network/src/legacy/gossip/mod.rs
index 7dea99656667..9e18d7ce2171 100644
--- a/network/src/legacy/gossip/mod.rs
+++ b/network/src/legacy/gossip/mod.rs
@@ -58,8 +58,8 @@ use sc_network_gossip::{
ValidatorContext, MessageIntent,
};
use polkadot_validation::{SignedStatement};
-use polkadot_primitives::{Block, Hash};
-use polkadot_primitives::parachain::{
+use polkadot_primitives::v0::{
+ Block, Hash,
ParachainHost, ValidatorId, ErasureChunk as PrimitiveChunk, SigningContext, PoVBlock,
};
use polkadot_erasure_coding::{self as erasure};
@@ -755,7 +755,7 @@ mod tests {
use sc_network_gossip::Validator as ValidatorT;
use std::sync::mpsc;
use parking_lot::Mutex;
- use polkadot_primitives::parachain::{AbridgedCandidateReceipt, BlockData};
+ use polkadot_primitives::v0::{AbridgedCandidateReceipt, BlockData};
use sp_core::sr25519::Signature as Sr25519Signature;
use polkadot_validation::GenericStatement;
diff --git a/network/src/legacy/local_collations.rs b/network/src/legacy/local_collations.rs
index 6bc9b985a7c1..d85911548613 100644
--- a/network/src/legacy/local_collations.rs
+++ b/network/src/legacy/local_collations.rs
@@ -19,7 +19,7 @@
//! Collations are attempted to be repropagated when a new validator connects,
//! a validator changes his session key, or when they are generated.
-use polkadot_primitives::{Hash, parachain::{ValidatorId}};
+use polkadot_primitives::v0::{Hash, ValidatorId};
use crate::legacy::collator_pool::Role;
use std::collections::{HashMap, HashSet};
use std::time::Duration;
@@ -144,7 +144,7 @@ impl LocalCollations {
mod tests {
use super::*;
use sp_core::crypto::UncheckedInto;
- use polkadot_primitives::parachain::ValidatorId;
+ use polkadot_primitives::v0::ValidatorId;
#[test]
fn add_validator_with_ready_collation() {
diff --git a/network/src/legacy/mod.rs b/network/src/legacy/mod.rs
index 28ea77a6bdc1..42698657c053 100644
--- a/network/src/legacy/mod.rs
+++ b/network/src/legacy/mod.rs
@@ -25,7 +25,7 @@ pub mod gossip;
use codec::Decode;
use futures::prelude::*;
-use polkadot_primitives::Hash;
+use polkadot_primitives::v0::Hash;
use sc_network::PeerId;
use sc_network_gossip::TopicNotification;
use log::debug;
diff --git a/network/src/lib.rs b/network/src/lib.rs
index 5048f09adaf5..eaed7b34d2cb 100644
--- a/network/src/lib.rs
+++ b/network/src/lib.rs
@@ -21,7 +21,7 @@
#![recursion_limit="256"]
-use polkadot_primitives::{Block, Hash, BlakeTwo256, HashT};
+use polkadot_primitives::v0::{Block, Hash, BlakeTwo256, HashT};
pub mod legacy;
pub mod protocol;
diff --git a/network/src/protocol/mod.rs b/network/src/protocol/mod.rs
index 9a94065e5be6..22e72dcfd6e4 100644
--- a/network/src/protocol/mod.rs
+++ b/network/src/protocol/mod.rs
@@ -30,12 +30,10 @@ use futures::task::{Context, Poll};
use futures::stream::{FuturesUnordered, StreamFuture};
use log::{debug, trace};
-use polkadot_primitives::{
+use polkadot_primitives::v0::{
Hash, Block,
- parachain::{
- PoVBlock, ValidatorId, ValidatorIndex, Collation, AbridgedCandidateReceipt,
- ErasureChunk, ParachainHost, Id as ParaId, CollatorId,
- },
+ PoVBlock, ValidatorId, ValidatorIndex, Collation, AbridgedCandidateReceipt,
+ ErasureChunk, ParachainHost, Id as ParaId, CollatorId,
};
use polkadot_validation::{
SharedTable, TableRouter, Network as ParachainNetwork, Validated, GenericStatement, Collators,
diff --git a/network/src/protocol/tests.rs b/network/src/protocol/tests.rs
index 049af3f5aca7..711906797be4 100644
--- a/network/src/protocol/tests.rs
+++ b/network/src/protocol/tests.rs
@@ -17,8 +17,8 @@ use super::*;
use crate::legacy::gossip::GossipPoVBlock;
use parking_lot::Mutex;
-use polkadot_primitives::Block;
-use polkadot_primitives::parachain::{
+use polkadot_primitives::v0::{
+ Block,
Id as ParaId, Chain, DutyRoster, ParachainHost, ValidatorId,
Retriable, CollatorId, AbridgedCandidateReceipt,
GlobalValidationSchedule, LocalValidationData, ErasureChunk, SigningContext,
@@ -198,7 +198,7 @@ sp_api::mock_impl_runtime_apis! {
parent_hash: Default::default(),
}
}
- fn downward_messages(_: ParaId) -> Vec {
+ fn downward_messages(_: ParaId) -> Vec {
Vec::new()
}
}
diff --git a/node/core/backing/src/lib.rs b/node/core/backing/src/lib.rs
index e4490d20d3f1..281147847e19 100644
--- a/node/core/backing/src/lib.rs
+++ b/node/core/backing/src/lib.rs
@@ -21,6 +21,7 @@
use std::collections::{HashMap, HashSet};
use std::convert::TryFrom;
use std::pin::Pin;
+use std::sync::Arc;
use std::time::Duration;
use bitvec::vec::BitVec;
@@ -36,17 +37,15 @@ use streamunordered::{StreamUnordered, StreamYield};
use primitives::Pair;
use keystore::KeyStorePtr;
-use polkadot_primitives::{
- Hash,
- parachain::{
- AbridgedCandidateReceipt, BackedCandidate, Id as ParaId, ValidatorPair, ValidatorId,
- ValidatorIndex, HeadData, SigningContext, PoVBlock, OmittedValidationData,
- CandidateDescriptor, LocalValidationData, GlobalValidationSchedule, AvailableData,
- ErasureChunk,
- },
+use polkadot_primitives::v1::{
+ CommittedCandidateReceipt, BackedCandidate, Id as ParaId, ValidatorPair, ValidatorId,
+ ValidatorIndex, SigningContext, PoV, OmittedValidationData,
+ CandidateDescriptor, AvailableData, ErasureChunk, ValidatorSignature, Hash, CandidateReceipt,
+ CandidateCommitments,
};
use polkadot_node_primitives::{
FromTableMisbehavior, Statement, SignedFullStatement, MisbehaviorReport, ValidationResult,
+ ValidationOutputs,
};
use polkadot_subsystem::{
FromOverseer, OverseerSignal, Subsystem, SubsystemContext, SpawnedSubsystem,
@@ -59,8 +58,12 @@ use polkadot_subsystem::messages::{
};
use statement_table::{
generic::AttestedCandidate as TableAttestedCandidate,
- Table, Context as TableContextTrait, Statement as TableStatement,
- SignedStatement as TableSignedStatement, Summary as TableSummary,
+ Context as TableContextTrait,
+ Table,
+ v1::{
+ Statement as TableStatement,
+ SignedStatement as TableSignedStatement, Summary as TableSummary,
+ },
};
#[derive(Debug, derive_more::From)]
@@ -90,8 +93,6 @@ struct CandidateBackingJob {
/// Outbound message channel sending part.
tx_from: mpsc::Sender,
- /// `HeadData`s of the parachains that this validator is assigned to.
- head_data: HeadData,
/// The `ParaId`s assigned to this validator.
assignment: ParaId,
/// We issued `Valid` or `Invalid` statements on about these candidates.
@@ -118,8 +119,22 @@ struct TableContext {
}
impl TableContextTrait for TableContext {
- fn is_member_of(&self, authority: ValidatorIndex, group: &ParaId) -> bool {
- self.groups.get(group).map_or(false, |g| g.iter().position(|&a| a == authority).is_some())
+ type AuthorityId = ValidatorIndex;
+ type Digest = Hash;
+ type GroupId = ParaId;
+ type Signature = ValidatorSignature;
+ type Candidate = CommittedCandidateReceipt;
+
+ fn candidate_digest(candidate: &CommittedCandidateReceipt) -> Hash {
+ candidate.hash()
+ }
+
+ fn candidate_group(candidate: &CommittedCandidateReceipt) -> ParaId {
+ candidate.descriptor().para_id
+ }
+
+ fn is_member_of(&self, authority: &ValidatorIndex, group: &ParaId) -> bool {
+ self.groups.get(group).map_or(false, |g| g.iter().position(|a| a == authority).is_some())
}
fn requisite_votes(&self, group: &ParaId) -> usize {
@@ -221,7 +236,7 @@ impl CandidateBackingJob {
async fn issue_candidate_invalid_message(
&mut self,
- candidate: AbridgedCandidateReceipt,
+ candidate: CandidateReceipt,
) -> Result<(), Error> {
self.tx_from.send(FromJob::CandidateSelection(
CandidateSelectionMessage::Invalid(self.parent, candidate)
@@ -231,34 +246,69 @@ impl CandidateBackingJob {
}
/// Validate the candidate that is requested to be `Second`ed and distribute validation result.
+ ///
+ /// Returns `Ok(true)` if we issued a `Seconded` statement about this candidate.
async fn validate_and_second(
&mut self,
- candidate: AbridgedCandidateReceipt,
- pov: PoVBlock,
- ) -> Result {
- let valid = self.request_candidate_validation(candidate.clone(), pov.clone()).await?;
- let statement = match valid.0 {
- ValidationResult::Valid => {
+ candidate: &CandidateReceipt,
+ pov: PoV,
+ ) -> Result {
+ let valid = self.request_candidate_validation(
+ candidate.descriptor().clone(),
+ Arc::new(pov.clone()),
+ ).await?;
+
+ let candidate_hash = candidate.hash();
+
+ let statement = match valid {
+ ValidationResult::Valid(outputs) => {
// make PoV available for later distribution. Send data to the availability
// store to keep. Sign and dispatch `valid` statement to network if we
// have not seconded the given candidate.
- self.make_pov_available(pov, valid.1, valid.2).await?;
- self.issued_statements.insert(candidate.hash());
- Statement::Seconded(candidate)
+ //
+ // If the commitments hash produced by validation is not the same as given by
+ // the collator, do not make available and report the collator.
+ let commitments_check = self.make_pov_available(
+ pov,
+ outputs,
+ |commitments| if commitments.hash() == candidate.commitments_hash {
+ Ok(CommittedCandidateReceipt {
+ descriptor: candidate.descriptor().clone(),
+ commitments,
+ })
+ } else {
+ Err(())
+ },
+ ).await?;
+
+ match commitments_check {
+ Ok(candidate) => {
+ self.issued_statements.insert(candidate_hash);
+ Some(Statement::Seconded(candidate))
+ }
+ Err(()) => {
+ self.issue_candidate_invalid_message(candidate.clone()).await?;
+ None
+ }
+ }
}
ValidationResult::Invalid => {
- let candidate_hash = candidate.hash();
- self.issue_candidate_invalid_message(candidate).await?;
- Statement::Invalid(candidate_hash)
+ // no need to issue a statement about this if we aren't seconding it.
+ //
+ // there's an infinite amount of garbage out there. no need to acknowledge
+ // all of it.
+ self.issue_candidate_invalid_message(candidate.clone()).await?;
+ None
}
};
- if let Some(signed_statement) = self.sign_statement(statement) {
+ let issued_statement = statement.is_some();
+ if let Some(signed_statement) = statement.and_then(|s| self.sign_statement(s)) {
self.import_statement(&signed_statement).await?;
self.distribute_signed_statement(signed_statement).await?;
}
- Ok(valid.0)
+ Ok(issued_statement)
}
fn get_backed(&self) -> Vec {
@@ -303,7 +353,7 @@ impl CandidateBackingJob {
}
/// Check if there have happened any new misbehaviors and issue necessary messages.
- ///
+ ///
/// TODO: Report multiple misbehaviors (https://github.com/paritytech/polkadot/issues/1387)
async fn issue_new_misbehaviors(&mut self) -> Result<(), Error> {
let mut reports = Vec::new();
@@ -354,7 +404,7 @@ impl CandidateBackingJob {
match msg {
CandidateBackingMessage::Second(_, candidate, pov) => {
// Sanity check that candidate is from our assignment.
- if candidate.parachain_index != self.assignment {
+ if candidate.descriptor().para_id != self.assignment {
return Ok(());
}
@@ -367,8 +417,8 @@ impl CandidateBackingJob {
let candidate_hash = candidate.hash();
if !self.issued_statements.contains(&candidate_hash) {
- if let Ok(ValidationResult::Valid) = self.validate_and_second(
- candidate,
+ if let Ok(true) = self.validate_and_second(
+ &candidate,
pov,
).await {
self.seconded = Some(candidate_hash);
@@ -397,17 +447,40 @@ impl CandidateBackingJob {
async fn kick_off_validation_work(
&mut self,
summary: TableSummary,
- ) -> Result {
- let candidate = self.table.get_candidate(&summary.candidate).ok_or(Error::CandidateNotFound)?;
- let candidate = candidate.clone();
- let descriptor = candidate.to_descriptor();
- let candidate_hash = candidate.hash();
- let pov = self.request_pov_from_distribution(descriptor).await?;
- let v = self.request_candidate_validation(candidate, pov).await?;
+ ) -> Result<(), Error> {
+ let candidate_hash = summary.candidate.clone();
+
+ if self.issued_statements.contains(&candidate_hash) {
+ return Ok(())
+ }
+
+ // We clone the commitments here because there are borrowck
+ // errors relating to this being a struct and methods borrowing the entirety of self
+ // and not just those things that the function uses.
+ let candidate = self.table.get_candidate(&candidate_hash).ok_or(Error::CandidateNotFound)?;
+ let expected_commitments = candidate.commitments.clone();
+
+ let descriptor = candidate.descriptor().clone();
+ let pov = self.request_pov_from_distribution(descriptor.clone()).await?;
+ let v = self.request_candidate_validation(descriptor, pov.clone()).await?;
+
+ let statement = match v {
+ ValidationResult::Valid(outputs) => {
+ // If validation produces a new set of commitments, we vote the candidate as invalid.
+ let commitments_check = self.make_pov_available(
+ (&*pov).clone(),
+ outputs,
+ |commitments| if commitments == expected_commitments {
+ Ok(())
+ } else {
+ Err(())
+ }
+ ).await?;
- let statement = match v.0 {
- ValidationResult::Valid => {
- Statement::Valid(candidate_hash)
+ match commitments_check {
+ Ok(()) => Statement::Valid(candidate_hash),
+ Err(()) => Statement::Invalid(candidate_hash),
+ }
}
ValidationResult::Invalid => {
Statement::Invalid(candidate_hash)
@@ -420,7 +493,7 @@ impl CandidateBackingJob {
self.distribute_signed_statement(signed_statement).await?;
}
- Ok(v.0)
+ Ok(())
}
/// Import the statement and kick off validation work if it is a part of our assignment.
@@ -478,29 +551,26 @@ impl CandidateBackingJob {
async fn request_pov_from_distribution(
&mut self,
descriptor: CandidateDescriptor,
- ) -> Result {
+ ) -> Result, Error> {
let (tx, rx) = oneshot::channel();
self.tx_from.send(FromJob::PoVDistribution(
PoVDistributionMessage::FetchPoV(self.parent, descriptor, tx)
)).await?;
- let pov = rx.await?;
- Ok((*pov).clone())
+ Ok(rx.await?)
}
async fn request_candidate_validation(
&mut self,
- candidate: AbridgedCandidateReceipt,
- pov: PoVBlock,
- ) -> Result<(ValidationResult, GlobalValidationSchedule, LocalValidationData), Error> {
+ candidate: CandidateDescriptor,
+ pov: Arc,
+ ) -> Result {
let (tx, rx) = oneshot::channel();
self.tx_from.send(FromJob::CandidateValidation(
- CandidateValidationMessage::Validate(
- self.parent,
+ CandidateValidationMessage::ValidateFromChainState(
candidate,
- self.head_data.clone(),
pov,
tx,
)
@@ -523,32 +593,51 @@ impl CandidateBackingJob {
Ok(())
}
- async fn make_pov_available(
+ // Compute the erasure-coding and make it available.
+ //
+ // This calls an inspection function before making the PoV available for any last checks
+ // that need to be done. If the inspection function returns an error, this function returns
+ // early without making the PoV available.
+ async fn make_pov_available(
&mut self,
- pov_block: PoVBlock,
- global_validation: GlobalValidationSchedule,
- local_validation: LocalValidationData,
- ) -> Result<(), Error> {
+ pov: PoV,
+ outputs: ValidationOutputs,
+ with_commitments: impl FnOnce(CandidateCommitments) -> Result,
+ ) -> Result, Error> {
let omitted_validation = OmittedValidationData {
- global_validation,
- local_validation,
+ global_validation: outputs.global_validation_schedule,
+ local_validation: outputs.local_validation_data,
};
let available_data = AvailableData {
- pov_block,
+ pov,
omitted_validation,
};
- let chunks = erasure_coding::obtain_chunks(
+ let chunks = erasure_coding::obtain_chunks_v1(
self.table_context.validators.len(),
&available_data,
)?;
let branches = erasure_coding::branches(chunks.as_ref());
+ let erasure_root = branches.root();
+
+ let commitments = CandidateCommitments {
+ fees: outputs.fees,
+ upward_messages: outputs.upward_messages,
+ erasure_root,
+ new_validation_code: outputs.new_validation_code,
+ head_data: outputs.head_data,
+ };
- for (index, (chunk, proof)) in chunks.iter().zip(branches.map(|(proof, _)| proof)).enumerate() {
+ let res = match with_commitments(commitments) {
+ Ok(x) => x,
+ Err(e) => return Ok(Err(e)),
+ };
+
+ for (index, (proof, chunk)) in branches.enumerate() {
let chunk = ErasureChunk {
- chunk: chunk.clone(),
+ chunk: chunk.to_vec(),
index: index as u32,
proof,
};
@@ -556,7 +645,7 @@ impl CandidateBackingJob {
self.store_chunk(index as ValidatorIndex, chunk).await?;
}
- Ok(())
+ Ok(Ok(res))
}
async fn distribute_signed_statement(&mut self, s: SignedFullStatement) -> Result<(), Error> {
@@ -635,13 +724,7 @@ async fn run_job(
}
}
- let (
- head_data,
- signing_context,
- ) = futures::try_join!(
- request_head_data(parent, &mut tx_from, assignment).await?,
- request_signing_context(parent, &mut tx_from).await?,
- )?;
+ let signing_context = request_signing_context(parent, &mut tx_from).await?.await?;
let table_context = TableContext {
signing_context,
@@ -654,7 +737,6 @@ async fn run_job(
parent,
rx_to,
tx_from,
- head_data,
assignment,
issued_statements: HashSet::new(),
seconded: None,
@@ -714,23 +796,6 @@ async fn request_signing_context(
Ok(rx)
}
-/// Request `HeadData` for some `ParaId` from `RuntimeApi`.
-async fn request_head_data(
- parent: Hash,
- s: &mut mpsc::Sender,
- id: ParaId,
-) -> Result, Error> {
- let (tx, rx) = oneshot::channel();
-
- s.send(FromJob::RuntimeApiMessage(RuntimeApiMessage::Request(
- parent,
- RuntimeApiRequest::HeadData(id, tx),
- )
- )).await?;
-
- Ok(rx)
-}
-
impl Jobs {
fn new(spawner: S) -> Self {
Self {
@@ -910,8 +975,9 @@ mod tests {
use std::collections::HashMap;
use std::sync::Arc;
use sp_keyring::Sr25519Keyring;
- use polkadot_primitives::parachain::{
+ use polkadot_primitives::v1::{
AssignmentKind, CollatorId, CoreAssignment, BlockData, CoreIndex, GroupIndex, ValidityAttestation,
+ CandidateCommitments, LocalValidationData, GlobalValidationSchedule, HeadData,
};
use assert_matches::assert_matches;
@@ -1006,6 +1072,7 @@ mod tests {
parent_head: HeadData(vec![7, 8, 9]),
balance: Default::default(),
code_upgrade_allowed: None,
+ validation_code_hash: Default::default(),
};
let global_validation_schedule = GlobalValidationSchedule {
@@ -1050,6 +1117,48 @@ mod tests {
executor::block_on(future::select(test_fut, subsystem));
}
+ fn make_erasure_root(test: &TestState, pov: PoV) -> Hash {
+ let omitted_validation = OmittedValidationData {
+ global_validation: test.global_validation_schedule.clone(),
+ local_validation: test.local_validation_data.clone(),
+ };
+
+ let available_data = AvailableData {
+ omitted_validation,
+ pov,
+ };
+
+ let chunks = erasure_coding::obtain_chunks_v1(test.validators.len(), &available_data).unwrap();
+ erasure_coding::branches(&chunks).root()
+ }
+
+ #[derive(Default)]
+ struct TestCandidateBuilder {
+ para_id: ParaId,
+ head_data: HeadData,
+ pov_hash: Hash,
+ relay_parent: Hash,
+ erasure_root: Hash,
+ }
+
+ impl TestCandidateBuilder {
+ fn build(self) -> CommittedCandidateReceipt {
+ CommittedCandidateReceipt {
+ descriptor: CandidateDescriptor {
+ para_id: self.para_id,
+ pov_hash: self.pov_hash,
+ relay_parent: self.relay_parent,
+ ..Default::default()
+ },
+ commitments: CandidateCommitments {
+ head_data: self.head_data,
+ erasure_root: self.erasure_root,
+ ..Default::default()
+ },
+ }
+ }
+ }
+
// Tests that the subsystem performs actions that are requied on startup.
async fn test_startup(
virtual_overseer: &mut subsystem_test::TestSubsystemContextHandle,
@@ -1080,16 +1189,6 @@ mod tests {
}
);
- // Check that subsystem job issues a request for the head data.
- assert_matches!(
- virtual_overseer.recv().await,
- AllMessages::RuntimeApi(
- RuntimeApiMessage::Request(parent, RuntimeApiRequest::HeadData(id, tx))
- ) if parent == test_state.relay_parent => {
- tx.send(test_state.head_data.get(&id).unwrap().clone()).unwrap();
- }
- );
-
// Check that subsystem job issues a request for the signing context.
assert_matches!(
virtual_overseer.recv().await,
@@ -1108,49 +1207,53 @@ mod tests {
let test_state = TestState::default();
test_harness(test_state.keystore.clone(), |test_harness| async move {
let TestHarness { mut virtual_overseer } = test_harness;
-
+
test_startup(&mut virtual_overseer, &test_state).await;
-
- let pov_block = PoVBlock {
+
+ let pov = PoV {
block_data: BlockData(vec![42, 43, 44]),
};
- let pov_block_hash = pov_block.hash();
- let candidate = AbridgedCandidateReceipt {
- parachain_index: test_state.chain_ids[0],
+ let expected_head_data = test_state.head_data.get(&test_state.chain_ids[0]).unwrap();
+
+ let pov_hash = pov.hash();
+ let candidate = TestCandidateBuilder {
+ para_id: test_state.chain_ids[0],
relay_parent: test_state.relay_parent,
- pov_block_hash,
+ pov_hash,
+ head_data: expected_head_data.clone(),
+ erasure_root: make_erasure_root(&test_state, pov.clone()),
..Default::default()
- };
+ }.build();
let second = CandidateBackingMessage::Second(
test_state.relay_parent,
- candidate.clone(),
- pov_block.clone(),
+ candidate.to_plain(),
+ pov.clone(),
);
virtual_overseer.send(FromOverseer::Communication{ msg: second }).await;
- let expected_head_data = test_state.head_data.get(&test_state.chain_ids[0]).unwrap();
assert_matches!(
virtual_overseer.recv().await,
AllMessages::CandidateValidation(
- CandidateValidationMessage::Validate(
- parent_hash,
+ CandidateValidationMessage::ValidateFromChainState(
c,
- head_data,
pov,
tx,
)
- ) if parent_hash == test_state.relay_parent &&
- pov == pov_block && c == candidate => {
- assert_eq!(head_data, *expected_head_data);
- tx.send(Ok((
- ValidationResult::Valid,
- test_state.global_validation_schedule,
- test_state.local_validation_data,
- ))).unwrap();
+ ) if pov == pov && &c == candidate.descriptor() => {
+ tx.send(Ok(
+ ValidationResult::Valid(ValidationOutputs {
+ global_validation_schedule: test_state.global_validation_schedule,
+ local_validation_data: test_state.local_validation_data,
+ head_data: expected_head_data.clone(),
+ upward_messages: Vec::new(),
+ fees: Default::default(),
+ new_validation_code: None,
+ }),
+ )).unwrap();
}
);
@@ -1193,18 +1296,22 @@ mod tests {
test_startup(&mut virtual_overseer, &test_state).await;
- let pov_block = PoVBlock {
+ let pov = PoV {
block_data: BlockData(vec![1, 2, 3]),
};
- let pov_block_hash = pov_block.hash();
+ let pov_hash = pov.hash();
+
+ let expected_head_data = test_state.head_data.get(&test_state.chain_ids[0]).unwrap();
- let candidate_a = AbridgedCandidateReceipt {
- parachain_index: test_state.chain_ids[0],
+ let candidate_a = TestCandidateBuilder {
+ para_id: test_state.chain_ids[0],
relay_parent: test_state.relay_parent,
- pov_block_hash,
+ pov_hash,
+ head_data: expected_head_data.clone(),
+ erasure_root: make_erasure_root(&test_state, pov.clone()),
..Default::default()
- };
+ }.build();
let candidate_a_hash = candidate_a.hash();
@@ -1227,39 +1334,38 @@ mod tests {
virtual_overseer.send(FromOverseer::Communication{ msg: statement }).await;
// Sending a `Statement::Seconded` for our assignment will start
- // validation process. The first thing requested is PoVBlock from the
+ // validation process. The first thing requested is PoV from the
// `PoVDistribution`.
assert_matches!(
virtual_overseer.recv().await,
AllMessages::PoVDistribution(
PoVDistributionMessage::FetchPoV(relay_parent, _, tx)
) if relay_parent == test_state.relay_parent => {
- tx.send(Arc::new(pov_block.clone())).unwrap();
+ tx.send(Arc::new(pov.clone())).unwrap();
}
);
- let expected_head_data = test_state.head_data.get(&test_state.chain_ids[0]).unwrap();
-
// The next step is the actual request to Validation subsystem
// to validate the `Seconded` candidate.
assert_matches!(
virtual_overseer.recv().await,
AllMessages::CandidateValidation(
- CandidateValidationMessage::Validate(
- relay_parent,
- candidate,
- head_data,
+ CandidateValidationMessage::ValidateFromChainState(
+ c,
pov,
tx,
)
- ) if relay_parent == test_state.relay_parent && candidate == candidate_a => {
- assert_eq!(head_data, *expected_head_data);
- assert_eq!(pov, pov_block);
- tx.send(Ok((
- ValidationResult::Valid,
- test_state.global_validation_schedule,
- test_state.local_validation_data,
- ))).unwrap();
+ ) if pov == pov && &c == candidate_a.descriptor() => {
+ tx.send(Ok(
+ ValidationResult::Valid(ValidationOutputs {
+ global_validation_schedule: test_state.global_validation_schedule,
+ local_validation_data: test_state.local_validation_data,
+ head_data: expected_head_data.clone(),
+ upward_messages: Vec::new(),
+ fees: Default::default(),
+ new_validation_code: None,
+ }),
+ )).unwrap();
}
);
@@ -1309,17 +1415,22 @@ mod tests {
test_startup(&mut virtual_overseer, &test_state).await;
- let pov_block = PoVBlock {
+ let pov = PoV {
block_data: BlockData(vec![1, 2, 3]),
};
- let pov_block_hash = pov_block.hash();
- let candidate_a = AbridgedCandidateReceipt {
- parachain_index: test_state.chain_ids[0],
+ let pov_hash = pov.hash();
+
+ let expected_head_data = test_state.head_data.get(&test_state.chain_ids[0]).unwrap();
+
+ let candidate_a = TestCandidateBuilder {
+ para_id: test_state.chain_ids[0],
relay_parent: test_state.relay_parent,
- pov_block_hash,
+ pov_hash,
+ erasure_root: make_erasure_root(&test_state, pov.clone()),
+ head_data: expected_head_data.clone(),
..Default::default()
- };
+ }.build();
let candidate_a_hash = candidate_a.hash();
@@ -1353,33 +1464,41 @@ mod tests {
AllMessages::PoVDistribution(
PoVDistributionMessage::FetchPoV(relay_parent, _, tx)
) if relay_parent == test_state.relay_parent => {
- tx.send(Arc::new(pov_block.clone())).unwrap();
+ tx.send(Arc::new(pov.clone())).unwrap();
}
);
- let expected_head_data = test_state.head_data.get(&test_state.chain_ids[0]).unwrap();
-
assert_matches!(
virtual_overseer.recv().await,
AllMessages::CandidateValidation(
- CandidateValidationMessage::Validate(
- relay_parent,
- candidate,
- head_data,
+ CandidateValidationMessage::ValidateFromChainState(
+ c,
pov,
tx,
)
- ) if relay_parent == test_state.relay_parent && candidate == candidate_a => {
- assert_eq!(pov, pov_block);
- assert_eq!(head_data, *expected_head_data);
- tx.send(Ok((
- ValidationResult::Valid,
- test_state.global_validation_schedule,
- test_state.local_validation_data,
- ))).unwrap();
+ ) if pov == pov && &c == candidate_a.descriptor() => {
+ tx.send(Ok(
+ ValidationResult::Valid(ValidationOutputs {
+ global_validation_schedule: test_state.global_validation_schedule,
+ local_validation_data: test_state.local_validation_data,
+ head_data: expected_head_data.clone(),
+ upward_messages: Vec::new(),
+ fees: Default::default(),
+ new_validation_code: None,
+ }),
+ )).unwrap();
}
);
+ for _ in 0..test_state.validators.len() {
+ assert_matches!(
+ virtual_overseer.recv().await,
+ AllMessages::AvailabilityStore(
+ AvailabilityStoreMessage::StoreChunk(parent_hash, _, _)
+ ) if parent_hash == test_state.relay_parent
+ );
+ }
+
assert_matches!(
virtual_overseer.recv().await,
AllMessages::StatementDistribution(
@@ -1440,86 +1559,68 @@ mod tests {
test_startup(&mut virtual_overseer, &test_state).await;
- let pov_block_a = PoVBlock {
+ let pov_block_a = PoV {
block_data: BlockData(vec![42, 43, 44]),
};
- let pov_block_b = PoVBlock {
+ let pov_block_b = PoV {
block_data: BlockData(vec![45, 46, 47]),
};
- let pov_block_hash_a = pov_block_a.hash();
- let pov_block_hash_b = pov_block_b.hash();
+ let pov_hash_a = pov_block_a.hash();
+ let pov_hash_b = pov_block_b.hash();
+
+ let expected_head_data = test_state.head_data.get(&test_state.chain_ids[0]).unwrap();
- let candidate_a = AbridgedCandidateReceipt {
- parachain_index: test_state.chain_ids[0],
+ let candidate_a = TestCandidateBuilder {
+ para_id: test_state.chain_ids[0],
relay_parent: test_state.relay_parent,
- pov_block_hash: pov_block_hash_a,
+ pov_hash: pov_hash_a,
+ erasure_root: make_erasure_root(&test_state, pov_block_a.clone()),
..Default::default()
- };
-
- let candidate_a_hash = candidate_a.hash();
+ }.build();
- let candidate_b = AbridgedCandidateReceipt {
- parachain_index: test_state.chain_ids[0],
+ let candidate_b = TestCandidateBuilder {
+ para_id: test_state.chain_ids[0],
relay_parent: test_state.relay_parent,
- pov_block_hash: pov_block_hash_b,
+ pov_hash: pov_hash_b,
+ erasure_root: make_erasure_root(&test_state, pov_block_b.clone()),
+ head_data: expected_head_data.clone(),
..Default::default()
- };
+ }.build();
let second = CandidateBackingMessage::Second(
test_state.relay_parent,
- candidate_a.clone(),
+ candidate_a.to_plain(),
pov_block_a.clone(),
);
virtual_overseer.send(FromOverseer::Communication{ msg: second }).await;
- let expected_head_data = test_state.head_data.get(&test_state.chain_ids[0]).unwrap();
assert_matches!(
virtual_overseer.recv().await,
AllMessages::CandidateValidation(
- CandidateValidationMessage::Validate(
- parent_hash,
+ CandidateValidationMessage::ValidateFromChainState(
c,
- head_data,
pov,
tx,
)
- ) if parent_hash == test_state.relay_parent &&
- pov == pov_block_a && c == candidate_a => {
- assert_eq!(head_data, *expected_head_data);
- tx.send(Ok((
- ValidationResult::Invalid,
- test_state.global_validation_schedule.clone(),
- test_state.local_validation_data.clone(),
- ))).unwrap();
+ ) if pov == pov && &c == candidate_a.descriptor() => {
+ tx.send(Ok(ValidationResult::Invalid)).unwrap();
}
);
assert_matches!(
virtual_overseer.recv().await,
AllMessages::CandidateSelection(
- CandidateSelectionMessage::Invalid(parent_hash, candidate)
- ) if parent_hash == test_state.relay_parent && candidate == candidate_a
- );
-
- assert_matches!(
- virtual_overseer.recv().await,
- AllMessages::StatementDistribution(
- StatementDistributionMessage::Share(
- relay_parent,
- statement,
- )
- ) if relay_parent == test_state.relay_parent => {
- assert_eq!(*statement.payload(), Statement::Invalid(candidate_a_hash));
- }
+ CandidateSelectionMessage::Invalid(parent_hash, c)
+ ) if parent_hash == test_state.relay_parent && c == candidate_a.to_plain()
);
let second = CandidateBackingMessage::Second(
test_state.relay_parent,
- candidate_b.clone(),
+ candidate_b.to_plain(),
pov_block_b.clone(),
);
@@ -1530,21 +1631,22 @@ mod tests {
assert_matches!(
virtual_overseer.recv().await,
AllMessages::CandidateValidation(
- CandidateValidationMessage::Validate(
- parent_hash,
+ CandidateValidationMessage::ValidateFromChainState(
c,
- head_data,
pov,
tx,
)
- ) if parent_hash == test_state.relay_parent &&
- pov == pov_block_b && c == candidate_b => {
- assert_eq!(head_data, *expected_head_data);
- tx.send(Ok((
- ValidationResult::Valid,
- test_state.global_validation_schedule,
- test_state.local_validation_data,
- ))).unwrap();
+ ) if pov == pov && &c == candidate_b.descriptor() => {
+ tx.send(Ok(
+ ValidationResult::Valid(ValidationOutputs {
+ global_validation_schedule: test_state.global_validation_schedule,
+ local_validation_data: test_state.local_validation_data,
+ head_data: expected_head_data.clone(),
+ upward_messages: Vec::new(),
+ fees: Default::default(),
+ new_validation_code: None,
+ }),
+ )).unwrap();
}
);
@@ -1590,18 +1692,19 @@ mod tests {
test_startup(&mut virtual_overseer, &test_state).await;
- let pov_block = PoVBlock {
+ let pov = PoV {
block_data: BlockData(vec![42, 43, 44]),
};
- let pov_block_hash = pov_block.hash();
+ let pov_hash = pov.hash();
- let candidate = AbridgedCandidateReceipt {
- parachain_index: test_state.chain_ids[0],
+ let candidate = TestCandidateBuilder {
+ para_id: test_state.chain_ids[0],
relay_parent: test_state.relay_parent,
- pov_block_hash,
+ pov_hash,
+ erasure_root: make_erasure_root(&test_state, pov.clone()),
..Default::default()
- };
+ }.build();
let candidate_hash = candidate.hash();
@@ -1627,33 +1730,22 @@ mod tests {
PoVDistributionMessage::FetchPoV(relay_parent, _, tx)
) => {
assert_eq!(relay_parent, test_state.relay_parent);
- tx.send(Arc::new(pov_block.clone())).unwrap();
+ tx.send(Arc::new(pov.clone())).unwrap();
}
);
- let expected_head_data = test_state.head_data.get(&test_state.chain_ids[0]).unwrap();
// Tell subsystem that this candidate is invalid.
assert_matches!(
virtual_overseer.recv().await,
AllMessages::CandidateValidation(
- CandidateValidationMessage::Validate(
- relay_parent,
- candidate_recvd,
- head_data,
+ CandidateValidationMessage::ValidateFromChainState(
+ c,
pov,
tx,
)
- ) => {
- assert_eq!(relay_parent, test_state.relay_parent);
- assert_eq!(candidate_recvd, candidate);
- assert_eq!(head_data, *expected_head_data);
- assert_eq!(pov, pov_block);
- tx.send(Ok((
- ValidationResult::Invalid,
- test_state.global_validation_schedule,
- test_state.local_validation_data,
- ))).unwrap();
+ ) if pov == pov && &c == candidate.descriptor() => {
+ tx.send(Ok(ValidationResult::Invalid)).unwrap();
}
);
@@ -1679,28 +1771,29 @@ mod tests {
// This should emit no actions from subsystem.
let second = CandidateBackingMessage::Second(
test_state.relay_parent,
- candidate.clone(),
- pov_block.clone(),
+ candidate.to_plain(),
+ pov.clone(),
);
virtual_overseer.send(FromOverseer::Communication{ msg: second }).await;
- let pov_to_second = PoVBlock {
+ let pov_to_second = PoV {
block_data: BlockData(vec![3, 2, 1]),
};
- let pov_block_hash = pov_to_second.hash();
+ let pov_hash = pov_to_second.hash();
- let candidate_to_second = AbridgedCandidateReceipt {
- parachain_index: test_state.chain_ids[0],
+ let candidate_to_second = TestCandidateBuilder {
+ para_id: test_state.chain_ids[0],
relay_parent: test_state.relay_parent,
- pov_block_hash,
+ pov_hash,
+ erasure_root: make_erasure_root(&test_state, pov_to_second.clone()),
..Default::default()
- };
+ }.build();
let second = CandidateBackingMessage::Second(
test_state.relay_parent,
- candidate_to_second.clone(),
+ candidate_to_second.to_plain(),
pov_to_second.clone(),
);
@@ -1712,16 +1805,13 @@ mod tests {
assert_matches!(
virtual_overseer.recv().await,
AllMessages::CandidateValidation(
- CandidateValidationMessage::Validate(
- relay_parent,
- _,
+ CandidateValidationMessage::ValidateFromChainState(
_,
pov,
_,
)
) => {
- assert_eq!(relay_parent, test_state.relay_parent);
- assert_eq!(pov, pov_to_second);
+ assert_eq!(&*pov, &pov_to_second);
}
);
});
diff --git a/node/core/proposer/src/lib.rs b/node/core/proposer/src/lib.rs
index b53ac5729fa9..d43810227ba4 100644
--- a/node/core/proposer/src/lib.rs
+++ b/node/core/proposer/src/lib.rs
@@ -2,9 +2,7 @@ use futures::prelude::*;
use futures::select;
use polkadot_node_subsystem::{messages::{AllMessages, ProvisionerInherentData, ProvisionerMessage}, SubsystemError};
use polkadot_overseer::OverseerHandler;
-use polkadot_primitives::{
- inclusion_inherent,
- parachain::ParachainHost,
+use polkadot_primitives::v1::{
Block, Hash, Header,
};
use sc_block_builder::{BlockBuilderApi, BlockBuilderProvider};
@@ -53,7 +51,7 @@ where
+ Send
+ Sync,
Client::Api:
- ParachainHost + BlockBuilderApi + ApiExt,
+ BlockBuilderApi + ApiExt,
Backend:
'static + sc_client_api::Backend>,
// Rust bug: https://github.com/rust-lang/rust/issues/24159
@@ -104,7 +102,7 @@ where
+ Send
+ Sync,
Client::Api:
- ParachainHost + BlockBuilderApi + ApiExt,
+ BlockBuilderApi + ApiExt,
Backend:
'static + sc_client_api::Backend>,
// Rust bug: https://github.com/rust-lang/rust/issues/24159
@@ -155,7 +153,7 @@ where
+ Send
+ Sync,
Client::Api:
- ParachainHost + BlockBuilderApi + ApiExt,
+ BlockBuilderApi + ApiExt,
Backend:
'static + sc_client_api::Backend>,
// Rust bug: https://github.com/rust-lang/rust/issues/24159
@@ -186,7 +184,7 @@ where
};
inherent_data.put_data(
- inclusion_inherent::INHERENT_IDENTIFIER,
+ polkadot_primitives::v1::INCLUSION_INHERENT_IDENTIFIER,
&provisioner_data,
)?;
diff --git a/node/network/bridge/src/lib.rs b/node/network/bridge/src/lib.rs
index 6f90779afe62..46b9dbd84024 100644
--- a/node/network/bridge/src/lib.rs
+++ b/node/network/bridge/src/lib.rs
@@ -33,7 +33,7 @@ use polkadot_subsystem::{
};
use polkadot_subsystem::messages::{NetworkBridgeEvent, NetworkBridgeMessage, AllMessages};
use node_primitives::{ProtocolId, View};
-use polkadot_primitives::{Block, Hash};
+use polkadot_primitives::v1::{Block, Hash};
use std::collections::btree_map::{BTreeMap, Entry as BEntry};
use std::collections::hash_map::{HashMap, Entry as HEntry};
diff --git a/node/network/pov-distribution/src/lib.rs b/node/network/pov-distribution/src/lib.rs
index 589e33fde0d6..84d6e803d2c7 100644
--- a/node/network/pov-distribution/src/lib.rs
+++ b/node/network/pov-distribution/src/lib.rs
@@ -19,8 +19,7 @@
//! This is a gossip implementation of code that is responsible for distributing PoVs
//! among validators.
-use polkadot_primitives::Hash;
-use polkadot_primitives::parachain::{PoVBlock as PoV, CandidateDescriptor};
+use polkadot_primitives::v1::{Hash, PoV, CandidateDescriptor};
use polkadot_subsystem::{
OverseerSignal, SubsystemContext, Subsystem, SubsystemResult, FromOverseer, SpawnedSubsystem,
};
@@ -550,7 +549,7 @@ async fn run(
mod tests {
use super::*;
use futures::executor::{self, ThreadPool};
- use polkadot_primitives::parachain::BlockData;
+ use polkadot_primitives::v1::BlockData;
use assert_matches::assert_matches;
fn make_pov(data: Vec) -> PoV {
diff --git a/node/network/statement-distribution/src/lib.rs b/node/network/statement-distribution/src/lib.rs
index f3d2653266f7..cef499eae98b 100644
--- a/node/network/statement-distribution/src/lib.rs
+++ b/node/network/statement-distribution/src/lib.rs
@@ -29,9 +29,8 @@ use polkadot_subsystem::messages::{
RuntimeApiRequest,
};
use node_primitives::{ProtocolId, View, SignedFullStatement};
-use polkadot_primitives::Hash;
-use polkadot_primitives::parachain::{
- CompactStatement, ValidatorIndex, ValidatorId, SigningContext, ValidatorSignature,
+use polkadot_primitives::v1::{
+ Hash, CompactStatement, ValidatorIndex, ValidatorId, SigningContext, ValidatorSignature,
};
use parity_scale_codec::{Encode, Decode};
@@ -891,7 +890,7 @@ mod tests {
use super::*;
use sp_keyring::Sr25519Keyring;
use node_primitives::Statement;
- use polkadot_primitives::parachain::{AbridgedCandidateReceipt};
+ use polkadot_primitives::v1::CommittedCandidateReceipt;
use assert_matches::assert_matches;
use futures::executor::{self, ThreadPool};
@@ -911,23 +910,23 @@ mod tests {
};
let candidate_a = {
- let mut c = AbridgedCandidateReceipt::default();
- c.relay_parent = parent_hash;
- c.parachain_index = 1.into();
+ let mut c = CommittedCandidateReceipt::default();
+ c.descriptor.relay_parent = parent_hash;
+ c.descriptor.para_id = 1.into();
c
};
let candidate_b = {
- let mut c = AbridgedCandidateReceipt::default();
- c.relay_parent = parent_hash;
- c.parachain_index = 2.into();
+ let mut c = CommittedCandidateReceipt::default();
+ c.descriptor.relay_parent = parent_hash;
+ c.descriptor.para_id = 2.into();
c
};
let candidate_c = {
- let mut c = AbridgedCandidateReceipt::default();
- c.relay_parent = parent_hash;
- c.parachain_index = 3.into();
+ let mut c = CommittedCandidateReceipt::default();
+ c.descriptor.relay_parent = parent_hash;
+ c.descriptor.para_id = 3.into();
c
};
@@ -1140,9 +1139,9 @@ mod tests {
let hash_c = [3; 32].into();
let candidate = {
- let mut c = AbridgedCandidateReceipt::default();
- c.relay_parent = hash_c;
- c.parachain_index = 1.into();
+ let mut c = CommittedCandidateReceipt::default();
+ c.descriptor.relay_parent = hash_c;
+ c.descriptor.para_id = 1.into();
c
};
let candidate_hash = candidate.hash();
@@ -1275,9 +1274,9 @@ mod tests {
let hash_c = [3; 32].into();
let candidate = {
- let mut c = AbridgedCandidateReceipt::default();
- c.relay_parent = hash_b;
- c.parachain_index = 1.into();
+ let mut c = CommittedCandidateReceipt::default();
+ c.descriptor.relay_parent = hash_b;
+ c.descriptor.para_id = 1.into();
c
};
diff --git a/node/overseer/examples/minimal-example.rs b/node/overseer/examples/minimal-example.rs
index 21e8eb3ab8fa..d5f7f043ff43 100644
--- a/node/overseer/examples/minimal-example.rs
+++ b/node/overseer/examples/minimal-example.rs
@@ -27,11 +27,11 @@ use futures::{
use futures_timer::Delay;
use kv_log_macro as log;
-use polkadot_primitives::parachain::{BlockData, PoVBlock};
+use polkadot_primitives::v1::{BlockData, PoV};
use polkadot_overseer::{Overseer, AllSubsystems};
use polkadot_subsystem::{
- Subsystem, SubsystemContext, DummySubsystem,
+ Subsystem, SubsystemContext, DummySubsystem,
SpawnedSubsystem, FromOverseer,
};
use polkadot_subsystem::messages::{
@@ -61,13 +61,11 @@ impl Subsystem1 {
let (tx, _) = oneshot::channel();
ctx.send_message(AllMessages::CandidateValidation(
- CandidateValidationMessage::Validate(
+ CandidateValidationMessage::ValidateFromChainState(
Default::default(),
- Default::default(),
- Default::default(),
- PoVBlock {
+ PoV {
block_data: BlockData(Vec::new()),
- },
+ }.into(),
tx,
)
)).await.unwrap();
diff --git a/node/overseer/src/lib.rs b/node/overseer/src/lib.rs
index 458aae91e871..91fceb0d3bb0 100644
--- a/node/overseer/src/lib.rs
+++ b/node/overseer/src/lib.rs
@@ -72,7 +72,7 @@ use futures::{
use futures_timer::Delay;
use streamunordered::{StreamYield, StreamUnordered};
-use polkadot_primitives::{Block, BlockNumber, Hash};
+use polkadot_primitives::v1::{Block, BlockNumber, Hash};
use client::{BlockImportNotification, BlockchainEvents, FinalityNotification};
use polkadot_subsystem::messages::{
@@ -932,7 +932,7 @@ fn spawn(
mod tests {
use futures::{executor, pin_mut, select, channel::mpsc, FutureExt};
- use polkadot_primitives::parachain::{BlockData, PoVBlock};
+ use polkadot_primitives::v1::{BlockData, PoV};
use polkadot_subsystem::DummySubsystem;
use super::*;
@@ -977,13 +977,11 @@ mod tests {
let (tx, _) = oneshot::channel();
ctx.send_message(
AllMessages::CandidateValidation(
- CandidateValidationMessage::Validate(
+ CandidateValidationMessage::ValidateFromChainState(
Default::default(),
- Default::default(),
- Default::default(),
- PoVBlock {
+ PoV {
block_data: BlockData(Vec::new()),
- },
+ }.into(),
tx,
)
)
diff --git a/node/primitives/src/lib.rs b/node/primitives/src/lib.rs
index 25313c09154e..f29be5737450 100644
--- a/node/primitives/src/lib.rs
+++ b/node/primitives/src/lib.rs
@@ -21,26 +21,31 @@
//! there.
use parity_scale_codec::{Decode, Encode};
-use polkadot_primitives::{Hash,
- parachain::{
- AbridgedCandidateReceipt, CompactStatement,
- EncodeAs, Signed, SigningContext, ValidatorIndex, ValidatorId,
- }
+use polkadot_primitives::v1::{
+ Hash, CommittedCandidateReceipt, CandidateReceipt, CompactStatement,
+ EncodeAs, Signed, SigningContext, ValidatorIndex, ValidatorId,
+ UpwardMessage, Balance, ValidationCode, GlobalValidationSchedule, LocalValidationData,
+ HeadData,
};
use polkadot_statement_table::{
generic::{
ValidityDoubleVote as TableValidityDoubleVote,
MultipleCandidates as TableMultipleCandidates,
},
- Misbehavior as TableMisbehavior,
+ v1::Misbehavior as TableMisbehavior,
};
/// A statement, where the candidate receipt is included in the `Seconded` variant.
+///
+/// This is the committed candidate receipt instead of the bare candidate receipt. As such,
+/// it gives access to the commitments to validators who have not executed the candidate. This
+/// is necessary to allow a block-producing validator to include candidates from outside of the para
+/// it is assigned to.
#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode)]
pub enum Statement {
/// A statement that a validator seconds a candidate.
#[codec(index = "1")]
- Seconded(AbridgedCandidateReceipt),
+ Seconded(CommittedCandidateReceipt),
/// A statement that a validator has deemed a candidate valid.
#[codec(index = "2")]
Valid(Hash),
@@ -50,6 +55,8 @@ pub enum Statement {
}
impl Statement {
+ /// Transform this statement into its compact version, which references only the hash
+ /// of the candidate.
pub fn to_compact(&self) -> CompactStatement {
match *self {
Statement::Seconded(ref c) => CompactStatement::Candidate(c.hash()),
@@ -84,9 +91,9 @@ pub enum MisbehaviorReport {
/// this message should be dispatched with all of them, in arbitrary order.
///
/// This variant is also used when our own validity checks disagree with others'.
- CandidateValidityDisagreement(AbridgedCandidateReceipt, Vec),
+ CandidateValidityDisagreement(CandidateReceipt, Vec),
/// I've noticed a peer contradicting itself about a particular candidate
- SelfContradiction(AbridgedCandidateReceipt, SignedFullStatement, SignedFullStatement),
+ SelfContradiction(CandidateReceipt, SignedFullStatement, SignedFullStatement),
/// This peer has seconded more than one parachain candidate for this relay parent head
DoubleVote(SignedFullStatement, SignedFullStatement),
}
@@ -103,11 +110,28 @@ pub struct FromTableMisbehavior {
pub key: ValidatorId,
}
+/// Outputs of validating a candidate.
+#[derive(Debug)]
+pub struct ValidationOutputs {
+ /// The head-data produced by validation.
+ pub head_data: HeadData,
+ /// The global validation schedule.
+ pub global_validation_schedule: GlobalValidationSchedule,
+ /// The local validation data.
+ pub local_validation_data: LocalValidationData,
+ /// Upward messages to the relay chain.
+ pub upward_messages: Vec,
+ /// Fees paid to the validators of the relay-chain.
+ pub fees: Balance,
+ /// The new validation code submitted by the execution, if any.
+ pub new_validation_code: Option,
+}
+
/// Result of the validation of the candidate.
#[derive(Debug)]
pub enum ValidationResult {
- /// Candidate is valid.
- Valid,
+ /// Candidate is valid. The validation process yields these outputs.
+ Valid(ValidationOutputs),
/// Candidate is invalid.
Invalid,
}
@@ -136,7 +160,7 @@ impl std::convert::TryFrom for MisbehaviorReport {
&f.key,
).ok_or(())?;
- Ok(MisbehaviorReport::SelfContradiction(receipt, signed_1, signed_2))
+ Ok(MisbehaviorReport::SelfContradiction(receipt.to_plain(), signed_1, signed_2))
}
TableMisbehavior::ValidityDoubleVote(
TableValidityDoubleVote::IssuedAndInvalidity((c, s1), (d, s2))
@@ -157,7 +181,7 @@ impl std::convert::TryFrom for MisbehaviorReport {
&f.key,
).ok_or(())?;
- Ok(MisbehaviorReport::SelfContradiction(receipt, signed_1, signed_2))
+ Ok(MisbehaviorReport::SelfContradiction(receipt.to_plain(), signed_1, signed_2))
}
TableMisbehavior::ValidityDoubleVote(
TableValidityDoubleVote::ValidityAndInvalidity(c, s1, s2)
@@ -177,7 +201,7 @@ impl std::convert::TryFrom for MisbehaviorReport {
&f.key,
).ok_or(())?;
- Ok(MisbehaviorReport::SelfContradiction(c, signed_1, signed_2))
+ Ok(MisbehaviorReport::SelfContradiction(c.to_plain(), signed_1, signed_2))
}
TableMisbehavior::MultipleCandidates(
TableMultipleCandidates {
diff --git a/node/service/src/chain_spec.rs b/node/service/src/chain_spec.rs
index 0659d0808301..db9d9c5dded9 100644
--- a/node/service/src/chain_spec.rs
+++ b/node/service/src/chain_spec.rs
@@ -17,7 +17,7 @@
//! Polkadot chain configurations.
use sp_core::{Pair, Public, crypto::UncheckedInto, sr25519};
-use polkadot_primitives::{AccountId, AccountPublic, parachain::ValidatorId};
+use polkadot_primitives::v1::{AccountId, AccountPublic, ValidatorId};
use polkadot_runtime as polkadot;
use kusama_runtime as kusama;
use westend_runtime as westend;
@@ -48,9 +48,9 @@ const DEFAULT_PROTOCOL_ID: &str = "dot";
#[serde(rename_all = "camelCase")]
pub struct Extensions {
/// Block numbers with known hashes.
- pub fork_blocks: sc_client_api::ForkBlocks,
+ pub fork_blocks: sc_client_api::ForkBlocks,
/// Known bad block hashes.
- pub bad_blocks: sc_client_api::BadBlocks,
+ pub bad_blocks: sc_client_api::BadBlocks,
}
/// The `ChainSpec parametrised for polkadot runtime`.
diff --git a/node/service/src/grandpa_support.rs b/node/service/src/grandpa_support.rs
index 806a189d9fe5..2a9b73b0868e 100644
--- a/node/service/src/grandpa_support.rs
+++ b/node/service/src/grandpa_support.rs
@@ -16,7 +16,7 @@
//! Polkadot-specific GRANDPA integration utilities.
-use polkadot_primitives::Hash;
+use polkadot_primitives::v1::Hash;
use sp_runtime::traits::{Block as BlockT, NumberFor};
/// A custom GRANDPA voting rule that "pauses" voting (i.e. keeps voting for the
@@ -98,7 +98,7 @@ impl grandpa::VotingRule for PauseAfterBlockFor Vec<(
grandpa_primitives::SetId,
- (Hash, polkadot_primitives::BlockNumber),
+ (Hash, polkadot_primitives::v1::BlockNumber),
grandpa_primitives::AuthorityList,
)> {
use sp_core::crypto::Ss58Codec;
diff --git a/node/service/src/lib.rs b/node/service/src/lib.rs
index 8a435e6b595b..1205d9f3ef19 100644
--- a/node/service/src/lib.rs
+++ b/node/service/src/lib.rs
@@ -22,7 +22,7 @@ mod client;
use std::sync::Arc;
use std::time::Duration;
-use polkadot_primitives::{parachain, AccountId, Nonce, Balance};
+use polkadot_primitives::v1::{AccountId, Nonce, Balance};
#[cfg(feature = "full-node")]
use service::{error::Error as ServiceError, ServiceBuilder};
use grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider};
@@ -45,8 +45,7 @@ pub use sc_consensus::LongestChain;
pub use sp_api::{ApiRef, Core as CoreApi, ConstructRuntimeApi, ProvideRuntimeApi, StateBackend};
pub use sp_runtime::traits::{DigestFor, HashFor, NumberFor};
pub use consensus_common::{Proposal, SelectChain, BlockImport, RecordProof, block_validation::Chain};
-pub use polkadot_primitives::parachain::{CollatorId, ParachainHost};
-pub use polkadot_primitives::{Block, BlockId};
+pub use polkadot_primitives::v1::{Block, BlockId, CollatorId, Id as ParaId};
pub use sp_runtime::traits::{Block as BlockT, self as runtime_traits, BlakeTwo256};
pub use chain_spec::{PolkadotChainSpec, KusamaChainSpec, WestendChainSpec};
#[cfg(feature = "full-node")]
@@ -84,7 +83,6 @@ pub trait RuntimeApiCollection:
+ sp_api::ApiExt
+ babe_primitives::BabeApi
+ grandpa_primitives::GrandpaApi
- + ParachainHost
+ sp_block_builder::BlockBuilder
+ system_rpc_runtime_api::AccountNonceApi
+ pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi
@@ -104,7 +102,6 @@ where
+ sp_api::ApiExt
+ babe_primitives::BabeApi
+ grandpa_primitives::GrandpaApi
- + ParachainHost
+ sp_block_builder::BlockBuilder
+ system_rpc_runtime_api::AccountNonceApi
+ pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi
@@ -578,7 +575,7 @@ macro_rules! new_light {
/// Builds a new object suitable for chain operations.
pub fn new_chain_ops(mut config: Configuration) -> Result<
(
- Arc>,
+ Arc>,
Arc>,
consensus_common::import_queue::BasicQueue>,
TaskManager,
@@ -601,7 +598,7 @@ where
#[cfg(feature = "full-node")]
pub fn polkadot_new_full(
mut config: Configuration,
- collating_for: Option<(CollatorId, parachain::Id)>,
+ collating_for: Option<(CollatorId, ParaId)>,
_max_block_data_size: Option,
_authority_discovery_enabled: bool,
_slot_duration: u64,
@@ -633,7 +630,7 @@ pub fn polkadot_new_full(
#[cfg(feature = "full-node")]
pub fn kusama_new_full(
mut config: Configuration,
- collating_for: Option<(CollatorId, parachain::Id)>,
+ collating_for: Option<(CollatorId, ParaId)>,
_max_block_data_size: Option,
_authority_discovery_enabled: bool,
_slot_duration: u64,
@@ -665,7 +662,7 @@ pub fn kusama_new_full(
#[cfg(feature = "full-node")]
pub fn westend_new_full(
mut config: Configuration,
- collating_for: Option<(CollatorId, parachain::Id)>,
+ collating_for: Option<(CollatorId, ParaId)>,
_max_block_data_size: Option,
_authority_discovery_enabled: bool,
_slot_duration: u64,
diff --git a/node/subsystem/src/lib.rs b/node/subsystem/src/lib.rs
index db9a0629cfd4..e374eb9cfcdd 100644
--- a/node/subsystem/src/lib.rs
+++ b/node/subsystem/src/lib.rs
@@ -26,7 +26,7 @@ use futures::prelude::*;
use futures::channel::{mpsc, oneshot};
use futures::future::BoxFuture;
-use polkadot_primitives::Hash;
+use polkadot_primitives::v1::Hash;
use async_trait::async_trait;
use crate::messages::AllMessages;
diff --git a/node/subsystem/src/messages.rs b/node/subsystem/src/messages.rs
index 36c293e49fe9..10c861f1410c 100644
--- a/node/subsystem/src/messages.rs
+++ b/node/subsystem/src/messages.rs
@@ -24,12 +24,12 @@
use futures::channel::{mpsc, oneshot};
-use polkadot_primitives::{BlockNumber, Hash, Signature};
-use polkadot_primitives::parachain::{
- AbridgedCandidateReceipt, PoVBlock, ErasureChunk, BackedCandidate, Id as ParaId,
+use polkadot_primitives::v1::{
+ BlockNumber, Hash,
+ CandidateReceipt, PoV, ErasureChunk, BackedCandidate, Id as ParaId,
SignedAvailabilityBitfield, SigningContext, ValidatorId, ValidationCode, ValidatorIndex,
- CoreAssignment, CoreOccupied, HeadData, CandidateDescriptor, GlobalValidationSchedule,
- LocalValidationData,
+ CoreAssignment, CoreOccupied, HeadData, CandidateDescriptor,
+ ValidatorSignature, OmittedValidationData,
};
use polkadot_node_primitives::{
MisbehaviorReport, SignedFullStatement, View, ProtocolId, ValidationResult,
@@ -48,7 +48,7 @@ pub struct NewBackedCandidate(pub BackedCandidate);
pub enum CandidateSelectionMessage {
/// We recommended a particular candidate to be seconded, but it was invalid; penalize the collator.
/// The hash is the relay parent.
- Invalid(Hash, AbridgedCandidateReceipt),
+ Invalid(Hash, CandidateReceipt),
}
/// Messages received by the Candidate Backing subsystem.
@@ -59,7 +59,7 @@ pub enum CandidateBackingMessage {
GetBackedCandidates(Hash, oneshot::Sender>),
/// Note that the Candidate Backing subsystem should second the given candidate in the context of the
/// given relay-parent (ref. by hash). This candidate must be validated.
- Second(Hash, AbridgedCandidateReceipt, PoVBlock),
+ Second(Hash, CandidateReceipt, PoV),
/// Note a validator's statement about a particular candidate. Disagreements about validity must be escalated
/// to a broader check by Misbehavior Arbitration. Agreements are simply tallied until a quorum is reached.
Statement(Hash, SignedFullStatement),
@@ -69,22 +69,36 @@ pub enum CandidateBackingMessage {
#[derive(Debug)]
pub struct ValidationFailed;
-/// Messages received by the Validation subsystem
+/// Messages received by the Validation subsystem.
+///
+/// ## Validation Requests
+///
+/// Validation requests made to the subsystem should return an error only on internal error.
+/// Otherwise, they should return either `Ok(ValidationResult::Valid(_))`
+/// or `Ok(ValidationResult::Invalid)`.
#[derive(Debug)]
pub enum CandidateValidationMessage {
- /// Validate a candidate, sending a side-channel response of valid or invalid.
+ /// Validate a candidate with provided parameters using relay-chain state.
+ ///
+ /// This will implicitly attempt to gather the `OmittedValidationData` and `ValidationCode`
+ /// from the runtime API of the chain, based on the `relay_parent`
+ /// of the `CandidateDescriptor`.
+ /// If there is no state available which can provide this data, an error is returned.
+ ValidateFromChainState(
+ CandidateDescriptor,
+ Arc,
+ oneshot::Sender>,
+ ),
+ /// Validate a candidate with provided, exhaustive parameters for validation.
///
- /// Provide the relay-parent in whose context this should be validated, the full candidate receipt,
- /// and the PoV.
- Validate(
- Hash,
- AbridgedCandidateReceipt,
- HeadData,
- PoVBlock,
- oneshot::Sender>,
+ /// Explicitly provide the `OmittedValidationData` and `ValidationCode` so this can do full
+ /// validation without needing to access the state of the relay-chain.
+ ValidateFromExhaustive(
+ OmittedValidationData,
+ ValidationCode,
+ CandidateDescriptor,
+ Arc,
+ oneshot::Sender>,
),
}
@@ -146,8 +160,8 @@ pub enum BitfieldDistributionMessage {
/// Availability store subsystem message.
#[derive(Debug)]
pub enum AvailabilityStoreMessage {
- /// Query a `PoVBlock` from the AV store.
- QueryPoV(Hash, oneshot::Sender>),
+ /// Query a `PoV` from the AV store.
+ QueryPoV(Hash, oneshot::Sender >),
/// Query an `ErasureChunk` from the AV store.
QueryChunk(Hash, ValidatorIndex, oneshot::Sender),
@@ -213,7 +227,7 @@ pub enum ProvisionableData {
/// Misbehavior reports are self-contained proofs of validator misbehavior.
MisbehaviorReport(Hash, MisbehaviorReport),
/// Disputes trigger a broad dispute resolution process.
- Dispute(Hash, Signature),
+ Dispute(Hash, ValidatorSignature),
}
/// This data needs to make its way from the provisioner into the InherentData.
@@ -246,10 +260,10 @@ pub enum PoVDistributionMessage {
///
/// This `CandidateDescriptor` should correspond to a candidate seconded under the provided
/// relay-parent hash.
- FetchPoV(Hash, CandidateDescriptor, oneshot::Sender>),
+ FetchPoV(Hash, CandidateDescriptor, oneshot::Sender>),
/// Distribute a PoV for the given relay-parent and CandidateDescriptor.
/// The PoV should correctly hash to the PoV hash mentioned in the CandidateDescriptor
- DistributePoV(Hash, CandidateDescriptor, Arc),
+ DistributePoV(Hash, CandidateDescriptor, Arc),
/// An update from the network bridge.
NetworkBridgeUpdate(NetworkBridgeEvent),
}
diff --git a/node/test-service/src/chain_spec.rs b/node/test-service/src/chain_spec.rs
index cbb08c470f07..e81050afdbbe 100644
--- a/node/test-service/src/chain_spec.rs
+++ b/node/test-service/src/chain_spec.rs
@@ -17,7 +17,7 @@
use babe_primitives::AuthorityId as BabeId;
use grandpa::AuthorityId as GrandpaId;
use pallet_staking::Forcing;
-use polkadot_primitives::{parachain::ValidatorId, AccountId};
+use polkadot_primitives::v0::{ValidatorId, AccountId};
use polkadot_service::chain_spec::{get_account_id_from_seed, get_from_seed, Extensions};
use polkadot_test_runtime::constants::currency::DOTS;
use sc_chain_spec::{ChainSpec, ChainType};
diff --git a/node/test-service/src/lib.rs b/node/test-service/src/lib.rs
index 7fc75d9f3719..751373265fc3 100644
--- a/node/test-service/src/lib.rs
+++ b/node/test-service/src/lib.rs
@@ -26,9 +26,8 @@ use futures::future::Future;
use grandpa::FinalityProofProvider as GrandpaFinalityProofProvider;
use log::info;
use polkadot_network::{legacy::gossip::Known, protocol as network_protocol};
-use polkadot_primitives::{
- parachain::{self, CollatorId},
- Block, BlockId, Hash,
+use polkadot_primitives::v0::{
+ Block, BlockId, Hash, CollatorId, Id as ParaId,
};
use polkadot_runtime_common::{parachains, registrar, BlockHashCount};
use polkadot_service::{
@@ -68,7 +67,7 @@ native_executor_instance!(
/// Create a new Polkadot test service for a full node.
pub fn polkadot_test_new_full(
config: Configuration,
- collating_for: Option<(CollatorId, parachain::Id)>,
+ collating_for: Option<(CollatorId, ParaId)>,
max_block_data_size: Option,
authority_discovery_enabled: bool,
slot_duration: u64,
@@ -287,7 +286,7 @@ where
let extrinsic = polkadot_test_runtime::UncheckedExtrinsic::new_signed(
function.clone(),
polkadot_test_runtime::Address::Id(caller.public().into()),
- polkadot_primitives::Signature::Sr25519(signature.clone()),
+ polkadot_primitives::v0::Signature::Sr25519(signature.clone()),
extra.clone(),
);
diff --git a/parachain/test-parachains/adder/collator/src/main.rs b/parachain/test-parachains/adder/collator/src/main.rs
index 42c3c824004a..ec5b626883c1 100644
--- a/parachain/test-parachains/adder/collator/src/main.rs
+++ b/parachain/test-parachains/adder/collator/src/main.rs
@@ -22,9 +22,9 @@ use std::sync::Arc;
use adder::{HeadData as AdderHead, BlockData as AdderBody};
use sp_core::Pair;
use codec::{Encode, Decode};
-use primitives::{
+use primitives::v0::{
Hash, DownwardMessage,
- parachain::{HeadData, BlockData, Id as ParaId, LocalValidationData, GlobalValidationSchedule},
+ HeadData, BlockData, Id as ParaId, LocalValidationData, GlobalValidationSchedule,
};
use collator::{ParachainContext, Network, BuildParachainContext, Cli, SubstrateCli};
use parking_lot::Mutex;
diff --git a/primitives/src/inclusion_inherent.rs b/primitives/src/inclusion_inherent.rs
deleted file mode 100644
index ca3f5ec23a16..000000000000
--- a/primitives/src/inclusion_inherent.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2017-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 .
-
-//! Inclusion Inherent primitives define types and constants which can be imported
-//! without needing to import the entire inherent module.
-
-use inherents::InherentIdentifier;
-
-/// Unique identifier for the Inclusion Inherent
-pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"inclusn0";
diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs
index 6f0a0986c933..82a5e7ca2e03 100644
--- a/primitives/src/lib.rs
+++ b/primitives/src/lib.rs
@@ -20,58 +20,5 @@
#![cfg_attr(not(feature = "std"), no_std)]
-pub use runtime_primitives::traits::{BlakeTwo256, Hash as HashT, Verify, IdentifyAccount};
-pub use polkadot_core_primitives::*;
-
-pub mod inclusion_inherent;
-pub mod parachain;
-
-pub use parity_scale_codec::Compact;
-
-/// Custom validity errors used in Polkadot while validating transactions.
-#[repr(u8)]
-pub enum ValidityError {
- /// The Ethereum signature is invalid.
- InvalidEthereumSignature = 0,
- /// The signer has no claim.
- SignerHasNoClaim = 1,
- /// No permission to execute the call.
- NoPermission = 2,
- /// An invalid statement was made for a claim.
- InvalidStatement = 3,
-}
-
-impl From for u8 {
- fn from(err: ValidityError) -> Self {
- err as u8
- }
-}
-
-/// App-specific crypto used for reporting equivocation/misbehavior in BABE,
-/// GRANDPA and Parachains, described in the white paper as the fisherman role.
-/// Any rewards for misbehavior reporting will be paid out to this account.
-pub mod fisherman {
- use super::{Signature, Verify};
- use primitives::crypto::KeyTypeId;
-
- /// Key type for the reporting module. Used for reporting BABE, GRANDPA
- /// and Parachain equivocations.
- pub const KEY_TYPE: KeyTypeId = KeyTypeId(*b"fish");
-
- mod app {
- use application_crypto::{app_crypto, sr25519};
- app_crypto!(sr25519, super::KEY_TYPE);
- }
-
- /// Identity of the equivocation/misbehavior reporter.
- pub type FishermanId = app::Public;
-
- /// An `AppCrypto` type to allow submitting signed transactions using the fisherman
- /// application key as signer.
- pub struct FishermanAppCrypto;
- impl frame_system::offchain::AppCrypto<::Signer, Signature> for FishermanAppCrypto {
- type RuntimeAppPublic = FishermanId;
- type GenericSignature = primitives::sr25519::Signature;
- type GenericPublic = primitives::sr25519::Public;
- }
-}
+pub mod v0;
+pub mod v1;
diff --git a/primitives/src/parachain.rs b/primitives/src/v0.rs
similarity index 83%
rename from primitives/src/parachain.rs
rename to primitives/src/v0.rs
index 19937798c646..e1ec3a55463c 100644
--- a/primitives/src/parachain.rs
+++ b/primitives/src/v0.rs
@@ -21,18 +21,20 @@ use sp_std::prelude::*;
use sp_std::cmp::Ordering;
use parity_scale_codec::{Encode, Decode};
use bitvec::vec::BitVec;
-use super::{Hash, Balance, BlockNumber};
#[cfg(feature = "std")]
use serde::{Serialize, Deserialize};
#[cfg(feature = "std")]
-use primitives::{bytes, crypto::Pair};
+use primitives::crypto::Pair;
use primitives::RuntimeDebug;
use runtime_primitives::traits::{AppVerify, Block as BlockT};
use inherents::InherentIdentifier;
use application_crypto::KeyTypeId;
-use polkadot_core_primitives::DownwardMessage;
+
+pub use runtime_primitives::traits::{BlakeTwo256, Hash as HashT, Verify, IdentifyAccount};
+pub use polkadot_core_primitives::*;
+pub use parity_scale_codec::Compact;
pub use polkadot_parachain::primitives::{
Id, ParachainDispatchOrigin, LOWEST_USER_ID, UpwardMessage, HeadData, BlockData,
@@ -171,100 +173,6 @@ pub struct DutyRoster {
pub validator_duty: Vec,
}
-/// The unique (during session) index of a core.
-#[derive(Encode, Decode, Default, PartialOrd, Ord, Eq, PartialEq, Clone, Copy)]
-#[cfg_attr(feature = "std", derive(Debug))]
-pub struct CoreIndex(pub u32);
-
-impl From for CoreIndex {
- fn from(i: u32) -> CoreIndex {
- CoreIndex(i)
- }
-}
-
-/// The unique (during session) index of a validator group.
-#[derive(Encode, Decode, Default, Clone, Copy)]
-#[cfg_attr(feature = "std", derive(Eq, Hash, PartialEq, Debug))]
-pub struct GroupIndex(pub u32);
-
-impl From for GroupIndex {
- fn from(i: u32) -> GroupIndex {
- GroupIndex(i)
- }
-}
-
-/// A claim on authoring the next block for a given parathread.
-#[derive(Clone, Encode, Decode, Default)]
-#[cfg_attr(feature = "std", derive(PartialEq, Debug))]
-pub struct ParathreadClaim(pub Id, pub CollatorId);
-
-/// An entry tracking a claim to ensure it does not pass the maximum number of retries.
-#[derive(Clone, Encode, Decode, Default)]
-#[cfg_attr(feature = "std", derive(PartialEq, Debug))]
-pub struct ParathreadEntry {
- /// The claim.
- pub claim: ParathreadClaim,
- /// Number of retries.
- pub retries: u32,
-}
-
-/// What is occupying a specific availability core.
-#[derive(Clone, Encode, Decode)]
-#[cfg_attr(feature = "std", derive(PartialEq, Debug))]
-pub enum CoreOccupied {
- /// A parathread.
- Parathread(ParathreadEntry),
- /// A parachain.
- Parachain,
-}
-
-/// The assignment type.
-#[derive(Clone, Encode, Decode)]
-#[cfg_attr(feature = "std", derive(PartialEq, Debug))]
-pub enum AssignmentKind {
- /// A parachain.
- Parachain,
- /// A parathread.
- Parathread(CollatorId, u32),
-}
-
-/// How a free core is scheduled to be assigned.
-#[derive(Clone, Encode, Decode)]
-#[cfg_attr(feature = "std", derive(PartialEq, Debug))]
-pub struct CoreAssignment {
- /// The core that is assigned.
- pub core: CoreIndex,
- /// The unique ID of the para that is assigned to the core.
- pub para_id: Id,
- /// The kind of the assignment.
- pub kind: AssignmentKind,
- /// The index of the validator group assigned to the core.
- pub group_idx: GroupIndex,
-}
-
-impl CoreAssignment {
- /// Get the ID of a collator who is required to collate this block.
- pub fn required_collator(&self) -> Option<&CollatorId> {
- match self.kind {
- AssignmentKind::Parachain => None,
- AssignmentKind::Parathread(ref id, _) => Some(id),
- }
- }
-
- /// Get the `CoreOccupied` from this.
- pub fn to_core_occupied(&self) -> CoreOccupied {
- match self.kind {
- AssignmentKind::Parachain => CoreOccupied::Parachain,
- AssignmentKind::Parathread(ref collator, retries) => CoreOccupied::Parathread(
- ParathreadEntry {
- claim: ParathreadClaim(self.para_id, collator.clone()),
- retries,
- }
- ),
- }
- }
-}
-
/// Extra data that is needed along with the other fields in a `CandidateReceipt`
/// to fully validate the candidate.
///
@@ -505,7 +413,6 @@ impl + Encode> AbridgedCandidateReceipt {
/// the relay-chain block in which context it should be executed, which implies
/// any blockchain state that must be referenced.
pub fn hash(&self) -> Hash {
- use runtime_primitives::traits::{BlakeTwo256, Hash};
BlakeTwo256::hash_of(self)
}
}
@@ -687,7 +594,6 @@ impl PoVBlock {
/// Compute hash of block data.
#[cfg(feature = "std")]
pub fn hash(&self) -> Hash {
- use runtime_primitives::traits::{BlakeTwo256, Hash};
BlakeTwo256::hash_of(&self)
}
}
@@ -716,16 +622,6 @@ pub struct ErasureChunk {
pub proof: Vec>,
}
-/// Parachain header raw bytes wrapper type.
-#[derive(PartialEq, Eq)]
-#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
-pub struct Header(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec);
-
-/// Activity bit field.
-#[derive(PartialEq, Eq, Clone, Default, Encode, Decode)]
-#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
-pub struct Activity(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec);
-
/// Statements that can be made about parachain candidates. These are the
/// actual values that are signed.
#[derive(Clone, PartialEq, Eq, Encode, Decode, Hash)]
@@ -854,87 +750,6 @@ impl FeeSchedule {
}
}
-/// A bitfield concerning availability of backed candidates.
-#[derive(PartialEq, Eq, Clone, Encode, Decode)]
-#[cfg_attr(feature = "std", derive(Debug))]
-pub struct AvailabilityBitfield(pub BitVec);
-
-impl From> for AvailabilityBitfield {
- fn from(inner: BitVec) -> Self {
- AvailabilityBitfield(inner)
- }
-}
-
-/// A bitfield signed by a particular validator about the availability of pending candidates.
-pub type SignedAvailabilityBitfield = Signed;
-
-/// A set of signed availability bitfields. Should be sorted by validator index, ascending.
-pub type SignedAvailabilityBitfields = Vec;
-
-/// A backed (or backable, depending on context) candidate.
-// TODO: yes, this is roughly the same as AttestedCandidate.
-// After https://github.com/paritytech/polkadot/issues/1250
-// they should be unified to this type.
-#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)]
-pub struct BackedCandidate {
- /// The candidate referred to.
- pub candidate: AbridgedCandidateReceipt,
- /// The validity votes themselves, expressed as signatures.
- pub validity_votes: Vec,
- /// The indices of the validators within the group, expressed as a bitfield.
- pub validator_indices: BitVec,
-}
-
-/// Verify the backing of the given candidate.
-///
-/// Provide a lookup from the index of a validator within the group assigned to this para,
-/// as opposed to the index of the validator within the overall validator set, as well as
-/// the number of validators in the group.
-///
-/// Also provide the signing context.
-///
-/// Returns either an error, indicating that one of the signatures was invalid or that the index
-/// was out-of-bounds, or the number of signatures checked.
-pub fn check_candidate_backing + Encode>(
- backed: &BackedCandidate,
- signing_context: &SigningContext,
- group_len: usize,
- validator_lookup: impl Fn(usize) -> Option,
-) -> Result {
- if backed.validator_indices.len() != group_len {
- return Err(())
- }
-
- if backed.validity_votes.len() > group_len {
- return Err(())
- }
-
- // this is known, even in runtime, to be blake2-256.
- let hash: Hash = backed.candidate.hash();
-
- let mut signed = 0;
- for ((val_in_group_idx, _), attestation) in backed.validator_indices.iter().enumerate()
- .filter(|(_, signed)| **signed)
- .zip(backed.validity_votes.iter())
- {
- let validator_id = validator_lookup(val_in_group_idx).ok_or(())?;
- let payload = attestation.signed_payload(hash.clone(), signing_context);
- let sig = attestation.signature();
-
- if sig.verify(&payload[..], &validator_id) {
- signed += 1;
- } else {
- return Err(())
- }
- }
-
- if signed != backed.validity_votes.len() {
- return Err(())
- }
-
- Ok(signed)
-}
-
sp_api::decl_runtime_apis! {
/// The API for querying the state of parachains on-chain.
#[api_version(3)]
@@ -1098,6 +913,55 @@ impl, RealPayload: Encode> Signed for u8 {
+ fn from(err: ValidityError) -> Self {
+ err as u8
+ }
+}
+
+/// App-specific crypto used for reporting equivocation/misbehavior in BABE,
+/// GRANDPA and Parachains, described in the white paper as the fisherman role.
+/// Any rewards for misbehavior reporting will be paid out to this account.
+pub mod fisherman {
+ use super::{Signature, Verify};
+ use primitives::crypto::KeyTypeId;
+
+ /// Key type for the reporting module. Used for reporting BABE, GRANDPA
+ /// and Parachain equivocations.
+ pub const KEY_TYPE: KeyTypeId = KeyTypeId(*b"fish");
+
+ mod app {
+ use application_crypto::{app_crypto, sr25519};
+ app_crypto!(sr25519, super::KEY_TYPE);
+ }
+
+ /// Identity of the equivocation/misbehavior reporter.
+ pub type FishermanId = app::Public;
+
+ /// An `AppCrypto` type to allow submitting signed transactions using the fisherman
+ /// application key as signer.
+ pub struct FishermanAppCrypto;
+ impl frame_system::offchain::AppCrypto<::Signer, Signature> for FishermanAppCrypto {
+ type RuntimeAppPublic = FishermanId;
+ type GenericSignature = primitives::sr25519::Signature;
+ type GenericPublic = primitives::sr25519::Public;
+ }
+}
+
+
#[cfg(test)]
mod tests {
use super::*;
diff --git a/primitives/src/v1.rs b/primitives/src/v1.rs
new file mode 100644
index 000000000000..9fb3d1662ec7
--- /dev/null
+++ b/primitives/src/v1.rs
@@ -0,0 +1,478 @@
+// Copyright 2017-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 .
+
+//! V1 Primitives.
+
+use sp_std::prelude::*;
+use parity_scale_codec::{Encode, Decode};
+use bitvec::vec::BitVec;
+
+use primitives::RuntimeDebug;
+use runtime_primitives::traits::AppVerify;
+use inherents::InherentIdentifier;
+
+use runtime_primitives::traits::{BlakeTwo256, Hash as HashT};
+
+// Export some core primitives.
+pub use polkadot_core_primitives::v1::{
+ BlockNumber, Moment, Signature, AccountPublic, AccountId, AccountIndex,
+ ChainId, Hash, Nonce, Balance, Header, Block, BlockId, UncheckedExtrinsic,
+ Remark, DownwardMessage,
+};
+
+// Export some polkadot-parachain primitives
+pub use polkadot_parachain::primitives::{
+ Id, ParachainDispatchOrigin, LOWEST_USER_ID, UpwardMessage, HeadData, BlockData,
+ ValidationCode,
+};
+
+// Export some basic parachain primitives from v0.
+pub use crate::v0::{
+ CollatorId, CollatorSignature, PARACHAIN_KEY_TYPE_ID, ValidatorId, ValidatorIndex,
+ ValidatorSignature, SigningContext, Signed, ValidityAttestation,
+ CompactStatement, SignedStatement, ErasureChunk, EncodeAs,
+};
+
+// More exports from v0 for std.
+#[cfg(feature = "std")]
+pub use crate::v0::{ValidatorPair, CollatorPair};
+
+/// Unique identifier for the Inclusion Inherent
+pub const INCLUSION_INHERENT_IDENTIFIER: InherentIdentifier = *b"inclusn0";
+
+/// Get a collator signature payload on a relay-parent, block-data combo.
+pub fn collator_signature_payload>(
+ relay_parent: &H,
+ para_id: &Id,
+ pov_hash: &Hash,
+) -> [u8; 68] {
+ // 32-byte hash length is protected in a test below.
+ let mut payload = [0u8; 68];
+
+ 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));
+ payload[36..68].copy_from_slice(pov_hash.as_ref());
+
+ payload
+}
+
+fn check_collator_signature>(
+ relay_parent: &H,
+ para_id: &Id,
+ pov_hash: &Hash,
+ collator: &CollatorId,
+ signature: &CollatorSignature,
+) -> Result<(),()> {
+ let payload = collator_signature_payload(relay_parent, para_id, pov_hash);
+ if signature.verify(&payload[..], collator) {
+ Ok(())
+ } else {
+ Err(())
+ }
+}
+
+/// A unique descriptor of the candidate receipt.
+#[derive(PartialEq, Eq, Clone, Encode, Decode)]
+#[cfg_attr(feature = "std", derive(Debug, Default))]
+pub struct CandidateDescriptor {
+ /// The ID of the para this is a candidate for.
+ pub para_id: Id,
+ /// The hash of the relay-chain block this is executed in the context of.
+ pub relay_parent: H,
+ /// The collator's sr25519 public key.
+ pub collator: CollatorId,
+ /// Signature on blake2-256 of components of this receipt:
+ /// The parachain index, the relay parent, and the pov_hash.
+ pub signature: CollatorSignature,
+ /// The blake2-256 hash of the pov.
+ pub pov_hash: Hash,
+}
+
+impl> CandidateDescriptor {
+ /// Check the signature of the collator within this descriptor.
+ pub fn check_collator_signature(&self) -> Result<(), ()> {
+ check_collator_signature(
+ &self.relay_parent,
+ &self.para_id,
+ &self.pov_hash,
+ &self.collator,
+ &self.signature,
+ )
+ }
+}
+
+/// A candidate-receipt.
+#[derive(PartialEq, Eq, Clone, Encode, Decode)]
+#[cfg_attr(feature = "std", derive(Debug, Default))]
+pub struct CandidateReceipt {
+ /// The descriptor of the candidate.
+ pub descriptor: CandidateDescriptor,
+ /// The hash of the encoded commitments made as a result of candidate execution.
+ pub commitments_hash: Hash,
+}
+
+impl CandidateReceipt {
+ /// Get a reference to the candidate descriptor.
+ pub fn descriptor(&self) -> &CandidateDescriptor {
+ &self.descriptor
+ }
+
+ /// Computes the blake2-256 hash of the receipt.
+ pub fn hash(&self) -> Hash where H: Encode {
+ BlakeTwo256::hash_of(self)
+ }
+}
+
+/// All data pertaining to the execution of a para candidate.
+#[derive(PartialEq, Eq, Clone, Encode, Decode)]
+#[cfg_attr(feature = "std", derive(Debug, Default))]
+pub struct FullCandidateReceipt {
+ /// The inner candidate receipt.
+ pub inner: CandidateReceipt,
+ /// The global validation schedule.
+ pub global_validation: GlobalValidationSchedule,
+ /// The local validation data.
+ pub local_validation: LocalValidationData,
+}
+
+/// A candidate-receipt with commitments directly included.
+#[derive(PartialEq, Eq, Clone, Encode, Decode)]
+#[cfg_attr(feature = "std", derive(Debug, Default))]
+pub struct CommittedCandidateReceipt {
+ /// The descriptor of the candidate.
+ pub descriptor: CandidateDescriptor,
+ /// The commitments of the candidate receipt.
+ pub commitments: CandidateCommitments,
+}
+
+impl CommittedCandidateReceipt {
+ /// Get a reference to the candidate descriptor.
+ pub fn descriptor(&self) -> &CandidateDescriptor {
+ &self.descriptor
+ }
+}
+
+impl CommittedCandidateReceipt {
+ /// Transforms this into a plain CandidateReceipt.
+ pub fn to_plain(&self) -> CandidateReceipt {
+ CandidateReceipt {
+ descriptor: self.descriptor.clone(),
+ commitments_hash: self.commitments.hash(),
+ }
+ }
+
+ /// Computes the hash of the committed candidate receipt.
+ ///
+ /// This computes the canonical hash, not the hash of the directly encoded data.
+ /// Thus this is a shortcut for `candidate.to_plain().hash()`.
+ pub fn hash(&self) -> Hash where H: Encode {
+ self.to_plain().hash()
+ }
+}
+
+impl PartialOrd for CommittedCandidateReceipt {
+ fn partial_cmp(&self, other: &Self) -> Option {
+ Some(self.cmp(other))
+ }
+}
+
+impl Ord for CommittedCandidateReceipt {
+ fn cmp(&self, other: &Self) -> sp_std::cmp::Ordering {
+ // TODO: compare signatures or something more sane
+ // https://github.com/paritytech/polkadot/issues/222
+ self.descriptor().para_id.cmp(&other.descriptor().para_id)
+ .then_with(|| self.commitments.head_data.cmp(&other.commitments.head_data))
+ }
+}
+
+/// Extra data that is needed along with the other fields in a `CandidateReceipt`
+/// to fully validate the candidate. These fields are parachain-specific.
+#[derive(PartialEq, Eq, Clone, Encode, Decode)]
+#[cfg_attr(feature = "std", derive(Debug, Default))]
+pub struct LocalValidationData {
+ /// The parent head-data.
+ pub parent_head: HeadData,
+ /// The balance of the parachain at the moment of validation.
+ pub balance: Balance,
+ /// The blake2-256 hash of the validation code used to execute the candidate.
+ pub validation_code_hash: Hash,
+ /// Whether the parachain is allowed to upgrade its validation code.
+ ///
+ /// This is `Some` if so, and contains the number of the minimum relay-chain
+ /// height at which the upgrade will be applied, if an upgrade is signaled
+ /// now.
+ ///
+ /// A parachain should enact its side of the upgrade at the end of the first
+ /// parablock executing in the context of a relay-chain block with at least this
+ /// height. This may be equal to the current perceived relay-chain block height, in
+ /// which case the code upgrade should be applied at the end of the signaling
+ /// block.
+ pub code_upgrade_allowed: Option,
+}
+
+/// Extra data that is needed along with the other fields in a `CandidateReceipt`
+/// to fully validate the candidate.
+///
+/// These are global parameters that apply to all candidates in a block.
+#[derive(PartialEq, Eq, Clone, Encode, Decode)]
+#[cfg_attr(feature = "std", derive(Debug, Default))]
+pub struct GlobalValidationSchedule {
+ /// The maximum code size permitted, in bytes.
+ pub max_code_size: u32,
+ /// The maximum head-data size permitted, in bytes.
+ pub max_head_data_size: u32,
+ /// The relay-chain block number this is in the context of.
+ pub block_number: BlockNumber,
+}
+
+/// Commitments made in a `CandidateReceipt`. Many of these are outputs of validation.
+#[derive(PartialEq, Eq, Clone, Encode, Decode)]
+#[cfg_attr(feature = "std", derive(Debug, Default))]
+pub struct CandidateCommitments {
+ /// Fees paid from the chain to the relay chain validators.
+ pub fees: Balance,
+ /// Messages destined to be interpreted by the Relay chain itself.
+ pub upward_messages: Vec,
+ /// The root of a block's erasure encoding Merkle tree.
+ pub erasure_root: Hash,
+ /// New validation code.
+ pub new_validation_code: Option,
+ /// The head-data produced as a result of execution.
+ pub head_data: HeadData,
+}
+
+impl CandidateCommitments {
+ /// Compute the blake2-256 hash of the commitments.
+ pub fn hash(&self) -> Hash {
+ BlakeTwo256::hash_of(self)
+ }
+}
+
+/// A Proof-of-Validity
+#[derive(PartialEq, Eq, Clone, Encode, Decode)]
+#[cfg_attr(feature = "std", derive(Debug))]
+pub struct PoV {
+ /// The block witness data.
+ pub block_data: BlockData,
+}
+
+impl PoV {
+ /// Get the blake2-256 hash of the PoV.
+ #[cfg(feature = "std")]
+ pub fn hash(&self) -> Hash {
+ BlakeTwo256::hash_of(self)
+ }
+}
+
+/// A bitfield concerning availability of backed candidates.
+#[derive(PartialEq, Eq, Clone, Encode, Decode)]
+#[cfg_attr(feature = "std", derive(Debug))]
+pub struct AvailabilityBitfield(pub BitVec);
+
+impl From> for AvailabilityBitfield {
+ fn from(inner: BitVec) -> Self {
+ AvailabilityBitfield(inner)
+ }
+}
+
+/// A bitfield signed by a particular validator about the availability of pending candidates.
+pub type SignedAvailabilityBitfield = Signed;
+
+/// A set of signed availability bitfields. Should be sorted by validator index, ascending.
+pub type SignedAvailabilityBitfields = Vec;
+
+/// A backed (or backable, depending on context) candidate.
+#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)]
+pub struct BackedCandidate {
+ /// The candidate referred to.
+ pub candidate: CommittedCandidateReceipt,
+ /// The validity votes themselves, expressed as signatures.
+ pub validity_votes: Vec,
+ /// The indices of the validators within the group, expressed as a bitfield.
+ pub validator_indices: BitVec,
+}
+
+impl BackedCandidate {
+ /// Get a reference to the descriptor of the para.
+ pub fn descriptor(&self) -> &CandidateDescriptor {
+ &self.candidate.descriptor
+ }
+}
+
+/// Verify the backing of the given candidate.
+///
+/// Provide a lookup from the index of a validator within the group assigned to this para,
+/// as opposed to the index of the validator within the overall validator set, as well as
+/// the number of validators in the group.
+///
+/// Also provide the signing context.
+///
+/// Returns either an error, indicating that one of the signatures was invalid or that the index
+/// was out-of-bounds, or the number of signatures checked.
+pub fn check_candidate_backing + Clone + Encode>(
+ backed: &BackedCandidate,
+ signing_context: &SigningContext,
+ group_len: usize,
+ validator_lookup: impl Fn(usize) -> Option,
+) -> Result {
+ if backed.validator_indices.len() != group_len {
+ return Err(())
+ }
+
+ if backed.validity_votes.len() > group_len {
+ return Err(())
+ }
+
+ // this is known, even in runtime, to be blake2-256.
+ let hash: Hash = backed.candidate.hash();
+
+ let mut signed = 0;
+ for ((val_in_group_idx, _), attestation) in backed.validator_indices.iter().enumerate()
+ .filter(|(_, signed)| **signed)
+ .zip(backed.validity_votes.iter())
+ {
+ let validator_id = validator_lookup(val_in_group_idx).ok_or(())?;
+ let payload = attestation.signed_payload(hash.clone(), signing_context);
+ let sig = attestation.signature();
+
+ if sig.verify(&payload[..], &validator_id) {
+ signed += 1;
+ } else {
+ return Err(())
+ }
+ }
+
+ if signed != backed.validity_votes.len() {
+ return Err(())
+ }
+
+ Ok(signed)
+}
+
+/// The unique (during session) index of a core.
+#[derive(Encode, Decode, Default, PartialOrd, Ord, Eq, PartialEq, Clone, Copy)]
+#[cfg_attr(feature = "std", derive(Debug))]
+pub struct CoreIndex(pub u32);
+
+impl From for CoreIndex {
+ fn from(i: u32) -> CoreIndex {
+ CoreIndex(i)
+ }
+}
+
+/// The unique (during session) index of a validator group.
+#[derive(Encode, Decode, Default, Clone, Copy)]
+#[cfg_attr(feature = "std", derive(Eq, Hash, PartialEq, Debug))]
+pub struct GroupIndex(pub u32);
+
+impl From for GroupIndex {
+ fn from(i: u32) -> GroupIndex {
+ GroupIndex(i)
+ }
+}
+
+/// A claim on authoring the next block for a given parathread.
+#[derive(Clone, Encode, Decode, Default)]
+#[cfg_attr(feature = "std", derive(PartialEq, Debug))]
+pub struct ParathreadClaim(pub Id, pub CollatorId);
+
+/// An entry tracking a claim to ensure it does not pass the maximum number of retries.
+#[derive(Clone, Encode, Decode, Default)]
+#[cfg_attr(feature = "std", derive(PartialEq, Debug))]
+pub struct ParathreadEntry {
+ /// The claim.
+ pub claim: ParathreadClaim,
+ /// Number of retries.
+ pub retries: u32,
+}
+
+/// What is occupying a specific availability core.
+#[derive(Clone, Encode, Decode)]
+#[cfg_attr(feature = "std", derive(PartialEq, Debug))]
+pub enum CoreOccupied {
+ /// A parathread.
+ Parathread(ParathreadEntry),
+ /// A parachain.
+ Parachain,
+}
+
+/// The assignment type.
+#[derive(Clone, Encode, Decode)]
+#[cfg_attr(feature = "std", derive(PartialEq, Debug))]
+pub enum AssignmentKind {
+ /// A parachain.
+ Parachain,
+ /// A parathread.
+ Parathread(CollatorId, u32),
+}
+
+/// How a free core is scheduled to be assigned.
+#[derive(Clone, Encode, Decode)]
+#[cfg_attr(feature = "std", derive(PartialEq, Debug))]
+pub struct CoreAssignment {
+ /// The core that is assigned.
+ pub core: CoreIndex,
+ /// The unique ID of the para that is assigned to the core.
+ pub para_id: Id,
+ /// The kind of the assignment.
+ pub kind: AssignmentKind,
+ /// The index of the validator group assigned to the core.
+ pub group_idx: GroupIndex,
+}
+
+impl CoreAssignment {
+ /// Get the ID of a collator who is required to collate this block.
+ pub fn required_collator(&self) -> Option<&CollatorId> {
+ match self.kind {
+ AssignmentKind::Parachain => None,
+ AssignmentKind::Parathread(ref id, _) => Some(id),
+ }
+ }
+
+ /// Get the `CoreOccupied` from this.
+ pub fn to_core_occupied(&self) -> CoreOccupied {
+ match self.kind {
+ AssignmentKind::Parachain => CoreOccupied::Parachain,
+ AssignmentKind::Parathread(ref collator, retries) => CoreOccupied::Parathread(
+ ParathreadEntry {
+ claim: ParathreadClaim(self.para_id, collator.clone()),
+ retries,
+ }
+ ),
+ }
+ }
+}
+
+/// Validation data omitted from most candidate descriptor structs, as it can be derived from the
+/// relay-parent.
+#[derive(Clone, Encode, Decode)]
+#[cfg_attr(feature = "std", derive(PartialEq, Debug))]
+pub struct OmittedValidationData {
+ /// The global validation schedule.
+ pub global_validation: GlobalValidationSchedule,
+ /// The local validation data.
+ pub local_validation: LocalValidationData,
+}
+
+/// This is the data we keep available for each candidate included in the relay chain.
+#[derive(Clone, Encode, Decode)]
+#[cfg_attr(feature = "std", derive(PartialEq, Debug))]
+pub struct AvailableData {
+ /// The Proof-of-Validation of the candidate.
+ pub pov: PoV,
+ /// The omitted validation data.
+ pub omitted_validation: OmittedValidationData,
+}
diff --git a/roadmap/implementers-guide/src/types/availability.md b/roadmap/implementers-guide/src/types/availability.md
index 3362908d6b63..be42c7a9278a 100644
--- a/roadmap/implementers-guide/src/types/availability.md
+++ b/roadmap/implementers-guide/src/types/availability.md
@@ -9,7 +9,7 @@ A bitfield [signed](backing.md#signed-wrapper) by a particular validator about t
```rust
-pub type SignedAvailabilityBitfield = Signed;
+type SignedAvailabilityBitfield = Signed;
struct Bitfields(Vec<(SignedAvailabilityBitfield)>), // bitfields sorted by validator index, ascending
```
@@ -21,3 +21,50 @@ Often referred to as PoV, this is a type-safe wrapper around bytes (`Vec`) w
```rust
struct PoV(Vec);
```
+
+## Omitted Validation Data
+
+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)
+
+```rust
+struct OmittedValidationData {
+ /// The global validation schedule.
+ global_validation: GlobalValidationSchedule,
+ /// The local validation data.
+ local_validation: LocalValidationData,
+}
+```
+
+
+## Available Data
+
+This is the data we want to keep available for each [candidate](candidate.md) included in the relay chain.
+
+```rust
+struct AvailableData {
+ /// The Proof-of-Validation of the candidate.
+ pov: PoV,
+ /// The omitted validation data.
+ omitted_validation: OmittedValidationData,
+}
+```
+
+> TODO: With XCMP, we also need to keep available the outgoing messages as a result of para-validation.
+
+## Erasure Chunk
+
+The [`AvailableData`](#availabledata) is split up into an erasure-coding as part of the availability process. Each validator gets a chunk. This describes one of those chunks, along with its proof against a merkle root hash, which should be apparent from context, and is the `erasure_root` field of a [`CandidateDescriptor`](candidate.md#candidatedescriptor).
+
+
+```rust
+struct ErasureChunk {
+ /// The erasure-encoded chunk of data belonging to the candidate block.
+ chunk: Vec,
+ /// The index of this erasure-encoded chunk of data.
+ index: u32,
+ /// Proof for this chunk's branch in the Merkle tree.
+ proof: Vec>,
+}
+```
diff --git a/roadmap/implementers-guide/src/types/candidate.md b/roadmap/implementers-guide/src/types/candidate.md
index fdba6919e57c..0ed38590a733 100644
--- a/roadmap/implementers-guide/src/types/candidate.md
+++ b/roadmap/implementers-guide/src/types/candidate.md
@@ -1,6 +1,7 @@
# Candidate Types
Para candidates are some of the most common types, both within the runtime and on the Node-side.
+Candidates are the fundamental datatype for advancing parachains and parathreads, encapsulating the collator's signature, the context of the parablock, the commitments to the output, and a commitment to the data which proves it valid.
In a way, this entire guide is about these candidates: how they are scheduled, constructed, backed, included, and challenged.
@@ -179,3 +180,24 @@ struct SigningContext {
session_index: SessionIndex,
}
```
+
+## Validation Outputs
+
+This struct encapsulates the outputs of candidate validation.
+
+```rust
+struct ValidationOutputs {
+ /// The head-data produced by validation.
+ head_data: HeadData,
+ /// The global validation schedule.
+ global_validation_schedule: GlobalValidationSchedule,
+ /// The local validation data.
+ local_validation_data: LocalValidationData,
+ /// Upwards messages to the relay chain.
+ upwards_messages: Vec,
+ /// Fees paid to the validators of the relay-chain.
+ fees: Balance,
+ /// The new validation code submitted by the execution, if any.
+ new_validation_code: Option,
+}
+```
diff --git a/roadmap/implementers-guide/src/types/overseer-protocol.md b/roadmap/implementers-guide/src/types/overseer-protocol.md
index 1e59eedff8db..b822508f4a3e 100644
--- a/roadmap/implementers-guide/src/types/overseer-protocol.md
+++ b/roadmap/implementers-guide/src/types/overseer-protocol.md
@@ -91,6 +91,7 @@ enum CandidateBackingMessage {
GetBackedCandidates(Hash, ResponseChannel>),
/// Note that the Candidate Backing subsystem should second the given candidate in the context of the
/// given relay-parent (ref. by hash). This candidate must be validated using the provided PoV.
+ /// The PoV is expected to match the `pov_hash` in the descriptor.
Second(Hash, CandidateReceipt, PoV),
/// Note a peer validator's statement about a particular candidate. Disagreements about validity must be escalated
/// to a broader check by Misbehavior Arbitration. Agreements are simply tallied until a quorum is reached.
@@ -282,29 +283,41 @@ enum StatementDistributionMessage {
## Validation Request Type
-Various modules request that the [Candidate Validation subsystem](../node/utility/candidate-validation.md) validate a block with this message
+Various modules request that the [Candidate Validation subsystem](../node/utility/candidate-validation.md) validate a block with this message. It returns [`ValidationOutputs`](candidate.md#validationoutputs) for successful validation.
```rust
/// Result of the validation of the candidate.
enum ValidationResult {
- /// Candidate is valid.
- Valid,
+ /// Candidate is valid, and here are the outputs. In practice, this should be a shared type
+ /// so that validation caching can be done.
+ Valid(ValidationOutputs),
/// Candidate is invalid.
Invalid,
}
+/// Messages issued to the candidate validation subsystem.
+///
+/// ## Validation Requests
+///
+/// Validation requests made to the subsystem should return an error only on internal error.
+/// Otherwise, they should return either `Ok(ValidationResult::Valid(_))` or `Ok(ValidationResult::Invalid)`.
enum CandidateValidationMessage {
- /// Validate a candidate with provided parameters. Returns `Err` if an only if an internal
- /// error is encountered.
- /// In case no internal error was encontered it returns a tuple containing the result of
- /// validation and `GlobalValidationSchedule` and `LocalValidationData` structures that
- /// may be used by the caller to make the candidate available.
- /// A bad candidate will return `Ok((ValidationResult::Invalid, _, _)`, while a good one will
- /// return `Ok((ValidationResult::Valid, _, _))`.
- Validate(
- Hash, CandidateReceipt, HeadData, PoV, ResponseChannel<
- Result<(ValidationResult, GlobalValidationSchedule, LocalValidationData)>
- >),
+ /// Validate a candidate with provided parameters. This will implicitly attempt to gather the
+ /// `OmittedValidationData` and `ValidationCode` from the runtime API of the chain,
+ /// based on the `relay_parent` of the `CandidateDescriptor`.
+ /// If there is no state available which can provide this data, an error is returned.
+ ValidateFromChainState(CandidateDescriptor, PoV, ResponseChannel>),
+
+ /// Validate a candidate with provided parameters. Explicitly provide the `OmittedValidationData`
+ /// and `ValidationCode` so this can do full validation without needing to access the state of
+ /// the relay-chain.
+ ValidateFromExhaustive(
+ OmittedValidationData,
+ ValidationCode,
+ CandidateDescriptor,
+ PoV,
+ ResponseChannel>,
+ ),
}
```
diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs
index 6bddc8ad8daf..c73b478329ee 100644
--- a/rpc/src/lib.rs
+++ b/rpc/src/lib.rs
@@ -20,7 +20,7 @@
use std::sync::Arc;
-use polkadot_primitives::{Block, BlockNumber, AccountId, Nonce, Balance, Hash};
+use polkadot_primitives::v0::{Block, BlockNumber, AccountId, Nonce, Balance, Hash};
use sp_api::ProvideRuntimeApi;
use txpool_api::TransactionPool;
use sp_blockchain::{HeaderBackend, HeaderMetadata, Error as BlockChainError};
diff --git a/runtime/common/src/attestations.rs b/runtime/common/src/attestations.rs
index f27874117aaa..e7a6854bbb13 100644
--- a/runtime/common/src/attestations.rs
+++ b/runtime/common/src/attestations.rs
@@ -28,7 +28,7 @@ use frame_support::{
weights::DispatchClass,
};
-use primitives::{Hash, parachain::{AttestedCandidate, AbridgedCandidateReceipt, Id as ParaId}};
+use primitives::v0::{Hash, AttestedCandidate, AbridgedCandidateReceipt, Id as ParaId};
use sp_runtime::RuntimeDebug;
use sp_staking::SessionIndex;
diff --git a/runtime/common/src/claims.rs b/runtime/common/src/claims.rs
index fd8c1c1c880a..6efc3d31d75d 100644
--- a/runtime/common/src/claims.rs
+++ b/runtime/common/src/claims.rs
@@ -35,7 +35,7 @@ use sp_runtime::{
TransactionSource, TransactionValidityError,
},
};
-use primitives::ValidityError;
+use primitives::v0::ValidityError;
type CurrencyOf = <::VestingSchedule as VestingSchedule<::AccountId>>::Currency;
type BalanceOf = as Currency<::AccountId>>::Balance;
diff --git a/runtime/common/src/crowdfund.rs b/runtime/common/src/crowdfund.rs
index ee2b740745b7..fc233d107abe 100644
--- a/runtime/common/src/crowdfund.rs
+++ b/runtime/common/src/crowdfund.rs
@@ -79,7 +79,7 @@ use sp_runtime::{ModuleId,
use crate::slots;
use codec::{Encode, Decode};
use sp_std::vec::Vec;
-use primitives::parachain::{Id as ParaId, HeadData};
+use primitives::v0::{Id as ParaId, HeadData};
pub type BalanceOf =
<::Currency as Currency<::AccountId>>::Balance;
@@ -568,7 +568,7 @@ mod tests {
};
use frame_support::traits::{Contains, ContainsLengthBound};
use sp_core::H256;
- use primitives::parachain::{Info as ParaInfo, Id as ParaId, Scheduling, ValidationCode};
+ use primitives::v0::{Info as ParaInfo, Id as ParaId, Scheduling, ValidationCode};
// The testing primitives are very useful for avoiding having to work with signatures
// or public keys. `u64` is used as the `AccountId` and no `Signature`s are requried.
use sp_runtime::{
diff --git a/runtime/common/src/impls.rs b/runtime/common/src/impls.rs
index 543e2c739adb..7e3b6d917f77 100644
--- a/runtime/common/src/impls.rs
+++ b/runtime/common/src/impls.rs
@@ -26,8 +26,8 @@ pub struct ToAuthor(sp_std::marker::PhantomData);
impl OnUnbalanced> for ToAuthor
where
R: balances::Trait + authorship::Trait,
- ::AccountId: From,
- ::AccountId: Into,
+ ::AccountId: From,
+ ::AccountId: Into,
::Event: From::AccountId,
::Balance,
diff --git a/runtime/common/src/lib.rs b/runtime/common/src/lib.rs
index da6fc5fcc27b..d32db38e05be 100644
--- a/runtime/common/src/lib.rs
+++ b/runtime/common/src/lib.rs
@@ -27,7 +27,7 @@ pub mod slots;
pub mod crowdfund;
pub mod impls;
-use primitives::BlockNumber;
+use primitives::v0::BlockNumber;
use sp_runtime::{Perquintill, Perbill, FixedPointNumber, traits::Saturating};
use frame_support::{
parameter_types, traits::{Currency},
diff --git a/runtime/common/src/parachains.rs b/runtime/common/src/parachains.rs
index 25d93b6fde78..b0228a5a53c8 100644
--- a/runtime/common/src/parachains.rs
+++ b/runtime/common/src/parachains.rs
@@ -37,16 +37,13 @@ use frame_support::{
dispatch::IsSubType,
weights::{DispatchClass, Weight},
};
-use primitives::{
- Balance,
- BlockNumber,
- parachain::{
- Id as ParaId, Chain, DutyRoster, AttestedCandidate, CompactStatement as Statement, ParachainDispatchOrigin,
- UpwardMessage, ValidatorId, ActiveParas, CollatorId, Retriable, OmittedValidationData,
- CandidateReceipt, GlobalValidationSchedule, AbridgedCandidateReceipt,
- LocalValidationData, Scheduling, ValidityAttestation, NEW_HEADS_IDENTIFIER, PARACHAIN_KEY_TYPE_ID,
- ValidatorSignature, SigningContext, HeadData, ValidationCode,
- },
+use primitives::v0::{
+ Balance, BlockNumber,
+ Id as ParaId, Chain, DutyRoster, AttestedCandidate, CompactStatement as Statement, ParachainDispatchOrigin,
+ UpwardMessage, ValidatorId, ActiveParas, CollatorId, Retriable, OmittedValidationData,
+ CandidateReceipt, GlobalValidationSchedule, AbridgedCandidateReceipt,
+ LocalValidationData, Scheduling, ValidityAttestation, NEW_HEADS_IDENTIFIER, PARACHAIN_KEY_TYPE_ID,
+ ValidatorSignature, SigningContext, HeadData, ValidationCode,
Remark, DownwardMessage
};
use frame_support::{
@@ -329,7 +326,7 @@ pub trait Trait: CreateSignedTransaction> + attestations::Trait + ses
>;
/// A type that converts the opaque hash type to exact one.
- type BlockHashConversion: Convert;
+ type BlockHashConversion: Convert;
}
/// Origin for the parachains module.
@@ -1681,13 +1678,10 @@ mod tests {
},
testing::TestXt,
};
- use primitives::{
- parachain::{
- CandidateReceipt, ValidityAttestation, ValidatorId, Info as ParaInfo,
- Scheduling, CandidateCommitments,
- },
- BlockNumber,
- Header,
+ use primitives::v0::{
+ CandidateReceipt, ValidityAttestation, ValidatorId, Info as ParaInfo,
+ Scheduling, CandidateCommitments,
+ BlockNumber, Header,
};
use keyring::Sr25519Keyring;
use frame_support::{
@@ -1819,7 +1813,7 @@ mod tests {
}
mod time {
- use primitives::{Moment, BlockNumber};
+ use primitives::v0::{Moment, BlockNumber};
pub const MILLISECS_PER_BLOCK: Moment = 6000;
pub const EPOCH_DURATION_IN_BLOCKS: BlockNumber = 1 * HOURS;
// These time units are defined in number of blocks.
@@ -2246,7 +2240,7 @@ mod tests {
println!("session index {}", i);
Staking::on_finalize(System::block_number());
System::set_block_number((i + 1).into());
- Timestamp::set_timestamp(System::block_number() as primitives::Moment * 6000);
+ Timestamp::set_timestamp(System::block_number() as primitives::v0::Moment * 6000);
// In order to be able to use `System::parent_hash()` in the tests
// we need to first get it via `System::finalize` and then set it
diff --git a/runtime/common/src/registrar.rs b/runtime/common/src/registrar.rs
index de152d9379b5..d7b9cb40caf9 100644
--- a/runtime/common/src/registrar.rs
+++ b/runtime/common/src/registrar.rs
@@ -34,7 +34,7 @@ use frame_support::{
weights::{DispatchClass, Weight},
};
use system::{self, ensure_root, ensure_signed};
-use primitives::parachain::{
+use primitives::v0::{
Id as ParaId, CollatorId, Scheduling, LOWEST_USER_ID, SwapAux, Info as ParaInfo, ActiveParas,
Retriable, ValidationCode, HeadData,
};
@@ -213,7 +213,7 @@ fn build(config: &GenesisConfig) {
Parachains::put(&only_ids);
for (id, code, genesis) in p {
- Paras::insert(id, &primitives::parachain::PARACHAIN_INFO);
+ Paras::insert(id, &primitives::v0::PARACHAIN_INFO);
// no ingress -- a chain cannot be routed to until it is live.
::insert(&id, &code);
::insert(&id, &genesis);
@@ -670,12 +670,10 @@ mod tests {
AccountIdConversion, Extrinsic as ExtrinsicT,
}, testing::{UintAuthorityId, TestXt}, KeyTypeId, Perbill, curve::PiecewiseLinear,
};
- use primitives::{
- parachain::{
- ValidatorId, Info as ParaInfo, Scheduling, LOWEST_USER_ID, AttestedCandidate,
- CandidateReceipt, HeadData, ValidityAttestation, CompactStatement as Statement, Chain,
- CollatorPair, CandidateCommitments,
- },
+ use primitives::v0::{
+ ValidatorId, Info as ParaInfo, Scheduling, LOWEST_USER_ID, AttestedCandidate,
+ CandidateReceipt, HeadData, ValidityAttestation, CompactStatement as Statement, Chain,
+ CollatorPair, CandidateCommitments,
Balance, BlockNumber, Header, Signature,
};
use frame_support::{
@@ -869,7 +867,7 @@ mod tests {
// This is needed for a custom `AccountId` type which is `u64` in testing here.
pub mod test_keys {
use sp_core::{crypto::KeyTypeId, sr25519};
- use primitives::Signature;
+ use primitives::v0::Signature;
pub const KEY_TYPE: KeyTypeId = KeyTypeId(*b"test");
diff --git a/runtime/common/src/slots.rs b/runtime/common/src/slots.rs
index 5618a680c5a0..eb0a7aff7d72 100644
--- a/runtime/common/src/slots.rs
+++ b/runtime/common/src/slots.rs
@@ -28,7 +28,7 @@ use frame_support::{
traits::{Currency, ReservableCurrency, WithdrawReason, ExistenceRequirement, Get, Randomness},
weights::{DispatchClass, Weight},
};
-use primitives::parachain::{
+use primitives::v0::{
SwapAux, PARACHAIN_INFO, Id as ParaId, ValidationCode, HeadData,
};
use system::{ensure_signed, ensure_root};
@@ -890,8 +890,7 @@ mod tests {
traits::{OnInitialize, OnFinalize}
};
use balances;
- use primitives::{BlockNumber, Header};
- use primitives::parachain::{Id as ParaId, Info as ParaInfo, Scheduling};
+ use primitives::v0::{BlockNumber, Header, Id as ParaId, Info as ParaInfo, Scheduling};
impl_outer_origin! {
pub enum Origin for Test {}
diff --git a/runtime/kusama/src/constants.rs b/runtime/kusama/src/constants.rs
index e06325d1bb95..560d83347d9b 100644
--- a/runtime/kusama/src/constants.rs
+++ b/runtime/kusama/src/constants.rs
@@ -16,7 +16,7 @@
/// Money matters.
pub mod currency {
- use primitives::Balance;
+ use primitives::v0::Balance;
pub const DOTS: Balance = 1_000_000_000_000;
pub const DOLLARS: Balance = DOTS / 6;
@@ -30,7 +30,7 @@ pub mod currency {
/// Time and blocks.
pub mod time {
- use primitives::{Moment, BlockNumber};
+ use primitives::v0::{Moment, BlockNumber};
// Kusama & mainnet
pub const MILLISECS_PER_BLOCK: Moment = 6000;
// Testnet
@@ -55,7 +55,7 @@ pub mod time {
/// Fee-related.
pub mod fee {
pub use sp_runtime::Perbill;
- use primitives::Balance;
+ use primitives::v0::Balance;
use runtime_common::ExtrinsicBaseWeight;
use frame_support::weights::{
WeightToFeePolynomial, WeightToFeeCoefficient, WeightToFeeCoefficients,
diff --git a/runtime/kusama/src/lib.rs b/runtime/kusama/src/lib.rs
index ee25e8961dec..569d055ccafe 100644
--- a/runtime/kusama/src/lib.rs
+++ b/runtime/kusama/src/lib.rs
@@ -23,9 +23,10 @@
use sp_std::prelude::*;
use sp_core::u32_trait::{_1, _2, _3, _4, _5};
use codec::{Encode, Decode};
-use primitives::{
+use primitives::v0::{
+ self as parachain,
AccountId, AccountIndex, Balance, BlockNumber, Hash, Nonce, Signature, Moment,
- parachain::{self, ActiveParas, AbridgedCandidateReceipt, SigningContext},
+ ActiveParas, AbridgedCandidateReceipt, SigningContext,
};
use runtime_common::{
attestations, claims, parachains, registrar, slots, SlowAdjustingFeeUpdate,
@@ -560,7 +561,7 @@ impl grandpa::Trait for Runtime {
type HandleEquivocation = grandpa::EquivocationHandler<
Self::KeyOwnerIdentification,
- primitives::fisherman::FishermanAppCrypto,
+ primitives::v0::fisherman::FishermanAppCrypto,
Runtime,
Offences,
>;
@@ -596,7 +597,7 @@ parameter_types! {
}
impl parachains::Trait for Runtime {
- type AuthorityId = primitives::fisherman::FishermanAppCrypto;
+ type AuthorityId = primitives::v0::fisherman::FishermanAppCrypto;
type Origin = Origin;
type Call = Call;
type ParachainCurrency = Balances;
@@ -939,7 +940,7 @@ impl frame_support::traits::OnRuntimeUpgrade for CustomOnRuntimeUpgrade {
construct_runtime! {
pub enum Runtime where
Block = Block,
- NodeBlock = primitives::Block,
+ NodeBlock = primitives::v0::Block,
UncheckedExtrinsic = UncheckedExtrinsic
{
// Basic stuff; balances is uncallable initially.
@@ -1147,7 +1148,7 @@ sp_api::impl_runtime_apis! {
fn signing_context() -> SigningContext {
Parachains::signing_context()
}
- fn downward_messages(id: parachain::Id) -> Vec {
+ fn downward_messages(id: parachain::Id) -> Vec {
Parachains::downward_messages(id)
}
}
diff --git a/runtime/parachains/src/configuration.rs b/runtime/parachains/src/configuration.rs
index 792dfe89a7b2..40688041b265 100644
--- a/runtime/parachains/src/configuration.rs
+++ b/runtime/parachains/src/configuration.rs
@@ -19,9 +19,7 @@
//! Configuration can change only at session boundaries and is buffered until then.
use sp_std::prelude::*;
-use primitives::{
- parachain::{ValidatorId},
-};
+use primitives::v1::ValidatorId;
use frame_support::{
decl_storage, decl_module, decl_error,
dispatch::DispatchResult,
diff --git a/runtime/parachains/src/inclusion.rs b/runtime/parachains/src/inclusion.rs
index 33a5e2d1e919..a2480f1c8034 100644
--- a/runtime/parachains/src/inclusion.rs
+++ b/runtime/parachains/src/inclusion.rs
@@ -21,12 +21,10 @@
//! to included.
use sp_std::prelude::*;
-use primitives::{
- parachain::{
- ValidatorId, AbridgedCandidateReceipt, ValidatorIndex, Id as ParaId,
- AvailabilityBitfield as AvailabilityBitfield, SignedAvailabilityBitfields, SigningContext,
- BackedCandidate, CoreIndex, GroupIndex, CoreAssignment,
- },
+use primitives::v1::{
+ ValidatorId, CommittedCandidateReceipt, ValidatorIndex, Id as ParaId,
+ AvailabilityBitfield as AvailabilityBitfield, SignedAvailabilityBitfields, SigningContext,
+ BackedCandidate, CoreIndex, GroupIndex, CoreAssignment,
};
use frame_support::{
decl_storage, decl_module, decl_error, ensure, dispatch::DispatchResult, IterableStorageMap,
@@ -53,13 +51,15 @@ pub struct AvailabilityBitfieldRecord {
}
/// A backed candidate pending availability.
+// TODO: split this type and change this to hold a plain `CandidateReceipt`.
+// https://github.com/paritytech/polkadot/issues/1357
#[derive(Encode, Decode, PartialEq)]
#[cfg_attr(test, derive(Debug))]
pub struct CandidatePendingAvailability {
/// The availability core this is assigned to.
core: CoreIndex,
/// The candidate receipt itself.
- receipt: AbridgedCandidateReceipt,
+ receipt: CommittedCandidateReceipt,
/// The received availability votes. One bit per validator.
availability_votes: BitVec,
/// The block number of the relay-parent of the receipt.
@@ -213,7 +213,10 @@ impl Module {
let validator_public = &validators[signed_bitfield.validator_index() as usize];
- signed_bitfield.check_signature(&signing_context, validator_public).map_err(|_| Error::::InvalidBitfieldSignature)?;
+ signed_bitfield.check_signature(
+ &signing_context,
+ validator_public,
+ ).map_err(|_| Error::::InvalidBitfieldSignature)?;
last_index = Some(signed_bitfield.validator_index());
}
@@ -331,11 +334,11 @@ impl Module {
// list.
'a:
for candidate in &candidates {
- let para_id = candidate.candidate.parachain_index;
+ let para_id = candidate.descriptor().para_id;
// we require that the candidate is in the context of the parent block.
ensure!(
- candidate.candidate.relay_parent == parent_hash,
+ candidate.descriptor().relay_parent == parent_hash,
Error::::CandidateNotInParentContext,
);
@@ -348,17 +351,17 @@ impl Module {
ensure!(code_upgrade_allowed, Error::::PrematureCodeUpgrade);
ensure!(
- candidate.candidate.check_signature().is_ok(),
+ candidate.descriptor().check_collator_signature().is_ok(),
Error::::NotCollatorSigned,
);
for (i, assignment) in scheduled[skip..].iter().enumerate() {
check_assignment_in_order(assignment)?;
- if candidate.candidate.parachain_index == assignment.para_id {
+ if candidate.descriptor().para_id == assignment.para_id {
if let Some(required_collator) = assignment.required_collator() {
ensure!(
- required_collator == &candidate.candidate.collator,
+ required_collator == &candidate.descriptor().collator,
Error::::WrongCollator,
);
}
@@ -377,7 +380,7 @@ impl Module {
// check the signatures in the backing and that it is a majority.
{
let maybe_amount_validated
- = primitives::parachain::check_candidate_backing(
+ = primitives::v1::check_candidate_backing(
&candidate,
&signing_context,
group_vals.len(),
@@ -419,7 +422,7 @@ impl Module {
// one more sweep for actually writing to storage.
for (candidate, core) in candidates.into_iter().zip(core_indices.iter().cloned()) {
- let para_id = candidate.candidate.parachain_index;
+ let para_id = candidate.descriptor().para_id;
// initialize all availability votes to 0.
let availability_votes: BitVec
@@ -438,7 +441,7 @@ impl Module {
fn enact_candidate(
relay_parent_number: T::BlockNumber,
- receipt: AbridgedCandidateReceipt