mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-31 14:31:02 +00:00
Validate code when scheduling uprades from registrar (#3232)
Currently, anyone can registrar a code that exceeds the code size limit when performing the upgrade from the registrar. This PR fixes that and adds a new test to cover this. cc @bkchr @eskimor
This commit is contained in:
@@ -57,8 +57,8 @@ pub use v6::{
|
||||
UpgradeRestriction, UpwardMessage, ValidDisputeStatementKind, ValidationCode,
|
||||
ValidationCodeHash, ValidatorId, ValidatorIndex, ValidatorSignature, ValidityAttestation,
|
||||
ValidityError, ASSIGNMENT_KEY_TYPE_ID, LEGACY_MIN_BACKING_VOTES, LOWEST_PUBLIC_ID,
|
||||
MAX_CODE_SIZE, MAX_HEAD_DATA_SIZE, MAX_POV_SIZE, ON_DEMAND_DEFAULT_QUEUE_MAX_SIZE,
|
||||
PARACHAINS_INHERENT_IDENTIFIER, PARACHAIN_KEY_TYPE_ID,
|
||||
MAX_CODE_SIZE, MAX_HEAD_DATA_SIZE, MAX_POV_SIZE, MIN_CODE_SIZE,
|
||||
ON_DEMAND_DEFAULT_QUEUE_MAX_SIZE, PARACHAINS_INHERENT_IDENTIFIER, PARACHAIN_KEY_TYPE_ID,
|
||||
};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
|
||||
@@ -362,6 +362,9 @@ pub const PARACHAINS_INHERENT_IDENTIFIER: InherentIdentifier = *b"parachn0";
|
||||
/// The key type ID for parachain assignment key.
|
||||
pub const ASSIGNMENT_KEY_TYPE_ID: KeyTypeId = KeyTypeId(*b"asgn");
|
||||
|
||||
/// Compressed or not the wasm blob can never be less than 9 bytes.
|
||||
pub const MIN_CODE_SIZE: u32 = 9;
|
||||
|
||||
/// Maximum compressed code size we support right now.
|
||||
/// At the moment we have runtime upgrade on chain, which restricts scalability severely. If we want
|
||||
/// to have bigger values, we should fix that first.
|
||||
|
||||
@@ -126,7 +126,7 @@ pub fn dummy_candidate_descriptor<H: AsRef<[u8]>>(relay_parent: H) -> CandidateD
|
||||
|
||||
/// Create meaningless validation code.
|
||||
pub fn dummy_validation_code() -> ValidationCode {
|
||||
ValidationCode(vec![1, 2, 3])
|
||||
ValidationCode(vec![1, 2, 3, 4, 5, 6, 7, 8, 9])
|
||||
}
|
||||
|
||||
/// Create meaningless head data.
|
||||
|
||||
@@ -36,6 +36,7 @@ use pallet_identity::{self, legacy::IdentityInfo};
|
||||
use parity_scale_codec::Encode;
|
||||
use primitives::{
|
||||
BlockNumber, HeadData, Id as ParaId, SessionIndex, ValidationCode, LOWEST_PUBLIC_ID,
|
||||
MAX_CODE_SIZE,
|
||||
};
|
||||
use runtime_parachains::{
|
||||
configuration, origin, paras, shared, Origin as ParaOrigin, ParaLifecycle,
|
||||
@@ -315,7 +316,7 @@ pub fn new_test_ext() -> TestExternalities {
|
||||
let mut t = frame_system::GenesisConfig::<Test>::default().build_storage().unwrap();
|
||||
configuration::GenesisConfig::<Test> {
|
||||
config: configuration::HostConfiguration {
|
||||
max_code_size: 2 * 1024 * 1024, // 2 MB
|
||||
max_code_size: MAX_CODE_SIZE,
|
||||
max_head_data_size: 1 * 1024 * 1024, // 1 MB
|
||||
..Default::default()
|
||||
},
|
||||
|
||||
@@ -26,7 +26,7 @@ use frame_support::{
|
||||
traits::{Currency, Get, ReservableCurrency},
|
||||
};
|
||||
use frame_system::{self, ensure_root, ensure_signed};
|
||||
use primitives::{HeadData, Id as ParaId, ValidationCode, LOWEST_PUBLIC_ID};
|
||||
use primitives::{HeadData, Id as ParaId, ValidationCode, LOWEST_PUBLIC_ID, MIN_CODE_SIZE};
|
||||
use runtime_parachains::{
|
||||
configuration, ensure_parachain,
|
||||
paras::{self, ParaGenesisArgs, SetGoAhead},
|
||||
@@ -182,8 +182,8 @@ pub mod pallet {
|
||||
ParaLocked,
|
||||
/// The ID given for registration has not been reserved.
|
||||
NotReserved,
|
||||
/// Registering parachain with empty code is not allowed.
|
||||
EmptyCode,
|
||||
/// The validation code is invalid.
|
||||
InvalidCode,
|
||||
/// Cannot perform a parachain slot / lifecycle swap. Check that the state of both paras
|
||||
/// are correct for the swap to work.
|
||||
CannotSwap,
|
||||
@@ -657,7 +657,7 @@ impl<T: Config> Pallet<T> {
|
||||
para_kind: ParaKind,
|
||||
) -> Result<(ParaGenesisArgs, BalanceOf<T>), sp_runtime::DispatchError> {
|
||||
let config = configuration::Pallet::<T>::config();
|
||||
ensure!(validation_code.0.len() > 0, Error::<T>::EmptyCode);
|
||||
ensure!(validation_code.0.len() >= MIN_CODE_SIZE as usize, Error::<T>::InvalidCode);
|
||||
ensure!(validation_code.0.len() <= config.max_code_size as usize, Error::<T>::CodeTooLarge);
|
||||
ensure!(
|
||||
genesis_head.0.len() <= config.max_head_data_size as usize,
|
||||
@@ -712,7 +712,7 @@ mod tests {
|
||||
};
|
||||
use frame_system::limits;
|
||||
use pallet_balances::Error as BalancesError;
|
||||
use primitives::{Balance, BlockNumber, SessionIndex};
|
||||
use primitives::{Balance, BlockNumber, SessionIndex, MAX_CODE_SIZE};
|
||||
use runtime_parachains::{configuration, origin, shared};
|
||||
use sp_core::H256;
|
||||
use sp_io::TestExternalities;
|
||||
@@ -849,7 +849,7 @@ mod tests {
|
||||
|
||||
configuration::GenesisConfig::<Test> {
|
||||
config: configuration::HostConfiguration {
|
||||
max_code_size: 2 * 1024 * 1024, // 2 MB
|
||||
max_code_size: MAX_CODE_SIZE,
|
||||
max_head_data_size: 1 * 1024 * 1024, // 1 MB
|
||||
..Default::default()
|
||||
},
|
||||
@@ -1032,6 +1032,51 @@ mod tests {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn schedule_code_upgrade_validates_code() {
|
||||
new_test_ext().execute_with(|| {
|
||||
const START_SESSION_INDEX: SessionIndex = 1;
|
||||
run_to_session(START_SESSION_INDEX);
|
||||
|
||||
let para_id = LOWEST_PUBLIC_ID;
|
||||
assert!(!Parachains::is_parathread(para_id));
|
||||
|
||||
let validation_code = test_validation_code(32);
|
||||
assert_ok!(Registrar::reserve(RuntimeOrigin::signed(1)));
|
||||
assert_eq!(Balances::reserved_balance(&1), <Test as Config>::ParaDeposit::get());
|
||||
assert_ok!(Registrar::register(
|
||||
RuntimeOrigin::signed(1),
|
||||
para_id,
|
||||
test_genesis_head(32),
|
||||
validation_code.clone(),
|
||||
));
|
||||
conclude_pvf_checking::<Test>(&validation_code, VALIDATORS, START_SESSION_INDEX);
|
||||
|
||||
run_to_session(START_SESSION_INDEX + 2);
|
||||
assert!(Parachains::is_parathread(para_id));
|
||||
|
||||
let new_code = test_validation_code(0);
|
||||
assert_noop!(
|
||||
Registrar::schedule_code_upgrade(
|
||||
RuntimeOrigin::signed(1),
|
||||
para_id,
|
||||
new_code.clone(),
|
||||
),
|
||||
paras::Error::<Test>::InvalidCode
|
||||
);
|
||||
|
||||
let new_code = test_validation_code(max_code_size() as usize + 1);
|
||||
assert_noop!(
|
||||
Registrar::schedule_code_upgrade(
|
||||
RuntimeOrigin::signed(1),
|
||||
para_id,
|
||||
new_code.clone(),
|
||||
),
|
||||
paras::Error::<Test>::InvalidCode
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn register_handles_basic_errors() {
|
||||
new_test_ext().execute_with(|| {
|
||||
@@ -1310,7 +1355,7 @@ mod tests {
|
||||
RuntimeOrigin::signed(1),
|
||||
para_id,
|
||||
vec![1; 3].into(),
|
||||
vec![1, 2, 3].into(),
|
||||
test_validation_code(32)
|
||||
));
|
||||
|
||||
assert_noop!(Registrar::add_lock(RuntimeOrigin::signed(2), para_id), BadOrigin);
|
||||
@@ -1473,7 +1518,7 @@ mod benchmarking {
|
||||
use crate::traits::Registrar as RegistrarT;
|
||||
use frame_support::assert_ok;
|
||||
use frame_system::RawOrigin;
|
||||
use primitives::{MAX_CODE_SIZE, MAX_HEAD_DATA_SIZE};
|
||||
use primitives::{MAX_CODE_SIZE, MAX_HEAD_DATA_SIZE, MIN_CODE_SIZE};
|
||||
use runtime_parachains::{paras, shared, Origin as ParaOrigin};
|
||||
use sp_runtime::traits::Bounded;
|
||||
|
||||
@@ -1604,7 +1649,7 @@ mod benchmarking {
|
||||
}
|
||||
|
||||
schedule_code_upgrade {
|
||||
let b in 1 .. MAX_CODE_SIZE;
|
||||
let b in MIN_CODE_SIZE .. MAX_CODE_SIZE;
|
||||
let new_code = ValidationCode(vec![0; b as usize]);
|
||||
let para_id = ParaId::from(1000);
|
||||
}: _(RawOrigin::Root, para_id, new_code)
|
||||
|
||||
@@ -281,7 +281,7 @@ impl<BlockNumber: Default + From<u32>> Default for HostConfiguration<BlockNumber
|
||||
validation_upgrade_cooldown: Default::default(),
|
||||
validation_upgrade_delay: 2u32.into(),
|
||||
code_retention_period: Default::default(),
|
||||
max_code_size: Default::default(),
|
||||
max_code_size: MAX_CODE_SIZE,
|
||||
max_pov_size: Default::default(),
|
||||
max_head_data_size: Default::default(),
|
||||
coretime_cores: Default::default(),
|
||||
|
||||
@@ -1233,7 +1233,7 @@ fn candidate_checks() {
|
||||
para_id: chain_a,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::repeat_byte(1),
|
||||
new_validation_code: Some(vec![5, 6, 7, 8].into()),
|
||||
new_validation_code: Some(dummy_validation_code()),
|
||||
persisted_validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
hrmp_watermark: RELAY_PARENT_NUM,
|
||||
..Default::default()
|
||||
@@ -1257,7 +1257,7 @@ fn candidate_checks() {
|
||||
assert_eq!(expected_at, 12);
|
||||
Paras::schedule_code_upgrade(
|
||||
chain_a,
|
||||
vec![1, 2, 3, 4].into(),
|
||||
vec![9, 8, 7, 6, 5, 4, 3, 2, 1].into(),
|
||||
expected_at,
|
||||
&cfg,
|
||||
SetGoAhead::Yes,
|
||||
@@ -1317,7 +1317,7 @@ fn candidate_checks() {
|
||||
pov_hash: Hash::repeat_byte(1),
|
||||
persisted_validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
hrmp_watermark: RELAY_PARENT_NUM,
|
||||
validation_code: ValidationCode(vec![1]),
|
||||
validation_code: ValidationCode(vec![9, 8, 7, 6, 5, 4, 3, 2, 1]),
|
||||
..Default::default()
|
||||
}
|
||||
.build();
|
||||
@@ -1726,7 +1726,7 @@ fn can_include_candidate_with_ok_code_upgrade() {
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::repeat_byte(1),
|
||||
persisted_validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
new_validation_code: Some(vec![1, 2, 3].into()),
|
||||
new_validation_code: Some(vec![9, 8, 7, 6, 5, 4, 3, 2, 1].into()),
|
||||
hrmp_watermark: RELAY_PARENT_NUM,
|
||||
..Default::default()
|
||||
}
|
||||
@@ -2133,7 +2133,7 @@ fn para_upgrade_delay_scheduled_from_inclusion() {
|
||||
shared::Pallet::<Test>::set_active_validators_ascending(validator_public.clone());
|
||||
shared::Pallet::<Test>::set_session_index(5);
|
||||
|
||||
let new_validation_code: ValidationCode = vec![1, 2, 3, 4, 5].into();
|
||||
let new_validation_code: ValidationCode = vec![9, 8, 7, 6, 5, 4, 3, 2, 1].into();
|
||||
let new_validation_code_hash = new_validation_code.hash();
|
||||
|
||||
// Otherwise upgrade is no-op.
|
||||
|
||||
@@ -27,10 +27,10 @@ const SESSION_INDEX: SessionIndex = 1;
|
||||
const VALIDATOR_NUM: usize = 800;
|
||||
const CAUSES_NUM: usize = 100;
|
||||
fn validation_code() -> ValidationCode {
|
||||
ValidationCode(vec![0])
|
||||
ValidationCode(vec![1, 2, 3, 4, 5, 6, 7, 8, 9])
|
||||
}
|
||||
fn old_validation_code() -> ValidationCode {
|
||||
ValidationCode(vec![1])
|
||||
ValidationCode(vec![9, 8, 7, 6, 5, 4, 3, 2, 1])
|
||||
}
|
||||
|
||||
/// Prepares the PVF check statement and the validator signature to pass into
|
||||
|
||||
@@ -119,7 +119,7 @@ use frame_system::pallet_prelude::*;
|
||||
use parity_scale_codec::{Decode, Encode};
|
||||
use primitives::{
|
||||
ConsensusLog, HeadData, Id as ParaId, PvfCheckStatement, SessionIndex, UpgradeGoAhead,
|
||||
UpgradeRestriction, ValidationCode, ValidationCodeHash, ValidatorSignature,
|
||||
UpgradeRestriction, ValidationCode, ValidationCodeHash, ValidatorSignature, MIN_CODE_SIZE,
|
||||
};
|
||||
use scale_info::{Type, TypeInfo};
|
||||
use sp_core::RuntimeDebug;
|
||||
@@ -679,6 +679,8 @@ pub mod pallet {
|
||||
PvfCheckSubjectInvalid,
|
||||
/// Parachain cannot currently schedule a code upgrade.
|
||||
CannotUpgradeCode,
|
||||
/// Invalid validation code size.
|
||||
InvalidCode,
|
||||
}
|
||||
|
||||
/// All currently active PVF pre-checking votes.
|
||||
@@ -1230,6 +1232,10 @@ impl<T: Config> Pallet<T> {
|
||||
// Check that we can schedule an upgrade at all.
|
||||
ensure!(Self::can_upgrade_validation_code(id), Error::<T>::CannotUpgradeCode);
|
||||
let config = configuration::Pallet::<T>::config();
|
||||
// Validation code sanity checks:
|
||||
ensure!(new_code.0.len() >= MIN_CODE_SIZE as usize, Error::<T>::InvalidCode);
|
||||
ensure!(new_code.0.len() <= config.max_code_size as usize, Error::<T>::InvalidCode);
|
||||
|
||||
let current_block = frame_system::Pallet::<T>::block_number();
|
||||
// Schedule the upgrade with a delay just like if a parachain triggered the upgrade.
|
||||
let upgrade_block = current_block.saturating_add(config.validation_upgrade_delay);
|
||||
@@ -1890,7 +1896,14 @@ impl<T: Config> Pallet<T> {
|
||||
) -> Weight {
|
||||
let mut weight = T::DbWeight::get().reads(1);
|
||||
|
||||
// Enacting this should be prevented by the `can_schedule_upgrade`
|
||||
// Should be prevented by checks in `schedule_code_upgrade_external`
|
||||
let new_code_len = new_code.0.len();
|
||||
if new_code_len < MIN_CODE_SIZE as usize || new_code_len > cfg.max_code_size as usize {
|
||||
log::warn!(target: LOG_TARGET, "attempted to schedule an upgrade with invalid new validation code",);
|
||||
return weight
|
||||
}
|
||||
|
||||
// Enacting this should be prevented by the `can_upgrade_validation_code`
|
||||
if FutureCodeHash::<T>::contains_key(&id) {
|
||||
// This branch should never be reached. Signalling an upgrade is disallowed for a para
|
||||
// that already has one upgrade scheduled.
|
||||
|
||||
@@ -67,6 +67,16 @@ fn submit_super_majority_pvf_votes(
|
||||
.for_each(sign_and_include_pvf_check_statement);
|
||||
}
|
||||
|
||||
fn test_validation_code_1() -> ValidationCode {
|
||||
let validation_code = vec![1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
ValidationCode(validation_code)
|
||||
}
|
||||
|
||||
fn test_validation_code_2() -> ValidationCode {
|
||||
let validation_code = vec![9, 8, 7, 6, 5, 4, 3, 2, 1];
|
||||
ValidationCode(validation_code)
|
||||
}
|
||||
|
||||
fn run_to_block(to: BlockNumber, new_session: Option<Vec<BlockNumber>>) {
|
||||
let keystore: KeystorePtr = Arc::new(LocalKeystore::in_memory());
|
||||
for validator in VALIDATORS.iter() {
|
||||
@@ -284,7 +294,7 @@ fn para_past_code_pruning_in_initialize() {
|
||||
let id = ParaId::from(0u32);
|
||||
let at_block: BlockNumber = 10;
|
||||
let included_block: BlockNumber = 12;
|
||||
let validation_code = ValidationCode(vec![4, 5, 6]);
|
||||
let validation_code = test_validation_code_2();
|
||||
|
||||
Paras::increase_code_ref(&validation_code.hash(), &validation_code);
|
||||
PastCodeHash::<Test>::insert(&(id, at_block), &validation_code.hash());
|
||||
@@ -377,8 +387,8 @@ fn note_past_code_sets_up_pruning_correctly() {
|
||||
let id_a = ParaId::from(0u32);
|
||||
let id_b = ParaId::from(1u32);
|
||||
|
||||
Paras::note_past_code(id_a, 10, 12, ValidationCode(vec![1, 2, 3]).hash());
|
||||
Paras::note_past_code(id_b, 20, 23, ValidationCode(vec![4, 5, 6]).hash());
|
||||
Paras::note_past_code(id_a, 10, 12, test_validation_code_1().hash());
|
||||
Paras::note_past_code(id_b, 20, 23, test_validation_code_2().hash());
|
||||
|
||||
assert_eq!(PastCodePruning::<Test>::get(), vec![(id_a, 12), (id_b, 23)]);
|
||||
assert_eq!(
|
||||
@@ -398,7 +408,7 @@ fn code_upgrade_applied_after_delay() {
|
||||
let validation_upgrade_delay = 5;
|
||||
let validation_upgrade_cooldown = 10;
|
||||
|
||||
let original_code = ValidationCode(vec![1, 2, 3]);
|
||||
let original_code = test_validation_code_1();
|
||||
let paras = vec![(
|
||||
0u32.into(),
|
||||
ParaGenesisArgs {
|
||||
@@ -425,7 +435,7 @@ fn code_upgrade_applied_after_delay() {
|
||||
check_code_is_stored(&original_code);
|
||||
|
||||
let para_id = ParaId::from(0);
|
||||
let new_code = ValidationCode(vec![4, 5, 6]);
|
||||
let new_code = test_validation_code_2();
|
||||
|
||||
// Wait for at least one session change to set active validators.
|
||||
const EXPECTED_SESSION: SessionIndex = 1;
|
||||
@@ -516,7 +526,7 @@ fn code_upgrade_applied_without_setting_go_ahead_signal() {
|
||||
let validation_upgrade_delay = 5;
|
||||
let validation_upgrade_cooldown = 10;
|
||||
|
||||
let original_code = ValidationCode(vec![1, 2, 3]);
|
||||
let original_code = test_validation_code_1();
|
||||
let paras = vec![(
|
||||
0u32.into(),
|
||||
ParaGenesisArgs {
|
||||
@@ -543,7 +553,7 @@ fn code_upgrade_applied_without_setting_go_ahead_signal() {
|
||||
check_code_is_stored(&original_code);
|
||||
|
||||
let para_id = ParaId::from(0);
|
||||
let new_code = ValidationCode(vec![4, 5, 6]);
|
||||
let new_code = test_validation_code_2();
|
||||
|
||||
// Wait for at least one session change to set active validators.
|
||||
const EXPECTED_SESSION: SessionIndex = 1;
|
||||
@@ -637,7 +647,7 @@ fn code_upgrade_applied_after_delay_even_when_late() {
|
||||
let validation_upgrade_delay = 5;
|
||||
let validation_upgrade_cooldown = 10;
|
||||
|
||||
let original_code = ValidationCode(vec![1, 2, 3]);
|
||||
let original_code = test_validation_code_1();
|
||||
let paras = vec![(
|
||||
0u32.into(),
|
||||
ParaGenesisArgs {
|
||||
@@ -662,7 +672,7 @@ fn code_upgrade_applied_after_delay_even_when_late() {
|
||||
|
||||
new_test_ext(genesis_config).execute_with(|| {
|
||||
let para_id = ParaId::from(0);
|
||||
let new_code = ValidationCode(vec![4, 5, 6]);
|
||||
let new_code = test_validation_code_2();
|
||||
|
||||
// Wait for at least one session change to set active validators.
|
||||
const EXPECTED_SESSION: SessionIndex = 1;
|
||||
@@ -750,8 +760,8 @@ fn submit_code_change_when_not_allowed_is_err() {
|
||||
|
||||
new_test_ext(genesis_config).execute_with(|| {
|
||||
let para_id = ParaId::from(0);
|
||||
let new_code = ValidationCode(vec![4, 5, 6]);
|
||||
let newer_code = ValidationCode(vec![4, 5, 6, 7]);
|
||||
let new_code = test_validation_code_1();
|
||||
let newer_code = test_validation_code_2();
|
||||
|
||||
// Wait for at least one session change to set active validators.
|
||||
const EXPECTED_SESSION: SessionIndex = 1;
|
||||
@@ -832,8 +842,8 @@ fn upgrade_restriction_elapsed_doesnt_mean_can_upgrade() {
|
||||
|
||||
new_test_ext(genesis_config).execute_with(|| {
|
||||
let para_id = 0u32.into();
|
||||
let new_code = ValidationCode(vec![4, 5, 6]);
|
||||
let newer_code = ValidationCode(vec![4, 5, 6, 7]);
|
||||
let new_code = test_validation_code_1();
|
||||
let newer_code = test_validation_code_2();
|
||||
|
||||
// Wait for at least one session change to set active validators.
|
||||
const EXPECTED_SESSION: SessionIndex = 1;
|
||||
@@ -880,7 +890,7 @@ fn full_parachain_cleanup_storage() {
|
||||
let code_retention_period = 20;
|
||||
let validation_upgrade_delay = 1 + 5;
|
||||
|
||||
let original_code = ValidationCode(vec![1, 2, 3]);
|
||||
let original_code = test_validation_code_1();
|
||||
let paras = vec![(
|
||||
0u32.into(),
|
||||
ParaGenesisArgs {
|
||||
@@ -910,7 +920,7 @@ fn full_parachain_cleanup_storage() {
|
||||
check_code_is_stored(&original_code);
|
||||
|
||||
let para_id = ParaId::from(0);
|
||||
let new_code = ValidationCode(vec![4, 5, 6]);
|
||||
let new_code = test_validation_code_2();
|
||||
|
||||
// Wait for at least one session change to set active validators.
|
||||
const EXPECTED_SESSION: SessionIndex = 1;
|
||||
@@ -993,8 +1003,8 @@ fn full_parachain_cleanup_storage() {
|
||||
fn cannot_offboard_ongoing_pvf_check() {
|
||||
let para_id = ParaId::from(0);
|
||||
|
||||
let existing_code: ValidationCode = vec![1, 2, 3].into();
|
||||
let new_code: ValidationCode = vec![3, 2, 1].into();
|
||||
let existing_code = test_validation_code_1();
|
||||
let new_code = test_validation_code_2();
|
||||
|
||||
let paras = vec![(
|
||||
para_id,
|
||||
@@ -1152,7 +1162,7 @@ fn code_hash_at_returns_up_to_end_of_code_retention_period() {
|
||||
ParaGenesisArgs {
|
||||
para_kind: ParaKind::Parachain,
|
||||
genesis_head: dummy_head_data(),
|
||||
validation_code: vec![1, 2, 3].into(),
|
||||
validation_code: test_validation_code_1(),
|
||||
},
|
||||
)];
|
||||
|
||||
@@ -1174,8 +1184,8 @@ fn code_hash_at_returns_up_to_end_of_code_retention_period() {
|
||||
const EXPECTED_SESSION: SessionIndex = 1;
|
||||
|
||||
let para_id = ParaId::from(0);
|
||||
let old_code: ValidationCode = vec![1, 2, 3].into();
|
||||
let new_code: ValidationCode = vec![4, 5, 6].into();
|
||||
let old_code = test_validation_code_1();
|
||||
let new_code = test_validation_code_2();
|
||||
Paras::schedule_code_upgrade(
|
||||
para_id,
|
||||
new_code.clone(),
|
||||
@@ -1219,7 +1229,7 @@ fn code_hash_at_returns_up_to_end_of_code_retention_period() {
|
||||
#[test]
|
||||
fn code_ref_is_cleaned_correctly() {
|
||||
new_test_ext(Default::default()).execute_with(|| {
|
||||
let code: ValidationCode = vec![1, 2, 3].into();
|
||||
let code = test_validation_code_1();
|
||||
Paras::increase_code_ref(&code.hash(), &code);
|
||||
Paras::increase_code_ref(&code.hash(), &code);
|
||||
|
||||
@@ -1244,8 +1254,8 @@ fn pvf_check_coalescing_onboarding_and_upgrade() {
|
||||
|
||||
let a = ParaId::from(111);
|
||||
let b = ParaId::from(222);
|
||||
let existing_code: ValidationCode = vec![1, 2, 3].into();
|
||||
let validation_code: ValidationCode = vec![3, 2, 1].into();
|
||||
let existing_code = test_validation_code_1();
|
||||
let validation_code = test_validation_code_2();
|
||||
|
||||
let paras = vec![(
|
||||
a,
|
||||
@@ -1320,7 +1330,7 @@ fn pvf_check_coalescing_onboarding_and_upgrade() {
|
||||
fn pvf_check_onboarding_reject_on_expiry() {
|
||||
let pvf_voting_ttl = 2;
|
||||
let a = ParaId::from(111);
|
||||
let validation_code: ValidationCode = vec![3, 2, 1].into();
|
||||
let validation_code = test_validation_code_1();
|
||||
|
||||
let genesis_config = MockGenesisConfig {
|
||||
configuration: crate::configuration::GenesisConfig {
|
||||
@@ -1368,8 +1378,8 @@ fn pvf_check_onboarding_reject_on_expiry() {
|
||||
#[test]
|
||||
fn pvf_check_upgrade_reject() {
|
||||
let a = ParaId::from(111);
|
||||
let old_code: ValidationCode = vec![1, 2, 3].into();
|
||||
let new_code: ValidationCode = vec![3, 2, 1].into();
|
||||
let old_code = test_validation_code_1();
|
||||
let new_code = test_validation_code_2();
|
||||
|
||||
let paras = vec![(
|
||||
a,
|
||||
@@ -1437,8 +1447,8 @@ fn pvf_check_upgrade_reject() {
|
||||
|
||||
#[test]
|
||||
fn pvf_check_submit_vote() {
|
||||
let code_a: ValidationCode = vec![3, 2, 1].into();
|
||||
let code_b: ValidationCode = vec![1, 2, 3].into();
|
||||
let code_a = test_validation_code_1();
|
||||
let code_b = test_validation_code_2();
|
||||
|
||||
let check = |stmt: PvfCheckStatement| -> (Result<_, _>, Result<_, _>) {
|
||||
let validators = &[
|
||||
@@ -1554,8 +1564,8 @@ fn pvf_check_submit_vote() {
|
||||
#[test]
|
||||
fn include_pvf_check_statement_refunds_weight() {
|
||||
let a = ParaId::from(111);
|
||||
let old_code: ValidationCode = vec![1, 2, 3].into();
|
||||
let new_code: ValidationCode = vec![3, 2, 1].into();
|
||||
let old_code = test_validation_code_1();
|
||||
let new_code = test_validation_code_2();
|
||||
|
||||
let paras = vec![(
|
||||
a,
|
||||
@@ -1620,7 +1630,7 @@ fn include_pvf_check_statement_refunds_weight() {
|
||||
fn add_trusted_validation_code_inserts_with_no_users() {
|
||||
// This test is to ensure that trusted validation code is inserted into the storage
|
||||
// with the reference count equal to 0.
|
||||
let validation_code = ValidationCode(vec![1, 2, 3]);
|
||||
let validation_code = test_validation_code_1();
|
||||
new_test_ext(Default::default()).execute_with(|| {
|
||||
assert_ok!(Paras::add_trusted_validation_code(
|
||||
RuntimeOrigin::root(),
|
||||
@@ -1634,7 +1644,7 @@ fn add_trusted_validation_code_inserts_with_no_users() {
|
||||
fn add_trusted_validation_code_idempotent() {
|
||||
// This test makes sure that calling add_trusted_validation_code twice with the same
|
||||
// parameters is a no-op.
|
||||
let validation_code = ValidationCode(vec![1, 2, 3]);
|
||||
let validation_code = test_validation_code_1();
|
||||
new_test_ext(Default::default()).execute_with(|| {
|
||||
assert_ok!(Paras::add_trusted_validation_code(
|
||||
RuntimeOrigin::root(),
|
||||
@@ -1653,7 +1663,7 @@ fn add_trusted_validation_code_idempotent() {
|
||||
fn poke_unused_validation_code_removes_code_cleanly() {
|
||||
// This test makes sure that calling poke_unused_validation_code with a code that is currently
|
||||
// in the storage but has no users will remove it cleanly from the storage.
|
||||
let validation_code = ValidationCode(vec![1, 2, 3]);
|
||||
let validation_code = test_validation_code_1();
|
||||
new_test_ext(Default::default()).execute_with(|| {
|
||||
assert_ok!(Paras::add_trusted_validation_code(
|
||||
RuntimeOrigin::root(),
|
||||
@@ -1672,7 +1682,7 @@ fn poke_unused_validation_code_removes_code_cleanly() {
|
||||
#[test]
|
||||
fn poke_unused_validation_code_doesnt_remove_code_with_users() {
|
||||
let para_id = 100.into();
|
||||
let validation_code = ValidationCode(vec![1, 2, 3]);
|
||||
let validation_code = test_validation_code_1();
|
||||
new_test_ext(Default::default()).execute_with(|| {
|
||||
// First we add the code to the storage.
|
||||
assert_ok!(Paras::add_trusted_validation_code(
|
||||
@@ -1708,7 +1718,7 @@ fn increase_code_ref_doesnt_have_allergy_on_add_trusted_validation_code() {
|
||||
// to a disaster.
|
||||
// NOTE that this test is extra paranoid, as it is not really possible to hit
|
||||
// `decrease_code_ref` without calling `increase_code_ref` first.
|
||||
let code = ValidationCode(vec![1, 2, 3]);
|
||||
let code = test_validation_code_1();
|
||||
|
||||
new_test_ext(Default::default()).execute_with(|| {
|
||||
assert_ok!(Paras::add_trusted_validation_code(RuntimeOrigin::root(), code.clone()));
|
||||
@@ -1732,7 +1742,7 @@ fn add_trusted_validation_code_insta_approval() {
|
||||
// `add_trusted_validation_code` and uses the `CodeByHash::contains_key` which is what
|
||||
// `add_trusted_validation_code` uses.
|
||||
let para_id = 100.into();
|
||||
let validation_code = ValidationCode(vec![1, 2, 3]);
|
||||
let validation_code = test_validation_code_1();
|
||||
let validation_upgrade_delay = 25;
|
||||
let minimum_validation_upgrade_delay = 2;
|
||||
let genesis_config = MockGenesisConfig {
|
||||
@@ -1779,7 +1789,7 @@ fn add_trusted_validation_code_enacts_existing_pvf_vote() {
|
||||
// already going through PVF pre-checking voting will conclude the voting and enact the
|
||||
// code upgrade.
|
||||
let para_id = 100.into();
|
||||
let validation_code = ValidationCode(vec![1, 2, 3]);
|
||||
let validation_code = test_validation_code_1();
|
||||
let validation_upgrade_delay = 25;
|
||||
let minimum_validation_upgrade_delay = 2;
|
||||
let genesis_config = MockGenesisConfig {
|
||||
@@ -1868,7 +1878,7 @@ fn verify_para_head_is_externally_accessible() {
|
||||
|
||||
#[test]
|
||||
fn most_recent_context() {
|
||||
let validation_code: ValidationCode = vec![1, 2, 3].into();
|
||||
let validation_code = test_validation_code_1();
|
||||
|
||||
let genesis_config = MockGenesisConfig::default();
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0
|
||||
# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json
|
||||
|
||||
title: Validate code when scheduling uprades
|
||||
|
||||
doc:
|
||||
- audience: Runtime User
|
||||
description: |
|
||||
Adds checks to ensure that the validation code is valid before scheduling
|
||||
a code upgrade.
|
||||
|
||||
crates:
|
||||
- name: polkadot-runtime-parachains
|
||||
Reference in New Issue
Block a user