mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 07:01:03 +00:00
Move parachain inherent data into its own crate (#326)
This renames and moves the `SystemInherentData` into its own crate. The struct is now called `ParachainInherentData`. Besides moving the struct, this also moves the code for creating this struct into this crate.
This commit is contained in:
Generated
+20
-2
@@ -1075,6 +1075,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"cumulus-client-network",
|
||||
"cumulus-primitives-core",
|
||||
"cumulus-primitives-parachain-inherent",
|
||||
"cumulus-test-client",
|
||||
"cumulus-test-runtime",
|
||||
"env_logger",
|
||||
@@ -1188,6 +1189,7 @@ name = "cumulus-pallet-parachain-system"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"cumulus-primitives-core",
|
||||
"cumulus-primitives-parachain-inherent",
|
||||
"cumulus-test-client",
|
||||
"cumulus-test-relay-sproof-builder",
|
||||
"env_logger",
|
||||
@@ -1241,18 +1243,34 @@ dependencies = [
|
||||
"polkadot-core-primitives",
|
||||
"polkadot-parachain",
|
||||
"polkadot-primitives",
|
||||
"sp-core",
|
||||
"sp-inherents",
|
||||
"sp-runtime",
|
||||
"sp-std",
|
||||
"sp-trie",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cumulus-primitives-parachain-inherent"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"cumulus-primitives-core",
|
||||
"parity-scale-codec",
|
||||
"sc-client-api",
|
||||
"sp-api",
|
||||
"sp-core",
|
||||
"sp-inherents",
|
||||
"sp-runtime",
|
||||
"sp-state-machine",
|
||||
"sp-std",
|
||||
"sp-trie",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cumulus-test-client"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"cumulus-primitives-core",
|
||||
"cumulus-primitives-parachain-inherent",
|
||||
"cumulus-test-relay-sproof-builder",
|
||||
"cumulus-test-runtime",
|
||||
"cumulus-test-service",
|
||||
|
||||
@@ -6,6 +6,7 @@ members = [
|
||||
"pallets/parachain-system",
|
||||
"pallets/xcm-handler",
|
||||
"primitives/core",
|
||||
"primitives/parachain-inherent",
|
||||
"rococo-parachains/",
|
||||
"rococo-parachains/pallets/parachain-info",
|
||||
"rococo-parachains/primitives",
|
||||
|
||||
@@ -27,6 +27,7 @@ polkadot-node-subsystem = { git = "https://github.com/paritytech/polkadot", bran
|
||||
# Cumulus dependencies
|
||||
cumulus-client-network = { path = "../network" }
|
||||
cumulus-primitives-core = { path = "../../primitives/core" }
|
||||
cumulus-primitives-parachain-inherent = { path = "../../primitives/parachain-inherent" }
|
||||
|
||||
# Other dependencies
|
||||
log = "0.4.8"
|
||||
|
||||
@@ -18,10 +18,9 @@
|
||||
|
||||
use cumulus_client_network::WaitToAnnounce;
|
||||
use cumulus_primitives_core::{
|
||||
inherents, ParachainBlockData,
|
||||
well_known_keys, InboundDownwardMessage, InboundHrmpMessage, OutboundHrmpMessage,
|
||||
PersistedValidationData, relay_chain,
|
||||
well_known_keys, OutboundHrmpMessage, ParachainBlockData, PersistedValidationData,
|
||||
};
|
||||
use cumulus_primitives_parachain_inherent::ParachainInherentData;
|
||||
|
||||
use sc_client_api::{BlockBackend, StateBackend};
|
||||
use sp_consensus::{
|
||||
@@ -41,7 +40,7 @@ use polkadot_node_subsystem::messages::{CollationGenerationMessage, CollatorProt
|
||||
use polkadot_overseer::OverseerHandler;
|
||||
use polkadot_primitives::v1::{
|
||||
Block as PBlock, BlockData, BlockNumber as PBlockNumber, CollatorPair, Hash as PHash, HeadData,
|
||||
Id as ParaId, PoV, UpwardMessage, HrmpChannelId,
|
||||
Id as ParaId, PoV, UpwardMessage,
|
||||
};
|
||||
use polkadot_service::RuntimeApiCollection;
|
||||
|
||||
@@ -51,7 +50,7 @@ use log::{debug, error, info, trace};
|
||||
|
||||
use futures::prelude::*;
|
||||
|
||||
use std::{collections::BTreeMap, marker::PhantomData, sync::Arc, time::Duration};
|
||||
use std::{marker::PhantomData, sync::Arc, time::Duration};
|
||||
|
||||
use parking_lot::Mutex;
|
||||
|
||||
@@ -101,10 +100,10 @@ where
|
||||
PF: Environment<Block> + 'static + Send,
|
||||
PF::Proposer: Send,
|
||||
BI: BlockImport<
|
||||
Block,
|
||||
Error = ConsensusError,
|
||||
Transaction = <PF::Proposer as Proposer<Block>>::Transaction,
|
||||
> + Send
|
||||
Block,
|
||||
Error = ConsensusError,
|
||||
Transaction = <PF::Proposer as Proposer<Block>>::Transaction,
|
||||
> + Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
BS: BlockBackend<Block>,
|
||||
@@ -150,161 +149,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the whole contents of the downward message queue for the parachain we are collating
|
||||
/// for.
|
||||
///
|
||||
/// Returns `None` in case of an error.
|
||||
fn retrieve_dmq_contents(&self, relay_parent: PHash) -> Option<Vec<InboundDownwardMessage>> {
|
||||
self.polkadot_client
|
||||
.runtime_api()
|
||||
.dmq_contents_with_context(
|
||||
&BlockId::hash(relay_parent),
|
||||
sp_core::ExecutionContext::Importing,
|
||||
self.para_id,
|
||||
)
|
||||
.map_err(|e| {
|
||||
error!(
|
||||
target: LOG_TARGET,
|
||||
"An error occured during requesting the downward messages for {}: {:?}",
|
||||
relay_parent, e,
|
||||
);
|
||||
})
|
||||
.ok()
|
||||
}
|
||||
|
||||
/// Returns channels contents for each inbound HRMP channel addressed to the parachain we are
|
||||
/// collating for.
|
||||
///
|
||||
/// Empty channels are also included.
|
||||
fn retrieve_all_inbound_hrmp_channel_contents(
|
||||
&self,
|
||||
relay_parent: PHash,
|
||||
) -> Option<BTreeMap<ParaId, Vec<InboundHrmpMessage>>> {
|
||||
self.polkadot_client
|
||||
.runtime_api()
|
||||
.inbound_hrmp_channels_contents_with_context(
|
||||
&BlockId::hash(relay_parent),
|
||||
sp_core::ExecutionContext::Importing,
|
||||
self.para_id,
|
||||
)
|
||||
.map_err(|e| {
|
||||
error!(
|
||||
target: LOG_TARGET,
|
||||
"An error occured during requesting the inbound HRMP messages for {}: {:?}",
|
||||
relay_parent, e,
|
||||
);
|
||||
})
|
||||
.ok()
|
||||
}
|
||||
|
||||
/// Collect the relevant relay chain state in form of a proof for putting it into the validation
|
||||
/// data inherent.
|
||||
fn collect_relay_storage_proof(
|
||||
&self,
|
||||
relay_parent: PHash,
|
||||
) -> Option<sp_state_machine::StorageProof> {
|
||||
use relay_chain::well_known_keys as relay_well_known_keys;
|
||||
|
||||
let relay_parent_state_backend = self
|
||||
.polkadot_backend
|
||||
.state_at(BlockId::Hash(relay_parent))
|
||||
.map_err(|e| {
|
||||
error!(
|
||||
target: LOG_TARGET,
|
||||
"Cannot obtain the state of the relay chain at `{:?}`: {:?}",
|
||||
relay_parent,
|
||||
e,
|
||||
)
|
||||
})
|
||||
.ok()?;
|
||||
|
||||
let ingress_channels = relay_parent_state_backend
|
||||
.storage(&relay_well_known_keys::hrmp_ingress_channel_index(
|
||||
self.para_id,
|
||||
))
|
||||
.map_err(|e| {
|
||||
error!(
|
||||
target: LOG_TARGET,
|
||||
"Cannot obtain the hrmp ingress channel index: {:?}",
|
||||
e,
|
||||
)
|
||||
})
|
||||
.ok()?;
|
||||
let ingress_channels = ingress_channels
|
||||
.map(|raw| <Vec<ParaId>>::decode(&mut &raw[..]))
|
||||
.transpose()
|
||||
.map_err(|e| {
|
||||
error!(
|
||||
target: LOG_TARGET,
|
||||
"Cannot decode the hrmp ingress channel index: {:?}",
|
||||
e,
|
||||
)
|
||||
})
|
||||
.ok()?
|
||||
.unwrap_or_default();
|
||||
|
||||
let egress_channels = relay_parent_state_backend
|
||||
.storage(&relay_well_known_keys::hrmp_egress_channel_index(
|
||||
self.para_id,
|
||||
))
|
||||
.map_err(|e| {
|
||||
error!(
|
||||
target: LOG_TARGET,
|
||||
"Cannot obtain the hrmp egress channel index: {:?}",
|
||||
e,
|
||||
)
|
||||
})
|
||||
.ok()?;
|
||||
let egress_channels = egress_channels
|
||||
.map(|raw| <Vec<ParaId>>::decode(&mut &raw[..]))
|
||||
.transpose()
|
||||
.map_err(|e| {
|
||||
error!(
|
||||
target: LOG_TARGET,
|
||||
"Cannot decode the hrmp egress channel index: {:?}",
|
||||
e,
|
||||
)
|
||||
})
|
||||
.ok()?
|
||||
.unwrap_or_default();
|
||||
|
||||
let mut relevant_keys = vec![];
|
||||
relevant_keys.push(relay_well_known_keys::ACTIVE_CONFIG.to_vec());
|
||||
relevant_keys.push(relay_well_known_keys::dmq_mqc_head(self.para_id));
|
||||
relevant_keys.push(relay_well_known_keys::relay_dispatch_queue_size(
|
||||
self.para_id,
|
||||
));
|
||||
relevant_keys.push(relay_well_known_keys::hrmp_ingress_channel_index(
|
||||
self.para_id,
|
||||
));
|
||||
relevant_keys.push(relay_well_known_keys::hrmp_egress_channel_index(
|
||||
self.para_id,
|
||||
));
|
||||
relevant_keys.extend(ingress_channels.into_iter().map(|sender| {
|
||||
relay_well_known_keys::hrmp_channels(HrmpChannelId {
|
||||
sender,
|
||||
recipient: self.para_id,
|
||||
})
|
||||
}));
|
||||
relevant_keys.extend(egress_channels.into_iter().map(|recipient| {
|
||||
relay_well_known_keys::hrmp_channels(HrmpChannelId {
|
||||
sender: self.para_id,
|
||||
recipient,
|
||||
})
|
||||
}));
|
||||
|
||||
sp_state_machine::prove_read(relay_parent_state_backend, relevant_keys)
|
||||
.map_err(|e| {
|
||||
error!(
|
||||
target: LOG_TARGET,
|
||||
"Failed to collect required relay chain state storage proof at `{:?}`: {:?}",
|
||||
relay_parent,
|
||||
e,
|
||||
)
|
||||
})
|
||||
.ok()
|
||||
}
|
||||
|
||||
/// Get the inherent data with validation function parameters injected
|
||||
fn inherent_data(
|
||||
&mut self,
|
||||
@@ -317,36 +161,28 @@ where
|
||||
.map_err(|e| {
|
||||
error!(
|
||||
target: LOG_TARGET,
|
||||
"Failed to create inherent data: {:?}",
|
||||
e,
|
||||
"Failed to create inherent data: {:?}", e,
|
||||
)
|
||||
})
|
||||
.ok()?;
|
||||
|
||||
let system_inherent_data = {
|
||||
let relay_chain_state = self.collect_relay_storage_proof(relay_parent)?;
|
||||
let downward_messages = self.retrieve_dmq_contents(relay_parent)?;
|
||||
let horizontal_messages =
|
||||
self.retrieve_all_inbound_hrmp_channel_contents(relay_parent)?;
|
||||
|
||||
inherents::SystemInherentData {
|
||||
downward_messages,
|
||||
horizontal_messages,
|
||||
validation_data: validation_data.clone(),
|
||||
relay_chain_state,
|
||||
}
|
||||
};
|
||||
let parachain_inherent_data = ParachainInherentData::create_at(
|
||||
relay_parent,
|
||||
&*self.polkadot_client,
|
||||
&*self.polkadot_backend,
|
||||
validation_data,
|
||||
self.para_id,
|
||||
)?;
|
||||
|
||||
inherent_data
|
||||
.put_data(
|
||||
inherents::SYSTEM_INHERENT_IDENTIFIER,
|
||||
&system_inherent_data,
|
||||
cumulus_primitives_parachain_inherent::INHERENT_IDENTIFIER,
|
||||
¶chain_inherent_data,
|
||||
)
|
||||
.map_err(|e| {
|
||||
error!(
|
||||
target: LOG_TARGET,
|
||||
"Failed to put the system inherent into inherent data: {:?}",
|
||||
e,
|
||||
"Failed to put the system inherent into inherent data: {:?}", e,
|
||||
)
|
||||
})
|
||||
.ok()?;
|
||||
@@ -371,8 +207,7 @@ where
|
||||
Ok(BlockStatus::InChainPruned) => {
|
||||
error!(
|
||||
target: LOG_TARGET,
|
||||
"Skipping candidate production, because block `{:?}` is already pruned!",
|
||||
hash,
|
||||
"Skipping candidate production, because block `{:?}` is already pruned!", hash,
|
||||
);
|
||||
false
|
||||
}
|
||||
@@ -394,8 +229,7 @@ where
|
||||
} else {
|
||||
debug!(
|
||||
target: LOG_TARGET,
|
||||
"Skipping candidate production, because block `{:?}` is unknown.",
|
||||
hash,
|
||||
"Skipping candidate production, because block `{:?}` is unknown.", hash,
|
||||
);
|
||||
}
|
||||
false
|
||||
@@ -403,9 +237,7 @@ where
|
||||
Err(e) => {
|
||||
error!(
|
||||
target: LOG_TARGET,
|
||||
"Failed to get block status of `{:?}`: {:?}",
|
||||
hash,
|
||||
e,
|
||||
"Failed to get block status of `{:?}`: {:?}", hash, e,
|
||||
);
|
||||
false
|
||||
}
|
||||
@@ -425,39 +257,45 @@ where
|
||||
let state = match self.backend.state_at(BlockId::Hash(block_hash)) {
|
||||
Ok(state) => state,
|
||||
Err(e) => {
|
||||
error!(target: LOG_TARGET, "Failed to get state of the freshly built block: {:?}", e);
|
||||
error!(
|
||||
target: LOG_TARGET,
|
||||
"Failed to get state of the freshly built block: {:?}", e
|
||||
);
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
state.inspect_state(|| {
|
||||
let upward_messages = sp_io::storage::get(well_known_keys::UPWARD_MESSAGES);
|
||||
let upward_messages = match upward_messages.map(|v| Vec::<UpwardMessage>::decode(&mut &v[..])) {
|
||||
Some(Ok(msgs)) => msgs,
|
||||
Some(Err(e)) => {
|
||||
error!(target: LOG_TARGET, "Failed to decode upward messages from the build block: {:?}", e);
|
||||
return None
|
||||
},
|
||||
None => Vec::new(),
|
||||
};
|
||||
let upward_messages =
|
||||
match upward_messages.map(|v| Vec::<UpwardMessage>::decode(&mut &v[..])) {
|
||||
Some(Ok(msgs)) => msgs,
|
||||
Some(Err(e)) => {
|
||||
error!(
|
||||
target: LOG_TARGET,
|
||||
"Failed to decode upward messages from the build block: {:?}", e
|
||||
);
|
||||
return None;
|
||||
}
|
||||
None => Vec::new(),
|
||||
};
|
||||
|
||||
let new_validation_code = sp_io::storage::get(well_known_keys::NEW_VALIDATION_CODE);
|
||||
|
||||
let processed_downward_messages = sp_io::storage::get(well_known_keys::PROCESSED_DOWNWARD_MESSAGES);
|
||||
let processed_downward_messages = match processed_downward_messages
|
||||
.map(|v| u32::decode(&mut &v[..]))
|
||||
{
|
||||
Some(Ok(processed_cnt)) => processed_cnt,
|
||||
Some(Err(e)) => {
|
||||
error!(
|
||||
target: LOG_TARGET,
|
||||
"Failed to decode the count of processed downward messages: {:?}",
|
||||
e
|
||||
);
|
||||
return None
|
||||
}
|
||||
None => 0,
|
||||
};
|
||||
let processed_downward_messages =
|
||||
sp_io::storage::get(well_known_keys::PROCESSED_DOWNWARD_MESSAGES);
|
||||
let processed_downward_messages =
|
||||
match processed_downward_messages.map(|v| u32::decode(&mut &v[..])) {
|
||||
Some(Ok(processed_cnt)) => processed_cnt,
|
||||
Some(Err(e)) => {
|
||||
error!(
|
||||
target: LOG_TARGET,
|
||||
"Failed to decode the count of processed downward messages: {:?}", e
|
||||
);
|
||||
return None;
|
||||
}
|
||||
None => 0,
|
||||
};
|
||||
|
||||
let horizontal_messages = sp_io::storage::get(well_known_keys::HRMP_OUTBOUND_MESSAGES);
|
||||
let horizontal_messages = match horizontal_messages
|
||||
@@ -467,10 +305,9 @@ where
|
||||
Some(Err(e)) => {
|
||||
error!(
|
||||
target: LOG_TARGET,
|
||||
"Failed to decode the horizontal messages: {:?}",
|
||||
e
|
||||
"Failed to decode the horizontal messages: {:?}", e
|
||||
);
|
||||
return None
|
||||
return None;
|
||||
}
|
||||
None => Vec::new(),
|
||||
};
|
||||
@@ -481,10 +318,9 @@ where
|
||||
Some(Err(e)) => {
|
||||
error!(
|
||||
target: LOG_TARGET,
|
||||
"Failed to decode the HRMP watermark: {:?}",
|
||||
e
|
||||
"Failed to decode the HRMP watermark: {:?}", e
|
||||
);
|
||||
return None
|
||||
return None;
|
||||
}
|
||||
None => {
|
||||
// If the runtime didn't set `HRMP_WATERMARK`, then it means no messages were
|
||||
@@ -514,14 +350,16 @@ where
|
||||
) -> Option<Collation> {
|
||||
trace!(target: LOG_TARGET, "Producing candidate");
|
||||
|
||||
let last_head =
|
||||
match Block::Header::decode(&mut &validation_data.parent_head.0[..]) {
|
||||
Ok(x) => x,
|
||||
Err(e) => {
|
||||
error!(target: LOG_TARGET, "Could not decode the head data: {:?}", e);
|
||||
return None;
|
||||
}
|
||||
};
|
||||
let last_head = match Block::Header::decode(&mut &validation_data.parent_head.0[..]) {
|
||||
Ok(x) => x,
|
||||
Err(e) => {
|
||||
error!(
|
||||
target: LOG_TARGET,
|
||||
"Could not decode the head data: {:?}", e
|
||||
);
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
let last_head_hash = last_head.hash();
|
||||
if !self.check_block_status(last_head_hash, &last_head) {
|
||||
@@ -539,13 +377,7 @@ where
|
||||
|
||||
let proposer = proposer_future
|
||||
.await
|
||||
.map_err(|e| {
|
||||
error!(
|
||||
target: LOG_TARGET,
|
||||
"Could not create proposer: {:?}",
|
||||
e,
|
||||
)
|
||||
})
|
||||
.map_err(|e| error!(target: LOG_TARGET, "Could not create proposer: {:?}", e,))
|
||||
.ok()?;
|
||||
|
||||
let inherent_data = self.inherent_data(&validation_data, relay_parent)?;
|
||||
@@ -563,13 +395,7 @@ where
|
||||
RecordProof::Yes,
|
||||
)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
error!(
|
||||
target: LOG_TARGET,
|
||||
"Proposing failed: {:?}",
|
||||
e,
|
||||
)
|
||||
})
|
||||
.map_err(|e| error!(target: LOG_TARGET, "Proposing failed: {:?}", e,))
|
||||
.ok()?;
|
||||
|
||||
let proof = match proof {
|
||||
@@ -619,8 +445,7 @@ where
|
||||
b.storage_proof().encode().len() as f64 / 1024f64,
|
||||
);
|
||||
|
||||
let collation =
|
||||
self.build_collation(b, block_hash, validation_data.relay_parent_number)?;
|
||||
let collation = self.build_collation(b, block_hash, validation_data.relay_parent_number)?;
|
||||
let pov_hash = collation.proof_of_validity.hash();
|
||||
|
||||
self.wait_to_announce
|
||||
@@ -629,9 +454,7 @@ where
|
||||
|
||||
info!(
|
||||
target: LOG_TARGET,
|
||||
"Produced proof-of-validity candidate {:?} from block {:?}.",
|
||||
pov_hash,
|
||||
block_hash,
|
||||
"Produced proof-of-validity candidate {:?} from block {:?}.", pov_hash, block_hash,
|
||||
);
|
||||
|
||||
Some(collation)
|
||||
|
||||
@@ -8,6 +8,7 @@ description = "Base pallet for cumulus-based parachains"
|
||||
[dependencies]
|
||||
# Cumulus dependencies
|
||||
cumulus-primitives-core = { path = "../../primitives/core", default-features = false }
|
||||
cumulus-primitives-parachain-inherent = { path = "../../primitives/parachain-inherent", default-features = false }
|
||||
|
||||
# Polkadot dependencies
|
||||
polkadot-parachain = { git = "https://github.com/paritytech/polkadot", default-features = false, features = [ "wasm-api" ], branch = "master" }
|
||||
@@ -68,4 +69,5 @@ std = [
|
||||
"frame-system/std",
|
||||
"frame-executive/std",
|
||||
"cumulus-primitives-core/std",
|
||||
"cumulus-primitives-parachain-inherent/std",
|
||||
]
|
||||
|
||||
@@ -28,13 +28,13 @@
|
||||
//! Users must ensure that they register this pallet as an inherent provider.
|
||||
|
||||
use cumulus_primitives_core::{
|
||||
inherents::{SystemInherentData, SYSTEM_INHERENT_IDENTIFIER},
|
||||
relay_chain,
|
||||
well_known_keys::{self, NEW_VALIDATION_CODE, VALIDATION_DATA},
|
||||
AbridgedHostConfiguration, DownwardMessageHandler, HrmpMessageHandler, HrmpMessageSender,
|
||||
InboundDownwardMessage, InboundHrmpMessage, OnValidationData, OutboundHrmpMessage, ParaId,
|
||||
PersistedValidationData, UpwardMessage, UpwardMessageSender,
|
||||
};
|
||||
use cumulus_primitives_parachain_inherent::ParachainInherentData;
|
||||
use frame_support::{
|
||||
decl_error, decl_event, decl_module, decl_storage,
|
||||
dispatch::DispatchResult,
|
||||
@@ -166,11 +166,11 @@ decl_module! {
|
||||
/// As a side effect, this function upgrades the current validation function
|
||||
/// if the appropriate time has come.
|
||||
#[weight = (0, DispatchClass::Mandatory)]
|
||||
fn set_validation_data(origin, data: SystemInherentData) -> DispatchResult {
|
||||
fn set_validation_data(origin, data: ParachainInherentData) -> DispatchResult {
|
||||
ensure_none(origin)?;
|
||||
assert!(!DidUpdateValidationData::exists(), "ValidationData must be updated only once in a block");
|
||||
|
||||
let SystemInherentData {
|
||||
let ParachainInherentData {
|
||||
validation_data: vfp,
|
||||
relay_chain_state,
|
||||
downward_messages,
|
||||
@@ -798,11 +798,12 @@ impl<T: Config> HrmpMessageSender for Module<T> {
|
||||
impl<T: Config> ProvideInherent for Module<T> {
|
||||
type Call = Call<T>;
|
||||
type Error = sp_inherents::MakeFatalError<()>;
|
||||
const INHERENT_IDENTIFIER: InherentIdentifier = SYSTEM_INHERENT_IDENTIFIER;
|
||||
const INHERENT_IDENTIFIER: InherentIdentifier =
|
||||
cumulus_primitives_parachain_inherent::INHERENT_IDENTIFIER;
|
||||
|
||||
fn create_inherent(data: &InherentData) -> Option<Self::Call> {
|
||||
let data: SystemInherentData = data
|
||||
.get_data(&SYSTEM_INHERENT_IDENTIFIER)
|
||||
let data: ParachainInherentData = data
|
||||
.get_data(&Self::INHERENT_IDENTIFIER)
|
||||
.ok()
|
||||
.flatten()
|
||||
.expect("validation function params are always injected into inherent data; qed");
|
||||
@@ -1029,7 +1030,7 @@ mod tests {
|
||||
persisted_validation_data_hook:
|
||||
Option<Box<dyn Fn(&BlockTests, RelayChainBlockNumber, &mut PersistedValidationData)>>,
|
||||
inherent_data_hook:
|
||||
Option<Box<dyn Fn(&BlockTests, RelayChainBlockNumber, &mut SystemInherentData)>>,
|
||||
Option<Box<dyn Fn(&BlockTests, RelayChainBlockNumber, &mut ParachainInherentData)>>,
|
||||
}
|
||||
|
||||
impl BlockTests {
|
||||
@@ -1089,7 +1090,7 @@ mod tests {
|
||||
|
||||
fn with_inherent_data<F>(mut self, f: F) -> Self
|
||||
where
|
||||
F: 'static + Fn(&BlockTests, RelayChainBlockNumber, &mut SystemInherentData),
|
||||
F: 'static + Fn(&BlockTests, RelayChainBlockNumber, &mut ParachainInherentData),
|
||||
{
|
||||
self.inherent_data_hook = Some(Box::new(f));
|
||||
self
|
||||
@@ -1142,7 +1143,7 @@ mod tests {
|
||||
// to storage; they must also be included in the inherent data.
|
||||
let inherent_data = {
|
||||
let mut inherent_data = InherentData::default();
|
||||
let mut system_inherent_data = SystemInherentData {
|
||||
let mut system_inherent_data = ParachainInherentData {
|
||||
validation_data: vfp.clone(),
|
||||
relay_chain_state,
|
||||
downward_messages: Default::default(),
|
||||
@@ -1152,7 +1153,10 @@ mod tests {
|
||||
hook(self, *n as RelayChainBlockNumber, &mut system_inherent_data);
|
||||
}
|
||||
inherent_data
|
||||
.put_data(SYSTEM_INHERENT_IDENTIFIER, &system_inherent_data)
|
||||
.put_data(
|
||||
cumulus_primitives_parachain_inherent::INHERENT_IDENTIFIER,
|
||||
&system_inherent_data,
|
||||
)
|
||||
.expect("failed to put VFP inherent");
|
||||
inherent_data
|
||||
};
|
||||
|
||||
@@ -6,33 +6,27 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
# Substrate dependencies
|
||||
sp-inherents = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
|
||||
sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
|
||||
sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
|
||||
sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
|
||||
sp-trie = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
|
||||
|
||||
# Polkadot dependencies
|
||||
polkadot-parachain = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
|
||||
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
|
||||
polkadot-core-primitives = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
|
||||
|
||||
# Other dependencies
|
||||
codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ "derive" ] }
|
||||
impl-trait-for-tuples = "0.2.1"
|
||||
|
||||
# Polkadot dependencies
|
||||
polkadot-core-primitives = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
|
||||
codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ "derive" ] }
|
||||
|
||||
[features]
|
||||
default = [ "std" ]
|
||||
std = [
|
||||
"sp-std/std",
|
||||
"codec/std",
|
||||
"sp-std/std",
|
||||
"polkadot-primitives/std",
|
||||
"polkadot-parachain/std",
|
||||
"sp-inherents/std",
|
||||
"polkadot-core-primitives/std",
|
||||
"sp-runtime/std",
|
||||
"sp-core/std",
|
||||
"sp-trie/std",
|
||||
]
|
||||
|
||||
@@ -39,37 +39,6 @@ pub type InboundHrmpMessage = polkadot_primitives::v1::InboundHrmpMessage<relay_
|
||||
/// And outbound HRMP message
|
||||
pub type OutboundHrmpMessage = polkadot_primitives::v1::OutboundHrmpMessage<ParaId>;
|
||||
|
||||
/// Identifiers and types related to Cumulus Inherents
|
||||
pub mod inherents {
|
||||
use super::{InboundDownwardMessage, InboundHrmpMessage, ParaId};
|
||||
use sp_inherents::InherentIdentifier;
|
||||
use sp_std::{collections::btree_map::BTreeMap, vec::Vec};
|
||||
|
||||
/// The identifier for the parachain-system inherent.
|
||||
pub const SYSTEM_INHERENT_IDENTIFIER: InherentIdentifier = *b"sysi1337";
|
||||
|
||||
/// The payload that system inherent carries.
|
||||
#[derive(codec::Encode, codec::Decode, sp_core::RuntimeDebug, Clone, PartialEq)]
|
||||
pub struct SystemInherentData {
|
||||
pub validation_data: crate::PersistedValidationData,
|
||||
/// A storage proof of a predefined set of keys from the relay-chain.
|
||||
///
|
||||
/// Specifically this witness contains the data for:
|
||||
///
|
||||
/// - active host configuration as per the relay parent,
|
||||
/// - the relay dispatch queue sizes
|
||||
/// - the list of egress HRMP channels (in the list of recipients form)
|
||||
/// - the metadata for the egress HRMP channels
|
||||
pub relay_chain_state: sp_trie::StorageProof,
|
||||
/// Downward messages in the order they were sent.
|
||||
pub downward_messages: Vec<InboundDownwardMessage>,
|
||||
/// HRMP messages grouped by channels. The messages in the inner vec must be in order they
|
||||
/// were sent. In combination with the rule of no more than one message in a channel per block,
|
||||
/// this means `sent_at` is **strictly** greater than the previous one (if any).
|
||||
pub horizontal_messages: BTreeMap<ParaId, Vec<InboundHrmpMessage>>,
|
||||
}
|
||||
}
|
||||
|
||||
/// Well known keys for values in the storage.
|
||||
pub mod well_known_keys {
|
||||
/// The storage key for the upward messages.
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
[package]
|
||||
name = "cumulus-primitives-parachain-inherent"
|
||||
version = "0.1.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
# Substrate dependencies
|
||||
sp-inherents = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
|
||||
sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
|
||||
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master", optional = true }
|
||||
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", optional = true }
|
||||
sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
|
||||
sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "master", optional = true }
|
||||
sp-trie = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
|
||||
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", optional = true }
|
||||
|
||||
# Cumulus dependencies
|
||||
cumulus-primitives-core = { path = "../core", default-features = false }
|
||||
|
||||
# Other dependencies
|
||||
codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ "derive" ] }
|
||||
tracing = { version = "0.1.22", optional = true }
|
||||
|
||||
[features]
|
||||
default = [ "std" ]
|
||||
std = [
|
||||
"codec/std",
|
||||
"cumulus-primitives-core/std",
|
||||
"sp-inherents/std",
|
||||
"sp-core/std",
|
||||
"sp-trie/std",
|
||||
"sp-std/std",
|
||||
"sp-state-machine",
|
||||
"tracing",
|
||||
"sp-runtime",
|
||||
"sc-client-api",
|
||||
"sp-api",
|
||||
]
|
||||
@@ -0,0 +1,225 @@
|
||||
// Copyright 2021 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Cumulus.
|
||||
|
||||
// Substrate 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.
|
||||
|
||||
// Substrate 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 Cumulus. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Client side code for generating the parachain inherent.
|
||||
|
||||
use crate::ParachainInherentData;
|
||||
use codec::Decode;
|
||||
use cumulus_primitives_core::{
|
||||
relay_chain::{
|
||||
self,
|
||||
v1::{HrmpChannelId, ParachainHost},
|
||||
Block as PBlock, Hash as PHash,
|
||||
},
|
||||
InboundDownwardMessage, InboundHrmpMessage, ParaId, PersistedValidationData,
|
||||
};
|
||||
use sc_client_api::Backend;
|
||||
use sp_api::ProvideRuntimeApi;
|
||||
use sp_runtime::generic::BlockId;
|
||||
use sp_state_machine::Backend as _;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
const LOG_TARGET: &str = "parachain-inherent";
|
||||
|
||||
/// Returns the whole contents of the downward message queue for the parachain we are collating
|
||||
/// for.
|
||||
///
|
||||
/// Returns `None` in case of an error.
|
||||
fn retrieve_dmq_contents<PClient>(
|
||||
polkadot_client: &PClient,
|
||||
para_id: ParaId,
|
||||
relay_parent: PHash,
|
||||
) -> Option<Vec<InboundDownwardMessage>>
|
||||
where
|
||||
PClient: ProvideRuntimeApi<PBlock>,
|
||||
PClient::Api: ParachainHost<PBlock>,
|
||||
{
|
||||
polkadot_client
|
||||
.runtime_api()
|
||||
.dmq_contents_with_context(
|
||||
&BlockId::hash(relay_parent),
|
||||
sp_core::ExecutionContext::Importing,
|
||||
para_id,
|
||||
)
|
||||
.map_err(|e| {
|
||||
tracing::error!(
|
||||
target: LOG_TARGET,
|
||||
relay_parent = ?relay_parent,
|
||||
error = ?e,
|
||||
"An error occured during requesting the downward messages.",
|
||||
);
|
||||
})
|
||||
.ok()
|
||||
}
|
||||
|
||||
/// Returns channels contents for each inbound HRMP channel addressed to the parachain we are
|
||||
/// collating for.
|
||||
///
|
||||
/// Empty channels are also included.
|
||||
fn retrieve_all_inbound_hrmp_channel_contents<PClient>(
|
||||
polkadot_client: &PClient,
|
||||
para_id: ParaId,
|
||||
relay_parent: PHash,
|
||||
) -> Option<BTreeMap<ParaId, Vec<InboundHrmpMessage>>>
|
||||
where
|
||||
PClient: ProvideRuntimeApi<PBlock>,
|
||||
PClient::Api: ParachainHost<PBlock>,
|
||||
{
|
||||
polkadot_client
|
||||
.runtime_api()
|
||||
.inbound_hrmp_channels_contents_with_context(
|
||||
&BlockId::hash(relay_parent),
|
||||
sp_core::ExecutionContext::Importing,
|
||||
para_id,
|
||||
)
|
||||
.map_err(|e| {
|
||||
tracing::error!(
|
||||
target: LOG_TARGET,
|
||||
relay_parent = ?relay_parent,
|
||||
error = ?e,
|
||||
"An error occured during requesting the inbound HRMP messages.",
|
||||
);
|
||||
})
|
||||
.ok()
|
||||
}
|
||||
|
||||
/// Collect the relevant relay chain state in form of a proof for putting it into the validation
|
||||
/// data inherent.
|
||||
fn collect_relay_storage_proof(
|
||||
polkadot_backend: &impl Backend<PBlock>,
|
||||
para_id: ParaId,
|
||||
relay_parent: PHash,
|
||||
) -> Option<sp_state_machine::StorageProof> {
|
||||
use relay_chain::well_known_keys as relay_well_known_keys;
|
||||
|
||||
let relay_parent_state_backend = polkadot_backend
|
||||
.state_at(BlockId::Hash(relay_parent))
|
||||
.map_err(|e| {
|
||||
tracing::error!(
|
||||
target: LOG_TARGET,
|
||||
relay_parent = ?relay_parent,
|
||||
error = ?e,
|
||||
"Cannot obtain the state of the relay chain.",
|
||||
)
|
||||
})
|
||||
.ok()?;
|
||||
|
||||
let ingress_channels = relay_parent_state_backend
|
||||
.storage(&relay_well_known_keys::hrmp_ingress_channel_index(para_id))
|
||||
.map_err(|e| {
|
||||
tracing::error!(
|
||||
target: LOG_TARGET,
|
||||
error = ?e,
|
||||
"Cannot obtain the hrmp ingress channel index."
|
||||
)
|
||||
})
|
||||
.ok()?;
|
||||
|
||||
let ingress_channels = ingress_channels
|
||||
.map(|raw| <Vec<ParaId>>::decode(&mut &raw[..]))
|
||||
.transpose()
|
||||
.map_err(|e| {
|
||||
tracing::error!(
|
||||
target: LOG_TARGET,
|
||||
error = ?e,
|
||||
"Cannot decode the hrmp ingress channel index.",
|
||||
)
|
||||
})
|
||||
.ok()?
|
||||
.unwrap_or_default();
|
||||
|
||||
let egress_channels = relay_parent_state_backend
|
||||
.storage(&relay_well_known_keys::hrmp_egress_channel_index(para_id))
|
||||
.map_err(|e| {
|
||||
tracing::error!(
|
||||
target: LOG_TARGET,
|
||||
error = ?e,
|
||||
"Cannot obtain the hrmp egress channel index.",
|
||||
)
|
||||
})
|
||||
.ok()?;
|
||||
let egress_channels = egress_channels
|
||||
.map(|raw| <Vec<ParaId>>::decode(&mut &raw[..]))
|
||||
.transpose()
|
||||
.map_err(|e| {
|
||||
tracing::error!(
|
||||
target: LOG_TARGET,
|
||||
error = ?e,
|
||||
"Cannot decode the hrmp egress channel index.",
|
||||
)
|
||||
})
|
||||
.ok()?
|
||||
.unwrap_or_default();
|
||||
|
||||
let mut relevant_keys = vec![];
|
||||
relevant_keys.push(relay_well_known_keys::ACTIVE_CONFIG.to_vec());
|
||||
relevant_keys.push(relay_well_known_keys::dmq_mqc_head(para_id));
|
||||
relevant_keys.push(relay_well_known_keys::relay_dispatch_queue_size(para_id));
|
||||
relevant_keys.push(relay_well_known_keys::hrmp_ingress_channel_index(para_id));
|
||||
relevant_keys.push(relay_well_known_keys::hrmp_egress_channel_index(para_id));
|
||||
relevant_keys.extend(ingress_channels.into_iter().map(|sender| {
|
||||
relay_well_known_keys::hrmp_channels(HrmpChannelId {
|
||||
sender,
|
||||
recipient: para_id,
|
||||
})
|
||||
}));
|
||||
relevant_keys.extend(egress_channels.into_iter().map(|recipient| {
|
||||
relay_well_known_keys::hrmp_channels(HrmpChannelId {
|
||||
sender: para_id,
|
||||
recipient,
|
||||
})
|
||||
}));
|
||||
|
||||
sp_state_machine::prove_read(relay_parent_state_backend, relevant_keys)
|
||||
.map_err(|e| {
|
||||
tracing::error!(
|
||||
target: LOG_TARGET,
|
||||
relay_parent = ?relay_parent,
|
||||
error = ?e,
|
||||
"Failed to collect required relay chain state storage proof.",
|
||||
)
|
||||
})
|
||||
.ok()
|
||||
}
|
||||
|
||||
impl ParachainInherentData {
|
||||
/// Create the [`ParachainInherentData`] at the given `relay_parent`.
|
||||
///
|
||||
/// Returns `None` if the creation failed.
|
||||
pub fn create_at<PClient>(
|
||||
relay_parent: PHash,
|
||||
polkadot_client: &PClient,
|
||||
polkadot_backend: &impl Backend<PBlock>,
|
||||
validation_data: &PersistedValidationData,
|
||||
para_id: ParaId,
|
||||
) -> Option<ParachainInherentData>
|
||||
where
|
||||
PClient: ProvideRuntimeApi<PBlock>,
|
||||
PClient::Api: ParachainHost<PBlock>,
|
||||
{
|
||||
let relay_chain_state = collect_relay_storage_proof(polkadot_backend, para_id, relay_parent)?;
|
||||
let downward_messages = retrieve_dmq_contents(polkadot_client, para_id, relay_parent)?;
|
||||
let horizontal_messages =
|
||||
retrieve_all_inbound_hrmp_channel_contents(polkadot_client, para_id, relay_parent)?;
|
||||
|
||||
Some(ParachainInherentData {
|
||||
downward_messages,
|
||||
horizontal_messages,
|
||||
validation_data: validation_data.clone(),
|
||||
relay_chain_state,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
// Copyright 2021 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Cumulus.
|
||||
|
||||
// Substrate 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.
|
||||
|
||||
// Substrate 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 Cumulus. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Cumulus parachain inherent
|
||||
//!
|
||||
//! The [`ParachainInherentData`] is the data that is passed by the collator to the parachain runtime.
|
||||
//! The runtime will use this data to execute messages from other parachains/the relay chain or to
|
||||
//! read data from the relay chain state. When the parachain is validated by a parachain validator on
|
||||
//! the relay chain, this data is checked for correctnes. If the data passed by the collator to the
|
||||
//! runtime isn't correct, the parachain candidate is considered invalid.
|
||||
//!
|
||||
//! Use [`ParachainInherentData::create_at`] to create the [`ParachainInherentData`] at a given
|
||||
//! relay chain block to include it in a parachain block.
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
use cumulus_primitives_core::{
|
||||
InboundDownwardMessage, InboundHrmpMessage, ParaId, PersistedValidationData,
|
||||
};
|
||||
|
||||
use sp_inherents::InherentIdentifier;
|
||||
use sp_std::{collections::btree_map::BTreeMap, vec::Vec};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
mod client_side;
|
||||
#[cfg(feature = "std")]
|
||||
pub use client_side::*;
|
||||
|
||||
/// The identifier for the parachain inherent.
|
||||
pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"sysi1337";
|
||||
|
||||
/// The inherent data that is passed by the collator to the parachain runtime.
|
||||
#[derive(codec::Encode, codec::Decode, sp_core::RuntimeDebug, Clone, PartialEq)]
|
||||
pub struct ParachainInherentData {
|
||||
pub validation_data: PersistedValidationData,
|
||||
/// A storage proof of a predefined set of keys from the relay-chain.
|
||||
///
|
||||
/// Specifically this witness contains the data for:
|
||||
///
|
||||
/// - active host configuration as per the relay parent,
|
||||
/// - the relay dispatch queue sizes
|
||||
/// - the list of egress HRMP channels (in the list of recipients form)
|
||||
/// - the metadata for the egress HRMP channels
|
||||
pub relay_chain_state: sp_trie::StorageProof,
|
||||
/// Downward messages in the order they were sent.
|
||||
pub downward_messages: Vec<InboundDownwardMessage>,
|
||||
/// HRMP messages grouped by channels. The messages in the inner vec must be in order they
|
||||
/// were sent. In combination with the rule of no more than one message in a channel per block,
|
||||
/// this means `sent_at` is **strictly** greater than the previous one (if any).
|
||||
pub horizontal_messages: BTreeMap<ParaId, Vec<InboundHrmpMessage>>,
|
||||
}
|
||||
@@ -27,6 +27,7 @@ cumulus-test-runtime = { path = "../runtime" }
|
||||
cumulus-test-service = { path = "../service" }
|
||||
cumulus-test-relay-sproof-builder = { path = "../relay-sproof-builder" }
|
||||
cumulus-primitives-core = { path = "../../primitives/core" }
|
||||
cumulus-primitives-parachain-inherent = { path = "../../primitives/parachain-inherent" }
|
||||
|
||||
# Polkadot deps
|
||||
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" }
|
||||
|
||||
@@ -15,11 +15,10 @@
|
||||
// along with Cumulus. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{Backend, Client};
|
||||
use cumulus_primitives_core::{
|
||||
inherents::{SystemInherentData, SYSTEM_INHERENT_IDENTIFIER}, PersistedValidationData,
|
||||
};
|
||||
use cumulus_test_runtime::{Block, GetLastTimestamp};
|
||||
use cumulus_primitives_core::PersistedValidationData;
|
||||
use cumulus_primitives_parachain_inherent::{ParachainInherentData, INHERENT_IDENTIFIER};
|
||||
use cumulus_test_relay_sproof_builder::RelayStateSproofBuilder;
|
||||
use cumulus_test_runtime::{Block, GetLastTimestamp};
|
||||
use polkadot_primitives::v1::BlockNumber as PBlockNumber;
|
||||
use sc_block_builder::{BlockBuilder, BlockBuilderProvider};
|
||||
use sp_api::ProvideRuntimeApi;
|
||||
@@ -101,8 +100,8 @@ impl InitBlockBuilder for Client {
|
||||
|
||||
inherent_data
|
||||
.put_data(
|
||||
SYSTEM_INHERENT_IDENTIFIER,
|
||||
&SystemInherentData {
|
||||
INHERENT_IDENTIFIER,
|
||||
&ParachainInherentData {
|
||||
validation_data,
|
||||
relay_chain_state,
|
||||
downward_messages: Default::default(),
|
||||
|
||||
Reference in New Issue
Block a user