mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 08:11:03 +00:00
Introduce a maximum code size and head data size (#835)
* add a maximum code size and head data size * get existing tests passing * add tests for slots logic * test registrar behavior * introduce maximums and bump versions * address review grumbles * work around publicizing derive * remove unneeded and wrong doc
This commit is contained in:
committed by
GitHub
parent
9b23f3f1f0
commit
295151338d
@@ -121,6 +121,15 @@ pub enum LastContribution<BlockNumber> {
|
|||||||
|
|
||||||
#[derive(Encode, Decode, Clone, PartialEq, Eq)]
|
#[derive(Encode, Decode, Clone, PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "std", derive(Debug))]
|
#[cfg_attr(feature = "std", derive(Debug))]
|
||||||
|
struct DeployData<Hash> {
|
||||||
|
code_hash: Hash,
|
||||||
|
code_size: u32,
|
||||||
|
initial_head_data: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Encode, Decode, Clone, PartialEq, Eq)]
|
||||||
|
#[cfg_attr(feature = "std", derive(Debug))]
|
||||||
|
#[codec(dumb_trait_bound)]
|
||||||
pub struct FundInfo<AccountId, Balance, Hash, BlockNumber> {
|
pub struct FundInfo<AccountId, Balance, Hash, BlockNumber> {
|
||||||
/// The parachain that this fund has funded, if there is one. As long as this is `Some`, then
|
/// The parachain that this fund has funded, if there is one. As long as this is `Some`, then
|
||||||
/// the funds may not be withdrawn and the fund cannot be dissolved.
|
/// the funds may not be withdrawn and the fund cannot be dissolved.
|
||||||
@@ -150,8 +159,8 @@ pub struct FundInfo<AccountId, Balance, Hash, BlockNumber> {
|
|||||||
/// BlockNumber.
|
/// BlockNumber.
|
||||||
last_slot: BlockNumber,
|
last_slot: BlockNumber,
|
||||||
/// The deployment data associated with this fund, if any. Once set it may not be reset. First
|
/// The deployment data associated with this fund, if any. Once set it may not be reset. First
|
||||||
/// is the code hash, second is the initial head data.
|
/// is the code hash, second is the code size, third is the initial head data.
|
||||||
deploy_data: Option<(Hash, Vec<u8>)>,
|
deploy_data: Option<DeployData<Hash>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
decl_storage! {
|
decl_storage! {
|
||||||
@@ -346,6 +355,7 @@ decl_module! {
|
|||||||
fn fix_deploy_data(origin,
|
fn fix_deploy_data(origin,
|
||||||
#[compact] index: FundIndex,
|
#[compact] index: FundIndex,
|
||||||
code_hash: T::Hash,
|
code_hash: T::Hash,
|
||||||
|
code_size: u32,
|
||||||
initial_head_data: Vec<u8>
|
initial_head_data: Vec<u8>
|
||||||
) {
|
) {
|
||||||
let who = ensure_signed(origin)?;
|
let who = ensure_signed(origin)?;
|
||||||
@@ -354,7 +364,7 @@ decl_module! {
|
|||||||
ensure!(fund.owner == who, Error::<T>::InvalidOrigin); // must be fund owner
|
ensure!(fund.owner == who, Error::<T>::InvalidOrigin); // must be fund owner
|
||||||
ensure!(fund.deploy_data.is_none(), Error::<T>::ExistingDeployData);
|
ensure!(fund.deploy_data.is_none(), Error::<T>::ExistingDeployData);
|
||||||
|
|
||||||
fund.deploy_data = Some((code_hash, initial_head_data));
|
fund.deploy_data = Some(DeployData { code_hash, code_size, initial_head_data });
|
||||||
|
|
||||||
<Funds<T>>::insert(index, &fund);
|
<Funds<T>>::insert(index, &fund);
|
||||||
|
|
||||||
@@ -374,12 +384,20 @@ decl_module! {
|
|||||||
let _ = ensure_signed(origin)?;
|
let _ = ensure_signed(origin)?;
|
||||||
|
|
||||||
let mut fund = Self::funds(index).ok_or(Error::<T>::InvalidFundIndex)?;
|
let mut fund = Self::funds(index).ok_or(Error::<T>::InvalidFundIndex)?;
|
||||||
let (code_hash, initial_head_data) = fund.clone().deploy_data.ok_or(Error::<T>::UnsetDeployData)?;
|
let DeployData { code_hash, code_size, initial_head_data }
|
||||||
|
= fund.clone().deploy_data.ok_or(Error::<T>::UnsetDeployData)?;
|
||||||
ensure!(fund.parachain.is_none(), Error::<T>::AlreadyOnboard);
|
ensure!(fund.parachain.is_none(), Error::<T>::AlreadyOnboard);
|
||||||
fund.parachain = Some(para_id);
|
fund.parachain = Some(para_id);
|
||||||
|
|
||||||
let fund_origin = system::RawOrigin::Signed(Self::fund_account_id(index)).into();
|
let fund_origin = system::RawOrigin::Signed(Self::fund_account_id(index)).into();
|
||||||
<slots::Module<T>>::fix_deploy_data(fund_origin, index, para_id, code_hash, initial_head_data)?;
|
<slots::Module<T>>::fix_deploy_data(
|
||||||
|
fund_origin,
|
||||||
|
index,
|
||||||
|
para_id,
|
||||||
|
code_hash,
|
||||||
|
code_size,
|
||||||
|
initial_head_data,
|
||||||
|
)?;
|
||||||
|
|
||||||
<Funds<T>>::insert(index, &fund);
|
<Funds<T>>::insert(index, &fund);
|
||||||
|
|
||||||
@@ -650,6 +668,9 @@ mod tests {
|
|||||||
RefCell<HashMap<u32, (Vec<u8>, Vec<u8>)>> = RefCell::new(HashMap::new());
|
RefCell<HashMap<u32, (Vec<u8>, Vec<u8>)>> = RefCell::new(HashMap::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const MAX_CODE_SIZE: u32 = 100;
|
||||||
|
const MAX_HEAD_DATA_SIZE: u32 = 10;
|
||||||
|
|
||||||
pub struct TestParachains;
|
pub struct TestParachains;
|
||||||
impl Registrar<u64> for TestParachains {
|
impl Registrar<u64> for TestParachains {
|
||||||
fn new_id() -> ParaId {
|
fn new_id() -> ParaId {
|
||||||
@@ -659,6 +680,14 @@ mod tests {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn head_data_size_allowed(head_data_size: u32) -> bool {
|
||||||
|
head_data_size <= MAX_HEAD_DATA_SIZE
|
||||||
|
}
|
||||||
|
|
||||||
|
fn code_size_allowed(code_size: u32) -> bool {
|
||||||
|
code_size <= MAX_CODE_SIZE
|
||||||
|
}
|
||||||
|
|
||||||
fn register_para(
|
fn register_para(
|
||||||
id: ParaId,
|
id: ParaId,
|
||||||
_info: ParaInfo,
|
_info: ParaInfo,
|
||||||
@@ -875,13 +904,21 @@ mod tests {
|
|||||||
Origin::signed(1),
|
Origin::signed(1),
|
||||||
0,
|
0,
|
||||||
<Test as system::Trait>::Hash::default(),
|
<Test as system::Trait>::Hash::default(),
|
||||||
|
0,
|
||||||
vec![0]
|
vec![0]
|
||||||
));
|
));
|
||||||
|
|
||||||
let fund = Crowdfund::funds(0).unwrap();
|
let fund = Crowdfund::funds(0).unwrap();
|
||||||
|
|
||||||
// Confirm deploy data is stored correctly
|
// Confirm deploy data is stored correctly
|
||||||
assert_eq!(fund.deploy_data, Some((<Test as system::Trait>::Hash::default(), vec![0])));
|
assert_eq!(
|
||||||
|
fund.deploy_data,
|
||||||
|
Some(DeployData {
|
||||||
|
code_hash: <Test as system::Trait>::Hash::default(),
|
||||||
|
code_size: 0,
|
||||||
|
initial_head_data: vec![0],
|
||||||
|
}),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -897,6 +934,7 @@ mod tests {
|
|||||||
Origin::signed(2),
|
Origin::signed(2),
|
||||||
0,
|
0,
|
||||||
<Test as system::Trait>::Hash::default(),
|
<Test as system::Trait>::Hash::default(),
|
||||||
|
0,
|
||||||
vec![0]),
|
vec![0]),
|
||||||
Error::<Test>::InvalidOrigin
|
Error::<Test>::InvalidOrigin
|
||||||
);
|
);
|
||||||
@@ -906,6 +944,7 @@ mod tests {
|
|||||||
Origin::signed(1),
|
Origin::signed(1),
|
||||||
1,
|
1,
|
||||||
<Test as system::Trait>::Hash::default(),
|
<Test as system::Trait>::Hash::default(),
|
||||||
|
0,
|
||||||
vec![0]),
|
vec![0]),
|
||||||
Error::<Test>::InvalidFundIndex
|
Error::<Test>::InvalidFundIndex
|
||||||
);
|
);
|
||||||
@@ -915,6 +954,7 @@ mod tests {
|
|||||||
Origin::signed(1),
|
Origin::signed(1),
|
||||||
0,
|
0,
|
||||||
<Test as system::Trait>::Hash::default(),
|
<Test as system::Trait>::Hash::default(),
|
||||||
|
0,
|
||||||
vec![0]
|
vec![0]
|
||||||
));
|
));
|
||||||
|
|
||||||
@@ -922,6 +962,7 @@ mod tests {
|
|||||||
Origin::signed(1),
|
Origin::signed(1),
|
||||||
0,
|
0,
|
||||||
<Test as system::Trait>::Hash::default(),
|
<Test as system::Trait>::Hash::default(),
|
||||||
|
0,
|
||||||
vec![1]),
|
vec![1]),
|
||||||
Error::<Test>::ExistingDeployData
|
Error::<Test>::ExistingDeployData
|
||||||
);
|
);
|
||||||
@@ -941,6 +982,7 @@ mod tests {
|
|||||||
Origin::signed(1),
|
Origin::signed(1),
|
||||||
0,
|
0,
|
||||||
<Test as system::Trait>::Hash::default(),
|
<Test as system::Trait>::Hash::default(),
|
||||||
|
0,
|
||||||
vec![0]
|
vec![0]
|
||||||
));
|
));
|
||||||
|
|
||||||
@@ -986,6 +1028,7 @@ mod tests {
|
|||||||
Origin::signed(1),
|
Origin::signed(1),
|
||||||
0,
|
0,
|
||||||
<Test as system::Trait>::Hash::default(),
|
<Test as system::Trait>::Hash::default(),
|
||||||
|
0,
|
||||||
vec![0]
|
vec![0]
|
||||||
));
|
));
|
||||||
|
|
||||||
@@ -1013,6 +1056,7 @@ mod tests {
|
|||||||
Origin::signed(1),
|
Origin::signed(1),
|
||||||
0,
|
0,
|
||||||
<Test as system::Trait>::Hash::default(),
|
<Test as system::Trait>::Hash::default(),
|
||||||
|
0,
|
||||||
vec![0]
|
vec![0]
|
||||||
));
|
));
|
||||||
|
|
||||||
@@ -1055,6 +1099,7 @@ mod tests {
|
|||||||
Origin::signed(1),
|
Origin::signed(1),
|
||||||
0,
|
0,
|
||||||
<Test as system::Trait>::Hash::default(),
|
<Test as system::Trait>::Hash::default(),
|
||||||
|
0,
|
||||||
vec![0]
|
vec![0]
|
||||||
));
|
));
|
||||||
|
|
||||||
@@ -1196,6 +1241,7 @@ mod tests {
|
|||||||
Origin::signed(1),
|
Origin::signed(1),
|
||||||
0,
|
0,
|
||||||
<Test as system::Trait>::Hash::default(),
|
<Test as system::Trait>::Hash::default(),
|
||||||
|
0,
|
||||||
vec![0]
|
vec![0]
|
||||||
));
|
));
|
||||||
assert_ok!(Crowdfund::onboard(Origin::signed(1), 0, 0.into()));
|
assert_ok!(Crowdfund::onboard(Origin::signed(1), 0, 0.into()));
|
||||||
@@ -1224,6 +1270,7 @@ mod tests {
|
|||||||
Origin::signed(1),
|
Origin::signed(1),
|
||||||
0,
|
0,
|
||||||
<Test as system::Trait>::Hash::default(),
|
<Test as system::Trait>::Hash::default(),
|
||||||
|
0,
|
||||||
vec![0]
|
vec![0]
|
||||||
));
|
));
|
||||||
// Move to the end of auction...
|
// Move to the end of auction...
|
||||||
@@ -1262,12 +1309,14 @@ mod tests {
|
|||||||
Origin::signed(1),
|
Origin::signed(1),
|
||||||
0,
|
0,
|
||||||
<Test as system::Trait>::Hash::default(),
|
<Test as system::Trait>::Hash::default(),
|
||||||
|
0,
|
||||||
vec![0]
|
vec![0]
|
||||||
));
|
));
|
||||||
assert_ok!(Crowdfund::fix_deploy_data(
|
assert_ok!(Crowdfund::fix_deploy_data(
|
||||||
Origin::signed(2),
|
Origin::signed(2),
|
||||||
1,
|
1,
|
||||||
<Test as system::Trait>::Hash::default(),
|
<Test as system::Trait>::Hash::default(),
|
||||||
|
0,
|
||||||
vec![0]
|
vec![0]
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|||||||
@@ -129,6 +129,14 @@ pub trait Trait: attestations::Trait {
|
|||||||
|
|
||||||
/// The way that we are able to register parachains.
|
/// The way that we are able to register parachains.
|
||||||
type Registrar: Registrar<Self::AccountId>;
|
type Registrar: Registrar<Self::AccountId>;
|
||||||
|
|
||||||
|
/// Maximum code size for parachains, in bytes. Note that this is not
|
||||||
|
/// the entire storage burden of the parachain, as old code is stored for
|
||||||
|
/// `SlashPeriod` blocks.
|
||||||
|
type MaxCodeSize: Get<u32>;
|
||||||
|
|
||||||
|
/// Max head data size.
|
||||||
|
type MaxHeadDataSize: Get<u32>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Origin for the parachains module.
|
/// Origin for the parachains module.
|
||||||
@@ -233,6 +241,8 @@ decl_error! {
|
|||||||
UntaggedVotes,
|
UntaggedVotes,
|
||||||
/// Wrong parent head for parachain receipt.
|
/// Wrong parent head for parachain receipt.
|
||||||
ParentMismatch,
|
ParentMismatch,
|
||||||
|
/// Head data was too large.
|
||||||
|
HeadDataTooLarge,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -778,6 +788,8 @@ impl<T: Trait> Module<T> {
|
|||||||
let mut validator_groups = GroupedDutyIter::new(&sorted_validators[..]);
|
let mut validator_groups = GroupedDutyIter::new(&sorted_validators[..]);
|
||||||
|
|
||||||
let mut para_block_hashes = Vec::new();
|
let mut para_block_hashes = Vec::new();
|
||||||
|
|
||||||
|
let max_head_data_size = T::MaxHeadDataSize::get();
|
||||||
for candidate in attested_candidates {
|
for candidate in attested_candidates {
|
||||||
let para_id = candidate.parachain_index();
|
let para_id = candidate.parachain_index();
|
||||||
let validator_group = validator_groups.group_for(para_id)
|
let validator_group = validator_groups.group_for(para_id)
|
||||||
@@ -801,6 +813,11 @@ impl<T: Trait> Module<T> {
|
|||||||
Error::<T>::VotesExceedsAuthorities,
|
Error::<T>::VotesExceedsAuthorities,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
ensure!(
|
||||||
|
max_head_data_size >= candidate.candidate().head_data.0.len() as _,
|
||||||
|
Error::<T>::HeadDataTooLarge,
|
||||||
|
);
|
||||||
|
|
||||||
let fees = candidate.candidate().fees;
|
let fees = candidate.candidate().fees;
|
||||||
T::ParachainCurrency::deduct(para_id, fees)?;
|
T::ParachainCurrency::deduct(para_id, fees)?;
|
||||||
|
|
||||||
@@ -1152,6 +1169,11 @@ mod tests {
|
|||||||
type MaxRetries = MaxRetries;
|
type MaxRetries = MaxRetries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parameter_types! {
|
||||||
|
pub const MaxHeadDataSize: u32 = 100;
|
||||||
|
pub const MaxCodeSize: u32 = 100;
|
||||||
|
}
|
||||||
|
|
||||||
impl Trait for Test {
|
impl Trait for Test {
|
||||||
type Origin = Origin;
|
type Origin = Origin;
|
||||||
type Call = Call;
|
type Call = Call;
|
||||||
@@ -1159,6 +1181,8 @@ mod tests {
|
|||||||
type Randomness = RandomnessCollectiveFlip;
|
type Randomness = RandomnessCollectiveFlip;
|
||||||
type ActiveParachains = registrar::Module<Test>;
|
type ActiveParachains = registrar::Module<Test>;
|
||||||
type Registrar = registrar::Module<Test>;
|
type Registrar = registrar::Module<Test>;
|
||||||
|
type MaxCodeSize = MaxCodeSize;
|
||||||
|
type MaxHeadDataSize = MaxHeadDataSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
type Parachains = Module<Test>;
|
type Parachains = Module<Test>;
|
||||||
|
|||||||
@@ -46,8 +46,19 @@ pub trait Registrar<AccountId> {
|
|||||||
/// Create a new unique parachain identity for later registration.
|
/// Create a new unique parachain identity for later registration.
|
||||||
fn new_id() -> ParaId;
|
fn new_id() -> ParaId;
|
||||||
|
|
||||||
|
/// Checks whether the given initial head data size falls within the limit.
|
||||||
|
fn head_data_size_allowed(head_data_size: u32) -> bool;
|
||||||
|
|
||||||
|
/// Checks whether the given validation code falls within the limit.
|
||||||
|
fn code_size_allowed(code_size: u32) -> bool;
|
||||||
|
|
||||||
/// Register a parachain with given `code` and `initial_head_data`. `id` must not yet be registered or it will
|
/// Register a parachain with given `code` and `initial_head_data`. `id` must not yet be registered or it will
|
||||||
/// result in a error.
|
/// result in a error.
|
||||||
|
///
|
||||||
|
/// This does not enforce any code size or initial head data limits, as these
|
||||||
|
/// are governable and parameters for parachain initialization are often
|
||||||
|
/// determined long ahead-of-time. Not checking these values ensures that changes to limits
|
||||||
|
/// do not invalidate in-progress auction winners.
|
||||||
fn register_para(
|
fn register_para(
|
||||||
id: ParaId,
|
id: ParaId,
|
||||||
info: ParaInfo,
|
info: ParaInfo,
|
||||||
@@ -64,6 +75,14 @@ impl<T: Trait> Registrar<T::AccountId> for Module<T> {
|
|||||||
<NextFreeId>::mutate(|n| { let r = *n; *n = ParaId::from(u32::from(*n) + 1); r })
|
<NextFreeId>::mutate(|n| { let r = *n; *n = ParaId::from(u32::from(*n) + 1); r })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn head_data_size_allowed(head_data_size: u32) -> bool {
|
||||||
|
head_data_size <= <T as parachains::Trait>::MaxHeadDataSize::get()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn code_size_allowed(code_size: u32) -> bool {
|
||||||
|
code_size <= <T as parachains::Trait>::MaxCodeSize::get()
|
||||||
|
}
|
||||||
|
|
||||||
fn register_para(
|
fn register_para(
|
||||||
id: ParaId,
|
id: ParaId,
|
||||||
info: ParaInfo,
|
info: ParaInfo,
|
||||||
@@ -71,6 +90,7 @@ impl<T: Trait> Registrar<T::AccountId> for Module<T> {
|
|||||||
initial_head_data: Vec<u8>,
|
initial_head_data: Vec<u8>,
|
||||||
) -> DispatchResult {
|
) -> DispatchResult {
|
||||||
ensure!(!Paras::exists(id), Error::<T>::ParaAlreadyExists);
|
ensure!(!Paras::exists(id), Error::<T>::ParaAlreadyExists);
|
||||||
|
|
||||||
if let Scheduling::Always = info.scheduling {
|
if let Scheduling::Always = info.scheduling {
|
||||||
Parachains::mutate(|parachains|
|
Parachains::mutate(|parachains|
|
||||||
match parachains.binary_search(&id) {
|
match parachains.binary_search(&id) {
|
||||||
@@ -222,6 +242,10 @@ decl_error! {
|
|||||||
InvalidChainId,
|
InvalidChainId,
|
||||||
/// Invalid parathread ID.
|
/// Invalid parathread ID.
|
||||||
InvalidThreadId,
|
InvalidThreadId,
|
||||||
|
/// Invalid para code size.
|
||||||
|
CodeTooLarge,
|
||||||
|
/// Invalid para head data size.
|
||||||
|
HeadDataTooLarge,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,8 +256,11 @@ decl_module! {
|
|||||||
|
|
||||||
fn deposit_event() = default;
|
fn deposit_event() = default;
|
||||||
|
|
||||||
/// Register a parachain with given code.
|
/// Register a parachain with given code. Must be called by root.
|
||||||
/// Fails if given ID is already used.
|
/// Fails if given ID is already used.
|
||||||
|
///
|
||||||
|
/// Unlike the `Registrar` trait function of the same name, this
|
||||||
|
/// checks the code and head data against size limits.
|
||||||
#[weight = SimpleDispatchInfo::FixedOperational(5_000_000)]
|
#[weight = SimpleDispatchInfo::FixedOperational(5_000_000)]
|
||||||
pub fn register_para(origin,
|
pub fn register_para(origin,
|
||||||
#[compact] id: ParaId,
|
#[compact] id: ParaId,
|
||||||
@@ -242,6 +269,18 @@ decl_module! {
|
|||||||
initial_head_data: Vec<u8>,
|
initial_head_data: Vec<u8>,
|
||||||
) -> DispatchResult {
|
) -> DispatchResult {
|
||||||
ensure_root(origin)?;
|
ensure_root(origin)?;
|
||||||
|
|
||||||
|
ensure!(
|
||||||
|
<Self as Registrar<T::AccountId>>::code_size_allowed(code.len() as _),
|
||||||
|
Error::<T>::CodeTooLarge,
|
||||||
|
);
|
||||||
|
|
||||||
|
ensure!(
|
||||||
|
<Self as Registrar<T::AccountId>>::head_data_size_allowed(
|
||||||
|
initial_head_data.len() as _
|
||||||
|
),
|
||||||
|
Error::<T>::HeadDataTooLarge,
|
||||||
|
);
|
||||||
<Self as Registrar<T::AccountId>>::
|
<Self as Registrar<T::AccountId>>::
|
||||||
register_para(id, info, code, initial_head_data)
|
register_para(id, info, code, initial_head_data)
|
||||||
}
|
}
|
||||||
@@ -267,6 +306,10 @@ decl_module! {
|
|||||||
///
|
///
|
||||||
/// Must be sent from a Signed origin that is able to have ParathreadDeposit reserved.
|
/// Must be sent from a Signed origin that is able to have ParathreadDeposit reserved.
|
||||||
/// `code` and `initial_head_data` are used to initialize the parathread's state.
|
/// `code` and `initial_head_data` are used to initialize the parathread's state.
|
||||||
|
///
|
||||||
|
/// Unlike `register_para`, this function does check that the maximum code size
|
||||||
|
/// and head data size are respected, as parathread registration is an atomic
|
||||||
|
/// action.
|
||||||
fn register_parathread(origin,
|
fn register_parathread(origin,
|
||||||
code: Vec<u8>,
|
code: Vec<u8>,
|
||||||
initial_head_data: Vec<u8>,
|
initial_head_data: Vec<u8>,
|
||||||
@@ -278,6 +321,19 @@ decl_module! {
|
|||||||
let info = ParaInfo {
|
let info = ParaInfo {
|
||||||
scheduling: Scheduling::Dynamic,
|
scheduling: Scheduling::Dynamic,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ensure!(
|
||||||
|
<Self as Registrar<T::AccountId>>::code_size_allowed(code.len() as _),
|
||||||
|
Error::<T>::CodeTooLarge,
|
||||||
|
);
|
||||||
|
|
||||||
|
ensure!(
|
||||||
|
<Self as Registrar<T::AccountId>>::head_data_size_allowed(
|
||||||
|
initial_head_data.len() as _
|
||||||
|
),
|
||||||
|
Error::<T>::HeadDataTooLarge,
|
||||||
|
);
|
||||||
|
|
||||||
let id = <Self as Registrar<T::AccountId>>::new_id();
|
let id = <Self as Registrar<T::AccountId>>::new_id();
|
||||||
|
|
||||||
let _ = <Self as Registrar<T::AccountId>>::
|
let _ = <Self as Registrar<T::AccountId>>::
|
||||||
@@ -709,6 +765,11 @@ mod tests {
|
|||||||
type DisabledValidatorsThreshold = DisabledValidatorsThreshold;
|
type DisabledValidatorsThreshold = DisabledValidatorsThreshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parameter_types! {
|
||||||
|
pub const MaxHeadDataSize: u32 = 100;
|
||||||
|
pub const MaxCodeSize: u32 = 100;
|
||||||
|
}
|
||||||
|
|
||||||
impl parachains::Trait for Test {
|
impl parachains::Trait for Test {
|
||||||
type Origin = Origin;
|
type Origin = Origin;
|
||||||
type Call = Call;
|
type Call = Call;
|
||||||
@@ -716,6 +777,8 @@ mod tests {
|
|||||||
type ActiveParachains = Registrar;
|
type ActiveParachains = Registrar;
|
||||||
type Registrar = Registrar;
|
type Registrar = Registrar;
|
||||||
type Randomness = RandomnessCollectiveFlip;
|
type Randomness = RandomnessCollectiveFlip;
|
||||||
|
type MaxCodeSize = MaxCodeSize;
|
||||||
|
type MaxHeadDataSize = MaxHeadDataSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
parameter_types! {
|
parameter_types! {
|
||||||
@@ -929,7 +992,7 @@ mod tests {
|
|||||||
|
|
||||||
run_to_block(10);
|
run_to_block(10);
|
||||||
let h = BlakeTwo256::hash(&[2u8; 3]);
|
let h = BlakeTwo256::hash(&[2u8; 3]);
|
||||||
assert_ok!(Slots::fix_deploy_data(Origin::signed(1), 0, user_id(1), h, vec![2; 3]));
|
assert_ok!(Slots::fix_deploy_data(Origin::signed(1), 0, user_id(1), h, 3, vec![2; 3]));
|
||||||
assert_ok!(Slots::elaborate_deploy_data(Origin::signed(0), user_id(1), vec![2; 3]));
|
assert_ok!(Slots::elaborate_deploy_data(Origin::signed(0), user_id(1), vec![2; 3]));
|
||||||
assert_ok!(Slots::set_offboarding(Origin::signed(user_id(1).into_account()), 1));
|
assert_ok!(Slots::set_offboarding(Origin::signed(user_id(1).into_account()), 1));
|
||||||
|
|
||||||
@@ -1380,4 +1443,26 @@ mod tests {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn register_does_not_enforce_limits_when_registering() {
|
||||||
|
new_test_ext(vec![]).execute_with(|| {
|
||||||
|
let bad_code_size = <Test as parachains::Trait>::MaxCodeSize::get() + 1;
|
||||||
|
let bad_head_size = <Test as parachains::Trait>::MaxHeadDataSize::get() + 1;
|
||||||
|
|
||||||
|
let code = vec![1u8; bad_code_size as _];
|
||||||
|
let head_data = vec![2u8; bad_head_size as _];
|
||||||
|
|
||||||
|
assert!(!<Registrar as super::Registrar<u64>>::code_size_allowed(bad_code_size));
|
||||||
|
assert!(!<Registrar as super::Registrar<u64>>::head_data_size_allowed(bad_head_size));
|
||||||
|
|
||||||
|
let id = <Registrar as super::Registrar<u64>>::new_id();
|
||||||
|
assert_ok!(<Registrar as super::Registrar<u64>>::register_para(
|
||||||
|
id,
|
||||||
|
ParaInfo { scheduling: Scheduling::Always },
|
||||||
|
code,
|
||||||
|
head_data,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,8 +108,12 @@ impl<AccountId: Clone + Default + Codec> Bidder<AccountId> {
|
|||||||
pub enum IncomingParachain<AccountId, Hash> {
|
pub enum IncomingParachain<AccountId, Hash> {
|
||||||
/// Deploy information not yet set; just the bidder identity.
|
/// Deploy information not yet set; just the bidder identity.
|
||||||
Unset(NewBidder<AccountId>),
|
Unset(NewBidder<AccountId>),
|
||||||
/// Deploy information set only by code hash; so we store the code hash and head data.
|
/// Deploy information set only by code hash; so we store the code hash, code size, and head data.
|
||||||
Fixed { code_hash: Hash, initial_head_data: Vec<u8> },
|
///
|
||||||
|
/// The code size must be included so that checks against a maximum code size
|
||||||
|
/// can be done. If the size of the preimage of the code hash does not match
|
||||||
|
/// the given code size, it will not be possible to register the parachain.
|
||||||
|
Fixed { code_hash: Hash, code_size: u32, initial_head_data: Vec<u8> },
|
||||||
/// Deploy information fully set; so we store the code and head data.
|
/// Deploy information fully set; so we store the code and head data.
|
||||||
Deploy { code: Vec<u8>, initial_head_data: Vec<u8> },
|
Deploy { code: Vec<u8>, initial_head_data: Vec<u8> },
|
||||||
}
|
}
|
||||||
@@ -250,6 +254,10 @@ decl_error! {
|
|||||||
NotCurrentAuction,
|
NotCurrentAuction,
|
||||||
/// Not an auction.
|
/// Not an auction.
|
||||||
NotAuction,
|
NotAuction,
|
||||||
|
/// Given code size is too large.
|
||||||
|
CodeTooLarge,
|
||||||
|
/// Given initial head data is too large.
|
||||||
|
HeadDataTooLarge,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -402,6 +410,7 @@ decl_module! {
|
|||||||
#[compact] sub: SubId,
|
#[compact] sub: SubId,
|
||||||
#[compact] para_id: ParaId,
|
#[compact] para_id: ParaId,
|
||||||
code_hash: T::Hash,
|
code_hash: T::Hash,
|
||||||
|
code_size: u32,
|
||||||
initial_head_data: Vec<u8>
|
initial_head_data: Vec<u8>
|
||||||
) {
|
) {
|
||||||
let who = ensure_signed(origin)?;
|
let who = ensure_signed(origin)?;
|
||||||
@@ -412,7 +421,17 @@ decl_module! {
|
|||||||
} else {
|
} else {
|
||||||
Err(Error::<T>::AlreadyRegistered)?
|
Err(Error::<T>::AlreadyRegistered)?
|
||||||
}
|
}
|
||||||
let item = (starts, IncomingParachain::Fixed{code_hash, initial_head_data});
|
|
||||||
|
ensure!(
|
||||||
|
T::Parachains::head_data_size_allowed(initial_head_data.len() as _),
|
||||||
|
Error::<T>::HeadDataTooLarge,
|
||||||
|
);
|
||||||
|
ensure!(
|
||||||
|
T::Parachains::code_size_allowed(code_size),
|
||||||
|
Error::<T>::CodeTooLarge,
|
||||||
|
);
|
||||||
|
|
||||||
|
let item = (starts, IncomingParachain::Fixed{code_hash, code_size, initial_head_data});
|
||||||
<Onboarding<T>>::insert(¶_id, item);
|
<Onboarding<T>>::insert(¶_id, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -432,8 +451,10 @@ decl_module! {
|
|||||||
pub fn elaborate_deploy_data(_origin, #[compact] para_id: ParaId, code: Vec<u8>) -> DispatchResult {
|
pub fn elaborate_deploy_data(_origin, #[compact] para_id: ParaId, code: Vec<u8>) -> DispatchResult {
|
||||||
let (starts, details) = <Onboarding<T>>::get(¶_id)
|
let (starts, details) = <Onboarding<T>>::get(¶_id)
|
||||||
.ok_or(Error::<T>::ParaNotOnboarding)?;
|
.ok_or(Error::<T>::ParaNotOnboarding)?;
|
||||||
if let IncomingParachain::Fixed{code_hash, initial_head_data} = details {
|
if let IncomingParachain::Fixed{code_hash, code_size, initial_head_data} = details {
|
||||||
|
ensure!(code.len() as u32 == code_size, Error::<T>::InvalidCode);
|
||||||
ensure!(<T as system::Trait>::Hashing::hash(&code) == code_hash, Error::<T>::InvalidCode);
|
ensure!(<T as system::Trait>::Hashing::hash(&code) == code_hash, Error::<T>::InvalidCode);
|
||||||
|
|
||||||
if starts > Self::lease_period_index() {
|
if starts > Self::lease_period_index() {
|
||||||
// Hasn't yet begun. Replace the on-boarding entry with the new information.
|
// Hasn't yet begun. Replace the on-boarding entry with the new information.
|
||||||
let item = (starts, IncomingParachain::Deploy{code, initial_head_data});
|
let item = (starts, IncomingParachain::Deploy{code, initial_head_data});
|
||||||
@@ -918,6 +939,9 @@ mod tests {
|
|||||||
RefCell<HashMap<u32, (Vec<u8>, Vec<u8>)>> = RefCell::new(HashMap::new());
|
RefCell<HashMap<u32, (Vec<u8>, Vec<u8>)>> = RefCell::new(HashMap::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const MAX_CODE_SIZE: u32 = 100;
|
||||||
|
const MAX_HEAD_DATA_SIZE: u32 = 10;
|
||||||
|
|
||||||
pub struct TestParachains;
|
pub struct TestParachains;
|
||||||
impl Registrar<u64> for TestParachains {
|
impl Registrar<u64> for TestParachains {
|
||||||
fn new_id() -> ParaId {
|
fn new_id() -> ParaId {
|
||||||
@@ -926,6 +950,15 @@ mod tests {
|
|||||||
(*p.borrow() - 1).into()
|
(*p.borrow() - 1).into()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn head_data_size_allowed(head_data_size: u32) -> bool {
|
||||||
|
head_data_size <= MAX_HEAD_DATA_SIZE
|
||||||
|
}
|
||||||
|
|
||||||
|
fn code_size_allowed(code_size: u32) -> bool {
|
||||||
|
code_size <= MAX_CODE_SIZE
|
||||||
|
}
|
||||||
|
|
||||||
fn register_para(
|
fn register_para(
|
||||||
id: ParaId,
|
id: ParaId,
|
||||||
_info: ParaInfo,
|
_info: ParaInfo,
|
||||||
@@ -1144,7 +1177,7 @@ mod tests {
|
|||||||
|
|
||||||
run_to_block(9);
|
run_to_block(9);
|
||||||
let h = BlakeTwo256::hash(&[42u8][..]);
|
let h = BlakeTwo256::hash(&[42u8][..]);
|
||||||
assert_ok!(Slots::fix_deploy_data(Origin::signed(1), 0, 0.into(), h, vec![69]));
|
assert_ok!(Slots::fix_deploy_data(Origin::signed(1), 0, 0.into(), h, 1, vec![69]));
|
||||||
assert_ok!(Slots::elaborate_deploy_data(Origin::signed(0), 0.into(), vec![42]));
|
assert_ok!(Slots::elaborate_deploy_data(Origin::signed(0), 0.into(), vec![42]));
|
||||||
|
|
||||||
run_to_block(10);
|
run_to_block(10);
|
||||||
@@ -1169,7 +1202,7 @@ mod tests {
|
|||||||
|
|
||||||
run_to_block(11);
|
run_to_block(11);
|
||||||
let h = BlakeTwo256::hash(&[42u8][..]);
|
let h = BlakeTwo256::hash(&[42u8][..]);
|
||||||
assert_ok!(Slots::fix_deploy_data(Origin::signed(1), 0, 0.into(), h, vec![69]));
|
assert_ok!(Slots::fix_deploy_data(Origin::signed(1), 0, 0.into(), h, 1, vec![69]));
|
||||||
assert_ok!(Slots::elaborate_deploy_data(Origin::signed(0), 0.into(), vec![42]));
|
assert_ok!(Slots::elaborate_deploy_data(Origin::signed(0), 0.into(), vec![42]));
|
||||||
with_parachains(|p| {
|
with_parachains(|p| {
|
||||||
assert_eq!(p.len(), 1);
|
assert_eq!(p.len(), 1);
|
||||||
@@ -1279,7 +1312,7 @@ mod tests {
|
|||||||
|
|
||||||
for &(para, sub, acc) in &[(0, 0, 1), (1, 0, 2), (2, 0, 3), (3, 1, 4), (4, 1, 5)] {
|
for &(para, sub, acc) in &[(0, 0, 1), (1, 0, 2), (2, 0, 3), (3, 1, 4), (4, 1, 5)] {
|
||||||
let h = BlakeTwo256::hash(&[acc][..]);
|
let h = BlakeTwo256::hash(&[acc][..]);
|
||||||
assert_ok!(Slots::fix_deploy_data(Origin::signed(acc as _), sub, para.into(), h, vec![acc]));
|
assert_ok!(Slots::fix_deploy_data(Origin::signed(acc as _), sub, para.into(), h, 1, vec![acc]));
|
||||||
assert_ok!(Slots::elaborate_deploy_data(Origin::signed(0), para.into(), vec![acc]));
|
assert_ok!(Slots::elaborate_deploy_data(Origin::signed(0), para.into(), vec![acc]));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1326,7 +1359,7 @@ mod tests {
|
|||||||
|
|
||||||
run_to_block(10);
|
run_to_block(10);
|
||||||
let h = BlakeTwo256::hash(&[1u8][..]);
|
let h = BlakeTwo256::hash(&[1u8][..]);
|
||||||
assert_ok!(Slots::fix_deploy_data(Origin::signed(1), 0, 0.into(), h, vec![1]));
|
assert_ok!(Slots::fix_deploy_data(Origin::signed(1), 0, 0.into(), h, 1, vec![1]));
|
||||||
assert_ok!(Slots::elaborate_deploy_data(Origin::signed(0), 0.into(), vec![1]));
|
assert_ok!(Slots::elaborate_deploy_data(Origin::signed(0), 0.into(), vec![1]));
|
||||||
|
|
||||||
assert_ok!(Slots::new_auction(Origin::ROOT, 5, 2));
|
assert_ok!(Slots::new_auction(Origin::ROOT, 5, 2));
|
||||||
@@ -1371,7 +1404,7 @@ mod tests {
|
|||||||
|
|
||||||
run_to_block(10);
|
run_to_block(10);
|
||||||
let h = BlakeTwo256::hash(&[1u8][..]);
|
let h = BlakeTwo256::hash(&[1u8][..]);
|
||||||
assert_ok!(Slots::fix_deploy_data(Origin::signed(1), 0, 0.into(), h, vec![1]));
|
assert_ok!(Slots::fix_deploy_data(Origin::signed(1), 0, 0.into(), h, 1, vec![1]));
|
||||||
assert_ok!(Slots::elaborate_deploy_data(Origin::signed(0), 0.into(), vec![1]));
|
assert_ok!(Slots::elaborate_deploy_data(Origin::signed(0), 0.into(), vec![1]));
|
||||||
|
|
||||||
assert_ok!(Slots::new_auction(Origin::ROOT, 5, 2));
|
assert_ok!(Slots::new_auction(Origin::ROOT, 5, 2));
|
||||||
@@ -1560,4 +1593,94 @@ mod tests {
|
|||||||
];
|
];
|
||||||
assert_eq!(Slots::calculate_winners(winning.clone(), TestParachains::new_id), winners);
|
assert_eq!(Slots::calculate_winners(winning.clone(), TestParachains::new_id), winners);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn deploy_code_too_large() {
|
||||||
|
new_test_ext().execute_with(|| {
|
||||||
|
run_to_block(1);
|
||||||
|
assert_ok!(Slots::new_auction(Origin::ROOT, 5, 1));
|
||||||
|
assert_ok!(Slots::bid(Origin::signed(1), 0, 1, 1, 1, 5));
|
||||||
|
|
||||||
|
run_to_block(9);
|
||||||
|
assert_eq!(Slots::onboard_queue(1), vec![0.into()]);
|
||||||
|
|
||||||
|
run_to_block(10);
|
||||||
|
|
||||||
|
let code = vec![0u8; (MAX_CODE_SIZE + 1) as _];
|
||||||
|
let h = BlakeTwo256::hash(&code[..]);
|
||||||
|
assert_eq!(
|
||||||
|
Slots::fix_deploy_data(
|
||||||
|
Origin::signed(1), 0, 0.into(), h, code.len() as _, vec![1],
|
||||||
|
),
|
||||||
|
Err(Error::<Test>::CodeTooLarge.into()),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn deploy_maximum_ok() {
|
||||||
|
new_test_ext().execute_with(|| {
|
||||||
|
run_to_block(1);
|
||||||
|
assert_ok!(Slots::new_auction(Origin::ROOT, 5, 1));
|
||||||
|
assert_ok!(Slots::bid(Origin::signed(1), 0, 1, 1, 1, 5));
|
||||||
|
|
||||||
|
run_to_block(9);
|
||||||
|
assert_eq!(Slots::onboard_queue(1), vec![0.into()]);
|
||||||
|
|
||||||
|
run_to_block(10);
|
||||||
|
|
||||||
|
let code = vec![0u8; MAX_CODE_SIZE as _];
|
||||||
|
let head_data = vec![1u8; MAX_HEAD_DATA_SIZE as _];
|
||||||
|
let h = BlakeTwo256::hash(&code[..]);
|
||||||
|
assert_ok!(Slots::fix_deploy_data(
|
||||||
|
Origin::signed(1), 0, 0.into(), h, code.len() as _, head_data,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn deploy_head_data_too_large() {
|
||||||
|
new_test_ext().execute_with(|| {
|
||||||
|
run_to_block(1);
|
||||||
|
assert_ok!(Slots::new_auction(Origin::ROOT, 5, 1));
|
||||||
|
assert_ok!(Slots::bid(Origin::signed(1), 0, 1, 1, 1, 5));
|
||||||
|
|
||||||
|
run_to_block(9);
|
||||||
|
assert_eq!(Slots::onboard_queue(1), vec![0.into()]);
|
||||||
|
|
||||||
|
run_to_block(10);
|
||||||
|
|
||||||
|
let code = vec![0u8; MAX_CODE_SIZE as _];
|
||||||
|
let head_data = vec![1u8; (MAX_HEAD_DATA_SIZE + 1) as _];
|
||||||
|
let h = BlakeTwo256::hash(&code[..]);
|
||||||
|
assert_eq!(
|
||||||
|
Slots::fix_deploy_data(
|
||||||
|
Origin::signed(1), 0, 0.into(), h, code.len() as _, head_data,
|
||||||
|
),
|
||||||
|
Err(Error::<Test>::HeadDataTooLarge.into()),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn code_size_must_be_correct() {
|
||||||
|
new_test_ext().execute_with(|| {
|
||||||
|
run_to_block(1);
|
||||||
|
assert_ok!(Slots::new_auction(Origin::ROOT, 5, 1));
|
||||||
|
assert_ok!(Slots::bid(Origin::signed(1), 0, 1, 1, 1, 5));
|
||||||
|
|
||||||
|
run_to_block(9);
|
||||||
|
assert_eq!(Slots::onboard_queue(1), vec![0.into()]);
|
||||||
|
|
||||||
|
run_to_block(10);
|
||||||
|
|
||||||
|
let code = vec![0u8; MAX_CODE_SIZE as _];
|
||||||
|
let head_data = vec![1u8; MAX_HEAD_DATA_SIZE as _];
|
||||||
|
let h = BlakeTwo256::hash(&code[..]);
|
||||||
|
assert_ok!(Slots::fix_deploy_data(
|
||||||
|
Origin::signed(1), 0, 0.into(), h, (code.len() - 1) as _, head_data,
|
||||||
|
));
|
||||||
|
assert!(Slots::elaborate_deploy_data(Origin::signed(0), 0.into(), code).is_err());
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
|
|||||||
spec_name: create_runtime_str!("kusama"),
|
spec_name: create_runtime_str!("kusama"),
|
||||||
impl_name: create_runtime_str!("parity-kusama"),
|
impl_name: create_runtime_str!("parity-kusama"),
|
||||||
authoring_version: 2,
|
authoring_version: 2,
|
||||||
spec_version: 1047,
|
spec_version: 1048,
|
||||||
impl_version: 0,
|
impl_version: 0,
|
||||||
apis: RUNTIME_API_VERSIONS,
|
apis: RUNTIME_API_VERSIONS,
|
||||||
};
|
};
|
||||||
@@ -461,6 +461,11 @@ impl attestations::Trait for Runtime {
|
|||||||
type RewardAttestation = Staking;
|
type RewardAttestation = Staking;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parameter_types! {
|
||||||
|
pub const MaxCodeSize: u32 = 10 * 1024 * 1024; // 10 MB
|
||||||
|
pub const MaxHeadDataSize: u32 = 20 * 1024; // 20 KB
|
||||||
|
}
|
||||||
|
|
||||||
impl parachains::Trait for Runtime {
|
impl parachains::Trait for Runtime {
|
||||||
type Origin = Origin;
|
type Origin = Origin;
|
||||||
type Call = Call;
|
type Call = Call;
|
||||||
@@ -468,6 +473,8 @@ impl parachains::Trait for Runtime {
|
|||||||
type Randomness = RandomnessCollectiveFlip;
|
type Randomness = RandomnessCollectiveFlip;
|
||||||
type ActiveParachains = Registrar;
|
type ActiveParachains = Registrar;
|
||||||
type Registrar = Registrar;
|
type Registrar = Registrar;
|
||||||
|
type MaxCodeSize = MaxCodeSize;
|
||||||
|
type MaxHeadDataSize = MaxHeadDataSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
parameter_types! {
|
parameter_types! {
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
|
|||||||
spec_name: create_runtime_str!("polkadot"),
|
spec_name: create_runtime_str!("polkadot"),
|
||||||
impl_name: create_runtime_str!("parity-polkadot"),
|
impl_name: create_runtime_str!("parity-polkadot"),
|
||||||
authoring_version: 2,
|
authoring_version: 2,
|
||||||
spec_version: 1002,
|
spec_version: 1003,
|
||||||
impl_version: 0,
|
impl_version: 0,
|
||||||
apis: RUNTIME_API_VERSIONS,
|
apis: RUNTIME_API_VERSIONS,
|
||||||
};
|
};
|
||||||
@@ -465,6 +465,11 @@ impl attestations::Trait for Runtime {
|
|||||||
type RewardAttestation = Staking;
|
type RewardAttestation = Staking;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parameter_types! {
|
||||||
|
pub const MaxCodeSize: u32 = 10 * 1024 * 1024; // 10 MB
|
||||||
|
pub const MaxHeadDataSize: u32 = 20 * 1024; // 20 KB
|
||||||
|
}
|
||||||
|
|
||||||
impl parachains::Trait for Runtime {
|
impl parachains::Trait for Runtime {
|
||||||
type Origin = Origin;
|
type Origin = Origin;
|
||||||
type Call = Call;
|
type Call = Call;
|
||||||
@@ -472,6 +477,8 @@ impl parachains::Trait for Runtime {
|
|||||||
type Randomness = RandomnessCollectiveFlip;
|
type Randomness = RandomnessCollectiveFlip;
|
||||||
type ActiveParachains = Registrar;
|
type ActiveParachains = Registrar;
|
||||||
type Registrar = Registrar;
|
type Registrar = Registrar;
|
||||||
|
type MaxCodeSize = MaxCodeSize;
|
||||||
|
type MaxHeadDataSize = MaxHeadDataSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
parameter_types! {
|
parameter_types! {
|
||||||
|
|||||||
Reference in New Issue
Block a user