Unverified Commit aba42e4a authored by Sergey Pepyakin's avatar Sergey Pepyakin Committed by GitHub
Browse files

Clean up PersistedValidationData (#2353)

* PVD: `block_number`->`relay_parent_number`

* ValidationParams: `relay_chain_height`->`relay_parent_number`

* Expose DMQ MQC hash as a well-known-key

This way the relay storage merkle proofs will be able to obtain the DMQ
MQC hash and we will be able to remove the it from the
PersistedValidationData struct.

* PersistedValidationData: Remove HRMP MQC heads

* PersistedValidationData: Remove `dmq_mqc_head`

* Expose the HRMP ingress channel index as a well-known-key

This way a parachain (PVF and collator) can find all the parachains that
have an outbound channel to the given one. That allows in turn to find
all the inbound channels for the given para.

Having access to that allows the parachain to get the same information
as the hrmp_mqc_heads now provide.

* Rename `relay_storage_root` to `relay_parent_storage_root`
parent ef761e8e
Pipeline #122762 passed with stages
in 27 minutes and 6 seconds
......@@ -103,11 +103,9 @@ impl Default for TestState {
fn default() -> Self {
let persisted_validation_data = PersistedValidationData {
parent_head: HeadData(vec![7, 8, 9]),
block_number: 5,
hrmp_mqc_heads: Vec::new(),
dmq_mqc_head: Default::default(),
relay_parent_number: 5,
max_pov_size: 1024,
relay_storage_root: Default::default(),
relay_parent_storage_root: Default::default(),
};
let pruning_config = PruningConfig {
......
......@@ -1274,11 +1274,9 @@ mod tests {
let validation_data = PersistedValidationData {
parent_head: HeadData(vec![7, 8, 9]),
block_number: Default::default(),
hrmp_mqc_heads: Vec::new(),
dmq_mqc_head: Default::default(),
relay_parent_number: Default::default(),
max_pov_size: 1024,
relay_storage_root: Default::default(),
relay_parent_storage_root: Default::default(),
};
Self {
......
......@@ -438,10 +438,8 @@ fn validate_candidate_exhaustive<B: ValidationBackend, S: SpawnNamed + 'static>(
let params = ValidationParams {
parent_head: persisted_validation_data.parent_head.clone(),
block_data: pov.block_data.clone(),
relay_chain_height: persisted_validation_data.block_number,
relay_storage_root: persisted_validation_data.relay_storage_root,
dmq_mqc_head: persisted_validation_data.dmq_mqc_head,
hrmp_mqc_heads: persisted_validation_data.hrmp_mqc_heads.clone(),
relay_parent_number: persisted_validation_data.relay_parent_number,
relay_parent_storage_root: persisted_validation_data.relay_parent_storage_root,
};
match B::validate(backend_arg, &validation_code, params, spawn) {
......
......@@ -201,11 +201,9 @@ impl Default for TestState {
let persisted_validation_data = PersistedValidationData {
parent_head: HeadData(vec![7, 8, 9]),
block_number: Default::default(),
hrmp_mqc_heads: Vec::new(),
dmq_mqc_head: Default::default(),
relay_parent_number: Default::default(),
max_pov_size: 1024,
relay_storage_root: Default::default(),
relay_parent_storage_root: Default::default(),
};
let pov_block_a = PoV {
......
......@@ -362,11 +362,9 @@ impl Default for TestState {
let persisted_validation_data = PersistedValidationData {
parent_head: HeadData(vec![7, 8, 9]),
block_number: Default::default(),
hrmp_mqc_heads: Vec::new(),
dmq_mqc_head: Default::default(),
relay_parent_number: Default::default(),
max_pov_size: 1024,
relay_storage_root: Default::default(),
relay_parent_storage_root: Default::default(),
};
let pov = PoV {
......
......@@ -267,18 +267,9 @@ pub struct ValidationParams {
/// The collation body.
pub block_data: BlockData,
/// The current relay-chain block number.
pub relay_chain_height: RelayChainBlockNumber,
pub relay_parent_number: RelayChainBlockNumber,
/// The relay-chain block's storage root.
pub relay_storage_root: Hash,
/// The MQC head for the DMQ.
///
/// The DMQ MQC head will be used by the validation function to authorize the downward messages
/// passed by the collator.
pub dmq_mqc_head: Hash,
/// The list of MQC heads for the inbound HRMP channels paired with the sender para ids. This
/// vector is sorted ascending by the para id and doesn't contain multiple entries with the same
/// sender.
pub hrmp_mqc_heads: Vec<(Id, Hash)>,
pub relay_parent_storage_root: Hash,
}
/// The result of parachain validation.
......
......@@ -168,7 +168,7 @@ impl Collator {
block_data: block_data.encode().into(),
},
processed_downward_messages: 0,
hrmp_watermark: validation_data.block_number,
hrmp_watermark: validation_data.relay_parent_number,
};
async move { Some(collation) }.boxed()
......@@ -230,10 +230,8 @@ mod tests {
ValidationParams {
parent_head: parent_head.encode().into(),
block_data: collation.proof_of_validity.block_data,
relay_chain_height: 1,
relay_storage_root: Default::default(),
hrmp_mqc_heads: Vec::new(),
dmq_mqc_head: Default::default(),
relay_parent_number: 1,
relay_parent_storage_root: Default::default(),
},
&IsolationStrategy::InProcess,
sp_core::testing::TaskExecutor::new(),
......
......@@ -41,7 +41,7 @@ pub extern "C" fn validate_block(params: *const u8, len: usize) -> u64 {
upward_messages: sp_std::vec::Vec::new(),
horizontal_messages: sp_std::vec::Vec::new(),
processed_downward_messages: 0,
hrmp_watermark: params.relay_chain_height,
hrmp_watermark: params.relay_parent_number,
}
)
}
......@@ -67,10 +67,8 @@ fn execute_good_on_parent(isolation_strategy: IsolationStrategy) {
ValidationParams {
parent_head: GenericHeadData(parent_head.encode()),
block_data: GenericBlockData(block_data.encode()),
relay_chain_height: 1,
relay_storage_root: Default::default(),
hrmp_mqc_heads: Vec::new(),
dmq_mqc_head: Default::default(),
relay_parent_number: 1,
relay_parent_storage_root: Default::default(),
},
&isolation_strategy,
sp_core::testing::TaskExecutor::new(),
......@@ -107,10 +105,8 @@ fn execute_good_chain_on_parent() {
ValidationParams {
parent_head: GenericHeadData(parent_head.encode()),
block_data: GenericBlockData(block_data.encode()),
relay_chain_height: number as RelayChainBlockNumber + 1,
relay_storage_root: Default::default(),
hrmp_mqc_heads: Vec::new(),
dmq_mqc_head: Default::default(),
relay_parent_number: number as RelayChainBlockNumber + 1,
relay_parent_storage_root: Default::default(),
},
&isolation_strategy,
sp_core::testing::TaskExecutor::new(),
......@@ -148,10 +144,8 @@ fn execute_bad_on_parent() {
ValidationParams {
parent_head: GenericHeadData(parent_head.encode()),
block_data: GenericBlockData(block_data.encode()),
relay_chain_height: 1,
relay_storage_root: Default::default(),
hrmp_mqc_heads: Vec::new(),
dmq_mqc_head: Default::default(),
relay_parent_number: 1,
relay_parent_storage_root: Default::default(),
},
&isolation_strategy,
sp_core::testing::TaskExecutor::new(),
......
......@@ -41,10 +41,8 @@ fn terminates_on_timeout() {
ValidationParams {
block_data: BlockData(Vec::new()),
parent_head: Default::default(),
relay_chain_height: 1,
relay_storage_root: Default::default(),
hrmp_mqc_heads: Vec::new(),
dmq_mqc_head: Default::default(),
relay_parent_number: 1,
relay_parent_storage_root: Default::default(),
},
&isolation_strategy,
sp_core::testing::TaskExecutor::new(),
......@@ -70,10 +68,8 @@ fn parallel_execution() {
ValidationParams {
block_data: BlockData(Vec::new()),
parent_head: Default::default(),
relay_chain_height: 1,
relay_storage_root: Default::default(),
hrmp_mqc_heads: Vec::new(),
dmq_mqc_head: Default::default(),
relay_parent_number: 1,
relay_parent_storage_root: Default::default(),
},
&isolation_strategy,
sp_core::testing::TaskExecutor::new(),
......@@ -83,10 +79,8 @@ fn parallel_execution() {
ValidationParams {
block_data: BlockData(Vec::new()),
parent_head: Default::default(),
relay_storage_root: Default::default(),
relay_chain_height: 1,
hrmp_mqc_heads: Vec::new(),
dmq_mqc_head: Default::default(),
relay_parent_storage_root: Default::default(),
relay_parent_number: 1,
},
&isolation_strategy_clone,
sp_core::testing::TaskExecutor::new(),
......
......@@ -119,6 +119,22 @@ pub mod well_known_keys {
})
}
/// The list of inbound channels for the given para.
///
/// The storage entry stores a `Vec<ParaId>`
pub fn hrmp_ingress_channel_index(para_id: Id) -> Vec<u8> {
let prefix = hex!["6a0da05ca59913bc38a8630590f2627c1d3719f5b0b12c7105c073c507445948"];
para_id.using_encoded(|para_id: &[u8]| {
prefix.as_ref()
.iter()
.chain(twox_64(para_id).iter())
.chain(para_id.iter())
.cloned()
.collect()
})
}
/// The list of outbound channels for the given para.
///
/// The storage entry stores a `Vec<ParaId>`
......@@ -134,6 +150,23 @@ pub mod well_known_keys {
.collect()
})
}
/// The MQC head for the downward message queue of the given para. See more in the `Dmp` module.
///
/// The storage entry stores a `Hash`. This is polkadot hash which is at the moment
/// `blake2b-256`.
pub fn dmq_mqc_head(para_id: Id) -> Vec<u8> {
let prefix = hex!["63f78c98723ddc9073523ef3beefda0c4d7fefc408aac59dbfe80a72ac8e3ce5"];
para_id.using_encoded(|para_id: &[u8]| {
prefix.as_ref()
.iter()
.chain(twox_64(para_id).iter())
.chain(para_id.iter())
.cloned()
.collect()
})
}
}
/// Unique identifier for the Inclusion Inherent
......@@ -360,18 +393,9 @@ pub struct PersistedValidationData<N = BlockNumber> {
/// The parent head-data.
pub parent_head: HeadData,
/// The relay-chain block number this is in the context of.
pub block_number: N,
pub relay_parent_number: N,
/// The relay-chain block storage root this is in the context of.
pub relay_storage_root: Hash,
/// The list of MQC heads for the inbound channels paired with the sender para ids. This
/// vector is sorted ascending by the para id and doesn't contain multiple entries with the same
/// sender.
pub hrmp_mqc_heads: Vec<(Id, Hash)>,
/// The MQC head for the DMQ.
///
/// The DMQ MQC head will be used by the validation function to authorize the downward messages
/// passed by the collator.
pub dmq_mqc_head: Hash,
pub relay_parent_storage_root: Hash,
/// The maximum legal size of a POV block, in bytes.
pub max_pov_size: u32,
}
......
......@@ -93,17 +93,12 @@ digraph {
<tr><td border="0" colspan="2" port="name">PersistedValidationData&lt;N = BlockNumber&gt;</td></tr>
<tr><td>parent_head</td><td port="parent_head">HeadData</td></tr>
<tr><td>block_number</td><td port="block_number">N</td></tr>
<tr><td>relay_storage_root</td><td port="relay_storage_root">Hash</td></tr>
<tr><td>hrmp_mqc_heads</td><td port="hrmp_mqc_heads">Vec&lt;(Id, Hash)&gt;</td></tr>
<tr><td>dmq_mqc_head</td><td port="dmq_mqc_head">Hash</td></tr>
<tr><td>relay_parent_storage_root</td><td port="relay_parent_storage_root">Hash</td></tr>
<tr><td>max_pov_size</td><td port="max_pov_size">u32</td></tr>
</table>
>]
PersistedValidationData:parent_head -> HeadData:w
PersistedValidationData:hrmp_mqc_heads -> Id:w
PersistedValidationData:hrmp_mqc_heads -> MQCHash
PersistedValidationData:dmq_mqc_head -> MQCHash
PersistedValidationDataHash [label = "Hash", shape="doublecircle", fill="gray90"]
PersistedValidationDataHash -> PersistedValidationData:name
......@@ -401,16 +396,14 @@ digraph {
<tr><td border="0" colspan="2" port="name">ValidationParams</td></tr>
<tr><td>parent_head</td><td port="parent_head">HeadData</td></tr>
<tr><td>block_data</td><td port="block_data">BlockData</td></tr>
<tr><td>relay_chain_height</td><td port="relay_chain_height">RelayChainBlockNumber</td></tr>
<tr><td>relay_storage_root</td><td port="relay_storage_root">Hash</td></tr>
<tr><td>dmq_mqc_head</td><td port="dmq_mqc_head">Hash</td></tr>
<tr><td>hrmp_mqc_heads</td><td port="hrmp_mqc_heads">Vec&lt;(Id, Hash)&gt;</td></tr>
<tr><td>relay_parent_number</td><td port="relay_parent_number">RelayChainBlockNumber</td></tr>
<tr><td>relay_parent_storage_root</td><td port="relay_parent_storage_root">Hash</td></tr>
</table>
>]
ValidationParams:parent_head -> HeadData:name
ValidationParams:block_data -> BlockData:name
ValidationParams:relay_chain_height -> RelayChainBlockNumber:w
ValidationParams:relay_parent_number -> RelayChainBlockNumber:w
RelayChainBlockNumber [label = "polkadot_core_primitives::BlockNumber"]
......
......@@ -107,14 +107,9 @@ struct PersistedValidationData {
/// The parent head-data.
parent_head: HeadData,
/// The relay-chain block number this is in the context of. This informs the collator.
block_number: BlockNumber,
relay_parent_number: BlockNumber,
/// The relay-chain block storage root this is in the context of.
relay_storage_root: Hash,
/// The MQC head for the DMQ.
///
/// The DMQ MQC head will be used by the validation function to authorize the downward messages
/// passed by the collator.
dmq_mqc_head: Hash,
relay_parent_storage_root: Hash,
/// The list of MQC heads for the inbound channels paired with the sender para ids. This
/// vector is sorted ascending by the para id and doesn't contain multiple entries with the same
/// sender.
......
......@@ -202,7 +202,8 @@ impl<T: Config> Module<T> {
/// Returns the Head of Message Queue Chain for the given para or `None` if there is none
/// associated with it.
pub(crate) fn dmq_mqc_head(para: ParaId) -> Hash {
#[cfg(test)]
fn dmq_mqc_head(para: ParaId) -> Hash {
<Self as Store>::DownwardMessageQueueHeads::get(&para)
}
......@@ -406,4 +407,25 @@ mod tests {
assert!(queue_downward_message(a, big).is_err());
});
}
#[test]
fn verify_dmq_mqc_head_is_externally_accessible() {
use primitives::v1::well_known_keys;
use hex_literal::hex;
let a = ParaId::from(2020);
new_test_ext(default_genesis_config()).execute_with(|| {
let head = sp_io::storage::get(&well_known_keys::dmq_mqc_head(a));
assert_eq!(head, None);
queue_downward_message(a, vec![1, 2, 3]).unwrap();
let head = sp_io::storage::get(&well_known_keys::dmq_mqc_head(a));
assert_eq!(
head,
Some(hex!["434f8579a2297dfea851bf6be33093c83a78b655a53ae141a7894494c0010589"].to_vec())
);
});
}
}
......@@ -1084,7 +1084,8 @@ impl<T: Config> Module<T> {
/// Returns the list of MQC heads for the inbound channels of the given recipient para paired
/// with the sender para ids. This vector is sorted ascending by the para id and doesn't contain
/// multiple entries with the same sender.
pub(crate) fn hrmp_mqc_heads(recipient: ParaId) -> Vec<(ParaId, Hash)> {
#[cfg(test)]
fn hrmp_mqc_heads(recipient: ParaId) -> Vec<(ParaId, Hash)> {
let sender_set = <Self as Store>::HrmpIngressChannelsIndex::get(&recipient);
// The ingress channels vector is sorted, thus `mqc_heads` is sorted as well.
......@@ -1706,6 +1707,18 @@ mod tests {
},
);
let raw_ingress_index =
sp_io::storage::get(
&well_known_keys::hrmp_ingress_channel_index(para_b),
)
.expect("the ingress index must be present for para_b");
let ingress_index = <Vec<ParaId>>::decode(&mut &raw_ingress_index[..])
.expect("ingress indexx should be decodable as a list of para ids");
assert_eq!(
ingress_index,
vec![para_a],
);
// Now, verify that we can access and decode the egress index.
let raw_egress_index =
sp_io::storage::get(
......
......@@ -200,13 +200,13 @@ pub fn persisted_validation_data<T: initializer::Config>(
) -> Option<PersistedValidationData<T::BlockNumber>> {
use parity_scale_codec::Decode as _;
let relay_parent_number = <frame_system::Module<T>>::block_number();
let relay_storage_root = Hash::decode(&mut &sp_io::storage::root()[..])
let relay_parent_storage_root = Hash::decode(&mut &sp_io::storage::root()[..])
.expect("storage root must decode to the Hash type; qed");
with_assumption::<T, _, _>(para_id, assumption, || {
crate::util::make_persisted_validation_data::<T>(
para_id,
relay_parent_number,
relay_storage_root,
relay_parent_storage_root,
)
})
}
......
......@@ -19,7 +19,7 @@
use primitives::v1::{Id as ParaId, PersistedValidationData, Hash};
use crate::{configuration, paras, dmp, hrmp};
use crate::{configuration, paras, hrmp};
/// Make the persisted validation data for a particular parachain, a specified relay-parent and it's
/// storage root.
......@@ -28,16 +28,14 @@ use crate::{configuration, paras, dmp, hrmp};
pub fn make_persisted_validation_data<T: paras::Config + hrmp::Config>(
para_id: ParaId,
relay_parent_number: T::BlockNumber,
relay_storage_root: Hash,
relay_parent_storage_root: Hash,
) -> Option<PersistedValidationData<T::BlockNumber>> {
let config = <configuration::Module<T>>::config();
Some(PersistedValidationData {
parent_head: <paras::Module<T>>::para_head(&para_id)?,
block_number: relay_parent_number,
relay_storage_root,
hrmp_mqc_heads: <hrmp::Module<T>>::hrmp_mqc_heads(para_id),
dmq_mqc_head: <dmp::Module<T>>::dmq_mqc_head(para_id),
relay_parent_number,
relay_parent_storage_root,
max_pov_size: config.max_pov_size,
})
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment