mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 08:11:03 +00:00
Ensure that para_head hash matches the actual head (#3808)
* Ensure that `para_head` hash matches the actual head This ensures that the `para_head` hash in the `CandidateDescriptor` matches the actual `head` in the candidate commitments. * Enable the code for `no_std` * Formatting
This commit is contained in:
@@ -45,7 +45,6 @@ pub use polkadot_core_primitives::BlockNumber as RelayChainBlockNumber;
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Default, Hash, MallocSizeOf))]
|
||||
pub struct HeadData(#[cfg_attr(feature = "std", serde(with = "bytes"))] pub Vec<u8>);
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl HeadData {
|
||||
/// Returns the hash of this head data.
|
||||
pub fn hash(&self) -> Hash {
|
||||
|
||||
@@ -194,6 +194,9 @@ pub mod pallet {
|
||||
InvalidOutboundHrmp,
|
||||
/// The validation code hash of the candidate is not valid.
|
||||
InvalidValidationCodeHash,
|
||||
/// The `para_head` hash in the candidate descriptor doesn't match the hash of the actual para head in the
|
||||
/// commitments.
|
||||
ParaHeadMismatch,
|
||||
}
|
||||
|
||||
/// The latest bitfield for each validator, referred to by their index in the validator set.
|
||||
@@ -465,6 +468,12 @@ impl<T: Config> Pallet<T> {
|
||||
Error::<T>::InvalidValidationCodeHash,
|
||||
);
|
||||
|
||||
ensure!(
|
||||
candidate.descriptor().para_head ==
|
||||
candidate.candidate.commitments.head_data.hash(),
|
||||
Error::<T>::ParaHeadMismatch,
|
||||
);
|
||||
|
||||
if let Err(err) = check_cx.check_validation_outputs(
|
||||
para_id,
|
||||
&candidate.candidate.commitments.head_data,
|
||||
@@ -1169,6 +1178,7 @@ mod tests {
|
||||
struct TestCandidateBuilder {
|
||||
para_id: ParaId,
|
||||
head_data: HeadData,
|
||||
para_head_hash: Option<Hash>,
|
||||
pov_hash: Hash,
|
||||
relay_parent: Hash,
|
||||
persisted_validation_data_hash: Hash,
|
||||
@@ -1186,6 +1196,7 @@ mod tests {
|
||||
relay_parent: self.relay_parent,
|
||||
persisted_validation_data_hash: self.persisted_validation_data_hash,
|
||||
validation_code_hash: self.validation_code.hash(),
|
||||
para_head: self.para_head_hash.unwrap_or_else(|| self.head_data.hash()),
|
||||
..Default::default()
|
||||
},
|
||||
commitments: CandidateCommitments {
|
||||
@@ -2214,6 +2225,41 @@ mod tests {
|
||||
Err(Error::<Test>::InvalidValidationCodeHash.into()),
|
||||
);
|
||||
}
|
||||
|
||||
// Para head hash in descriptor doesn't match head data
|
||||
{
|
||||
let mut candidate = TestCandidateBuilder {
|
||||
para_id: chain_a,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::repeat_byte(1),
|
||||
persisted_validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
hrmp_watermark: RELAY_PARENT_NUM,
|
||||
para_head_hash: Some(Hash::random()),
|
||||
..Default::default()
|
||||
}
|
||||
.build();
|
||||
|
||||
collator_sign_candidate(Sr25519Keyring::One, &mut candidate);
|
||||
|
||||
let backed = block_on(back_candidate(
|
||||
candidate,
|
||||
&validators,
|
||||
group_validators(GroupIndex::from(0)).unwrap().as_ref(),
|
||||
&keystore,
|
||||
&signing_context,
|
||||
BackingKind::Threshold,
|
||||
));
|
||||
|
||||
assert_eq!(
|
||||
ParaInclusion::process_candidates(
|
||||
Default::default(),
|
||||
vec![backed],
|
||||
vec![chain_a_assignment.clone()],
|
||||
&group_validators,
|
||||
),
|
||||
Err(Error::<Test>::ParaHeadMismatch.into()),
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user