mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-14 05:11:09 +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:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user