Newer
Older
/// Inform the system module of some additional weight that should be accounted for, in the
/// current block.
///
/// NOTE: use with extra care; this function is made public only be used for certain modules
/// 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::mutate(|current_weight| {
current_weight.add(weight, class);
});
pub fn initialize(
number: &T::BlockNumber,
parent_hash: &T::Hash,
txs_root: &T::Hash,
Tomasz Drwięga
committed
kind: InitKind,
ExecutionPhase::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::kill();
// Kill inspectable storage entries in state when `InitKind::Full`.
Tomasz Drwięga
committed
if let InitKind::Full = kind {
<Events<T>>::kill();
EventCount::kill();
<EventTopics<T>>::remove_all();
}
}
/// Remove temporary "environment" entries in storage.
ExtrinsicCount::kill();
let number = <Number<T>>::take();
let parent_hash = <ParentHash<T>>::take();
Svyatoslav Nikolsky
committed
let mut digest = <Digest<T>>::take();
// move block hash pruning window by one block
let block_hash_count = <T::BlockHashCount>::get();
if number > block_hash_count {
let to_remove = number - block_hash_count - One::one();
// keep genesis hash
if to_remove != Zero::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);
}
// The following fields
//
// - <Events<T>>
// - <EventCount<T>>
// - <EventTopics<T>>
//
// stay to be inspected by the client and will be cleared by `Self::initialize`.
<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 module, useful for tests.
#[cfg(any(feature = "std", test))]
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_limits(weight: Weight, len: usize) {
BlockWeight::mutate(|current_weight| {
current_weight.put(weight, DispatchClass::Normal)
});
AllExtrinsicsLen::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::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());
/// Note what the extrinsic data of the current extrinsic index is. If this
/// is called, then ensure `derive_extrinsics` is also called before
/// block-building is completed.
/// NOTE: This function is called only when the block is being constructed locally.
/// `execute_block` doesn't note any extrinsics.
pub fn note_extrinsic(encoded_xt: Vec<u8>) {
ExtrinsicData::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(_) => RawEvent::ExtrinsicSuccess(info),
Err(err) => {
sp_runtime::print(err);
RawEvent::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::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::put(extrinsic_index);
ExecutionPhase::put(Phase::Finalization);
}
/// To be called immediately after finishing the initialization of the block
/// (e.g., called `on_initialize` for all modules).
pub fn note_finished_initialize() {
ExecutionPhase::put(Phase::ApplyExtrinsic(0))
/// Remove all extrinsic data and save the extrinsics trie root.
pub fn derive_extrinsics() {
let extrinsics = (0..ExtrinsicCount::get().unwrap_or_default())
.map(ExtrinsicData::take).collect();
let xts_root = extrinsics_data_root::<T::Hashing>(extrinsics);
<ExtrinsicsRoot<T>>::put(xts_root);
}
/// An account is being created.
pub fn on_created_account(who: T::AccountId) {
T::OnNewAccount::on_new_account(&who);
Self::deposit_event(RawEvent::NewAccount(who));
}
/// Do anything that needs to be done after an account has been killed.
fn on_killed_account(who: T::AccountId) {
T::OnKilledAccount::on_killed_account(&who);
Self::deposit_event(RawEvent::KilledAccount(who));
}
/// Remove an account from storage. This should only be done when its refs are zero or you'll
/// get storage leaks in other modules. Nonetheless we assume that the calling logic knows best.
///
/// This is a no-op if the account doesn't already exist. If it does then it will ensure
/// cleanups (those in `on_killed_account`) take place.
fn kill_account(who: &T::AccountId) {
if Account::<T>::contains_key(who) {
let account = Account::<T>::take(who);
if account.refcount > 0 {
debug::debug!(
target: "system",
"WARNING: Referenced account deleted. This is probably a bug."
);
}
}
Module::<T>::on_killed_account(who.clone());
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
/// Determine whether or not it is possible to update the code.
///
/// This function has no side effects and is idempotent, but is fairly
/// heavy. It is automatically called by `set_code`; in most cases,
/// a direct call to `set_code` is preferable. It is useful to call
/// `can_set_code` when it is desirable to perform the appropriate
/// runtime checks without actually changing the code yet.
pub fn can_set_code(origin: T::Origin, code: &[u8]) -> Result<(), sp_runtime::DispatchError> {
ensure_root(origin)?;
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 calls on_created_account when it happens.
pub struct CallOnCreatedAccount<T>(PhantomData<T>);
impl<T: Trait> Happened<T::AccountId> for CallOnCreatedAccount<T> {
fn happened(who: &T::AccountId) {
Module::<T>::on_created_account(who.clone());
}
}
/// Event handler which calls kill_account when it happens.
pub struct CallKillAccount<T>(PhantomData<T>);
impl<T: Trait> Happened<T::AccountId> for CallKillAccount<T> {
fn happened(who: &T::AccountId) {
impl<T: Trait> BlockNumberProvider for Module<T>
{
type BlockNumber = <T as Trait>::BlockNumber;
fn current_block_number() -> Self::BlockNumber {
Module::<T>::block_number()
}
}
// Implement StoredMap for a simple single-item, kill-account-on-remove system. This works fine for
// storing a single item which is required to not be empty/default for the account to exist.
// Anything more complex will need more sophisticated logic.
impl<T: Trait> StoredMap<T::AccountId, T::AccountData> for Module<T> {
fn get(k: &T::AccountId) -> T::AccountData {
}
fn is_explicit(k: &T::AccountId) -> bool {
Account::<T>::contains_key(k)
}
if !existed {
Self::on_created_account(k.clone());
}
}
fn remove(k: &T::AccountId) {
}
fn mutate<R>(k: &T::AccountId, f: impl FnOnce(&mut T::AccountData) -> R) -> R {
let existed = Account::<T>::contains_key(k);
if !existed {
Self::on_created_account(k.clone());
}
r
}
fn mutate_exists<R>(k: &T::AccountId, f: impl FnOnce(&mut Option<T::AccountData>) -> R) -> R {
Self::try_mutate_exists(k, |x| -> Result<R, Infallible> { Ok(f(x)) }).expect("Infallible; qed")
}
fn try_mutate_exists<R, E>(k: &T::AccountId, f: impl FnOnce(&mut Option<T::AccountData>) -> Result<R, E>) -> Result<R, E> {
Account::<T>::try_mutate_exists(k, |maybe_value| {
let existed = maybe_value.is_some();
let (maybe_prefix, mut maybe_data) = split_inner(
maybe_value.take(),
|account| ((account.nonce, account.refcount), account.data)
);
f(&mut maybe_data).map(|result| {
*maybe_value = maybe_data.map(|data| {
let (nonce, refcount) = maybe_prefix.unwrap_or_default();
AccountInfo { nonce, refcount, data }
});
(existed, maybe_value.is_some(), result)
})
}).map(|(existed, exists, v)| {
if !existed && exists {
Self::on_created_account(k.clone());
} else if existed && !exists {
Self::on_killed_account(k.clone());
}
v
})
}
/// 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),
/// resource limit check.
#[derive(Encode, Decode, Clone, Eq, PartialEq)]
pub struct CheckWeight<T: Trait + Send + Sync>(PhantomData<T>);
impl<T: Trait + Send + Sync> CheckWeight<T> where
T::Call: Dispatchable<Info=DispatchInfo, PostInfo=PostDispatchInfo>
/// Get the quota ratio of each dispatch class type. This indicates that all operational and mandatory
/// dispatches can use the full capacity of any resource, while user-triggered ones can consume
/// a portion.
fn get_dispatch_limit_ratio(class: DispatchClass) -> Perbill {
match class {
DispatchClass::Operational | DispatchClass::Mandatory
=> <Perbill as sp_runtime::PerThing>::one(),
DispatchClass::Normal => T::AvailableBlockRatio::get(),
}
/// Checks if the current extrinsic does not exceed `MaximumExtrinsicWeight` limit.
fn check_extrinsic_weight(
info: &DispatchInfoOf<T::Call>,
) -> Result<(), TransactionValidityError> {
match info.class {
// Mandatory and Operational transactions does not
DispatchClass::Mandatory | DispatchClass::Operational => Ok(()),
DispatchClass::Normal => {
let maximum_weight = T::MaximumExtrinsicWeight::get();
let extrinsic_weight = info.weight.saturating_add(T::ExtrinsicBaseWeight::get());
if extrinsic_weight > maximum_weight {
Err(InvalidTransaction::ExhaustsResources.into())
} else {
Ok(())
}
}
}
}
/// Checks if the current extrinsic can fit into the block with respect to block weight limits.
///
/// Upon successes, it returns the new block weight as a `Result`.
) -> Result<ExtrinsicsWeight, TransactionValidityError> {
let maximum_weight = T::MaximumBlockWeight::get();
let mut all_weight = Module::<T>::block_weight();
// If we have a dispatch that must be included in the block, it ignores all the limits.
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
DispatchClass::Mandatory => {
let extrinsic_weight = info.weight.saturating_add(T::ExtrinsicBaseWeight::get());
all_weight.add(extrinsic_weight, DispatchClass::Mandatory);
Ok(all_weight)
},
// If we have a normal dispatch, we follow all the normal rules and limits.
DispatchClass::Normal => {
let normal_limit = Self::get_dispatch_limit_ratio(DispatchClass::Normal) * maximum_weight;
let extrinsic_weight = info.weight.checked_add(T::ExtrinsicBaseWeight::get())
.ok_or(InvalidTransaction::ExhaustsResources)?;
all_weight.checked_add(extrinsic_weight, DispatchClass::Normal)
.map_err(|_| InvalidTransaction::ExhaustsResources)?;
if all_weight.get(DispatchClass::Normal) > normal_limit {
Err(InvalidTransaction::ExhaustsResources.into())
} else {
Ok(all_weight)
}
},
// If we have an operational dispatch, allow it if we have not used our full
// "operational space" (independent of existing fullness).
DispatchClass::Operational => {
let operational_limit = Self::get_dispatch_limit_ratio(DispatchClass::Operational) * maximum_weight;
let normal_limit = Self::get_dispatch_limit_ratio(DispatchClass::Normal) * maximum_weight;
let operational_space = operational_limit.saturating_sub(normal_limit);
let extrinsic_weight = info.weight.checked_add(T::ExtrinsicBaseWeight::get())
.ok_or(InvalidTransaction::ExhaustsResources)?;
all_weight.checked_add(extrinsic_weight, DispatchClass::Operational)
.map_err(|_| InvalidTransaction::ExhaustsResources)?;
// If it would fit in normally, its okay
if all_weight.total() <= maximum_weight ||
// If we have not used our operational space
all_weight.get(DispatchClass::Operational) <= operational_space {
Ok(all_weight)
} else {
Err(InvalidTransaction::ExhaustsResources.into())
}
}
}
/// Checks if the current extrinsic can fit into the block with respect to block length limits.
///
/// Upon successes, it returns the new block length as a `Result`.
fn check_block_length(
len: usize,
) -> Result<u32, TransactionValidityError> {
let current_len = Module::<T>::all_extrinsics_len();
let maximum_len = T::MaximumBlockLength::get();
let limit = Self::get_dispatch_limit_ratio(info.class) * maximum_len;
let added_len = len as u32;
let next_len = current_len.saturating_add(added_len);
if next_len > limit {
Err(InvalidTransaction::ExhaustsResources.into())
} else {
Ok(next_len)
}
}
/// get the priority of an extrinsic denoted by `info`.
fn get_priority(info: &DispatchInfoOf<T::Call>) -> TransactionPriority {
match info.class {
DispatchClass::Normal => info.weight.into(),
DispatchClass::Operational => Bounded::max_value(),
// Mandatory extrinsics are only for inherents; never transactions.
DispatchClass::Mandatory => Bounded::min_value(),
/// Creates new `SignedExtension` to check weight of the extrinsic.
pub fn new() -> Self {
/// Do the pre-dispatch checks. This can be applied to both signed and unsigned.
///
/// It checks and notes the new weight and length.
fn do_pre_dispatch(
len: usize,
) -> Result<(), TransactionValidityError> {
let next_len = Self::check_block_length(info, len)?;
let next_weight = Self::check_block_weight(info)?;
Self::check_extrinsic_weight(info)?;
AllExtrinsicsLen::put(next_len);
Ok(())
}
/// Do the validate checks. This can be applied to both signed and unsigned.
///
/// It only checks that the block weight and length limit will not exceed.
fn do_validate(
len: usize,
) -> TransactionValidity {
// ignore the next length. If they return `Ok`, then it is below the limit.
let _ = Self::check_block_length(info, len)?;
// during validation we skip block limit check. Since the `validate_transaction`
// call runs on an empty block anyway, by this we prevent `on_initialize` weight
// consumption from causing false negatives.
Self::check_extrinsic_weight(info)?;
Ok(ValidTransaction { priority: Self::get_priority(info), ..Default::default() })
}
impl<T: Trait + Send + Sync> SignedExtension for CheckWeight<T> where
T::Call: Dispatchable<Info=DispatchInfo, PostInfo=PostDispatchInfo>
const IDENTIFIER: &'static str = "CheckWeight";
fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { Ok(()) }
fn pre_dispatch(
self,
_who: &Self::AccountId,
info: &DispatchInfoOf<Self::Call>,
Sergey Pepyakin
committed
) -> Result<(), TransactionValidityError> {
if info.class == DispatchClass::Mandatory {
Err(InvalidTransaction::MandatoryDispatch)?
}
Self::do_pre_dispatch(info, len)
}
fn validate(
&self,
_who: &Self::AccountId,
info: &DispatchInfoOf<Self::Call>,
if info.class == DispatchClass::Mandatory {
Err(InvalidTransaction::MandatoryDispatch)?
}
Self::do_validate(info, len)
}
fn pre_dispatch_unsigned(
_call: &Self::Call,
info: &DispatchInfoOf<Self::Call>,
len: usize,
) -> Result<(), TransactionValidityError> {
Self::do_pre_dispatch(info, len)
}
fn validate_unsigned(
_call: &Self::Call,
info: &DispatchInfoOf<Self::Call>,
len: usize,
) -> TransactionValidity {
Self::do_validate(info, len)
fn post_dispatch(
_pre: Self::Pre,
info: &DispatchInfoOf<Self::Call>,
post_info: &PostDispatchInfoOf<Self::Call>,
_len: usize,
result: &DispatchResult,
) -> Result<(), TransactionValidityError> {
// Since mandatory dispatched do not get validated for being overweight, we are sensitive
// to them actually being useful. Block producers are thus not allowed to include mandatory
// extrinsics that result in error.
if let (DispatchClass::Mandatory, Err(e)) = (info.class, result) {
"Bad mandantory".print();
e.print();
Err(InvalidTransaction::BadMandatory)?
}
let unspent = post_info.calc_unspent(info);
if unspent > 0 {
BlockWeight::mutate(|current_weight| {
current_weight.sub(unspent, info.class);
impl<T: Trait + Send + Sync> Debug for CheckWeight<T> {
#[cfg(feature = "std")]
fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
write!(f, "CheckWeight")
}
#[cfg(not(feature = "std"))]
fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
}
}
/// Nonce check and increment to give replay protection for transactions.
#[derive(Encode, Decode, Clone, Eq, PartialEq)]
pub struct CheckNonce<T: Trait>(#[codec(compact)] T::Index);
impl<T: Trait> CheckNonce<T> {
/// utility constructor. Used only in client/factory code.
pub fn from(nonce: T::Index) -> Self {
Self(nonce)
}
}
impl<T: Trait> Debug for CheckNonce<T> {
#[cfg(feature = "std")]
fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
write!(f, "CheckNonce({})", self.0)
fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
impl<T: Trait> SignedExtension for CheckNonce<T> where
T::Call: Dispatchable<Info=DispatchInfo>
{
const IDENTIFIER: &'static str = "CheckNonce";
fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { Ok(()) }
fn pre_dispatch(
self,
who: &Self::AccountId,
_info: &DispatchInfoOf<Self::Call>,
Sergey Pepyakin
committed
) -> Result<(), TransactionValidityError> {
let mut account = Account::<T>::get(who);
if self.0 != account.nonce {
InvalidTransaction::Stale
} else {
InvalidTransaction::Future
}.into()
account.nonce += T::Index::one();
Account::<T>::insert(who, account);
Ok(())
}
fn validate(
&self,
who: &Self::AccountId,
info: &DispatchInfoOf<Self::Call>,
let account = Account::<T>::get(who);
if self.0 < account.nonce {
return InvalidTransaction::Stale.into()
}
let provides = vec![Encode::encode(&(who, self.0))];
vec![Encode::encode(&(who, self.0 - One::one()))]
} else {
vec![]
};
Ok(ValidTransaction {
priority: info.weight as TransactionPriority,
requires,
provides,
longevity: TransactionLongevity::max_value(),
propagate: true,
})
}
}
impl<T: Trait> IsDeadAccount<T::AccountId> for Module<T> {
fn is_dead_account(who: &T::AccountId) -> bool {
!Account::<T>::contains_key(who)
}
}
/// Check for transaction mortality.
#[derive(Encode, Decode, Clone, Eq, PartialEq)]
pub struct CheckEra<T: Trait + Send + Sync>(Era, sp_std::marker::PhantomData<T>);
impl<T: Trait + Send + Sync> CheckEra<T> {
/// utility constructor. Used only in client/factory code.
pub fn from(era: Era) -> Self {
Self(era, sp_std::marker::PhantomData)
impl<T: Trait + Send + Sync> Debug for CheckEra<T> {
#[cfg(feature = "std")]
fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
write!(f, "CheckEra({:?})", self.0)
fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
}
impl<T: Trait + Send + Sync> SignedExtension for CheckEra<T> {
type AccountId = T::AccountId;
type AdditionalSigned = T::Hash;
const IDENTIFIER: &'static str = "CheckEra";
fn validate(
&self,
_who: &Self::AccountId,
_call: &Self::Call,
_info: &DispatchInfoOf<Self::Call>,
let current_u64 = <Module<T>>::block_number().saturated_into::<u64>();
let valid_till = self.0.death(current_u64);
Ok(ValidTransaction {
longevity: valid_till.saturating_sub(current_u64),
..Default::default()
})
}
fn additional_signed(&self) -> Result<Self::AdditionalSigned, TransactionValidityError> {
let current_u64 = <Module<T>>::block_number().saturated_into::<u64>();
let n = self.0.birth(current_u64).saturated_into::<T::BlockNumber>();
if !<BlockHash<T>>::contains_key(n) {
Err(InvalidTransaction::AncientBirthBlock.into())
} else {
Ok(<Module<T>>::block_hash(n))
}
/// Nonce check and increment to give replay protection for transactions.
#[derive(Encode, Decode, Clone, Eq, PartialEq)]
pub struct CheckGenesis<T: Trait + Send + Sync>(sp_std::marker::PhantomData<T>);
impl<T: Trait + Send + Sync> Debug for CheckGenesis<T> {
#[cfg(feature = "std")]
fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
write!(f, "CheckGenesis")
}
#[cfg(not(feature = "std"))]
fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
Ok(())
}
}
impl<T: Trait + Send + Sync> CheckGenesis<T> {
/// Creates new `SignedExtension` to check genesis hash.
pub fn new() -> Self {
Self(sp_std::marker::PhantomData)
}
}
impl<T: Trait + Send + Sync> SignedExtension for CheckGenesis<T> {
type AccountId = T::AccountId;
type AdditionalSigned = T::Hash;
const IDENTIFIER: &'static str = "CheckGenesis";
fn additional_signed(&self) -> Result<Self::AdditionalSigned, TransactionValidityError> {
Ok(<Module<T>>::block_hash(T::BlockNumber::zero()))
}
}
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
/// Ensure the transaction version registered in the transaction is the same as at present.
#[derive(Encode, Decode, Clone, Eq, PartialEq)]
pub struct CheckTxVersion<T: Trait + Send + Sync>(sp_std::marker::PhantomData<T>);
impl<T: Trait + Send + Sync> Debug for CheckTxVersion<T> {
#[cfg(feature = "std")]
fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
write!(f, "CheckTxVersion")
}
#[cfg(not(feature = "std"))]
fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
Ok(())
}
}
impl<T: Trait + Send + Sync> CheckTxVersion<T> {
/// Create new `SignedExtension` to check transaction version.
pub fn new() -> Self {
Self(sp_std::marker::PhantomData)
}
}
impl<T: Trait + Send + Sync> SignedExtension for CheckTxVersion<T> {
type AccountId = T::AccountId;
type Call = <T as Trait>::Call;
type AdditionalSigned = u32;
type Pre = ();
const IDENTIFIER: &'static str = "CheckTxVersion";
fn additional_signed(&self) -> Result<Self::AdditionalSigned, TransactionValidityError> {
Ok(<Module<T>>::runtime_version().transaction_version)
}
}
/// Ensure the runtime version registered in the transaction is the same as at present.
#[derive(Encode, Decode, Clone, Eq, PartialEq)]
pub struct CheckSpecVersion<T: Trait + Send + Sync>(sp_std::marker::PhantomData<T>);
impl<T: Trait + Send + Sync> Debug for CheckSpecVersion<T> {
fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
write!(f, "CheckSpecVersion")
fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
Ok(())
}
}
impl<T: Trait + Send + Sync> CheckSpecVersion<T> {
/// Create new `SignedExtension` to check runtime version.
pub fn new() -> Self {
Self(sp_std::marker::PhantomData)
}
}
impl<T: Trait + Send + Sync> SignedExtension for CheckSpecVersion<T> {
type AccountId = T::AccountId;
type Call = <T as Trait>::Call;
type AdditionalSigned = u32;
type Pre = ();
const IDENTIFIER: &'static str = "CheckSpecVersion";
fn additional_signed(&self) -> Result<Self::AdditionalSigned, TransactionValidityError> {
Ok(<Module<T>>::runtime_version().spec_version)
}
}
pub struct ChainContext<T>(sp_std::marker::PhantomData<T>);
impl<T> Default for ChainContext<T> {
fn default() -> Self {
ChainContext(sp_std::marker::PhantomData)
}
}
impl<T: Trait> 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)
use sp_runtime::{traits::{BlakeTwo256, IdentityLookup, SignedExtension}, testing::Header, DispatchError};
use frame_support::{
impl_outer_origin, parameter_types, assert_ok, assert_noop,
weights::{WithPostDispatchInfo, Pays},
};
pub enum Origin for Test where system = super {}
}
parameter_types! {
pub const BlockHashCount: u64 = 10;
pub const MaximumBlockWeight: Weight = 1024;
pub const MaximumExtrinsicWeight: Weight = 768;
pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);
pub const MaximumBlockLength: u32 = 1024;
pub Version: RuntimeVersion = RuntimeVersion {
spec_name: sp_version::create_runtime_str!("test"),
impl_name: sp_version::create_runtime_str!("system-test"),
authoring_version: 1,
spec_version: 1,
impl_version: 1,
apis: sp_version::create_apis_vec!([]),
transaction_version: 1,
pub const BlockExecutionWeight: Weight = 10;
pub const ExtrinsicBaseWeight: Weight = 5;
pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight {
read: 10,
write: 100,
};
thread_local!{
pub static KILLED: RefCell<Vec<u64>> = RefCell::new(vec![]);
}
pub struct RecordKilled;
impl OnKilledAccount<u64> for RecordKilled {
fn on_killed_account(who: &u64) { KILLED.with(|r| r.borrow_mut().push(*who)) }
}
#[derive(Debug, codec::Encode, codec::Decode)]
pub struct Call;
type Trait = ();
type Info = DispatchInfo;
type PostInfo = PostDispatchInfo;
fn dispatch(self, _origin: Self::Origin)
-> sp_runtime::DispatchResultWithInfo<Self::PostInfo> {
panic!("Do not use dummy implementation for dispatch.");
}
}
type Index = u64;
type BlockNumber = u64;
type Hash = H256;
type Hashing = BlakeTwo256;
type AccountId = u64;
type Lookup = IdentityLookup<Self::AccountId>;
type Event = Event<Self>;
type BlockHashCount = BlockHashCount;
type MaximumBlockWeight = MaximumBlockWeight;
type DbWeight = DbWeight;
type BlockExecutionWeight = BlockExecutionWeight;
type ExtrinsicBaseWeight = ExtrinsicBaseWeight;
type MaximumExtrinsicWeight = MaximumExtrinsicWeight;
type AvailableBlockRatio = AvailableBlockRatio;
type MaximumBlockLength = MaximumBlockLength;
type Version = Version;
type SysEvent = <Test as Trait>::Event;
fn new_test_ext() -> sp_io::TestExternalities {
let mut ext: sp_io::TestExternalities = GenesisConfig::default().build_storage::<Test>().unwrap().into();
// Add to each test the initial weight of a block
ext.execute_with(|| System::register_extra_weight_unchecked(<Test as Trait>::BlockExecutionWeight::get(), DispatchClass::Mandatory));
fn normal_weight_limit() -> Weight {
<Test as Trait>::AvailableBlockRatio::get() * <Test as Trait>::MaximumBlockWeight::get()
}
fn normal_length_limit() -> u32 {