diff --git a/polkadot/runtime/common/src/lib.rs b/polkadot/runtime/common/src/lib.rs index 9569412b7c..ed0aad5950 100644 --- a/polkadot/runtime/common/src/lib.rs +++ b/polkadot/runtime/common/src/lib.rs @@ -49,6 +49,10 @@ pub use impls::ToAuthor; pub type NegativeImbalance = as Currency<::AccountId>>::NegativeImbalance; +/// The sequence of bytes a valid wasm module binary always starts with. Apart from that it's also a +/// valid wasm module. +const WASM_MAGIC: &[u8] = &[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00]; + /// We assume that an on-initialize consumes 2.5% of the weight on average, hence a single extrinsic /// will not be allowed to consume more than `AvailableBlockRatio - 2.5%`. pub const AVERAGE_ON_INITIALIZE_WEIGHT: Perbill = Perbill::from_perthousand(25); diff --git a/polkadot/runtime/common/src/paras_registrar.rs b/polkadot/runtime/common/src/paras_registrar.rs index 6ecd99aee9..474402d61f 100644 --- a/polkadot/runtime/common/src/paras_registrar.rs +++ b/polkadot/runtime/common/src/paras_registrar.rs @@ -17,8 +17,8 @@ //! Module to handle parathread/parachain registration and related fund management. //! In essence this is a simple wrapper around `paras`. +use crate::WASM_MAGIC; use sp_std::{prelude::*, result}; - use frame_support::{ decl_storage, decl_module, decl_error, ensure, dispatch::DispatchResult, @@ -86,6 +86,8 @@ decl_error! { HeadDataTooLarge, /// Parathreads registration is disabled. ParathreadsRegistrationDisabled, + /// The validation code provided doesn't start with the Wasm file magic string. + DefinitelyNotWasm, } } @@ -96,7 +98,7 @@ decl_module! { /// Register a parathread with given code for immediate use. /// /// Must be sent from a Signed origin that is able to have `ParathreadDeposit` reserved. - /// `gensis_head` and `validation_code` are used to initalize the parathread's state. + /// `genesis_head` and `validation_code` are used to initalize the parathread's state. #[weight = 0] fn register_parathread( origin, @@ -107,6 +109,7 @@ decl_module! { let who = ensure_signed(origin)?; ensure!(ParathreadsRegistrationEnabled::get(), Error::::ParathreadsRegistrationDisabled); + ensure!(validation_code.0.starts_with(WASM_MAGIC), Error::::DefinitelyNotWasm); ensure!(!Paras::contains_key(id), Error::::ParaAlreadyExists); @@ -217,6 +220,7 @@ impl Module { validation_code: ValidationCode, ) -> DispatchResult { ensure!(!Paras::contains_key(id), Error::::ParaAlreadyExists); + ensure!(validation_code.0.starts_with(WASM_MAGIC), Error::::DefinitelyNotWasm); let outgoing = >::outgoing_paras(); @@ -609,7 +613,7 @@ mod tests { assert_ok!(Registrar::register_parachain( 2u32.into(), vec![3; 3].into(), - vec![3; 3].into(), + WASM_MAGIC.to_vec().into(), )); let orig_bal = Balances::free_balance(&3u64); @@ -619,7 +623,7 @@ mod tests { Origin::signed(3u64), 8u32.into(), vec![3; 3].into(), - vec![3; 3].into(), + WASM_MAGIC.to_vec().into(), )); // deposit should be taken (reserved) @@ -658,13 +662,13 @@ mod tests { Origin::signed(1), 8u32.into(), vec![1; 3].into(), - vec![1; 3].into(), + WASM_MAGIC.to_vec().into(), )); assert_ok!(Registrar::register_parachain( 2u32.into(), vec![1; 3].into(), - vec![1; 3].into(), + WASM_MAGIC.to_vec().into(), )); run_to_block(9); @@ -692,7 +696,7 @@ mod tests { assert_ok!(Registrar::register_parachain( 1u32.into(), vec![1; 3].into(), - vec![1; 3].into(), + WASM_MAGIC.to_vec().into(), )); run_to_block(4); @@ -703,7 +707,7 @@ mod tests { assert!(Registrar::register_parachain( 1u32.into(), vec![1; 3].into(), - vec![1; 3].into(), + WASM_MAGIC.to_vec().into(), ).is_err()); run_to_block(6); @@ -711,7 +715,7 @@ mod tests { assert_ok!(Registrar::register_parachain( 1u32.into(), vec![1; 3].into(), - vec![1; 3].into(), + WASM_MAGIC.to_vec().into(), )); }); } diff --git a/polkadot/runtime/common/src/paras_sudo_wrapper.rs b/polkadot/runtime/common/src/paras_sudo_wrapper.rs index c6b1817f0a..fcaf598d64 100644 --- a/polkadot/runtime/common/src/paras_sudo_wrapper.rs +++ b/polkadot/runtime/common/src/paras_sudo_wrapper.rs @@ -16,6 +16,7 @@ //! A simple wrapper allowing `Sudo` to call into `paras` routines. +use crate::WASM_MAGIC; use sp_std::prelude::*; use frame_support::{ decl_error, decl_module, ensure, @@ -41,6 +42,8 @@ decl_error! { /// A DMP message couldn't be sent because it exceeds the maximum size allowed for a downward /// message. ExceedsMaxMessageSize, + /// The validation code provided doesn't start with the Wasm file magic string. + DefinitelyNotWasm, } } @@ -57,6 +60,7 @@ decl_module! { genesis: ParaGenesisArgs, ) -> DispatchResult { ensure_root(origin)?; + ensure!(genesis.validation_code.0.starts_with(WASM_MAGIC), Error::::DefinitelyNotWasm); runtime_parachains::schedule_para_initialize::(id, genesis); Ok(()) }