Newer
Older
///
/// 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);
Branislav Kontur
committed
info.pays_fee = extract_actual_pays_fee(r, &info);
Self::deposit_event(match r {
Ok(_) => Event::ExtrinsicSuccess { dispatch_info: info },
Err(err) => {
log::trace!(
target: LOG_TARGET,
"Extrinsic failed at block({:?}): {:?}",
Self::block_number(),
err,
);
Event::ExtrinsicFailed { dispatch_error: err.error, dispatch_info: info }
Svyatoslav Nikolsky
committed
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))
pub fn on_created_account(who: T::AccountId, _a: &mut AccountInfo<T::Nonce, T::AccountData>) {
Self::deposit_event(Event::NewAccount { account: who });
}
/// Do anything that needs to be done after an account has been killed.
fn on_killed_account(who: T::AccountId) {
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)?;
cfg_if::cfg_if! {
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())
}
Ok(())
}
}
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
/// 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);
Ok(())
}
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> {
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);
Gavin Wood
committed
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)?;
if Self::providers(k) > 0 || Self::sufficients(k) > 0 {
Gavin Wood
committed
Account::<T>::mutate(k, |a| a.data = some_data.unwrap_or_default());
}
Ok(result)
/// 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>) {
match option {
Some(inner) => {
let (r, s) = splitter(inner);
(Some(r), Some(s))
pub struct ChainContext<T>(PhantomData<T>);
impl<T> Default for ChainContext<T> {
fn default() -> Self {
ChainContext(PhantomData)
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;