lib.rs 75.1 KiB
Newer Older
				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;