mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 09:21:04 +00:00
Include a reference to the validation data in the candidate descriptor (#1442)
* rename GlobalValidationSchedule to GlobalValidationData * guide: update candidate descriptor to contain validation data hash * guide: add note in inclusion module about checking validation data hash * primitives: update CandidateDescriptor to contain new hash * fix payload computation * add helpers for computing validation data to runtime modules * guide: note routines * inclusion: check validation data hash and fix local_validation_data bug * add a case to candidate_checks and improve that test substantially * bump versions * address review comments * add a test for including code upgrade * bump kusama version * bump westend & polkadot versions
This commit is contained in:
committed by
GitHub
parent
1ed17cd467
commit
09f602f8de
@@ -19,12 +19,13 @@
|
||||
//! Configuration can change only at session boundaries and is buffered until then.
|
||||
|
||||
use sp_std::prelude::*;
|
||||
use primitives::v1::ValidatorId;
|
||||
use primitives::v1::{ValidatorId, GlobalValidationData};
|
||||
use frame_support::{
|
||||
decl_storage, decl_module, decl_error,
|
||||
dispatch::DispatchResult,
|
||||
weights::{DispatchClass, Weight},
|
||||
};
|
||||
use sp_runtime::traits::One;
|
||||
use codec::{Encode, Decode};
|
||||
use system::ensure_root;
|
||||
|
||||
@@ -219,6 +220,16 @@ impl<T: Trait> Module<T> {
|
||||
<Self as Store>::PendingConfig::set(Some(prev));
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes the global validation-data, assuming the context of the parent block.
|
||||
pub(crate) fn global_validation_data() -> GlobalValidationData<T::BlockNumber> {
|
||||
let config = Self::config();
|
||||
GlobalValidationData {
|
||||
max_code_size: config.max_code_size,
|
||||
max_head_data_size: config.max_head_data_size,
|
||||
block_number: <system::Module<T>>::block_number() - One::one(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
use sp_std::prelude::*;
|
||||
use primitives::v1::{
|
||||
validation_data_hash,
|
||||
ValidatorId, CandidateCommitments, CandidateDescriptor, ValidatorIndex, Id as ParaId,
|
||||
AvailabilityBitfield as AvailabilityBitfield, SignedAvailabilityBitfields, SigningContext,
|
||||
BackedCandidate, CoreIndex, GroupIndex, CoreAssignment, CommittedCandidateReceipt,
|
||||
@@ -145,6 +146,8 @@ decl_error! {
|
||||
InvalidBacking,
|
||||
/// Collator did not sign PoV.
|
||||
NotCollatorSigned,
|
||||
/// The validation data hash does not match expected.
|
||||
ValidationDataHashMismatch,
|
||||
/// Internal error only returned when compiled with debug assertions.
|
||||
InternalError,
|
||||
}
|
||||
@@ -399,14 +402,21 @@ impl<T: Trait> Module<T> {
|
||||
Error::<T>::CandidateNotInParentContext,
|
||||
);
|
||||
|
||||
let code_upgrade_allowed = <paras::Module<T>>::last_code_upgrade(para_id, true)
|
||||
.map_or(
|
||||
true,
|
||||
|last| last <= relay_parent_number &&
|
||||
relay_parent_number.saturating_sub(last) >= config.validation_upgrade_frequency,
|
||||
);
|
||||
// if any, the code upgrade attempt is allowed.
|
||||
let valid_upgrade_attempt =
|
||||
candidate.candidate.commitments.new_validation_code.is_none() ||
|
||||
<paras::Module<T>>::last_code_upgrade(para_id, true)
|
||||
.map_or(
|
||||
true,
|
||||
|last| last <= relay_parent_number &&
|
||||
relay_parent_number.saturating_sub(last)
|
||||
>= config.validation_upgrade_frequency,
|
||||
);
|
||||
|
||||
ensure!(code_upgrade_allowed, Error::<T>::PrematureCodeUpgrade);
|
||||
ensure!(
|
||||
valid_upgrade_attempt,
|
||||
Error::<T>::PrematureCodeUpgrade,
|
||||
);
|
||||
ensure!(
|
||||
candidate.descriptor().check_collator_signature().is_ok(),
|
||||
Error::<T>::NotCollatorSigned,
|
||||
@@ -423,6 +433,32 @@ impl<T: Trait> Module<T> {
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
// this should never fail because the para is registered
|
||||
let (global_validation_data, local_validation_data) = (
|
||||
<configuration::Module<T>>::global_validation_data(),
|
||||
match <paras::Module<T>>::local_validation_data(para_id) {
|
||||
Some(l) => l,
|
||||
None => {
|
||||
// We don't want to error out here because it will
|
||||
// brick the relay-chain. So we return early without
|
||||
// doing anything.
|
||||
return Ok(Vec::new());
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
let expected = validation_data_hash(
|
||||
&global_validation_data,
|
||||
&local_validation_data,
|
||||
);
|
||||
|
||||
ensure!(
|
||||
expected == candidate.descriptor().validation_data_hash,
|
||||
Error::<T>::ValidationDataHashMismatch,
|
||||
);
|
||||
}
|
||||
|
||||
ensure!(
|
||||
<PendingAvailability<T>>::get(¶_id).is_none() &&
|
||||
<PendingAvailabilityCommitments>::get(¶_id).is_none(),
|
||||
@@ -686,6 +722,7 @@ mod tests {
|
||||
let payload = primitives::v1::collator_signature_payload(
|
||||
&candidate.descriptor.relay_parent,
|
||||
&candidate.descriptor.para_id,
|
||||
&candidate.descriptor.validation_data_hash,
|
||||
&candidate.descriptor.pov_hash,
|
||||
);
|
||||
|
||||
@@ -814,6 +851,7 @@ mod tests {
|
||||
head_data: HeadData,
|
||||
pov_hash: Hash,
|
||||
relay_parent: Hash,
|
||||
validation_data_hash: Hash,
|
||||
new_validation_code: Option<ValidationCode>,
|
||||
}
|
||||
|
||||
@@ -824,6 +862,7 @@ mod tests {
|
||||
para_id: self.para_id,
|
||||
pov_hash: self.pov_hash,
|
||||
relay_parent: self.relay_parent,
|
||||
validation_data_hash: self.validation_data_hash,
|
||||
..Default::default()
|
||||
},
|
||||
commitments: CandidateCommitments {
|
||||
@@ -835,6 +874,12 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
fn make_vdata_hash(para_id: ParaId) -> Option<Hash> {
|
||||
let global_validation_data = Configuration::global_validation_data();
|
||||
let local_validation_data = Paras::local_validation_data(para_id)?;
|
||||
Some(validation_data_hash(&global_validation_data, &local_validation_data))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn collect_pending_cleans_up_pending() {
|
||||
let chain_a = ParaId::from(1);
|
||||
@@ -1261,6 +1306,7 @@ mod tests {
|
||||
para_id: chain_a,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([1; 32]),
|
||||
validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
..Default::default()
|
||||
}.build();
|
||||
collator_sign_candidate(
|
||||
@@ -1276,11 +1322,14 @@ mod tests {
|
||||
BackingKind::Threshold,
|
||||
);
|
||||
|
||||
assert!(Inclusion::process_candidates(
|
||||
vec![backed],
|
||||
vec![chain_b_assignment.clone()],
|
||||
&group_validators,
|
||||
).is_err());
|
||||
assert_eq!(
|
||||
Inclusion::process_candidates(
|
||||
vec![backed],
|
||||
vec![chain_b_assignment.clone()],
|
||||
&group_validators,
|
||||
),
|
||||
Err(Error::<Test>::UnscheduledCandidate.into()),
|
||||
);
|
||||
}
|
||||
|
||||
// candidates out of order.
|
||||
@@ -1289,12 +1338,14 @@ mod tests {
|
||||
para_id: chain_a,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([1; 32]),
|
||||
validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
..Default::default()
|
||||
}.build();
|
||||
let mut candidate_b = TestCandidateBuilder {
|
||||
para_id: chain_b,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([2; 32]),
|
||||
validation_data_hash: make_vdata_hash(chain_b).unwrap(),
|
||||
..Default::default()
|
||||
}.build();
|
||||
|
||||
@@ -1324,11 +1375,15 @@ mod tests {
|
||||
BackingKind::Threshold,
|
||||
);
|
||||
|
||||
assert!(Inclusion::process_candidates(
|
||||
vec![backed_b, backed_a],
|
||||
vec![chain_a_assignment.clone(), chain_b_assignment.clone()],
|
||||
&group_validators,
|
||||
).is_err());
|
||||
// out-of-order manifests as unscheduled.
|
||||
assert_eq!(
|
||||
Inclusion::process_candidates(
|
||||
vec![backed_b, backed_a],
|
||||
vec![chain_a_assignment.clone(), chain_b_assignment.clone()],
|
||||
&group_validators,
|
||||
),
|
||||
Err(Error::<Test>::UnscheduledCandidate.into()),
|
||||
);
|
||||
}
|
||||
|
||||
// candidate not backed.
|
||||
@@ -1337,6 +1392,7 @@ mod tests {
|
||||
para_id: chain_a,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([1; 32]),
|
||||
validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
..Default::default()
|
||||
}.build();
|
||||
collator_sign_candidate(
|
||||
@@ -1352,11 +1408,14 @@ mod tests {
|
||||
BackingKind::Lacking,
|
||||
);
|
||||
|
||||
assert!(Inclusion::process_candidates(
|
||||
vec![backed],
|
||||
vec![chain_a_assignment.clone()],
|
||||
&group_validators,
|
||||
).is_err());
|
||||
assert_eq!(
|
||||
Inclusion::process_candidates(
|
||||
vec![backed],
|
||||
vec![chain_a_assignment.clone()],
|
||||
&group_validators,
|
||||
),
|
||||
Err(Error::<Test>::InsufficientBacking.into()),
|
||||
);
|
||||
}
|
||||
|
||||
// candidate not in parent context.
|
||||
@@ -1368,6 +1427,7 @@ mod tests {
|
||||
para_id: chain_a,
|
||||
relay_parent: wrong_parent_hash,
|
||||
pov_hash: Hash::from([1; 32]),
|
||||
validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
..Default::default()
|
||||
}.build();
|
||||
collator_sign_candidate(
|
||||
@@ -1383,11 +1443,14 @@ mod tests {
|
||||
BackingKind::Threshold,
|
||||
);
|
||||
|
||||
assert!(Inclusion::process_candidates(
|
||||
vec![backed],
|
||||
vec![chain_a_assignment.clone()],
|
||||
&group_validators,
|
||||
).is_err());
|
||||
assert_eq!(
|
||||
Inclusion::process_candidates(
|
||||
vec![backed],
|
||||
vec![chain_a_assignment.clone()],
|
||||
&group_validators,
|
||||
),
|
||||
Err(Error::<Test>::CandidateNotInParentContext.into()),
|
||||
);
|
||||
}
|
||||
|
||||
// candidate has wrong collator.
|
||||
@@ -1396,6 +1459,7 @@ mod tests {
|
||||
para_id: thread_a,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([1; 32]),
|
||||
validation_data_hash: make_vdata_hash(thread_a).unwrap(),
|
||||
..Default::default()
|
||||
}.build();
|
||||
|
||||
@@ -1413,15 +1477,18 @@ mod tests {
|
||||
BackingKind::Threshold,
|
||||
);
|
||||
|
||||
assert!(Inclusion::process_candidates(
|
||||
vec![backed],
|
||||
vec![
|
||||
chain_a_assignment.clone(),
|
||||
chain_b_assignment.clone(),
|
||||
thread_a_assignment.clone(),
|
||||
],
|
||||
&group_validators,
|
||||
).is_err());
|
||||
assert_eq!(
|
||||
Inclusion::process_candidates(
|
||||
vec![backed],
|
||||
vec![
|
||||
chain_a_assignment.clone(),
|
||||
chain_b_assignment.clone(),
|
||||
thread_a_assignment.clone(),
|
||||
],
|
||||
&group_validators,
|
||||
),
|
||||
Err(Error::<Test>::WrongCollator.into()),
|
||||
);
|
||||
}
|
||||
|
||||
// candidate not well-signed by collator.
|
||||
@@ -1430,6 +1497,7 @@ mod tests {
|
||||
para_id: thread_a,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([1; 32]),
|
||||
validation_data_hash: make_vdata_hash(thread_a).unwrap(),
|
||||
..Default::default()
|
||||
}.build();
|
||||
|
||||
@@ -1450,11 +1518,14 @@ mod tests {
|
||||
BackingKind::Threshold,
|
||||
);
|
||||
|
||||
assert!(Inclusion::process_candidates(
|
||||
vec![backed],
|
||||
vec![thread_a_assignment.clone()],
|
||||
&group_validators,
|
||||
).is_err());
|
||||
assert_eq!(
|
||||
Inclusion::process_candidates(
|
||||
vec![backed],
|
||||
vec![thread_a_assignment.clone()],
|
||||
&group_validators,
|
||||
),
|
||||
Err(Error::<Test>::NotCollatorSigned.into()),
|
||||
);
|
||||
}
|
||||
|
||||
// para occupied - reject.
|
||||
@@ -1463,6 +1534,7 @@ mod tests {
|
||||
para_id: chain_a,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([1; 32]),
|
||||
validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
..Default::default()
|
||||
}.build();
|
||||
|
||||
@@ -1489,11 +1561,14 @@ mod tests {
|
||||
});
|
||||
<PendingAvailabilityCommitments>::insert(&chain_a, candidate.commitments);
|
||||
|
||||
assert!(Inclusion::process_candidates(
|
||||
vec![backed],
|
||||
vec![chain_a_assignment.clone()],
|
||||
&group_validators,
|
||||
).is_err());
|
||||
assert_eq!(
|
||||
Inclusion::process_candidates(
|
||||
vec![backed],
|
||||
vec![chain_a_assignment.clone()],
|
||||
&group_validators,
|
||||
),
|
||||
Err(Error::<Test>::CandidateScheduledBeforeParaFree.into()),
|
||||
);
|
||||
|
||||
<PendingAvailability<Test>>::remove(&chain_a);
|
||||
<PendingAvailabilityCommitments>::remove(&chain_a);
|
||||
@@ -1505,6 +1580,7 @@ mod tests {
|
||||
para_id: chain_a,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([1; 32]),
|
||||
validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
..Default::default()
|
||||
}.build();
|
||||
|
||||
@@ -1524,11 +1600,14 @@ mod tests {
|
||||
BackingKind::Threshold,
|
||||
);
|
||||
|
||||
assert!(Inclusion::process_candidates(
|
||||
vec![backed],
|
||||
vec![chain_a_assignment.clone()],
|
||||
&group_validators,
|
||||
).is_err());
|
||||
assert_eq!(
|
||||
Inclusion::process_candidates(
|
||||
vec![backed],
|
||||
vec![chain_a_assignment.clone()],
|
||||
&group_validators,
|
||||
),
|
||||
Err(Error::<Test>::CandidateScheduledBeforeParaFree.into()),
|
||||
);
|
||||
|
||||
<PendingAvailabilityCommitments>::remove(&chain_a);
|
||||
}
|
||||
@@ -1540,6 +1619,7 @@ mod tests {
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([1; 32]),
|
||||
new_validation_code: Some(vec![5, 6, 7, 8].into()),
|
||||
validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
..Default::default()
|
||||
}.build();
|
||||
|
||||
@@ -1564,11 +1644,47 @@ mod tests {
|
||||
|
||||
assert_eq!(Paras::last_code_upgrade(chain_a, true), Some(10));
|
||||
|
||||
assert!(Inclusion::process_candidates(
|
||||
vec![backed],
|
||||
vec![thread_a_assignment.clone()],
|
||||
&group_validators,
|
||||
).is_err());
|
||||
assert_eq!(
|
||||
Inclusion::process_candidates(
|
||||
vec![backed],
|
||||
vec![chain_a_assignment.clone()],
|
||||
&group_validators,
|
||||
),
|
||||
Err(Error::<Test>::PrematureCodeUpgrade.into()),
|
||||
);
|
||||
}
|
||||
|
||||
// Bad validation data hash - reject
|
||||
{
|
||||
let mut candidate = TestCandidateBuilder {
|
||||
para_id: chain_a,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([1; 32]),
|
||||
validation_data_hash: [42u8; 32].into(),
|
||||
..Default::default()
|
||||
}.build();
|
||||
|
||||
collator_sign_candidate(
|
||||
Sr25519Keyring::One,
|
||||
&mut candidate,
|
||||
);
|
||||
|
||||
let backed = back_candidate(
|
||||
candidate,
|
||||
&validators,
|
||||
group_validators(GroupIndex::from(0)).unwrap().as_ref(),
|
||||
&signing_context,
|
||||
BackingKind::Threshold,
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Inclusion::process_candidates(
|
||||
vec![backed],
|
||||
vec![chain_a_assignment.clone()],
|
||||
&group_validators,
|
||||
),
|
||||
Err(Error::<Test>::ValidationDataHashMismatch.into()),
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1634,6 +1750,7 @@ mod tests {
|
||||
para_id: chain_a,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([1; 32]),
|
||||
validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
..Default::default()
|
||||
}.build();
|
||||
collator_sign_candidate(
|
||||
@@ -1645,6 +1762,7 @@ mod tests {
|
||||
para_id: chain_b,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([2; 32]),
|
||||
validation_data_hash: make_vdata_hash(chain_b).unwrap(),
|
||||
..Default::default()
|
||||
}.build();
|
||||
collator_sign_candidate(
|
||||
@@ -1656,6 +1774,7 @@ mod tests {
|
||||
para_id: thread_a,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([3; 32]),
|
||||
validation_data_hash: make_vdata_hash(thread_a).unwrap(),
|
||||
..Default::default()
|
||||
}.build();
|
||||
collator_sign_candidate(
|
||||
@@ -1746,6 +1865,91 @@ mod tests {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_include_candidate_with_ok_code_upgrade() {
|
||||
let chain_a = ParaId::from(1);
|
||||
|
||||
let paras = vec![(chain_a, true)];
|
||||
let validators = vec![
|
||||
Sr25519Keyring::Alice,
|
||||
Sr25519Keyring::Bob,
|
||||
Sr25519Keyring::Charlie,
|
||||
Sr25519Keyring::Dave,
|
||||
Sr25519Keyring::Ferdie,
|
||||
];
|
||||
let validator_public = validator_pubkeys(&validators);
|
||||
|
||||
new_test_ext(genesis_config(paras)).execute_with(|| {
|
||||
Validators::set(validator_public.clone());
|
||||
CurrentSessionIndex::set(5);
|
||||
|
||||
run_to_block(5, |_| None);
|
||||
|
||||
let signing_context = SigningContext {
|
||||
parent_hash: System::parent_hash(),
|
||||
session_index: 5,
|
||||
};
|
||||
|
||||
let group_validators = |group_index: GroupIndex| match group_index {
|
||||
group_index if group_index == GroupIndex::from(0) => Some(vec![0, 1, 2, 3, 4]),
|
||||
_ => panic!("Group index out of bounds for 1 parachain"),
|
||||
};
|
||||
|
||||
let chain_a_assignment = CoreAssignment {
|
||||
core: CoreIndex::from(0),
|
||||
para_id: chain_a,
|
||||
kind: AssignmentKind::Parachain,
|
||||
group_idx: GroupIndex::from(0),
|
||||
};
|
||||
|
||||
let mut candidate_a = TestCandidateBuilder {
|
||||
para_id: chain_a,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([1; 32]),
|
||||
validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
new_validation_code: Some(vec![1, 2, 3].into()),
|
||||
..Default::default()
|
||||
}.build();
|
||||
collator_sign_candidate(
|
||||
Sr25519Keyring::One,
|
||||
&mut candidate_a,
|
||||
);
|
||||
|
||||
let backed_a = back_candidate(
|
||||
candidate_a.clone(),
|
||||
&validators,
|
||||
group_validators(GroupIndex::from(0)).unwrap().as_ref(),
|
||||
&signing_context,
|
||||
BackingKind::Threshold,
|
||||
);
|
||||
|
||||
let occupied_cores = Inclusion::process_candidates(
|
||||
vec![backed_a],
|
||||
vec![
|
||||
chain_a_assignment.clone(),
|
||||
],
|
||||
&group_validators,
|
||||
).expect("candidates scheduled, in order, and backed");
|
||||
|
||||
assert_eq!(occupied_cores, vec![CoreIndex::from(0)]);
|
||||
|
||||
assert_eq!(
|
||||
<PendingAvailability<Test>>::get(&chain_a),
|
||||
Some(CandidatePendingAvailability {
|
||||
core: CoreIndex::from(0),
|
||||
descriptor: candidate_a.descriptor,
|
||||
availability_votes: default_availability_votes(),
|
||||
relay_parent_number: System::block_number() - 1,
|
||||
backed_in_number: System::block_number(),
|
||||
})
|
||||
);
|
||||
assert_eq!(
|
||||
<PendingAvailabilityCommitments>::get(&chain_a),
|
||||
Some(candidate_a.commitments),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn session_change_wipes_and_updates_session_info() {
|
||||
let chain_a = ParaId::from(1);
|
||||
|
||||
@@ -25,9 +25,9 @@
|
||||
|
||||
use sp_std::prelude::*;
|
||||
use sp_std::marker::PhantomData;
|
||||
use sp_runtime::traits::One;
|
||||
use sp_runtime::traits::{One, BlakeTwo256, Hash as HashT, Saturating};
|
||||
use primitives::v1::{
|
||||
Id as ParaId, ValidationCode, HeadData,
|
||||
Id as ParaId, ValidationCode, HeadData, LocalValidationData,
|
||||
};
|
||||
use frame_support::{
|
||||
decl_storage, decl_module, decl_error,
|
||||
@@ -536,6 +536,37 @@ impl<T: Trait> Module<T> {
|
||||
|
||||
Self::past_code_meta(&id).most_recent_change()
|
||||
}
|
||||
|
||||
/// Compute the local-validation data based on the head of the para. This assumes the
|
||||
/// relay-parent is the parent of the current block.
|
||||
pub(crate) fn local_validation_data(para_id: ParaId) -> Option<LocalValidationData<T::BlockNumber>> {
|
||||
let relay_parent_number = <system::Module<T>>::block_number() - One::one();
|
||||
|
||||
let config = <configuration::Module<T>>::config();
|
||||
let freq = config.validation_upgrade_frequency;
|
||||
let delay = config.validation_upgrade_delay;
|
||||
|
||||
let last_code_upgrade = Self::last_code_upgrade(para_id, true);
|
||||
let can_upgrade_code = last_code_upgrade.map_or(
|
||||
true,
|
||||
|l| { l <= relay_parent_number && relay_parent_number.saturating_sub(l) >= freq },
|
||||
);
|
||||
|
||||
let code_upgrade_allowed = if can_upgrade_code {
|
||||
Some(relay_parent_number + delay)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Some(LocalValidationData {
|
||||
parent_head: Self::para_head(¶_id)?,
|
||||
balance: 0,
|
||||
validation_code_hash: BlakeTwo256::hash_of(
|
||||
&Self::current_code(¶_id)?
|
||||
),
|
||||
code_upgrade_allowed,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -18,12 +18,12 @@
|
||||
//! functions.
|
||||
|
||||
use primitives::v1::{
|
||||
ValidatorId, ValidatorIndex, GroupRotationInfo, CoreState, GlobalValidationSchedule,
|
||||
ValidatorId, ValidatorIndex, GroupRotationInfo, CoreState, GlobalValidationData,
|
||||
Id as ParaId, OccupiedCoreAssumption, LocalValidationData, SessionIndex, ValidationCode,
|
||||
CommittedCandidateReceipt, ScheduledCore, OccupiedCore, CoreOccupied, CoreIndex,
|
||||
GroupIndex, CandidateEvent,
|
||||
};
|
||||
use sp_runtime::traits::{One, BlakeTwo256, Hash as HashT, Saturating, Zero};
|
||||
use sp_runtime::traits::Zero;
|
||||
use frame_support::debug;
|
||||
use crate::{initializer, inclusion, scheduler, configuration, paras};
|
||||
|
||||
@@ -160,16 +160,11 @@ pub fn availability_cores<T: initializer::Trait>() -> Vec<CoreState<T::BlockNumb
|
||||
core_states
|
||||
}
|
||||
|
||||
/// Implementation for the `global_validation_schedule` function of the runtime API.
|
||||
pub fn global_validation_schedule<T: initializer::Trait>()
|
||||
-> GlobalValidationSchedule<T::BlockNumber>
|
||||
/// Implementation for the `global_validation_data` function of the runtime API.
|
||||
pub fn global_validation_data<T: initializer::Trait>()
|
||||
-> GlobalValidationData<T::BlockNumber>
|
||||
{
|
||||
let config = <configuration::Module<T>>::config();
|
||||
GlobalValidationSchedule {
|
||||
max_code_size: config.max_code_size,
|
||||
max_head_data_size: config.max_head_data_size,
|
||||
block_number: <system::Module<T>>::block_number() - One::one(),
|
||||
}
|
||||
<configuration::Module<T>>::global_validation_data()
|
||||
}
|
||||
|
||||
/// Implementation for the `local_validation_data` function of the runtime API.
|
||||
@@ -177,46 +172,19 @@ pub fn local_validation_data<T: initializer::Trait>(
|
||||
para_id: ParaId,
|
||||
assumption: OccupiedCoreAssumption,
|
||||
) -> Option<LocalValidationData<T::BlockNumber>> {
|
||||
let construct = || {
|
||||
let relay_parent_number = <system::Module<T>>::block_number() - One::one();
|
||||
|
||||
let config = <configuration::Module<T>>::config();
|
||||
let freq = config.validation_upgrade_frequency;
|
||||
let delay = config.validation_upgrade_delay;
|
||||
|
||||
let last_code_upgrade = <paras::Module<T>>::last_code_upgrade(para_id, true)?;
|
||||
let can_upgrade_code = last_code_upgrade <= relay_parent_number
|
||||
&& relay_parent_number.saturating_sub(last_code_upgrade) >= freq;
|
||||
|
||||
let code_upgrade_allowed = if can_upgrade_code {
|
||||
Some(relay_parent_number + delay)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Some(LocalValidationData {
|
||||
parent_head: <paras::Module<T>>::para_head(¶_id)?,
|
||||
balance: 0,
|
||||
validation_code_hash: BlakeTwo256::hash_of(
|
||||
&<paras::Module<T>>::current_code(¶_id)?
|
||||
),
|
||||
code_upgrade_allowed,
|
||||
})
|
||||
};
|
||||
|
||||
match assumption {
|
||||
OccupiedCoreAssumption::Included => {
|
||||
<inclusion::Module<T>>::force_enact(para_id);
|
||||
construct()
|
||||
<paras::Module<T>>::local_validation_data(para_id)
|
||||
}
|
||||
OccupiedCoreAssumption::TimedOut => {
|
||||
construct()
|
||||
<paras::Module<T>>::local_validation_data(para_id)
|
||||
}
|
||||
OccupiedCoreAssumption::Free => {
|
||||
if <inclusion::Module<T>>::pending_availability(para_id).is_some() {
|
||||
None
|
||||
} else {
|
||||
construct()
|
||||
<paras::Module<T>>::local_validation_data(para_id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user