lib.rs 78.1 KiB
Newer Older

	/// To be called immediately after an extrinsic has been applied.
	///
	/// Emits an `ExtrinsicSuccess` or `ExtrinsicFailed` event depending on the outcome.
	/// The emitted event contains the post-dispatch corrected weight including
	/// the base-weight for its dispatch class.
	pub fn note_applied_extrinsic(r: &DispatchResultWithPostInfo, mut info: DispatchInfo) {
		info.weight = extract_actual_weight(r, &info)
			.saturating_add(T::BlockWeights::get().get(info.class).base_extrinsic);
		info.pays_fee = extract_actual_pays_fee(r, &info);
		Self::deposit_event(match r {
			Ok(_) => Event::ExtrinsicSuccess { dispatch_info: info },
			Err(err) => {
				log::trace!(
					"Extrinsic failed at block({:?}): {:?}",
					Self::block_number(),
					err,
				);
				Event::ExtrinsicFailed { dispatch_error: err.error, dispatch_info: info }

		let next_extrinsic_index = Self::extrinsic_index().unwrap_or_default() + 1u32;
		storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &next_extrinsic_index);
		ExecutionPhase::<T>::put(Phase::ApplyExtrinsic(next_extrinsic_index));
	}

	/// To be called immediately after `note_applied_extrinsic` of the last extrinsic of the block
	/// has been called.
	pub fn note_finished_extrinsics() {
		let extrinsic_index: u32 =
			storage::unhashed::take(well_known_keys::EXTRINSIC_INDEX).unwrap_or_default();
		ExtrinsicCount::<T>::put(extrinsic_index);
		ExecutionPhase::<T>::put(Phase::Finalization);
	}

	/// To be called immediately after finishing the initialization of the block
	/// (e.g., called `on_initialize` for all pallets).
	pub fn note_finished_initialize() {
		ExecutionPhase::<T>::put(Phase::ApplyExtrinsic(0))
Gavin Wood's avatar
Gavin Wood committed
	/// An account is being created.
	pub fn on_created_account(who: T::AccountId, _a: &mut AccountInfo<T::Nonce, T::AccountData>) {
Gavin Wood's avatar
Gavin Wood committed
		T::OnNewAccount::on_new_account(&who);
		Self::deposit_event(Event::NewAccount { account: who });
Gavin Wood's avatar
Gavin Wood committed
	}

	/// Do anything that needs to be done after an account has been killed.
	fn on_killed_account(who: T::AccountId) {
Gavin Wood's avatar
Gavin Wood committed
		T::OnKilledAccount::on_killed_account(&who);
		Self::deposit_event(Event::KilledAccount { account: who });
	/// Determine whether or not it is possible to update the code.
	///
	/// Checks the given code if it is a valid runtime wasm blob by instantiating
	/// it and extracting the runtime version of it. It checks that the runtime version
	/// of the old and new runtime has the same spec name and that the spec version is increasing.
	pub fn can_set_code(code: &[u8]) -> Result<(), sp_runtime::DispatchError> {
		if T::MultiBlockMigrator::ongoing() {
			return Err(Error::<T>::MultiBlockMigrationsOngoing.into())
		}

		let current_version = T::Version::get();
		let new_version = sp_io::misc::runtime_version(code)
			.and_then(|v| RuntimeVersion::decode(&mut &v[..]).ok())
			.ok_or(Error::<T>::FailedToExtractRuntimeVersion)?;
			if #[cfg(all(feature = "runtime-benchmarks", not(test)))] {
					// Let's ensure the compiler doesn't optimize our fetching of the runtime version away.
					core::hint::black_box((new_version, current_version));
					Ok(())
			} else {
				if new_version.spec_name != current_version.spec_name {
					return Err(Error::<T>::InvalidSpecName.into())
				}
				if new_version.spec_version <= current_version.spec_version {
					return Err(Error::<T>::SpecVersionNeedsToIncrease.into())
				}

	/// To be called after any origin/privilege checks. Put the code upgrade authorization into
	/// storage and emit an event. Infallible.
	pub fn do_authorize_upgrade(code_hash: T::Hash, check_version: bool) {
		AuthorizedUpgrade::<T>::put(CodeUpgradeAuthorization { code_hash, check_version });
		Self::deposit_event(Event::UpgradeAuthorized { code_hash, check_version });
	}

	/// Apply an authorized upgrade, performing any validation checks, and remove the authorization.
	/// Whether or not the code is set directly depends on the `OnSetCode` configuration of the
	/// runtime.
	pub fn do_apply_authorize_upgrade(code: Vec<u8>) -> Result<PostDispatchInfo, DispatchError> {
		Self::validate_authorized_upgrade(&code[..])?;
		T::OnSetCode::set_code(code)?;
		AuthorizedUpgrade::<T>::kill();
		let post = PostDispatchInfo {
			// consume the rest of the block to prevent further transactions
			actual_weight: Some(T::BlockWeights::get().max_block),
			// no fee for valid upgrade
			pays_fee: Pays::No,
		};
		Ok(post)
	}

	/// Check that provided `code` can be upgraded to. Namely, check that its hash matches an
	/// existing authorization and that it meets the specification requirements of `can_set_code`.
	pub fn validate_authorized_upgrade(code: &[u8]) -> Result<T::Hash, DispatchError> {
		let authorization = AuthorizedUpgrade::<T>::get().ok_or(Error::<T>::NothingAuthorized)?;
		let actual_hash = T::Hashing::hash(code);
		ensure!(actual_hash == authorization.code_hash, Error::<T>::Unauthorized);
		if authorization.check_version {
			Self::can_set_code(code)?
		}
		Ok(actual_hash)
	}
/// Returns a 32 byte datum which is guaranteed to be universally unique. `entropy` is provided
/// as a facility to reduce the potential for precalculating results.
pub fn unique(entropy: impl Encode) -> [u8; 32] {
	let mut last = [0u8; 32];
	sp_io::storage::read(well_known_keys::INTRABLOCK_ENTROPY, &mut last[..], 0);
	let next = (b"frame_system::unique", entropy, last).using_encoded(blake2_256);
	sp_io::storage::set(well_known_keys::INTRABLOCK_ENTROPY, &next);
/// Event handler which registers a provider when created.
pub struct Provider<T>(PhantomData<T>);
impl<T: Config> HandleLifetime<T::AccountId> for Provider<T> {
	fn created(t: &T::AccountId) -> Result<(), DispatchError> {
		Pallet::<T>::inc_providers(t);
	fn killed(t: &T::AccountId) -> Result<(), DispatchError> {
		Pallet::<T>::dec_providers(t).map(|_| ())
/// Event handler which registers a self-sufficient when created.
pub struct SelfSufficient<T>(PhantomData<T>);
impl<T: Config> HandleLifetime<T::AccountId> for SelfSufficient<T> {
	fn created(t: &T::AccountId) -> Result<(), DispatchError> {
		Pallet::<T>::inc_sufficients(t);
	fn killed(t: &T::AccountId) -> Result<(), DispatchError> {
		Pallet::<T>::dec_sufficients(t);
/// Event handler which registers a consumer when created.
pub struct Consumer<T>(PhantomData<T>);
impl<T: Config> HandleLifetime<T::AccountId> for Consumer<T> {
	fn created(t: &T::AccountId) -> Result<(), DispatchError> {
		Pallet::<T>::inc_consumers(t)
	fn killed(t: &T::AccountId) -> Result<(), DispatchError> {
		Pallet::<T>::dec_consumers(t);
impl<T: Config> BlockNumberProvider for Pallet<T> {
	type BlockNumber = BlockNumberFor<T>;

	fn current_block_number() -> Self::BlockNumber {
		Pallet::<T>::block_number()

	#[cfg(feature = "runtime-benchmarks")]
	fn set_block_number(n: BlockNumberFor<T>) {
		Self::set_block_number(n)
	}
/// Implement StoredMap for a simple single-item, provide-when-not-default system. This works fine
/// for storing a single item which allows the account to continue existing as long as it's not
/// empty/default.
///
/// Anything more complex will need more sophisticated logic.
impl<T: Config> StoredMap<T::AccountId, T::AccountData> for Pallet<T> {
Gavin Wood's avatar
Gavin Wood committed
	fn get(k: &T::AccountId) -> T::AccountData {
Gavin Wood's avatar
Gavin Wood committed
		Account::<T>::get(k).data
	fn try_mutate_exists<R, E: From<DispatchError>>(
		k: &T::AccountId,
		f: impl FnOnce(&mut Option<T::AccountData>) -> Result<R, E>,
	) -> Result<R, E> {
		let account = Account::<T>::get(k);
		let is_default = account.data == T::AccountData::default();
		let mut some_data = if is_default { None } else { Some(account.data) };
		let result = f(&mut some_data)?;
Gavin Wood's avatar
Gavin Wood committed
		if Self::providers(k) > 0 || Self::sufficients(k) > 0 {
			Account::<T>::mutate(k, |a| a.data = some_data.unwrap_or_default());
Gavin Wood's avatar
Gavin Wood committed
		} else {
			Account::<T>::remove(k)
Gavin Wood's avatar
Gavin Wood committed
/// Split an `option` into two constituent options, as defined by a `splitter` function.
pub fn split_inner<T, R, S>(
	option: Option<T>,
	splitter: impl FnOnce(T) -> (R, S),
) -> (Option<R>, Option<S>) {
Gavin Wood's avatar
Gavin Wood committed
	match option {
		Some(inner) => {
			let (r, s) = splitter(inner);
			(Some(r), Some(s))
Gavin Wood's avatar
Gavin Wood committed
		None => (None, None),
pub struct ChainContext<T>(PhantomData<T>);
impl<T> Default for ChainContext<T> {
	fn default() -> Self {
impl<T: Config> Lookup for ChainContext<T> {
	type Source = <T::Lookup as StaticLookup>::Source;
	type Target = <T::Lookup as StaticLookup>::Target;

	fn lookup(&self, s: Self::Source) -> Result<Self::Target, LookupError> {
		<T::Lookup as StaticLookup>::lookup(s)

/// Prelude to be used alongside pallet macro, for ease of use.
pub mod pallet_prelude {
	pub use crate::{ensure_none, ensure_root, ensure_signed, ensure_signed_or_root};

	/// Type alias for the `Origin` associated type of system config.
	pub type OriginFor<T> = <T as crate::Config>::RuntimeOrigin;
	/// Type alias for the `Header`.
	pub type HeaderFor<T> =
		<<T as crate::Config>::Block as sp_runtime::traits::HeaderProvider>::HeaderT;

	/// Type alias for the `BlockNumber` associated type of system config.
	pub type BlockNumberFor<T> = <HeaderFor<T> as sp_runtime::traits::Header>::Number;

	/// Type alias for the `Extrinsic` associated type of system config.
	pub type ExtrinsicFor<T> =
		<<T as crate::Config>::Block as sp_runtime::traits::Block>::Extrinsic;

	/// Type alias for the `RuntimeCall` associated type of system config.
	pub type RuntimeCallFor<T> = <T as crate::Config>::RuntimeCall;