Newer
Older
#[deprecated = "Use `inc_consumers` instead"]
let _ = Self::inc_consumers(who);
}
/// Decrement the reference counter on an account. This *MUST* only be done once for every time
/// you called `inc_consumers` on `who`.
#[deprecated = "Use `dec_consumers` instead"]
let _ = Self::dec_consumers(who);
}
/// The number of outstanding references for the account `who`.
#[deprecated = "Use `consumers` instead"]
Self::consumers(who)
}
/// True if the account has no outstanding references.
#[deprecated = "Use `!is_provider_required` instead"]
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
!Self::is_provider_required(who)
}
/// Increment the reference counter on an account.
///
/// The account `who`'s `providers` must be non-zero or this will return an error.
pub fn inc_providers(who: &T::AccountId) -> IncRefStatus {
Account::<T>::mutate(who, |a| if a.providers == 0 {
// Account is being created.
a.providers = 1;
Self::on_created_account(who.clone(), a);
IncRefStatus::Created
} else {
a.providers = a.providers.saturating_add(1);
IncRefStatus::Existed
})
}
/// Decrement the reference counter on an account. This *MUST* only be done once for every time
/// you called `inc_consumers` on `who`.
pub fn dec_providers(who: &T::AccountId) -> Result<DecRefStatus, DecRefError> {
Account::<T>::try_mutate_exists(who, |maybe_account| {
if let Some(mut account) = maybe_account.take() {
match (account.providers, account.consumers) {
(0, _) => {
// Logic error - cannot decrement beyond zero and no item should
// exist with zero providers.
debug::print!("Logic error: Unexpected underflow in reducing provider");
Ok(DecRefStatus::Reaped)
},
(1, 0) => {
Module::<T>::on_killed_account(who.clone());
Ok(DecRefStatus::Reaped)
}
(1, _) => {
// Cannot remove last provider if there are consumers.
Err(DecRefError::ConsumerRemaining)
}
(x, _) => {
account.providers = x - 1;
*maybe_account = Some(account);
Ok(DecRefStatus::Exists)
}
}
} else {
debug::print!("Logic error: Account already dead when reducing provider");
Ok(DecRefStatus::Reaped)
}
})
}
/// The number of outstanding references for the account `who`.
pub fn providers(who: &T::AccountId) -> RefCount {
Account::<T>::get(who).providers
}
/// Increment the reference counter on an account.
///
/// The account `who`'s `providers` must be non-zero or this will return an error.
pub fn inc_consumers(who: &T::AccountId) -> Result<(), IncRefError> {
Account::<T>::try_mutate(who, |a| if a.providers > 0 {
a.consumers = a.consumers.saturating_add(1);
Ok(())
} else {
Err(IncRefError::NoProviders)
})
}
/// Decrement the reference counter on an account. This *MUST* only be done once for every time
/// you called `inc_consumers` on `who`.
pub fn dec_consumers(who: &T::AccountId) {
Account::<T>::mutate(who, |a| if a.consumers > 0 {
a.consumers -= 1;
} else {
debug::print!("Logic error: Unexpected underflow in reducing consumer");
})
}
/// The number of outstanding references for the account `who`.
pub fn consumers(who: &T::AccountId) -> RefCount {
Account::<T>::get(who).consumers
}
/// True if the account has some outstanding references.
pub fn is_provider_required(who: &T::AccountId) -> bool {
Account::<T>::get(who).consumers != 0
}
/// Deposits an event into this block's event record.
pub fn deposit_event(event: impl Into<T::Event>) {
Self::deposit_event_indexed(&[], event.into());
}
/// Deposits an event into this block's event record adding this event
/// to the corresponding topic indexes.
///
/// This will update storage entries that correspond to the specified topics.
/// It is expected that light-clients could subscribe to this topics.
pub fn deposit_event_indexed(topics: &[T::Hash], event: T::Event) {
let block_number = Self::block_number();
// Don't populate events on genesis.
if block_number.is_zero() { return }
let phase = ExecutionPhase::<T>::get().unwrap_or_default();
let event = EventRecord {
phase,
event,
topics: topics.iter().cloned().collect::<Vec<_>>(),
};
// Index of the to be added event.
let event_idx = {
let old_event_count = EventCount::<T>::get();
let new_event_count = match old_event_count.checked_add(1) {
// We've reached the maximum number of events at this block, just
// don't do anything and leave the event_count unaltered.
None => return,
Some(nc) => nc,
};
EventCount::<T>::put(new_event_count);
Events::<T>::append(&event);
<EventTopics<T>>::append(topic, &(block_number, event_idx));
/// Gets the index of extrinsic that is currently executing.
Svyatoslav Nikolsky
committed
pub fn extrinsic_index() -> Option<u32> {
storage::unhashed::get(well_known_keys::EXTRINSIC_INDEX)
Svyatoslav Nikolsky
committed
}
/// Gets extrinsics count.
pub fn extrinsic_count() -> u32 {
ExtrinsicCount::<T>::get().unwrap_or_default()
pub fn all_extrinsics_len() -> u32 {
AllExtrinsicsLen::<T>::get().unwrap_or_default()
/// Inform the system pallet of some additional weight that should be accounted for, in the
/// NOTE: use with extra care; this function is made public only be used for certain pallets
/// that need it. A runtime that does not have dynamic calls should never need this and should
/// stick to static weights. A typical use case for this is inner calls or smart contract calls.
/// Furthermore, it only makes sense to use this when it is presumably _cheap_ to provide the
/// argument `weight`; In other words, if this function is to be used to account for some
/// unknown, user provided call's weight, it would only make sense to use it if you are sure you
/// can rapidly compute the weight of the inner call.
///
/// Even more dangerous is to note that this function does NOT take any action, if the new sum
/// of block weight is more than the block weight limit. This is what the _unchecked_.
///
/// Another potential use-case could be for the `on_initialize` and `on_finalize` hooks.
pub fn register_extra_weight_unchecked(weight: Weight, class: DispatchClass) {
BlockWeight::<T>::mutate(|current_weight| {
current_weight.add(weight, class);
});
pub fn initialize(
number: &T::BlockNumber,
parent_hash: &T::Hash,
Tomasz Drwięga
committed
kind: InitKind,
ExecutionPhase::<T>::put(Phase::Initialization);
storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &0u32);
<BlockHash<T>>::insert(*number - One::one(), parent_hash);
Tomasz Drwięga
committed
// Remove previous block data from storage
BlockWeight::<T>::kill();
// Kill inspectable storage entries in state when `InitKind::Full`.
Tomasz Drwięga
committed
if let InitKind::Full = kind {
<Events<T>>::kill();
EventCount::<T>::kill();
Tomasz Drwięga
committed
<EventTopics<T>>::remove_all();
}
/// Remove temporary "environment" entries in storage, compute the storage root and return the
/// resulting header for this block.
ExecutionPhase::<T>::kill();
AllExtrinsicsLen::<T>::kill();
// The following fields
//
// - <Events<T>>
// - <EventCount<T>>
// - <EventTopics<T>>
// - <Number<T>>
// - <ParentHash<T>>
// - <Digest<T>>
//
// stay to be inspected by the client and will be cleared by `Self::initialize`.
let number = <Number<T>>::get();
let parent_hash = <ParentHash<T>>::get();
let mut digest = <Digest<T>>::get();
let extrinsics = (0..ExtrinsicCount::<T>::take().unwrap_or_default())
.map(ExtrinsicData::<T>::take)
Bastian Köcher
committed
.collect();
let extrinsics_root = extrinsics_data_root::<T::Hashing>(extrinsics);
// move block hash pruning window by one block
Bastian Köcher
committed
let block_hash_count = T::BlockHashCount::get();
let to_remove = number.saturating_sub(block_hash_count).saturating_sub(One::one());
Bastian Köcher
committed
// keep genesis hash
if !to_remove.is_zero() {
<BlockHash<T>>::remove(to_remove);
let storage_root = T::Hash::decode(&mut &sp_io::storage::root()[..])
.expect("Node is configured to use the same hash; qed");
let storage_changes_root = sp_io::storage::changes_root(&parent_hash.encode());
Svyatoslav Nikolsky
committed
// we can't compute changes trie root earlier && put it to the Digest
// because it will include all currently existing temporaries.
Svyatoslav Nikolsky
committed
if let Some(storage_changes_root) = storage_changes_root {
let item = generic::DigestItem::ChangesTrieRoot(
T::Hash::decode(&mut &storage_changes_root[..])
.expect("Node is configured to use the same hash; qed")
);
Svyatoslav Nikolsky
committed
digest.push(item);
}
<T::Header as traits::Header>::new(number, extrinsics_root, storage_root, parent_hash, digest)
/// Deposits a log and ensures it matches the block's log data.
/// # <weight>
/// - `O(1)`
/// - 1 storage write (codec `O(1)`)
/// # </weight>
pub fn deposit_log(item: DigestItemOf<T>) {
<Digest<T>>::append(item);
/// Get the basic externalities for this pallet, useful for tests.
pub fn externalities() -> TestExternalities {
TestExternalities::new(sp_core::storage::Storage {
top: map![
<BlockHash<T>>::hashed_key_for(T::BlockNumber::zero()) => [69u8; 32].encode(),
<Number<T>>::hashed_key().to_vec() => T::BlockNumber::one().encode(),
<ParentHash<T>>::hashed_key().to_vec() => [69u8; 32].encode()
],
}
/// Set the block number to something in particular. Can be used as an alternative to
/// `initialize` for tests that don't need to bother with the other environment entries.
#[cfg(any(feature = "std", feature = "runtime-benchmarks", test))]
pub fn set_block_number(n: T::BlockNumber) {
<Number<T>>::put(n);
}
/// Sets the index of extrinsic that is currently executing.
Svyatoslav Nikolsky
committed
#[cfg(any(feature = "std", test))]
pub fn set_extrinsic_index(extrinsic_index: u32) {
storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &extrinsic_index)
Svyatoslav Nikolsky
committed
}
/// Set the parent hash number to something in particular. Can be used as an alternative to
/// `initialize` for tests that don't need to bother with the other environment entries.
#[cfg(any(feature = "std", test))]
pub fn set_parent_hash(n: T::Hash) {
<ParentHash<T>>::put(n);
}
/// Set the current block weight. This should only be used in some integration tests.
#[cfg(any(feature = "std", test))]
pub fn set_block_consumed_resources(weight: Weight, len: usize) {
BlockWeight::<T>::mutate(|current_weight| {
current_weight.set(weight, DispatchClass::Normal)
AllExtrinsicsLen::<T>::put(len as u32);
/// Reset events. Can be used as an alternative to
/// `initialize` for tests that don't need to bother with the other environment entries.
#[cfg(any(feature = "std", feature = "runtime-benchmarks", test))]
pub fn reset_events() {
<Events<T>>::kill();
EventCount::<T>::kill();
<EventTopics<T>>::remove_all();
}
/// Return the chain's current runtime version.
pub fn runtime_version() -> RuntimeVersion { T::Version::get() }
/// Retrieve the account transaction counter from storage.
pub fn account_nonce(who: impl EncodeLike<T::AccountId>) -> T::Index {
pub fn inc_account_nonce(who: impl EncodeLike<T::AccountId>) {
Account::<T>::mutate(who, |a| a.nonce += T::Index::one());
Bastian Köcher
committed
/// Note what the extrinsic data of the current extrinsic index is.
Bastian Köcher
committed
/// This is required to be called before applying an extrinsic. The data will used
/// in [`Self::finalize`] to calculate the correct extrinsics root.
pub fn note_extrinsic(encoded_xt: Vec<u8>) {
ExtrinsicData::<T>::insert(Self::extrinsic_index().unwrap_or_default(), encoded_xt);
}
/// To be called immediately after an extrinsic has been applied.
pub fn note_applied_extrinsic(r: &DispatchResultWithPostInfo, mut info: DispatchInfo) {
info.weight = extract_actual_weight(r, &info);
Self::deposit_event(
match r {
Ok(_) => Event::ExtrinsicSuccess(info),
Err(err) => {
sp_runtime::print(err);
Event::ExtrinsicFailed(err.error, 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::Index, T::AccountData>) {
Self::deposit_event(Event::NewAccount(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(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 instantianting
/// 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> {
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_else(|| Error::<T>::FailedToExtractRuntimeVersion)?;
if new_version.spec_name != current_version.spec_name {
Err(Error::<T>::InvalidSpecName)?
}
if new_version.spec_version <= current_version.spec_version {
Err(Error::<T>::SpecVersionNeedsToIncrease)?
}
Ok(())
}
/// 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<(), StoredMapError> {
Module::<T>::inc_providers(t);
Ok(())
}
fn killed(t: &T::AccountId) -> Result<(), StoredMapError> {
Module::<T>::dec_providers(t)
.map(|_| ())
.or_else(|e| match e {
DecRefError::ConsumerRemaining => Err(StoredMapError::ConsumerRemaining),
})
/// 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<(), StoredMapError> {
Module::<T>::inc_consumers(t)
.map_err(|e| match e {
IncRefError::NoProviders => StoredMapError::NoProviders
})
}
fn killed(t: &T::AccountId) -> Result<(), StoredMapError> {
Module::<T>::dec_consumers(t);
Ok(())
impl<T: Config> BlockNumberProvider for Pallet<T>
type BlockNumber = <T as Config>::BlockNumber;
fn current_block_number() -> Self::BlockNumber {
Pallet::<T>::block_number()
fn is_providing<T: Default + Eq>(d: &T) -> bool {
d != &T::default()
}
/// 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<StoredMapError>>(
k: &T::AccountId,
f: impl FnOnce(&mut Option<T::AccountData>) -> Result<R, E>,
) -> Result<R, E> {
let account = Account::<T>::get(k);
let was_providing = is_providing(&account.data);
let mut some_data = if was_providing { Some(account.data) } else { None };
let result = f(&mut some_data)?;
let is_providing = some_data.is_some();
if !was_providing && is_providing {
Self::inc_providers(k);
} else if was_providing && !is_providing {
match Self::dec_providers(k) {
Err(DecRefError::ConsumerRemaining) => Err(StoredMapError::ConsumerRemaining)?,
Ok(DecRefStatus::Reaped) => return Ok(result),
Ok(DecRefStatus::Exists) => {
// Update value as normal...
}
} else if !was_providing && !is_providing {
return Ok(result)
}
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))
}
None => (None, None),
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_signed, ensure_none, ensure_root};
/// Type alias for the `Origin` associated type of system config.
pub type OriginFor<T> = <T as crate::Config>::Origin;
/// Type alias for the `BlockNumber` associated type of system config.
pub type BlockNumberFor<T> = <T as crate::Config>::BlockNumber;
}