From 295151338de8875b16b429743c3b702585ef997d Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Tue, 11 Feb 2020 19:21:56 +0100 Subject: [PATCH] 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 --- polkadot/runtime/common/src/crowdfund.rs | 61 +++++++++- polkadot/runtime/common/src/parachains.rs | 24 ++++ polkadot/runtime/common/src/registrar.rs | 89 +++++++++++++- polkadot/runtime/common/src/slots.rs | 141 ++++++++++++++++++++-- polkadot/runtime/kusama/src/lib.rs | 9 +- polkadot/runtime/polkadot/src/lib.rs | 9 +- 6 files changed, 314 insertions(+), 19 deletions(-) diff --git a/polkadot/runtime/common/src/crowdfund.rs b/polkadot/runtime/common/src/crowdfund.rs index 7184142488..0383834986 100644 --- a/polkadot/runtime/common/src/crowdfund.rs +++ b/polkadot/runtime/common/src/crowdfund.rs @@ -121,6 +121,15 @@ pub enum LastContribution { #[derive(Encode, Decode, Clone, PartialEq, Eq)] #[cfg_attr(feature = "std", derive(Debug))] +struct DeployData { + code_hash: Hash, + code_size: u32, + initial_head_data: Vec, +} + +#[derive(Encode, Decode, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(Debug))] +#[codec(dumb_trait_bound)] pub struct FundInfo { /// 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. @@ -150,8 +159,8 @@ pub struct FundInfo { /// BlockNumber. last_slot: BlockNumber, /// 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. - deploy_data: Option<(Hash, Vec)>, + /// is the code hash, second is the code size, third is the initial head data. + deploy_data: Option>, } decl_storage! { @@ -346,6 +355,7 @@ decl_module! { fn fix_deploy_data(origin, #[compact] index: FundIndex, code_hash: T::Hash, + code_size: u32, initial_head_data: Vec ) { let who = ensure_signed(origin)?; @@ -354,7 +364,7 @@ decl_module! { ensure!(fund.owner == who, Error::::InvalidOrigin); // must be fund owner ensure!(fund.deploy_data.is_none(), Error::::ExistingDeployData); - fund.deploy_data = Some((code_hash, initial_head_data)); + fund.deploy_data = Some(DeployData { code_hash, code_size, initial_head_data }); >::insert(index, &fund); @@ -374,12 +384,20 @@ decl_module! { let _ = ensure_signed(origin)?; let mut fund = Self::funds(index).ok_or(Error::::InvalidFundIndex)?; - let (code_hash, initial_head_data) = fund.clone().deploy_data.ok_or(Error::::UnsetDeployData)?; + let DeployData { code_hash, code_size, initial_head_data } + = fund.clone().deploy_data.ok_or(Error::::UnsetDeployData)?; ensure!(fund.parachain.is_none(), Error::::AlreadyOnboard); fund.parachain = Some(para_id); let fund_origin = system::RawOrigin::Signed(Self::fund_account_id(index)).into(); - >::fix_deploy_data(fund_origin, index, para_id, code_hash, initial_head_data)?; + >::fix_deploy_data( + fund_origin, + index, + para_id, + code_hash, + code_size, + initial_head_data, + )?; >::insert(index, &fund); @@ -650,6 +668,9 @@ mod tests { RefCell, Vec)>> = RefCell::new(HashMap::new()); } + const MAX_CODE_SIZE: u32 = 100; + const MAX_HEAD_DATA_SIZE: u32 = 10; + pub struct TestParachains; impl Registrar for TestParachains { 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( id: ParaId, _info: ParaInfo, @@ -875,13 +904,21 @@ mod tests { Origin::signed(1), 0, ::Hash::default(), + 0, vec![0] )); let fund = Crowdfund::funds(0).unwrap(); // Confirm deploy data is stored correctly - assert_eq!(fund.deploy_data, Some((::Hash::default(), vec![0]))); + assert_eq!( + fund.deploy_data, + Some(DeployData { + code_hash: ::Hash::default(), + code_size: 0, + initial_head_data: vec![0], + }), + ); }); } @@ -897,6 +934,7 @@ mod tests { Origin::signed(2), 0, ::Hash::default(), + 0, vec![0]), Error::::InvalidOrigin ); @@ -906,6 +944,7 @@ mod tests { Origin::signed(1), 1, ::Hash::default(), + 0, vec![0]), Error::::InvalidFundIndex ); @@ -915,6 +954,7 @@ mod tests { Origin::signed(1), 0, ::Hash::default(), + 0, vec![0] )); @@ -922,6 +962,7 @@ mod tests { Origin::signed(1), 0, ::Hash::default(), + 0, vec![1]), Error::::ExistingDeployData ); @@ -941,6 +982,7 @@ mod tests { Origin::signed(1), 0, ::Hash::default(), + 0, vec![0] )); @@ -986,6 +1028,7 @@ mod tests { Origin::signed(1), 0, ::Hash::default(), + 0, vec![0] )); @@ -1013,6 +1056,7 @@ mod tests { Origin::signed(1), 0, ::Hash::default(), + 0, vec![0] )); @@ -1055,6 +1099,7 @@ mod tests { Origin::signed(1), 0, ::Hash::default(), + 0, vec![0] )); @@ -1196,6 +1241,7 @@ mod tests { Origin::signed(1), 0, ::Hash::default(), + 0, vec![0] )); assert_ok!(Crowdfund::onboard(Origin::signed(1), 0, 0.into())); @@ -1224,6 +1270,7 @@ mod tests { Origin::signed(1), 0, ::Hash::default(), + 0, vec![0] )); // Move to the end of auction... @@ -1262,12 +1309,14 @@ mod tests { Origin::signed(1), 0, ::Hash::default(), + 0, vec![0] )); assert_ok!(Crowdfund::fix_deploy_data( Origin::signed(2), 1, ::Hash::default(), + 0, vec![0] )); diff --git a/polkadot/runtime/common/src/parachains.rs b/polkadot/runtime/common/src/parachains.rs index d9b7bd4770..00e51adeaf 100644 --- a/polkadot/runtime/common/src/parachains.rs +++ b/polkadot/runtime/common/src/parachains.rs @@ -129,6 +129,14 @@ pub trait Trait: attestations::Trait { /// The way that we are able to register parachains. type Registrar: Registrar; + + /// 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; + + /// Max head data size. + type MaxHeadDataSize: Get; } /// Origin for the parachains module. @@ -233,6 +241,8 @@ decl_error! { UntaggedVotes, /// Wrong parent head for parachain receipt. ParentMismatch, + /// Head data was too large. + HeadDataTooLarge, } } @@ -778,6 +788,8 @@ impl Module { let mut validator_groups = GroupedDutyIter::new(&sorted_validators[..]); let mut para_block_hashes = Vec::new(); + + let max_head_data_size = T::MaxHeadDataSize::get(); for candidate in attested_candidates { let para_id = candidate.parachain_index(); let validator_group = validator_groups.group_for(para_id) @@ -801,6 +813,11 @@ impl Module { Error::::VotesExceedsAuthorities, ); + ensure!( + max_head_data_size >= candidate.candidate().head_data.0.len() as _, + Error::::HeadDataTooLarge, + ); + let fees = candidate.candidate().fees; T::ParachainCurrency::deduct(para_id, fees)?; @@ -1152,6 +1169,11 @@ mod tests { type MaxRetries = MaxRetries; } + parameter_types! { + pub const MaxHeadDataSize: u32 = 100; + pub const MaxCodeSize: u32 = 100; + } + impl Trait for Test { type Origin = Origin; type Call = Call; @@ -1159,6 +1181,8 @@ mod tests { type Randomness = RandomnessCollectiveFlip; type ActiveParachains = registrar::Module; type Registrar = registrar::Module; + type MaxCodeSize = MaxCodeSize; + type MaxHeadDataSize = MaxHeadDataSize; } type Parachains = Module; diff --git a/polkadot/runtime/common/src/registrar.rs b/polkadot/runtime/common/src/registrar.rs index e4f97c61dd..2775a49fec 100644 --- a/polkadot/runtime/common/src/registrar.rs +++ b/polkadot/runtime/common/src/registrar.rs @@ -46,8 +46,19 @@ pub trait Registrar { /// Create a new unique parachain identity for later registration. 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 /// 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( id: ParaId, info: ParaInfo, @@ -64,6 +75,14 @@ impl Registrar for Module { ::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 <= ::MaxHeadDataSize::get() + } + + fn code_size_allowed(code_size: u32) -> bool { + code_size <= ::MaxCodeSize::get() + } + fn register_para( id: ParaId, info: ParaInfo, @@ -71,6 +90,7 @@ impl Registrar for Module { initial_head_data: Vec, ) -> DispatchResult { ensure!(!Paras::exists(id), Error::::ParaAlreadyExists); + if let Scheduling::Always = info.scheduling { Parachains::mutate(|parachains| match parachains.binary_search(&id) { @@ -222,6 +242,10 @@ decl_error! { InvalidChainId, /// Invalid parathread ID. InvalidThreadId, + /// Invalid para code size. + CodeTooLarge, + /// Invalid para head data size. + HeadDataTooLarge, } } @@ -232,8 +256,11 @@ decl_module! { 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. + /// + /// 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)] pub fn register_para(origin, #[compact] id: ParaId, @@ -242,6 +269,18 @@ decl_module! { initial_head_data: Vec, ) -> DispatchResult { ensure_root(origin)?; + + ensure!( + >::code_size_allowed(code.len() as _), + Error::::CodeTooLarge, + ); + + ensure!( + >::head_data_size_allowed( + initial_head_data.len() as _ + ), + Error::::HeadDataTooLarge, + ); >:: 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. /// `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, code: Vec, initial_head_data: Vec, @@ -278,6 +321,19 @@ decl_module! { let info = ParaInfo { scheduling: Scheduling::Dynamic, }; + + ensure!( + >::code_size_allowed(code.len() as _), + Error::::CodeTooLarge, + ); + + ensure!( + >::head_data_size_allowed( + initial_head_data.len() as _ + ), + Error::::HeadDataTooLarge, + ); + let id = >::new_id(); let _ = >:: @@ -709,6 +765,11 @@ mod tests { type DisabledValidatorsThreshold = DisabledValidatorsThreshold; } + parameter_types! { + pub const MaxHeadDataSize: u32 = 100; + pub const MaxCodeSize: u32 = 100; + } + impl parachains::Trait for Test { type Origin = Origin; type Call = Call; @@ -716,6 +777,8 @@ mod tests { type ActiveParachains = Registrar; type Registrar = Registrar; type Randomness = RandomnessCollectiveFlip; + type MaxCodeSize = MaxCodeSize; + type MaxHeadDataSize = MaxHeadDataSize; } parameter_types! { @@ -929,7 +992,7 @@ mod tests { run_to_block(10); 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::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 = ::MaxCodeSize::get() + 1; + let bad_head_size = ::MaxHeadDataSize::get() + 1; + + let code = vec![1u8; bad_code_size as _]; + let head_data = vec![2u8; bad_head_size as _]; + + assert!(!>::code_size_allowed(bad_code_size)); + assert!(!>::head_data_size_allowed(bad_head_size)); + + let id = >::new_id(); + assert_ok!(>::register_para( + id, + ParaInfo { scheduling: Scheduling::Always }, + code, + head_data, + )); + }); + } } diff --git a/polkadot/runtime/common/src/slots.rs b/polkadot/runtime/common/src/slots.rs index 0a0403b1a8..46ff147373 100644 --- a/polkadot/runtime/common/src/slots.rs +++ b/polkadot/runtime/common/src/slots.rs @@ -108,8 +108,12 @@ impl Bidder { pub enum IncomingParachain { /// Deploy information not yet set; just the bidder identity. Unset(NewBidder), - /// Deploy information set only by code hash; so we store the code hash and head data. - Fixed { code_hash: Hash, initial_head_data: Vec }, + /// Deploy information set only by code hash; so we store the code hash, code size, and head data. + /// + /// 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 }, /// Deploy information fully set; so we store the code and head data. Deploy { code: Vec, initial_head_data: Vec }, } @@ -250,6 +254,10 @@ decl_error! { NotCurrentAuction, /// Not an auction. 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] para_id: ParaId, code_hash: T::Hash, + code_size: u32, initial_head_data: Vec ) { let who = ensure_signed(origin)?; @@ -412,7 +421,17 @@ decl_module! { } else { Err(Error::::AlreadyRegistered)? } - let item = (starts, IncomingParachain::Fixed{code_hash, initial_head_data}); + + ensure!( + T::Parachains::head_data_size_allowed(initial_head_data.len() as _), + Error::::HeadDataTooLarge, + ); + ensure!( + T::Parachains::code_size_allowed(code_size), + Error::::CodeTooLarge, + ); + + let item = (starts, IncomingParachain::Fixed{code_hash, code_size, initial_head_data}); >::insert(¶_id, item); } @@ -432,8 +451,10 @@ decl_module! { pub fn elaborate_deploy_data(_origin, #[compact] para_id: ParaId, code: Vec) -> DispatchResult { let (starts, details) = >::get(¶_id) .ok_or(Error::::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::::InvalidCode); ensure!(::Hashing::hash(&code) == code_hash, Error::::InvalidCode); + if starts > Self::lease_period_index() { // Hasn't yet begun. Replace the on-boarding entry with the new information. let item = (starts, IncomingParachain::Deploy{code, initial_head_data}); @@ -918,6 +939,9 @@ mod tests { RefCell, Vec)>> = RefCell::new(HashMap::new()); } + const MAX_CODE_SIZE: u32 = 100; + const MAX_HEAD_DATA_SIZE: u32 = 10; + pub struct TestParachains; impl Registrar for TestParachains { fn new_id() -> ParaId { @@ -926,6 +950,15 @@ mod tests { (*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( id: ParaId, _info: ParaInfo, @@ -1144,7 +1177,7 @@ mod tests { run_to_block(9); 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])); run_to_block(10); @@ -1169,7 +1202,7 @@ mod tests { run_to_block(11); 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])); with_parachains(|p| { 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)] { 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])); } @@ -1326,7 +1359,7 @@ mod tests { run_to_block(10); 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::new_auction(Origin::ROOT, 5, 2)); @@ -1371,7 +1404,7 @@ mod tests { run_to_block(10); 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::new_auction(Origin::ROOT, 5, 2)); @@ -1560,4 +1593,94 @@ mod tests { ]; 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::::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::::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()); + }); + } } diff --git a/polkadot/runtime/kusama/src/lib.rs b/polkadot/runtime/kusama/src/lib.rs index 4eefe33896..f85319cca8 100644 --- a/polkadot/runtime/kusama/src/lib.rs +++ b/polkadot/runtime/kusama/src/lib.rs @@ -77,7 +77,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("kusama"), impl_name: create_runtime_str!("parity-kusama"), authoring_version: 2, - spec_version: 1047, + spec_version: 1048, impl_version: 0, apis: RUNTIME_API_VERSIONS, }; @@ -461,6 +461,11 @@ impl attestations::Trait for Runtime { 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 { type Origin = Origin; type Call = Call; @@ -468,6 +473,8 @@ impl parachains::Trait for Runtime { type Randomness = RandomnessCollectiveFlip; type ActiveParachains = Registrar; type Registrar = Registrar; + type MaxCodeSize = MaxCodeSize; + type MaxHeadDataSize = MaxHeadDataSize; } parameter_types! { diff --git a/polkadot/runtime/polkadot/src/lib.rs b/polkadot/runtime/polkadot/src/lib.rs index 7b41734d77..95f6ee3d65 100644 --- a/polkadot/runtime/polkadot/src/lib.rs +++ b/polkadot/runtime/polkadot/src/lib.rs @@ -78,7 +78,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("polkadot"), impl_name: create_runtime_str!("parity-polkadot"), authoring_version: 2, - spec_version: 1002, + spec_version: 1003, impl_version: 0, apis: RUNTIME_API_VERSIONS, }; @@ -465,6 +465,11 @@ impl attestations::Trait for Runtime { 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 { type Origin = Origin; type Call = Call; @@ -472,6 +477,8 @@ impl parachains::Trait for Runtime { type Randomness = RandomnessCollectiveFlip; type ActiveParachains = Registrar; type Registrar = Registrar; + type MaxCodeSize = MaxCodeSize; + type MaxHeadDataSize = MaxHeadDataSize; } parameter_types! {