Per-things trait. (#4904)

* Give perthigns the trait it always deserved.

* Make staking and phragmen work with the new generic per_thing

* Make everything work together 🔨

* a bit of cleanup

* Clean usage

* Bump.

* Fix name

* fix grumbles

* hopefully fix the ui test

* Some grumbles

* revamp traits again

* Better naming again.
This commit is contained in:
Kian Paimani
2020-02-13 13:09:33 +01:00
committed by GitHub
parent e6454eb091
commit c871eaacbc
42 changed files with 346 additions and 241 deletions
+3 -3
View File
@@ -133,7 +133,7 @@
#![cfg_attr(not(feature = "std"), no_std)]
use frame_support::{Parameter, decl_module, decl_event, decl_storage, decl_error, ensure};
use sp_runtime::traits::{Member, SimpleArithmetic, Zero, StaticLookup};
use sp_runtime::traits::{Member, AtLeast32Bit, Zero, StaticLookup};
use frame_system::{self as system, ensure_signed};
use sp_runtime::traits::One;
@@ -143,10 +143,10 @@ pub trait Trait: frame_system::Trait {
type Event: From<Event<Self>> + Into<<Self as frame_system::Trait>::Event>;
/// The units in which we record balances.
type Balance: Member + Parameter + SimpleArithmetic + Default + Copy;
type Balance: Member + Parameter + AtLeast32Bit + Default + Copy;
/// The arithmetic type of asset identifier.
type AssetId: Parameter + SimpleArithmetic + Default + Copy;
type AssetId: Parameter + AtLeast32Bit + Default + Copy;
}
decl_module! {
+1 -1
View File
@@ -25,7 +25,7 @@ pub use pallet_timestamp;
use sp_std::{result, prelude::*};
use frame_support::{decl_storage, decl_module, traits::{FindAuthor, Get, Randomness as RandomnessT}};
use sp_timestamp::OnTimestampSet;
use sp_runtime::{generic::DigestItem, ConsensusEngineId, Perbill};
use sp_runtime::{generic::DigestItem, ConsensusEngineId, Perbill, PerThing};
use sp_runtime::traits::{IsMember, SaturatedConversion, Saturating, Hash};
use sp_staking::{
SessionIndex,
+1 -1
View File
@@ -20,7 +20,7 @@
use super::{Trait, Module, GenesisConfig};
use sp_consensus_babe::AuthorityId;
use sp_runtime::{
traits::IdentityLookup, Perbill, testing::{Header, UintAuthorityId}, impl_opaque_keys,
traits::IdentityLookup, Perbill, PerThing, testing::{Header, UintAuthorityId}, impl_opaque_keys,
};
use sp_version::RuntimeVersion;
use frame_support::{impl_outer_origin, parameter_types, weights::Weight};
+3 -3
View File
@@ -169,7 +169,7 @@ use frame_support::{
use sp_runtime::{
RuntimeDebug, DispatchResult, DispatchError,
traits::{
Zero, SimpleArithmetic, StaticLookup, Member, CheckedAdd, CheckedSub,
Zero, AtLeast32Bit, StaticLookup, Member, CheckedAdd, CheckedSub,
MaybeSerializeDeserialize, Saturating, Bounded,
},
};
@@ -180,7 +180,7 @@ pub use self::imbalances::{PositiveImbalance, NegativeImbalance};
pub trait Subtrait<I: Instance = DefaultInstance>: frame_system::Trait {
/// The balance of an account.
type Balance: Parameter + Member + SimpleArithmetic + Codec + Default + Copy +
type Balance: Parameter + Member + AtLeast32Bit + Codec + Default + Copy +
MaybeSerializeDeserialize + Debug;
/// A function that is invoked when the free-balance and the reserved-balance has fallen below
@@ -202,7 +202,7 @@ pub trait Subtrait<I: Instance = DefaultInstance>: frame_system::Trait {
pub trait Trait<I: Instance = DefaultInstance>: frame_system::Trait {
/// The balance of an account.
type Balance: Parameter + Member + SimpleArithmetic + Codec + Default + Copy +
type Balance: Parameter + Member + AtLeast32Bit + Codec + Default + Copy +
MaybeSerializeDeserialize + Debug;
/// A function that is invoked when the free-balance and the reserved-balance has fallen below
+2 -2
View File
@@ -17,7 +17,7 @@
use crate::{GasSpent, Module, Trait, BalanceOf, NegativeImbalanceOf};
use sp_std::convert::TryFrom;
use sp_runtime::traits::{
CheckedMul, Zero, SaturatedConversion, SimpleArithmetic, UniqueSaturatedInto,
CheckedMul, Zero, SaturatedConversion, AtLeast32Bit, UniqueSaturatedInto,
};
use frame_support::{
traits::{Currency, ExistenceRequirement, Imbalance, OnUnbalanced, WithdrawReason}, StorageValue,
@@ -248,7 +248,7 @@ pub fn refund_unused_gas<T: Trait>(
/// A little handy utility for converting a value in balance units into approximate value in gas units
/// at the given gas price.
pub fn approx_gas_for_balance<Balance>(gas_price: Balance, balance: Balance) -> Gas
where Balance: SimpleArithmetic
where Balance: AtLeast32Bit
{
(balance / gas_price).saturated_into::<Gas>()
}
@@ -83,7 +83,10 @@
#![cfg_attr(not(feature = "std"), no_std)]
use sp_std::prelude::*;
use sp_runtime::{print, DispatchResult, DispatchError, traits::{Zero, StaticLookup, Convert}};
use sp_runtime::{
print, DispatchResult, DispatchError, Perbill,
traits::{Zero, StaticLookup, Convert},
};
use frame_support::{
decl_storage, decl_event, ensure, decl_module, decl_error, weights::SimpleDispatchInfo,
traits::{
@@ -637,7 +640,7 @@ impl<T: Trait> Module<T> {
let voters_and_votes = <VotesOf<T>>::enumerate()
.map(|(v, i)| (v, i))
.collect::<Vec<(T::AccountId, Vec<T::AccountId>)>>();
let maybe_phragmen_result = sp_phragmen::elect::<_, _, _, T::CurrencyToVote>(
let maybe_phragmen_result = sp_phragmen::elect::<_, _, _, T::CurrencyToVote, Perbill>(
num_to_elect,
0,
candidates,
@@ -664,7 +667,7 @@ impl<T: Trait> Module<T> {
.filter_map(|(m, a)| if a.is_zero() { None } else { Some(m) } )
.collect::<Vec<T::AccountId>>();
let support_map = sp_phragmen::build_support_map::<_, _, _, T::CurrencyToVote>(
let support_map = sp_phragmen::build_support_map::<_, _, _, T::CurrencyToVote, Perbill>(
&new_set,
&phragmen_result.assignments,
Self::locked_stake_of,
+2 -1
View File
@@ -651,7 +651,8 @@ mod tests {
// The testing primitives are very useful for avoiding having to work with signatures
// or public keys. `u64` is used as the `AccountId` and no `Signature`s are required.
use sp_runtime::{
Perbill, testing::Header,
Perbill,
testing::Header,
traits::{BlakeTwo256, OnInitialize, OnFinalize, IdentityLookup},
};
+5 -5
View File
@@ -156,7 +156,7 @@ use codec::{Decode, Encode, HasCompact, Input, Output, Error as CodecError};
use sp_runtime::{RuntimeDebug, DispatchResult, DispatchError};
use sp_runtime::traits::{
CheckedAdd, CheckedSub, MaybeSerializeDeserialize, Member, One, Saturating, SimpleArithmetic,
CheckedAdd, CheckedSub, MaybeSerializeDeserialize, Member, One, Saturating, AtLeast32Bit,
Zero, Bounded,
};
@@ -180,24 +180,24 @@ pub use self::imbalances::{NegativeImbalance, PositiveImbalance};
pub trait Trait: frame_system::Trait {
type Balance: Parameter
+ Member
+ SimpleArithmetic
+ AtLeast32Bit
+ Default
+ Copy
+ MaybeSerializeDeserialize
+ Debug;
type AssetId: Parameter + Member + SimpleArithmetic + Default + Copy;
type AssetId: Parameter + Member + AtLeast32Bit + Default + Copy;
type Event: From<Event<Self>> + Into<<Self as frame_system::Trait>::Event>;
}
pub trait Subtrait: frame_system::Trait {
type Balance: Parameter
+ Member
+ SimpleArithmetic
+ AtLeast32Bit
+ Default
+ Copy
+ MaybeSerializeDeserialize
+ Debug;
type AssetId: Parameter + Member + SimpleArithmetic + Default + Copy;
type AssetId: Parameter + Member + AtLeast32Bit + Default + Copy;
}
impl<T: Trait> Subtrait for T {
+1 -1
View File
@@ -34,7 +34,7 @@ use sp_std::prelude::*;
use codec::{self as codec, Encode, Decode};
use frame_support::{decl_event, decl_storage, decl_module, decl_error, storage};
use sp_runtime::{
DispatchResult, generic::{DigestItem, OpaqueDigestItemId}, traits::Zero, Perbill,
DispatchResult, generic::{DigestItem, OpaqueDigestItemId}, traits::Zero, Perbill, PerThing,
};
use sp_staking::{
SessionIndex,
+2 -2
View File
@@ -79,7 +79,7 @@ use pallet_session::historical::IdentificationTuple;
use sp_runtime::{
offchain::storage::StorageValueRef,
RuntimeDebug,
traits::{Convert, Member, Saturating, SimpleArithmetic}, Perbill,
traits::{Convert, Member, Saturating, AtLeast32Bit}, Perbill, PerThing,
transaction_validity::{
TransactionValidity, ValidTransaction, InvalidTransaction,
TransactionPriority,
@@ -151,7 +151,7 @@ struct HeartbeatStatus<BlockNumber> {
pub sent_at: BlockNumber,
}
impl<BlockNumber: PartialEq + SimpleArithmetic + Copy> HeartbeatStatus<BlockNumber> {
impl<BlockNumber: PartialEq + AtLeast32Bit + Copy> HeartbeatStatus<BlockNumber> {
/// Returns true if heartbeat has been recently sent.
///
/// Parameters:
+2 -2
View File
@@ -22,7 +22,7 @@
use sp_std::{prelude::*, marker::PhantomData, convert::TryInto};
use codec::{Encode, Codec};
use frame_support::{Parameter, decl_module, decl_event, decl_storage};
use sp_runtime::traits::{One, SimpleArithmetic, StaticLookup, Member, LookupError};
use sp_runtime::traits::{One, AtLeast32Bit, StaticLookup, Member, LookupError};
use frame_system::{IsDeadAccount, OnNewAccount};
use self::address::Address as RawAddress;
@@ -59,7 +59,7 @@ impl<AccountId: Encode, AccountIndex: From<u32>>
pub trait Trait: frame_system::Trait {
/// Type used for storing an account's index; implies the maximum number of accounts the system
/// can hold.
type AccountIndex: Parameter + Member + Codec + Default + SimpleArithmetic + Copy;
type AccountIndex: Parameter + Member + Codec + Default + AtLeast32Bit + Copy;
/// Whether an account is dead or not.
type IsDeadAccount: IsDeadAccount<Self::AccountId>;
@@ -154,7 +154,9 @@ mod tests {
use super::*;
use sp_core::H256;
use sp_runtime::{
Perbill, traits::{BlakeTwo256, OnInitialize, Header as _, IdentityLookup}, testing::Header,
Perbill,
testing::Header,
traits::{BlakeTwo256, OnInitialize, Header as _, IdentityLookup},
};
use frame_support::{impl_outer_origin, parameter_types, weights::Weight, traits::Randomness};
+2 -2
View File
@@ -99,7 +99,7 @@ use frame_support::{
};
use frame_system::{self as system, ensure_root, ensure_signed};
use sp_runtime::{
traits::{EnsureOrigin, SimpleArithmetic, MaybeSerializeDeserialize, Zero, StaticLookup},
traits::{EnsureOrigin, AtLeast32Bit, MaybeSerializeDeserialize, Zero, StaticLookup},
};
type BalanceOf<T, I> = <<T as Trait<I>>::Currency as Currency<<T as frame_system::Trait>::AccountId>>::Balance;
@@ -121,7 +121,7 @@ pub trait Trait<I=DefaultInstance>: frame_system::Trait {
/// The score attributed to a member or candidate.
type Score:
SimpleArithmetic + Clone + Copy + Default + FullCodec + MaybeSerializeDeserialize + Debug;
AtLeast32Bit + Clone + Copy + Default + FullCodec + MaybeSerializeDeserialize + Debug;
/// The overarching event type.
type Event: From<Event<Self, I>> + Into<<Self as frame_system::Trait>::Event>;
+3 -2
View File
@@ -21,8 +21,9 @@ use std::cell::RefCell;
use frame_support::{impl_outer_origin, parameter_types, weights::Weight};
use sp_core::{crypto::key_types::DUMMY, H256};
use sp_runtime::{
Perbill, impl_opaque_keys, traits::{BlakeTwo256, IdentityLookup, ConvertInto},
testing::{Header, UintAuthorityId}
Perbill, impl_opaque_keys,
traits::{BlakeTwo256, IdentityLookup, ConvertInto},
testing::{Header, UintAuthorityId},
};
use sp_staking::SessionIndex;
+3 -1
View File
@@ -23,7 +23,9 @@ use sp_core::H256;
// The testing primitives are very useful for avoiding having to work with signatures
// or public keys. `u64` is used as the `AccountId` and no `Signature`s are requried.
use sp_runtime::{
Perbill, traits::{BlakeTwo256, IdentityLookup, OnInitialize, OnFinalize}, testing::Header,
Perbill,
testing::Header,
traits::{BlakeTwo256, IdentityLookup, OnInitialize, OnFinalize},
};
use frame_system::EnsureSignedBy;
+2 -2
View File
@@ -19,7 +19,7 @@
//! The staking rate in NPoS is the total amount of tokens staked by nominators and validators,
//! divided by the total token supply.
use sp_runtime::{Perbill, traits::SimpleArithmetic, curve::PiecewiseLinear};
use sp_runtime::{Perbill, PerThing, traits::AtLeast32Bit, curve::PiecewiseLinear};
/// The total payout to all validators (and their nominators) per era.
///
@@ -32,7 +32,7 @@ pub fn compute_total_payout<N>(
npos_token_staked: N,
total_tokens: N,
era_duration: u64
) -> (N, N) where N: SimpleArithmetic + Clone {
) -> (N, N) where N: AtLeast32Bit + Clone {
// Milliseconds per year for the Julian year (365.25 days).
const MILLISECONDS_PER_YEAR: u64 = 1000 * 3600 * 24 * 36525 / 100;
+6 -7
View File
@@ -267,12 +267,11 @@ use frame_support::{
};
use pallet_session::historical::SessionManager;
use sp_runtime::{
Perbill,
RuntimeDebug,
Perbill, PerThing, RuntimeDebug,
curve::PiecewiseLinear,
traits::{
Convert, Zero, One, StaticLookup, CheckedSub, Saturating, Bounded, SaturatedConversion,
SimpleArithmetic, EnsureOrigin,
AtLeast32Bit, EnsureOrigin,
}
};
use sp_staking::{
@@ -396,7 +395,7 @@ pub struct StakingLedger<AccountId, Balance: HasCompact> {
impl<
AccountId,
Balance: HasCompact + Copy + Saturating + SimpleArithmetic,
Balance: HasCompact + Copy + Saturating + AtLeast32Bit,
> StakingLedger<AccountId, Balance> {
/// Remove entries from `unlocking` that are sufficiently old and reduce the
/// total by the sum of their balances.
@@ -440,7 +439,7 @@ impl<
}
impl<AccountId, Balance> StakingLedger<AccountId, Balance> where
Balance: SimpleArithmetic + Saturating + Copy,
Balance: AtLeast32Bit + Saturating + Copy,
{
/// Slash the validator for a given amount of balance. This can grow the value
/// of the slash in the case that the validator has less than `minimum_balance`
@@ -1503,7 +1502,7 @@ impl<T: Trait> Module<T> {
});
all_nominators.extend(nominator_votes);
let maybe_phragmen_result = sp_phragmen::elect::<_, _, _, T::CurrencyToVote>(
let maybe_phragmen_result = sp_phragmen::elect::<_, _, _, T::CurrencyToVote, Perbill>(
Self::validator_count() as usize,
Self::minimum_validator_count().max(1) as usize,
all_validators,
@@ -1520,7 +1519,7 @@ impl<T: Trait> Module<T> {
let to_balance = |e: ExtendedBalance|
<T::CurrencyToVote as Convert<ExtendedBalance, BalanceOf<T>>>::convert(e);
let supports = sp_phragmen::build_support_map::<_, _, _, T::CurrencyToVote>(
let supports = sp_phragmen::build_support_map::<_, _, _, T::CurrencyToVote, Perbill>(
&elected_stashes,
&assignments,
Self::slashable_balance_of,
+1 -1
View File
@@ -52,7 +52,7 @@ use super::{
EraIndex, Trait, Module, Store, BalanceOf, Exposure, Perbill, SessionInterface,
NegativeImbalanceOf, UnappliedSlash,
};
use sp_runtime::traits::{Zero, Saturating};
use sp_runtime::{traits::{Zero, Saturating}, PerThing};
use frame_support::{
StorageMap, StorageDoubleMap,
traits::{Currency, OnUnbalanced, Imbalance},
+4 -4
View File
@@ -24,7 +24,7 @@ use sp_core::u32_trait::Value as U32;
use sp_runtime::{
RuntimeDebug,
ConsensusEngineId, DispatchResult, DispatchError,
traits::{MaybeSerializeDeserialize, SimpleArithmetic, Saturating, TrailingZeroInput},
traits::{MaybeSerializeDeserialize, AtLeast32Bit, Saturating, TrailingZeroInput},
};
use crate::dispatch::Parameter;
@@ -267,7 +267,7 @@ pub enum SignedImbalance<B, P: Imbalance<B>>{
impl<
P: Imbalance<B, Opposite=N>,
N: Imbalance<B, Opposite=P>,
B: SimpleArithmetic + FullCodec + Copy + MaybeSerializeDeserialize + Debug + Default,
B: AtLeast32Bit + FullCodec + Copy + MaybeSerializeDeserialize + Debug + Default,
> SignedImbalance<B, P> {
pub fn zero() -> Self {
SignedImbalance::Positive(P::zero())
@@ -330,7 +330,7 @@ impl<
/// Abstraction over a fungible assets system.
pub trait Currency<AccountId> {
/// The balance of an account.
type Balance: SimpleArithmetic + FullCodec + Copy + MaybeSerializeDeserialize + Debug + Default;
type Balance: AtLeast32Bit + FullCodec + Copy + MaybeSerializeDeserialize + Debug + Default;
/// The opaque token type for an imbalance. This is returned by unbalanced operations
/// and must be dealt with. It may be dropped but cannot be cloned.
@@ -659,7 +659,7 @@ bitmask! {
}
pub trait Time {
type Moment: SimpleArithmetic + Parameter + Default + Copy;
type Moment: AtLeast32Bit + Parameter + Default + Copy;
fn now() -> Self::Moment;
}
+1 -1
View File
@@ -18,7 +18,7 @@ use criterion::{Criterion, criterion_group, criterion_main, black_box};
use frame_system as system;
use frame_support::{decl_module, decl_event, impl_outer_origin, impl_outer_event, weights::Weight};
use sp_core::H256;
use sp_runtime::{Perbill, traits::{BlakeTwo256, IdentityLookup}, testing::Header};
use sp_runtime::{Perbill, PerThing, traits::{BlakeTwo256, IdentityLookup}, testing::Header};
mod module {
use super::*;
+6 -6
View File
@@ -97,14 +97,14 @@ use sp_std::marker::PhantomData;
use sp_std::fmt::Debug;
use sp_version::RuntimeVersion;
use sp_runtime::{
RuntimeDebug,
generic::{self, Era}, Perbill, DispatchOutcome, DispatchError,
RuntimeDebug, Perbill, DispatchOutcome, DispatchError,
generic::{self, Era},
transaction_validity::{
ValidTransaction, TransactionPriority, TransactionLongevity, TransactionValidityError,
InvalidTransaction, TransactionValidity,
},
traits::{
self, CheckEqual, SimpleArithmetic, Zero, SignedExtension, Lookup, LookupError,
self, CheckEqual, AtLeast32Bit, Zero, SignedExtension, Lookup, LookupError,
SimpleBitOps, Hash, Member, MaybeDisplay, EnsureOrigin, BadOrigin, SaturatedConversion,
MaybeSerialize, MaybeSerializeDeserialize, MaybeMallocSizeOf, StaticLookup, One, Bounded,
},
@@ -165,12 +165,12 @@ pub trait Trait: 'static + Eq + Clone {
/// Account index (aka nonce) type. This stores the number of previous transactions associated
/// with a sender account.
type Index:
Parameter + Member + MaybeSerialize + Debug + Default + MaybeDisplay + SimpleArithmetic
Parameter + Member + MaybeSerialize + Debug + Default + MaybeDisplay + AtLeast32Bit
+ Copy;
/// The block number type used by the runtime.
type BlockNumber:
Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + SimpleArithmetic
Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + AtLeast32Bit
+ Default + Bounded + Copy + sp_std::hash::Hash + sp_std::str::FromStr + MaybeMallocSizeOf;
/// The output of the `Hashing` function.
@@ -898,7 +898,7 @@ impl<T: Trait + Send + Sync> CheckWeight<T> {
/// a portion.
fn get_dispatch_limit_ratio(class: DispatchClass) -> Perbill {
match class {
DispatchClass::Operational => Perbill::one(),
DispatchClass::Operational => <Perbill as sp_runtime::PerThing>::one(),
DispatchClass::Normal => T::AvailableBlockRatio::get(),
}
}
+2 -2
View File
@@ -99,7 +99,7 @@ use frame_support::traits::{Time, Get};
use sp_runtime::{
RuntimeString,
traits::{
SimpleArithmetic, Zero, SaturatedConversion, Scale
AtLeast32Bit, Zero, SaturatedConversion, Scale
}
};
use frame_support::weights::SimpleDispatchInfo;
@@ -112,7 +112,7 @@ use sp_timestamp::{
/// The module configuration trait
pub trait Trait: frame_system::Trait {
/// Type used for expressing timestamp.
type Moment: Parameter + Default + SimpleArithmetic
type Moment: Parameter + Default + AtLeast32Bit
+ Scale<Self::BlockNumber, Output = Self::Moment> + Copy;
/// Something which can be notified when the timestamp is set. Set this to `()` if not needed.
+4 -2
View File
@@ -590,7 +590,7 @@ impl<T: Trait> Module<T> {
}
}
/// Remove any non-members of `Tippers` from a `tips` vectr. `O(T)`.
/// Remove any non-members of `Tippers` from a `tips` vector. `O(T)`.
fn retain_active_tips(tips: &mut Vec<(T::AccountId, BalanceOf<T>)>) {
let members = T::Tippers::sorted_members();
let mut members_iter = members.iter();
@@ -724,7 +724,9 @@ mod tests {
use frame_support::traits::Contains;
use sp_core::H256;
use sp_runtime::{
traits::{BlakeTwo256, OnFinalize, IdentityLookup, BadOrigin}, testing::Header, Perbill
Perbill,
testing::Header,
traits::{BlakeTwo256, OnFinalize, IdentityLookup, BadOrigin},
};
impl_outer_origin! {
+6 -4
View File
@@ -50,7 +50,7 @@ use sp_std::prelude::*;
use sp_std::fmt::Debug;
use codec::{Encode, Decode};
use sp_runtime::{DispatchResult, RuntimeDebug, traits::{
StaticLookup, Zero, SimpleArithmetic, MaybeSerializeDeserialize, Saturating, Convert
StaticLookup, Zero, AtLeast32Bit, MaybeSerializeDeserialize, Saturating, Convert
}};
use frame_support::{decl_module, decl_event, decl_storage, decl_error};
use frame_support::traits::{
@@ -85,8 +85,8 @@ pub struct VestingInfo<Balance, BlockNumber> {
}
impl<
Balance: SimpleArithmetic + Copy,
BlockNumber: SimpleArithmetic + Copy,
Balance: AtLeast32Bit + Copy,
BlockNumber: AtLeast32Bit + Copy,
> VestingInfo<Balance, BlockNumber> {
/// Amount locked at block `n`.
pub fn locked_at<
@@ -298,7 +298,9 @@ mod tests {
// The testing primitives are very useful for avoiding having to work with signatures
// or public keys. `u64` is used as the `AccountId` and no `Signature`s are required.
use sp_runtime::{
Perbill, testing::Header, traits::{BlakeTwo256, IdentityLookup, Identity, OnInitialize},
Perbill,
testing::Header,
traits::{BlakeTwo256, IdentityLookup, Identity, OnInitialize},
};
use sp_storage::Storage;