Run cargo fmt on the whole code base (#9394)

* Run cargo fmt on the whole code base

* Second run

* Add CI check

* Fix compilation

* More unnecessary braces

* Handle weights

* Use --all

* Use correct attributes...

* Fix UI tests

* AHHHHHHHHH

* 🤦

* Docs

* Fix compilation

* 🤷

* Please stop

* 🤦 x 2

* More

* make rustfmt.toml consistent with polkadot

Co-authored-by: André Silva <andrerfosilva@gmail.com>
This commit is contained in:
Bastian Köcher
2021-07-21 16:32:32 +02:00
committed by GitHub
parent d451c38c1c
commit 7b56ab15b4
1010 changed files with 53339 additions and 51208 deletions
+47 -40
View File
@@ -18,20 +18,26 @@
//! Dispatch system. Contains a macro for defining runtime modules and
//! generating values representing lazy module function calls.
pub use crate::sp_std::{result, fmt, prelude::{Vec, Clone, Eq, PartialEq}, marker};
pub use crate::codec::{Codec, EncodeLike, Decode, Encode, Input, Output, HasCompact, EncodeAsRef};
pub use frame_metadata::{
FunctionMetadata, DecodeDifferent, DecodeDifferentArray, FunctionArgumentMetadata,
ModuleConstantMetadata, DefaultByte, DefaultByteGetter, ModuleErrorMetadata, ErrorMetadata
pub use crate::{
codec::{Codec, Decode, Encode, EncodeAsRef, EncodeLike, HasCompact, Input, Output},
sp_std::{
fmt, marker,
prelude::{Clone, Eq, PartialEq, Vec},
result,
},
traits::{
CallMetadata, GetCallMetadata, GetCallName, GetPalletVersion, UnfilteredDispatchable,
},
weights::{
ClassifyDispatch, DispatchInfo, GetDispatchInfo, PaysFee, PostDispatchInfo,
TransactionPriority, WeighData, Weight, WithPostDispatchInfo,
},
};
pub use crate::weights::{
GetDispatchInfo, DispatchInfo, WeighData, ClassifyDispatch, TransactionPriority, Weight,
PaysFee, PostDispatchInfo, WithPostDispatchInfo,
pub use frame_metadata::{
DecodeDifferent, DecodeDifferentArray, DefaultByte, DefaultByteGetter, ErrorMetadata,
FunctionArgumentMetadata, FunctionMetadata, ModuleConstantMetadata, ModuleErrorMetadata,
};
pub use sp_runtime::{traits::Dispatchable, DispatchError};
pub use crate::traits::{
CallMetadata, GetCallMetadata, GetCallName, UnfilteredDispatchable, GetPalletVersion,
};
/// The return typ of a `Dispatchable` in frame. When returned explicitly from
/// a dispatchable function it allows overriding the default `PostDispatchInfo`
@@ -2331,7 +2337,6 @@ macro_rules! __call_to_functions {
};
}
/// Convert a list of functions into a list of `FunctionMetadata` items.
#[macro_export]
#[doc(hidden)]
@@ -2465,13 +2470,19 @@ macro_rules! __check_reserved_fn_name {
#[allow(dead_code)]
mod tests {
use super::*;
use crate::weights::{DispatchInfo, DispatchClass, Pays, RuntimeDbWeight};
use crate::traits::{
GetCallName, OnInitialize, OnFinalize, OnIdle, OnRuntimeUpgrade,
IntegrityTest, Get, PalletInfo,
use crate::{
traits::{
Get, GetCallName, IntegrityTest, OnFinalize, OnIdle, OnInitialize, OnRuntimeUpgrade,
PalletInfo,
},
weights::{DispatchClass, DispatchInfo, Pays, RuntimeDbWeight},
};
pub trait Config: system::Config + Sized where Self::AccountId: From<u32> { }
pub trait Config: system::Config + Sized
where
Self::AccountId: From<u32>,
{
}
pub mod system {
use super::*;
@@ -2546,18 +2557,14 @@ mod tests {
FunctionMetadata {
name: DecodeDifferent::Encode("aux_0"),
arguments: DecodeDifferent::Encode(&[]),
documentation: DecodeDifferent::Encode(&[
" Hi, this is a comment."
])
documentation: DecodeDifferent::Encode(&[" Hi, this is a comment."]),
},
FunctionMetadata {
name: DecodeDifferent::Encode("aux_1"),
arguments: DecodeDifferent::Encode(&[
FunctionArgumentMetadata {
name: DecodeDifferent::Encode("_data"),
ty: DecodeDifferent::Encode("Compact<u32>")
}
]),
arguments: DecodeDifferent::Encode(&[FunctionArgumentMetadata {
name: DecodeDifferent::Encode("_data"),
ty: DecodeDifferent::Encode("Compact<u32>"),
}]),
documentation: DecodeDifferent::Encode(&[]),
},
FunctionMetadata {
@@ -2570,7 +2577,7 @@ mod tests {
FunctionArgumentMetadata {
name: DecodeDifferent::Encode("_data2"),
ty: DecodeDifferent::Encode("String"),
}
},
]),
documentation: DecodeDifferent::Encode(&[]),
},
@@ -2581,12 +2588,10 @@ mod tests {
},
FunctionMetadata {
name: DecodeDifferent::Encode("aux_4"),
arguments: DecodeDifferent::Encode(&[
FunctionArgumentMetadata {
name: DecodeDifferent::Encode("_data"),
ty: DecodeDifferent::Encode("i32"),
}
]),
arguments: DecodeDifferent::Encode(&[FunctionArgumentMetadata {
name: DecodeDifferent::Encode("_data"),
ty: DecodeDifferent::Encode("i32"),
}]),
documentation: DecodeDifferent::Encode(&[]),
},
FunctionMetadata {
@@ -2598,8 +2603,8 @@ mod tests {
},
FunctionArgumentMetadata {
name: DecodeDifferent::Encode("_data2"),
ty: DecodeDifferent::Encode("Compact<u32>")
}
ty: DecodeDifferent::Encode("Compact<u32>"),
},
]),
documentation: DecodeDifferent::Encode(&[]),
},
@@ -2611,7 +2616,7 @@ mod tests {
];
pub struct TraitImpl {}
impl Config for TraitImpl { }
impl Config for TraitImpl {}
type Test = Module<TraitImpl>;
@@ -2679,7 +2684,6 @@ mod tests {
}
}
impl system::Config for TraitImpl {
type Origin = OuterOrigin;
type AccountId = u32;
@@ -2760,9 +2764,9 @@ mod tests {
#[test]
fn on_runtime_upgrade_should_work() {
sp_io::TestExternalities::default().execute_with(||
sp_io::TestExternalities::default().execute_with(|| {
assert_eq!(<Module<TraitImpl> as OnRuntimeUpgrade>::on_runtime_upgrade(), 10)
);
});
}
#[test]
@@ -2788,7 +2792,10 @@ mod tests {
#[test]
fn get_call_names() {
let call_names = Call::<TraitImpl>::get_call_names();
assert_eq!(["aux_0", "aux_1", "aux_2", "aux_3", "aux_4", "aux_5", "operational"], call_names);
assert_eq!(
["aux_0", "aux_1", "aux_2", "aux_3", "aux_4", "aux_5", "operational"],
call_names
);
}
#[test]
+2 -2
View File
@@ -18,9 +18,9 @@
//! Macro for declaring a module error.
#[doc(hidden)]
pub use sp_runtime::traits::{LookupError, BadOrigin};
pub use frame_metadata::{DecodeDifferent, ErrorMetadata, ModuleErrorMetadata};
#[doc(hidden)]
pub use frame_metadata::{ModuleErrorMetadata, ErrorMetadata, DecodeDifferent};
pub use sp_runtime::traits::{BadOrigin, LookupError};
/// Declare an error type for a runtime module.
///
+29 -34
View File
@@ -21,7 +21,7 @@
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
pub use frame_metadata::{EventMetadata, DecodeDifferent, OuterEventMetadata, FnEncode};
pub use frame_metadata::{DecodeDifferent, EventMetadata, FnEncode, OuterEventMetadata};
/// Implement the `Event` for a module.
///
@@ -35,7 +35,7 @@ pub use frame_metadata::{EventMetadata, DecodeDifferent, OuterEventMetadata, FnE
/// }
/// );
///
///# fn main() {}
/// # fn main() {}
/// ```
///
/// # Generic Event Example:
@@ -75,7 +75,7 @@ pub use frame_metadata::{EventMetadata, DecodeDifferent, OuterEventMetadata, FnE
/// );
/// }
///
///# fn main() {}
/// # fn main() {}
/// ```
///
/// The syntax for generic events requires the `where`.
@@ -83,9 +83,9 @@ pub use frame_metadata::{EventMetadata, DecodeDifferent, OuterEventMetadata, FnE
/// # Generic Event with Instance Example:
///
/// ```rust
///# struct DefaultInstance;
///# trait Instance {}
///# impl Instance for DefaultInstance {}
/// # struct DefaultInstance;
/// # trait Instance {}
/// # impl Instance for DefaultInstance {}
/// trait Config<I: Instance=DefaultInstance> {
/// type Balance;
/// type Token;
@@ -100,7 +100,7 @@ pub use frame_metadata::{EventMetadata, DecodeDifferent, OuterEventMetadata, FnE
/// Message(Balance, Token),
/// }
/// );
///# fn main() {}
/// # fn main() {}
/// ```
#[macro_export]
macro_rules! decl_event {
@@ -337,8 +337,8 @@ macro_rules! __events_to_metadata {
#[allow(dead_code)]
mod tests {
use super::*;
use codec::{Decode, Encode};
use serde::Serialize;
use codec::{Encode, Decode};
mod system {
pub trait Config: 'static {
@@ -414,9 +414,10 @@ mod tests {
decl_event!(
/// Event with renamed generic parameter
pub enum Event<T> where
pub enum Event<T>
where
BalanceRenamed = <T as Config>::Balance,
OriginRenamed = <T as system::Config>::Origin
OriginRenamed = <T as system::Config>::Origin,
{
TestEvent(BalanceRenamed),
TestOrigin(OriginRenamed),
@@ -467,15 +468,13 @@ mod tests {
decl_event!(
/// Event finish formatting on an named one with trailing comma
pub enum Event<T> where
pub enum Event<T>
where
BalanceRenamed = <T as Config>::Balance,
OriginRenamed = <T as system::Config>::Origin,
{
TestEvent(BalanceRenamed, OriginRenamed),
TrailingCommaInArgs(
u32,
u32,
),
TrailingCommaInArgs(u32, u32),
}
);
}
@@ -505,26 +504,24 @@ mod tests {
fn event_metadata() {
assert_eq!(
system_renamed::Event::metadata(),
&[
EventMetadata {
name: DecodeDifferent::Encode("SystemEvent"),
arguments: DecodeDifferent::Encode(&[]),
documentation: DecodeDifferent::Encode(&[]),
},
]
&[EventMetadata {
name: DecodeDifferent::Encode("SystemEvent"),
arguments: DecodeDifferent::Encode(&[]),
documentation: DecodeDifferent::Encode(&[]),
},]
);
assert_eq!(
event_module::Event::<TestRuntime>::metadata(),
&[
EventMetadata {
name: DecodeDifferent::Encode("TestEvent"),
arguments: DecodeDifferent::Encode(&[ "Balance", "Origin" ]),
documentation: DecodeDifferent::Encode(&[ " Hi, I am a comment." ])
arguments: DecodeDifferent::Encode(&["Balance", "Origin"]),
documentation: DecodeDifferent::Encode(&[" Hi, I am a comment."])
},
EventMetadata {
name: DecodeDifferent::Encode("EventWithoutParams"),
arguments: DecodeDifferent::Encode(&[]),
documentation: DecodeDifferent::Encode(&[ " Dog" ]),
documentation: DecodeDifferent::Encode(&[" Dog"]),
},
]
);
@@ -533,25 +530,23 @@ mod tests {
&[
EventMetadata {
name: DecodeDifferent::Encode("TestEvent"),
arguments: DecodeDifferent::Encode(&[ "BalanceRenamed" ]),
arguments: DecodeDifferent::Encode(&["BalanceRenamed"]),
documentation: DecodeDifferent::Encode(&[])
},
EventMetadata {
name: DecodeDifferent::Encode("TestOrigin"),
arguments: DecodeDifferent::Encode(&[ "OriginRenamed" ]),
arguments: DecodeDifferent::Encode(&["OriginRenamed"]),
documentation: DecodeDifferent::Encode(&[]),
},
]
);
assert_eq!(
event_module3::Event::metadata(),
&[
EventMetadata {
name: DecodeDifferent::Encode("HiEvent"),
arguments: DecodeDifferent::Encode(&[]),
documentation: DecodeDifferent::Encode(&[])
}
],
&[EventMetadata {
name: DecodeDifferent::Encode("HiEvent"),
arguments: DecodeDifferent::Encode(&[]),
documentation: DecodeDifferent::Encode(&[])
}],
);
}
}
+6 -12
View File
@@ -18,8 +18,8 @@
//! Hash utilities.
use codec::{Codec, MaxEncodedLen};
use sp_io::hashing::{blake2_128, blake2_256, twox_128, twox_256, twox_64};
use sp_std::prelude::Vec;
use sp_io::hashing::{blake2_128, blake2_256, twox_64, twox_128, twox_256};
// This trait must be kept coherent with frame-support-procedural HasherKind usage
pub trait Hashable: Sized {
@@ -51,7 +51,9 @@ impl<T: Codec> Hashable for T {
fn twox_64_concat(&self) -> Vec<u8> {
self.using_encoded(Twox64Concat::hash)
}
fn identity(&self) -> Vec<u8> { self.encode() }
fn identity(&self) -> Vec<u8> {
self.encode()
}
}
/// Hasher to use to hash keys to insert to storage.
@@ -98,11 +100,7 @@ impl StorageHasher for Twox64Concat {
const METADATA: frame_metadata::StorageHasher = frame_metadata::StorageHasher::Twox64Concat;
type Output = Vec<u8>;
fn hash(x: &[u8]) -> Vec<u8> {
twox_64(x)
.iter()
.chain(x.into_iter())
.cloned()
.collect::<Vec<_>>()
twox_64(x).iter().chain(x.into_iter()).cloned().collect::<Vec<_>>()
}
fn max_len<K: MaxEncodedLen>() -> usize {
K::max_encoded_len().saturating_add(8)
@@ -124,11 +122,7 @@ impl StorageHasher for Blake2_128Concat {
const METADATA: frame_metadata::StorageHasher = frame_metadata::StorageHasher::Blake2_128Concat;
type Output = Vec<u8>;
fn hash(x: &[u8]) -> Vec<u8> {
blake2_128(x)
.iter()
.chain(x.into_iter())
.cloned()
.collect::<Vec<_>>()
blake2_128(x).iter().chain(x.into_iter()).cloned().collect::<Vec<_>>()
}
fn max_len<K: MaxEncodedLen>() -> usize {
K::max_encoded_len().saturating_add(16)
+6 -4
View File
@@ -15,13 +15,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#[doc(hidden)]
pub use crate::sp_std::vec::Vec;
#[doc(hidden)]
pub use crate::sp_runtime::traits::{Block as BlockT, Extrinsic};
#[doc(hidden)]
pub use crate::sp_std::vec::Vec;
pub use sp_inherents::{
InherentData, CheckInherentsResult, IsFatalError, InherentIdentifier, MakeFatalError,
CheckInherentsResult, InherentData, InherentIdentifier, IsFatalError, MakeFatalError,
};
/// A pallet that provides or verifies an inherent extrinsic.
@@ -53,7 +53,9 @@ pub trait ProvideInherent {
/// one inherent for which:
/// * type is [`Self::Call`],
/// * [`Self::is_inherent`] returns true.
fn is_inherent_required(_: &InherentData) -> Result<Option<Self::Error>, Self::Error> { Ok(None) }
fn is_inherent_required(_: &InherentData) -> Result<Option<Self::Error>, Self::Error> {
Ok(None)
}
/// Check whether the given inherent is valid. Checking the inherent is optional and can be
/// omitted by using the default implementation.
+222 -203
View File
@@ -25,42 +25,42 @@ extern crate self as frame_support;
#[doc(hidden)]
pub use sp_tracing;
#[cfg(feature = "std")]
pub use serde;
pub use sp_core::Void;
#[doc(hidden)]
pub use sp_std;
#[doc(hidden)]
pub use codec;
#[doc(hidden)]
pub use frame_metadata as metadata;
#[doc(hidden)]
pub use log;
#[cfg(feature = "std")]
#[doc(hidden)]
pub use once_cell;
#[doc(hidden)]
pub use paste;
#[cfg(feature = "std")]
pub use serde;
pub use sp_core::Void;
#[doc(hidden)]
pub use sp_io::{self, storage::root as storage_root};
#[doc(hidden)]
pub use sp_runtime::RuntimeDebug;
#[cfg(feature = "std")]
#[doc(hidden)]
pub use sp_state_machine::BasicExternalities;
#[doc(hidden)]
pub use sp_io::{storage::root as storage_root, self};
#[doc(hidden)]
pub use sp_runtime::RuntimeDebug;
#[doc(hidden)]
pub use log;
#[doc(hidden)]
pub use frame_metadata as metadata;
pub use sp_std;
#[macro_use]
pub mod dispatch;
pub mod storage;
mod hash;
pub mod storage;
#[macro_use]
pub mod event;
pub mod inherent;
#[macro_use]
pub mod error;
pub mod instances;
pub mod traits;
pub mod weights;
pub mod instances;
#[doc(hidden)]
pub mod unsigned {
@@ -68,23 +68,27 @@ pub mod unsigned {
pub use crate::sp_runtime::traits::ValidateUnsigned;
#[doc(hidden)]
pub use crate::sp_runtime::transaction_validity::{
TransactionValidity, UnknownTransaction, TransactionValidityError, TransactionSource,
TransactionSource, TransactionValidity, TransactionValidityError, UnknownTransaction,
};
}
pub use self::hash::{
Twox256, Twox128, Blake2_256, Blake2_128, Identity, Twox64Concat, Blake2_128Concat, Hashable,
StorageHasher, ReversibleStorageHasher
pub use self::{
dispatch::{Callable, Parameter},
hash::{
Blake2_128, Blake2_128Concat, Blake2_256, Hashable, Identity, ReversibleStorageHasher,
StorageHasher, Twox128, Twox256, Twox64Concat,
},
storage::{
bounded_vec::{BoundedSlice, BoundedVec},
migration,
weak_bounded_vec::WeakBoundedVec,
IterableStorageDoubleMap, IterableStorageMap, IterableStorageNMap, StorageDoubleMap,
StorageMap, StorageNMap, StoragePrefixedMap, StorageValue,
},
};
pub use self::storage::{
StorageValue, StorageMap, StorageDoubleMap, StorageNMap, StoragePrefixedMap,
IterableStorageMap, IterableStorageDoubleMap, IterableStorageNMap, migration,
bounded_vec::{BoundedVec, BoundedSlice}, weak_bounded_vec::WeakBoundedVec,
};
pub use self::dispatch::{Parameter, Callable};
pub use sp_runtime::{self, ConsensusEngineId, print, traits::Printable};
pub use sp_runtime::{self, print, traits::Printable, ConsensusEngineId};
use codec::{Encode, Decode};
use codec::{Decode, Encode};
use sp_runtime::TypeId;
/// A unified log target for support operations.
@@ -108,14 +112,14 @@ impl TypeId for PalletId {
///
/// Useful for creating a *storage-like* struct for test and migrations.
///
///```
/// ```
/// # use frame_support::generate_storage_alias;
/// use frame_support::codec;
/// use frame_support::Twox64Concat;
/// // generate a storage value with type u32.
/// generate_storage_alias!(Prefix, StorageName => Value<u32>);
///
/// // generate a double map from `(u32, u32)` (with hashers `Twox64Concat` for each key)
/// // generate a double map from `(u32, u32)` (with hashers `Twox64Concat` for each key)
/// // to `Vec<u8>`
/// generate_storage_alias!(
/// OtherPrefix, OtherStorageName => DoubleMap<
@@ -534,7 +538,7 @@ pub fn debug(data: &impl sp_std::fmt::Debug) {
#[doc(inline)]
pub use frame_support_procedural::{
decl_storage, construct_runtime, transactional, RuntimeDebugNoBound,
construct_runtime, decl_storage, transactional, RuntimeDebugNoBound,
};
#[doc(hidden)]
@@ -546,14 +550,14 @@ pub use frame_support_procedural::__generate_dummy_part_checker;
/// ```
/// # use frame_support::CloneNoBound;
/// trait Config {
/// type C: Clone;
/// type C: Clone;
/// }
///
/// // Foo implements [`Clone`] because `C` bounds [`Clone`].
/// // Otherwise compilation will fail with an output telling `c` doesn't implement [`Clone`].
/// #[derive(CloneNoBound)]
/// struct Foo<T: Config> {
/// c: T::C,
/// c: T::C,
/// }
/// ```
pub use frame_support_procedural::CloneNoBound;
@@ -564,14 +568,14 @@ pub use frame_support_procedural::CloneNoBound;
/// ```
/// # use frame_support::{EqNoBound, PartialEqNoBound};
/// trait Config {
/// type C: Eq;
/// type C: Eq;
/// }
///
/// // Foo implements [`Eq`] because `C` bounds [`Eq`].
/// // Otherwise compilation will fail with an output telling `c` doesn't implement [`Eq`].
/// #[derive(PartialEqNoBound, EqNoBound)]
/// struct Foo<T: Config> {
/// c: T::C,
/// c: T::C,
/// }
/// ```
pub use frame_support_procedural::EqNoBound;
@@ -582,14 +586,14 @@ pub use frame_support_procedural::EqNoBound;
/// ```
/// # use frame_support::PartialEqNoBound;
/// trait Config {
/// type C: PartialEq;
/// type C: PartialEq;
/// }
///
/// // Foo implements [`PartialEq`] because `C` bounds [`PartialEq`].
/// // Otherwise compilation will fail with an output telling `c` doesn't implement [`PartialEq`].
/// #[derive(PartialEqNoBound)]
/// struct Foo<T: Config> {
/// c: T::C,
/// c: T::C,
/// }
/// ```
pub use frame_support_procedural::PartialEqNoBound;
@@ -601,14 +605,14 @@ pub use frame_support_procedural::PartialEqNoBound;
/// # use frame_support::DebugNoBound;
/// # use core::fmt::Debug;
/// trait Config {
/// type C: Debug;
/// type C: Debug;
/// }
///
/// // Foo implements [`Debug`] because `C` bounds [`Debug`].
/// // Otherwise compilation will fail with an output telling `c` doesn't implement [`Debug`].
/// #[derive(DebugNoBound)]
/// struct Foo<T: Config> {
/// c: T::C,
/// c: T::C,
/// }
/// ```
pub use frame_support_procedural::DebugNoBound;
@@ -620,14 +624,14 @@ pub use frame_support_procedural::DebugNoBound;
/// # use frame_support::DefaultNoBound;
/// # use core::default::Default;
/// trait Config {
/// type C: Default;
/// type C: Default;
/// }
///
/// // Foo implements [`Default`] because `C` bounds [`Default`].
/// // Otherwise compilation will fail with an output telling `c` doesn't implement [`Default`].
/// #[derive(DefaultNoBound)]
/// struct Foo<T: Config> {
/// c: T::C,
/// c: T::C,
/// }
/// ```
pub use frame_support_procedural::DefaultNoBound;
@@ -684,8 +688,8 @@ pub use frame_support_procedural::crate_to_pallet_version;
#[macro_export]
macro_rules! fail {
( $y:expr ) => {{
return Err($y.into());
}}
return Err($y.into())
}};
}
/// Evaluate `$x:expr` and if not true return `Err($y:expr)`.
@@ -697,7 +701,7 @@ macro_rules! ensure {
if !$x {
$crate::fail!($y);
}
}}
}};
}
/// Evaluate an expression, assert it returns an expected `Err` value and that
@@ -713,7 +717,7 @@ macro_rules! assert_noop {
let h = $crate::storage_root();
$crate::assert_err!($x, $y);
assert_eq!(h, $crate::storage_root());
}
};
}
/// Evaluate any expression and assert that runtime storage has not been mutated
@@ -728,7 +732,7 @@ macro_rules! assert_storage_noop {
let h = $crate::storage_root();
$x;
assert_eq!(h, $crate::storage_root());
}
};
}
/// Assert an expression returns an error specified.
@@ -738,7 +742,7 @@ macro_rules! assert_storage_noop {
macro_rules! assert_err {
( $x:expr , $y:expr $(,)? ) => {
assert_eq!($x, Err($y.into()));
}
};
}
/// Assert an expression returns an error specified.
@@ -749,7 +753,7 @@ macro_rules! assert_err {
macro_rules! assert_err_ignore_postinfo {
( $x:expr , $y:expr $(,)? ) => {
$crate::assert_err!($x.map(|_| ()).map_err(|e| e.error), $y);
}
};
}
/// Assert an expression returns error with the given weight.
@@ -762,7 +766,7 @@ macro_rules! assert_err_with_weight {
} else {
panic!("expected Err(_), got Ok(_).")
}
}
};
}
/// Panic if an expression doesn't evaluate to `Ok`.
@@ -780,23 +784,23 @@ macro_rules! assert_ok {
};
( $x:expr, $y:expr $(,)? ) => {
assert_eq!($x, Ok($y));
}
};
}
#[cfg(feature = "std")]
#[doc(hidden)]
pub use serde::{Serialize, Deserialize};
pub use serde::{Deserialize, Serialize};
#[cfg(test)]
pub mod tests {
use super::*;
use codec::{Codec, EncodeLike};
use frame_metadata::{
DecodeDifferent, StorageEntryMetadata, StorageMetadata, StorageEntryType,
StorageEntryModifier, DefaultByteGetter, StorageHasher,
DecodeDifferent, DefaultByteGetter, StorageEntryMetadata, StorageEntryModifier,
StorageEntryType, StorageHasher, StorageMetadata,
};
use sp_std::{marker::PhantomData, result};
use sp_io::TestExternalities;
use sp_std::{marker::PhantomData, result};
/// A PalletInfo implementation which just panics.
pub struct PanicPalletInfo;
@@ -864,7 +868,9 @@ pub mod tests {
type Map = Data;
trait Sorted { fn sorted(self) -> Self; }
trait Sorted {
fn sorted(self) -> Self;
}
impl<T: Ord> Sorted for Vec<T> {
fn sorted(mut self) -> Self {
self.sort();
@@ -918,13 +924,15 @@ pub mod tests {
DataDM::insert(1, 0, 2);
DataDM::insert(1, 1, 3);
let get_all = || vec![
DataDM::get(0, 1),
DataDM::get(1, 0),
DataDM::get(1, 1),
DataDM::get(2, 0),
DataDM::get(2, 1),
];
let get_all = || {
vec![
DataDM::get(0, 1),
DataDM::get(1, 0),
DataDM::get(1, 1),
DataDM::get(2, 0),
DataDM::get(2, 1),
]
};
assert_eq!(get_all(), vec![1, 2, 3, 0, 0]);
// Two existing
@@ -990,15 +998,24 @@ pub mod tests {
Map::mutate(&key, |val| {
*val = 15;
});
assert_eq!(Map::iter().collect::<Vec<_>>().sorted(), vec![(key - 2, 42), (key - 1, 43), (key, 15)]);
assert_eq!(
Map::iter().collect::<Vec<_>>().sorted(),
vec![(key - 2, 42), (key - 1, 43), (key, 15)]
);
Map::mutate(&key, |val| {
*val = 17;
});
assert_eq!(Map::iter().collect::<Vec<_>>().sorted(), vec![(key - 2, 42), (key - 1, 43), (key, 17)]);
assert_eq!(
Map::iter().collect::<Vec<_>>().sorted(),
vec![(key - 2, 42), (key - 1, 43), (key, 17)]
);
// remove first
Map::remove(&key);
assert_eq!(Map::iter().collect::<Vec<_>>().sorted(), vec![(key - 2, 42), (key - 1, 43)]);
assert_eq!(
Map::iter().collect::<Vec<_>>().sorted(),
vec![(key - 2, 42), (key - 1, 43)]
);
// remove last from the list
Map::remove(&(key - 2));
@@ -1049,7 +1066,6 @@ pub mod tests {
assert_eq!(DoubleMap::get(&key1, &(key2 + 1)), 0u64);
assert_eq!(DoubleMap::get(&(key1 + 1), &key2), 4u64);
assert_eq!(DoubleMap::get(&(key1 + 1), &(key2 + 1)), 4u64);
});
}
@@ -1100,10 +1116,13 @@ pub mod tests {
assert_eq!(DoubleMap::get(&key1, key2), 1);
// no-op if `Err`
assert_noop!(DoubleMap::try_mutate_exists(key1, key2, |v| -> TestResult {
*v = Some(2);
Err("nah")
}), "nah");
assert_noop!(
DoubleMap::try_mutate_exists(key1, key2, |v| -> TestResult {
*v = Some(2);
Err("nah")
}),
"nah"
);
// removed if mutated to`None`
assert_ok!(DoubleMap::try_mutate_exists(key1, key2, |v| -> TestResult {
@@ -1116,126 +1135,124 @@ pub mod tests {
const EXPECTED_METADATA: StorageMetadata = StorageMetadata {
prefix: DecodeDifferent::Encode("Test"),
entries: DecodeDifferent::Encode(
&[
StorageEntryMetadata {
name: DecodeDifferent::Encode("Data"),
modifier: StorageEntryModifier::Default,
ty: StorageEntryType::Map{
hasher: StorageHasher::Twox64Concat,
key: DecodeDifferent::Encode("u32"),
value: DecodeDifferent::Encode("u64"),
unused: false,
},
default: DecodeDifferent::Encode(
DefaultByteGetter(&__GetByteStructData(PhantomData::<Test>))
),
documentation: DecodeDifferent::Encode(&[]),
entries: DecodeDifferent::Encode(&[
StorageEntryMetadata {
name: DecodeDifferent::Encode("Data"),
modifier: StorageEntryModifier::Default,
ty: StorageEntryType::Map {
hasher: StorageHasher::Twox64Concat,
key: DecodeDifferent::Encode("u32"),
value: DecodeDifferent::Encode("u64"),
unused: false,
},
StorageEntryMetadata {
name: DecodeDifferent::Encode("OptionLinkedMap"),
modifier: StorageEntryModifier::Optional,
ty: StorageEntryType::Map {
hasher: StorageHasher::Blake2_128Concat,
key: DecodeDifferent::Encode("u32"),
value: DecodeDifferent::Encode("u32"),
unused: false,
},
default: DecodeDifferent::Encode(
DefaultByteGetter(&__GetByteStructOptionLinkedMap(PhantomData::<Test>))
),
documentation: DecodeDifferent::Encode(&[]),
default: DecodeDifferent::Encode(DefaultByteGetter(&__GetByteStructData(
PhantomData::<Test>,
))),
documentation: DecodeDifferent::Encode(&[]),
},
StorageEntryMetadata {
name: DecodeDifferent::Encode("OptionLinkedMap"),
modifier: StorageEntryModifier::Optional,
ty: StorageEntryType::Map {
hasher: StorageHasher::Blake2_128Concat,
key: DecodeDifferent::Encode("u32"),
value: DecodeDifferent::Encode("u32"),
unused: false,
},
StorageEntryMetadata {
name: DecodeDifferent::Encode("GenericData"),
modifier: StorageEntryModifier::Default,
ty: StorageEntryType::Map{
hasher: StorageHasher::Identity,
key: DecodeDifferent::Encode("T::BlockNumber"),
value: DecodeDifferent::Encode("T::BlockNumber"),
unused: false
},
default: DecodeDifferent::Encode(
DefaultByteGetter(&__GetByteStructGenericData(PhantomData::<Test>))
),
documentation: DecodeDifferent::Encode(&[]),
default: DecodeDifferent::Encode(DefaultByteGetter(
&__GetByteStructOptionLinkedMap(PhantomData::<Test>),
)),
documentation: DecodeDifferent::Encode(&[]),
},
StorageEntryMetadata {
name: DecodeDifferent::Encode("GenericData"),
modifier: StorageEntryModifier::Default,
ty: StorageEntryType::Map {
hasher: StorageHasher::Identity,
key: DecodeDifferent::Encode("T::BlockNumber"),
value: DecodeDifferent::Encode("T::BlockNumber"),
unused: false,
},
StorageEntryMetadata {
name: DecodeDifferent::Encode("GenericData2"),
modifier: StorageEntryModifier::Optional,
ty: StorageEntryType::Map{
hasher: StorageHasher::Blake2_128Concat,
key: DecodeDifferent::Encode("T::BlockNumber"),
value: DecodeDifferent::Encode("T::BlockNumber"),
unused: false
},
default: DecodeDifferent::Encode(
DefaultByteGetter(&__GetByteStructGenericData2(PhantomData::<Test>))
),
documentation: DecodeDifferent::Encode(&[]),
default: DecodeDifferent::Encode(DefaultByteGetter(&__GetByteStructGenericData(
PhantomData::<Test>,
))),
documentation: DecodeDifferent::Encode(&[]),
},
StorageEntryMetadata {
name: DecodeDifferent::Encode("GenericData2"),
modifier: StorageEntryModifier::Optional,
ty: StorageEntryType::Map {
hasher: StorageHasher::Blake2_128Concat,
key: DecodeDifferent::Encode("T::BlockNumber"),
value: DecodeDifferent::Encode("T::BlockNumber"),
unused: false,
},
StorageEntryMetadata {
name: DecodeDifferent::Encode("DataDM"),
modifier: StorageEntryModifier::Default,
ty: StorageEntryType::DoubleMap{
hasher: StorageHasher::Twox64Concat,
key1: DecodeDifferent::Encode("u32"),
key2: DecodeDifferent::Encode("u32"),
value: DecodeDifferent::Encode("u64"),
key2_hasher: StorageHasher::Blake2_128Concat,
},
default: DecodeDifferent::Encode(
DefaultByteGetter(&__GetByteStructDataDM(PhantomData::<Test>))
),
documentation: DecodeDifferent::Encode(&[]),
default: DecodeDifferent::Encode(DefaultByteGetter(&__GetByteStructGenericData2(
PhantomData::<Test>,
))),
documentation: DecodeDifferent::Encode(&[]),
},
StorageEntryMetadata {
name: DecodeDifferent::Encode("DataDM"),
modifier: StorageEntryModifier::Default,
ty: StorageEntryType::DoubleMap {
hasher: StorageHasher::Twox64Concat,
key1: DecodeDifferent::Encode("u32"),
key2: DecodeDifferent::Encode("u32"),
value: DecodeDifferent::Encode("u64"),
key2_hasher: StorageHasher::Blake2_128Concat,
},
StorageEntryMetadata {
name: DecodeDifferent::Encode("GenericDataDM"),
modifier: StorageEntryModifier::Default,
ty: StorageEntryType::DoubleMap{
hasher: StorageHasher::Blake2_128Concat,
key1: DecodeDifferent::Encode("T::BlockNumber"),
key2: DecodeDifferent::Encode("T::BlockNumber"),
value: DecodeDifferent::Encode("T::BlockNumber"),
key2_hasher: StorageHasher::Identity,
},
default: DecodeDifferent::Encode(
DefaultByteGetter(&__GetByteStructGenericDataDM(PhantomData::<Test>))
),
documentation: DecodeDifferent::Encode(&[]),
default: DecodeDifferent::Encode(DefaultByteGetter(&__GetByteStructDataDM(
PhantomData::<Test>,
))),
documentation: DecodeDifferent::Encode(&[]),
},
StorageEntryMetadata {
name: DecodeDifferent::Encode("GenericDataDM"),
modifier: StorageEntryModifier::Default,
ty: StorageEntryType::DoubleMap {
hasher: StorageHasher::Blake2_128Concat,
key1: DecodeDifferent::Encode("T::BlockNumber"),
key2: DecodeDifferent::Encode("T::BlockNumber"),
value: DecodeDifferent::Encode("T::BlockNumber"),
key2_hasher: StorageHasher::Identity,
},
StorageEntryMetadata {
name: DecodeDifferent::Encode("GenericData2DM"),
modifier: StorageEntryModifier::Optional,
ty: StorageEntryType::DoubleMap{
hasher: StorageHasher::Blake2_128Concat,
key1: DecodeDifferent::Encode("T::BlockNumber"),
key2: DecodeDifferent::Encode("T::BlockNumber"),
value: DecodeDifferent::Encode("T::BlockNumber"),
key2_hasher: StorageHasher::Twox64Concat,
},
default: DecodeDifferent::Encode(
DefaultByteGetter(&__GetByteStructGenericData2DM(PhantomData::<Test>))
),
documentation: DecodeDifferent::Encode(&[]),
default: DecodeDifferent::Encode(DefaultByteGetter(&__GetByteStructGenericDataDM(
PhantomData::<Test>,
))),
documentation: DecodeDifferent::Encode(&[]),
},
StorageEntryMetadata {
name: DecodeDifferent::Encode("GenericData2DM"),
modifier: StorageEntryModifier::Optional,
ty: StorageEntryType::DoubleMap {
hasher: StorageHasher::Blake2_128Concat,
key1: DecodeDifferent::Encode("T::BlockNumber"),
key2: DecodeDifferent::Encode("T::BlockNumber"),
value: DecodeDifferent::Encode("T::BlockNumber"),
key2_hasher: StorageHasher::Twox64Concat,
},
StorageEntryMetadata {
name: DecodeDifferent::Encode("AppendableDM"),
modifier: StorageEntryModifier::Default,
ty: StorageEntryType::DoubleMap{
hasher: StorageHasher::Blake2_128Concat,
key1: DecodeDifferent::Encode("u32"),
key2: DecodeDifferent::Encode("T::BlockNumber"),
value: DecodeDifferent::Encode("Vec<u32>"),
key2_hasher: StorageHasher::Blake2_128Concat,
},
default: DecodeDifferent::Encode(
DefaultByteGetter(&__GetByteStructGenericData2DM(PhantomData::<Test>))
),
documentation: DecodeDifferent::Encode(&[]),
default: DecodeDifferent::Encode(DefaultByteGetter(
&__GetByteStructGenericData2DM(PhantomData::<Test>),
)),
documentation: DecodeDifferent::Encode(&[]),
},
StorageEntryMetadata {
name: DecodeDifferent::Encode("AppendableDM"),
modifier: StorageEntryModifier::Default,
ty: StorageEntryType::DoubleMap {
hasher: StorageHasher::Blake2_128Concat,
key1: DecodeDifferent::Encode("u32"),
key2: DecodeDifferent::Encode("T::BlockNumber"),
value: DecodeDifferent::Encode("Vec<u32>"),
key2_hasher: StorageHasher::Blake2_128Concat,
},
]
),
default: DecodeDifferent::Encode(DefaultByteGetter(
&__GetByteStructGenericData2DM(PhantomData::<Test>),
)),
documentation: DecodeDifferent::Encode(&[]),
},
]),
};
#[test]
@@ -1269,35 +1286,38 @@ pub mod tests {
/// Prelude to be used alongside pallet macro, for ease of use.
pub mod pallet_prelude {
pub use sp_std::marker::PhantomData;
#[cfg(feature = "std")]
pub use crate::traits::GenesisBuild;
pub use crate::{
EqNoBound, PartialEqNoBound, RuntimeDebugNoBound, DebugNoBound, CloneNoBound, Twox256,
Twox128, Blake2_256, Blake2_128, Identity, Twox64Concat, Blake2_128Concat, ensure,
RuntimeDebug, storage,
dispatch::{DispatchError, DispatchResult, DispatchResultWithPostInfo, Parameter},
ensure,
inherent::{InherentData, InherentIdentifier, ProvideInherent},
storage,
storage::{
bounded_vec::BoundedVec,
types::{
Key as NMapKey, OptionQuery, StorageDoubleMap, StorageMap, StorageNMap,
StorageValue, ValueQuery,
},
},
traits::{
Get, Hooks, IsType, GetPalletVersion, EnsureOrigin, PalletInfoAccess, StorageInfoTrait,
ConstU32, GetDefault,
ConstU32, EnsureOrigin, Get, GetDefault, GetPalletVersion, Hooks, IsType,
PalletInfoAccess, StorageInfoTrait,
},
dispatch::{DispatchResultWithPostInfo, Parameter, DispatchError, DispatchResult},
weights::{DispatchClass, Pays, Weight},
storage::types::{
Key as NMapKey, StorageDoubleMap, StorageMap, StorageNMap, StorageValue, ValueQuery,
OptionQuery,
},
storage::bounded_vec::BoundedVec,
Blake2_128, Blake2_128Concat, Blake2_256, CloneNoBound, DebugNoBound, EqNoBound, Identity,
PartialEqNoBound, RuntimeDebug, RuntimeDebugNoBound, Twox128, Twox256, Twox64Concat,
};
pub use codec::{Encode, Decode, MaxEncodedLen};
pub use crate::inherent::{InherentData, InherentIdentifier, ProvideInherent};
pub use codec::{Decode, Encode, MaxEncodedLen};
pub use sp_runtime::{
traits::{MaybeSerializeDeserialize, Member, ValidateUnsigned},
transaction_validity::{
TransactionSource, TransactionValidity, ValidTransaction, TransactionPriority,
TransactionTag, TransactionLongevity, TransactionValidityError, InvalidTransaction,
UnknownTransaction,
InvalidTransaction, TransactionLongevity, TransactionPriority, TransactionSource,
TransactionTag, TransactionValidity, TransactionValidityError, UnknownTransaction,
ValidTransaction,
},
};
pub use sp_std::marker::PhantomData;
}
/// `pallet` attribute macro allows to define a pallet to be used in `construct_runtime!`.
@@ -1321,9 +1341,9 @@ pub mod pallet_prelude {
/// ```ignore
/// #[pallet]
/// pub mod pallet {
/// use frame_support::pallet_prelude::*;
/// use frame_system::pallet_prelude::*;
/// ...
/// use frame_support::pallet_prelude::*;
/// use frame_system::pallet_prelude::*;
/// ...
/// }
/// ```
///
@@ -1350,8 +1370,8 @@ pub mod pallet_prelude {
/// ```ignore
/// #[pallet::config]
/// pub trait Config: frame_system::Config {
/// #[pallet::constant]
/// type Foo: Get<u32>;
/// #[pallet::constant]
/// type Foo: Get<u32>;
/// }
/// ```
///
@@ -2378,5 +2398,4 @@ pub mod pallet_prelude {
/// }
/// ```
/// * use the newest nightly possible.
///
pub use frame_support_procedural::pallet;
@@ -17,15 +17,12 @@
//! Traits, types and structs to support a bounded BTreeMap.
use crate::{storage::StorageDecodeLength, traits::Get};
use codec::{Decode, Encode, MaxEncodedLen};
use sp_std::{
borrow::Borrow, collections::btree_map::BTreeMap, convert::TryFrom, fmt, marker::PhantomData,
ops::Deref,
};
use crate::{
storage::StorageDecodeLength,
traits::Get,
};
use codec::{Encode, Decode, MaxEncodedLen};
/// A bounded map based on a B-Tree.
///
@@ -46,7 +43,7 @@ where
fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
let inner = BTreeMap::<K, V>::decode(input)?;
if inner.len() > S::get() as usize {
return Err("BoundedBTreeMap exceeds its limit".into());
return Err("BoundedBTreeMap exceeds its limit".into())
}
Ok(Self(inner, PhantomData))
}
@@ -280,7 +277,9 @@ where
type Error = ();
fn try_from(value: BTreeMap<K, V>) -> Result<Self, Self::Error> {
(value.len() <= Self::bound()).then(move || BoundedBTreeMap(value, PhantomData)).ok_or(())
(value.len() <= Self::bound())
.then(move || BoundedBTreeMap(value, PhantomData))
.ok_or(())
}
}
@@ -303,9 +302,9 @@ impl<K, V, S> codec::EncodeLike<BTreeMap<K, V>> for BoundedBTreeMap<K, V, S> whe
#[cfg(test)]
pub mod test {
use super::*;
use crate::Twox128;
use sp_io::TestExternalities;
use sp_std::convert::TryInto;
use crate::Twox128;
crate::parameter_types! {
pub const Seven: u32 = 7;
@@ -17,15 +17,12 @@
//! Traits, types and structs to support a bounded `BTreeSet`.
use crate::{storage::StorageDecodeLength, traits::Get};
use codec::{Decode, Encode, MaxEncodedLen};
use sp_std::{
borrow::Borrow, collections::btree_set::BTreeSet, convert::TryFrom, fmt, marker::PhantomData,
ops::Deref,
};
use crate::{
storage::StorageDecodeLength,
traits::Get,
};
use codec::{Encode, Decode, MaxEncodedLen};
/// A bounded set based on a B-Tree.
///
@@ -45,7 +42,7 @@ where
fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
let inner = BTreeSet::<T>::decode(input)?;
if inner.len() > S::get() as usize {
return Err("BoundedBTreeSet exceeds its limit".into());
return Err("BoundedBTreeSet exceeds its limit".into())
}
Ok(Self(inner, PhantomData))
}
@@ -266,7 +263,9 @@ where
type Error = ();
fn try_from(value: BTreeSet<T>) -> Result<Self, Self::Error> {
(value.len() <= Self::bound()).then(move || BoundedBTreeSet(value, PhantomData)).ok_or(())
(value.len() <= Self::bound())
.then(move || BoundedBTreeSet(value, PhantomData))
.ok_or(())
}
}
@@ -281,16 +280,14 @@ impl<T, S> codec::DecodeLength for BoundedBTreeSet<T, S> {
impl<T, S> StorageDecodeLength for BoundedBTreeSet<T, S> {}
impl<T, S> codec::EncodeLike<BTreeSet<T>> for BoundedBTreeSet<T, S> where
BTreeSet<T>: Encode
{}
impl<T, S> codec::EncodeLike<BTreeSet<T>> for BoundedBTreeSet<T, S> where BTreeSet<T>: Encode {}
#[cfg(test)]
pub mod test {
use super::*;
use crate::Twox128;
use sp_io::TestExternalities;
use sp_std::convert::TryInto;
use crate::Twox128;
crate::parameter_types! {
pub const Seven: u32 = 7;
@@ -18,17 +18,16 @@
//! Traits, types and structs to support putting a bounded vector into storage, as a raw value, map
//! or a double map.
use sp_std::prelude::*;
use sp_std::{convert::TryFrom, fmt, marker::PhantomData};
use codec::{Encode, Decode, EncodeLike, MaxEncodedLen};
use crate::{
storage::{StorageDecodeLength, StorageTryAppend},
traits::Get,
};
use codec::{Decode, Encode, EncodeLike, MaxEncodedLen};
use core::{
ops::{Deref, Index, IndexMut},
slice::SliceIndex,
};
use crate::{
traits::Get,
storage::{StorageDecodeLength, StorageTryAppend},
};
use sp_std::{convert::TryFrom, fmt, marker::PhantomData, prelude::*};
/// A bounded vector.
///
@@ -71,7 +70,7 @@ impl<T: Decode, S: Get<u32>> Decode for BoundedVec<T, S> {
fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
let inner = Vec::<T>::decode(input)?;
if inner.len() > S::get() as usize {
return Err("BoundedVec exceeds its limit".into());
return Err("BoundedVec exceeds its limit".into())
}
Ok(Self(inner, PhantomData))
}
@@ -341,9 +340,9 @@ where
#[cfg(test)]
pub mod test {
use super::*;
use crate::Twox128;
use sp_io::TestExternalities;
use sp_std::convert::TryInto;
use crate::Twox128;
crate::parameter_types! {
pub const Seven: u32 = 7;
+33 -104
View File
@@ -21,23 +21,17 @@
// NOTE: could replace unhashed by having only one kind of storage (top trie being the child info
// of null length parent storage key).
use crate::sp_std::prelude::*;
use codec::{Codec, Encode, Decode};
pub use sp_core::storage::{ChildInfo, ChildType};
pub use crate::sp_io::KillStorageResult;
use crate::sp_std::prelude::*;
use codec::{Codec, Decode, Encode};
pub use sp_core::storage::{ChildInfo, ChildType};
/// Return the value of the item in storage under `key`, or `None` if there is no explicit entry.
pub fn get<T: Decode + Sized>(
child_info: &ChildInfo,
key: &[u8],
) -> Option<T> {
pub fn get<T: Decode + Sized>(child_info: &ChildInfo, key: &[u8]) -> Option<T> {
match child_info.child_type() {
ChildType::ParentKeyId => {
let storage_key = child_info.storage_key();
sp_io::default_child_storage::get(
storage_key,
key,
).and_then(|v| {
sp_io::default_child_storage::get(storage_key, key).and_then(|v| {
Decode::decode(&mut &v[..]).map(Some).unwrap_or_else(|_| {
// TODO #3700: error should be handleable.
crate::runtime_print!(
@@ -54,20 +48,13 @@ pub fn get<T: Decode + Sized>(
/// Return the value of the item in storage under `key`, or the type's default if there is no
/// explicit entry.
pub fn get_or_default<T: Decode + Sized + Default>(
child_info: &ChildInfo,
key: &[u8],
) -> T {
pub fn get_or_default<T: Decode + Sized + Default>(child_info: &ChildInfo, key: &[u8]) -> T {
get(child_info, key).unwrap_or_else(Default::default)
}
/// Return the value of the item in storage under `key`, or `default_value` if there is no
/// explicit entry.
pub fn get_or<T: Decode + Sized>(
child_info: &ChildInfo,
key: &[u8],
default_value: T,
) -> T {
pub fn get_or<T: Decode + Sized>(child_info: &ChildInfo, key: &[u8], default_value: T) -> T {
get(child_info, key).unwrap_or(default_value)
}
@@ -82,27 +69,16 @@ pub fn get_or_else<T: Decode + Sized, F: FnOnce() -> T>(
}
/// Put `value` in storage under `key`.
pub fn put<T: Encode>(
child_info: &ChildInfo,
key: &[u8],
value: &T,
) {
pub fn put<T: Encode>(child_info: &ChildInfo, key: &[u8], value: &T) {
match child_info.child_type() {
ChildType::ParentKeyId => value.using_encoded(|slice|
sp_io::default_child_storage::set(
child_info.storage_key(),
key,
slice,
)
),
ChildType::ParentKeyId => value.using_encoded(|slice| {
sp_io::default_child_storage::set(child_info.storage_key(), key, slice)
}),
}
}
/// Remove `key` from storage, returning its value if it had an explicit entry or `None` otherwise.
pub fn take<T: Decode + Sized>(
child_info: &ChildInfo,
key: &[u8],
) -> Option<T> {
pub fn take<T: Decode + Sized>(child_info: &ChildInfo, key: &[u8]) -> Option<T> {
let r = get(child_info, key);
if r.is_some() {
kill(child_info, key);
@@ -112,20 +88,13 @@ pub fn take<T: Decode + Sized>(
/// Remove `key` from storage, returning its value, or, if there was no explicit entry in storage,
/// the default for its type.
pub fn take_or_default<T: Codec + Sized + Default>(
child_info: &ChildInfo,
key: &[u8],
) -> T {
pub fn take_or_default<T: Codec + Sized + Default>(child_info: &ChildInfo, key: &[u8]) -> T {
take(child_info, key).unwrap_or_else(Default::default)
}
/// Return the value of the item in storage under `key`, or `default_value` if there is no
/// explicit entry. Ensure there is no explicit entry on return.
pub fn take_or<T: Codec + Sized>(
child_info: &ChildInfo,
key: &[u8],
default_value: T,
) -> T {
pub fn take_or<T: Codec + Sized>(child_info: &ChildInfo, key: &[u8], default_value: T) -> T {
take(child_info, key).unwrap_or(default_value)
}
@@ -140,15 +109,11 @@ pub fn take_or_else<T: Codec + Sized, F: FnOnce() -> T>(
}
/// Check to see if `key` has an explicit entry in storage.
pub fn exists(
child_info: &ChildInfo,
key: &[u8],
) -> bool {
pub fn exists(child_info: &ChildInfo, key: &[u8]) -> bool {
match child_info.child_type() {
ChildType::ParentKeyId => sp_io::default_child_storage::read(
child_info.storage_key(),
key, &mut [0;0][..], 0,
).is_some(),
ChildType::ParentKeyId =>
sp_io::default_child_storage::read(child_info.storage_key(), key, &mut [0; 0][..], 0)
.is_some(),
}
}
@@ -171,86 +136,50 @@ pub fn exists(
/// not make much sense because it is not cumulative when called inside the same block.
/// Use this function to distribute the deletion of a single child trie across multiple
/// blocks.
pub fn kill_storage(
child_info: &ChildInfo,
limit: Option<u32>,
) -> KillStorageResult {
pub fn kill_storage(child_info: &ChildInfo, limit: Option<u32>) -> KillStorageResult {
match child_info.child_type() {
ChildType::ParentKeyId => sp_io::default_child_storage::storage_kill(
child_info.storage_key(),
limit
),
ChildType::ParentKeyId =>
sp_io::default_child_storage::storage_kill(child_info.storage_key(), limit),
}
}
/// Ensure `key` has no explicit entry in storage.
pub fn kill(
child_info: &ChildInfo,
key: &[u8],
) {
pub fn kill(child_info: &ChildInfo, key: &[u8]) {
match child_info.child_type() {
ChildType::ParentKeyId => {
sp_io::default_child_storage::clear(
child_info.storage_key(),
key,
);
sp_io::default_child_storage::clear(child_info.storage_key(), key);
},
}
}
/// Get a Vec of bytes from storage.
pub fn get_raw(
child_info: &ChildInfo,
key: &[u8],
) -> Option<Vec<u8>> {
pub fn get_raw(child_info: &ChildInfo, key: &[u8]) -> Option<Vec<u8>> {
match child_info.child_type() {
ChildType::ParentKeyId => sp_io::default_child_storage::get(
child_info.storage_key(),
key,
),
ChildType::ParentKeyId => sp_io::default_child_storage::get(child_info.storage_key(), key),
}
}
/// Put a raw byte slice into storage.
pub fn put_raw(
child_info: &ChildInfo,
key: &[u8],
value: &[u8],
) {
pub fn put_raw(child_info: &ChildInfo, key: &[u8], value: &[u8]) {
match child_info.child_type() {
ChildType::ParentKeyId => sp_io::default_child_storage::set(
child_info.storage_key(),
key,
value,
),
ChildType::ParentKeyId =>
sp_io::default_child_storage::set(child_info.storage_key(), key, value),
}
}
/// Calculate current child root value.
pub fn root(
child_info: &ChildInfo,
) -> Vec<u8> {
pub fn root(child_info: &ChildInfo) -> Vec<u8> {
match child_info.child_type() {
ChildType::ParentKeyId => sp_io::default_child_storage::root(
child_info.storage_key(),
),
ChildType::ParentKeyId => sp_io::default_child_storage::root(child_info.storage_key()),
}
}
/// Return the length in bytes of the value without reading it. `None` if it does not exist.
pub fn len(
child_info: &ChildInfo,
key: &[u8],
) -> Option<u32> {
pub fn len(child_info: &ChildInfo, key: &[u8]) -> Option<u32> {
match child_info.child_type() {
ChildType::ParentKeyId => {
let mut buffer = [0; 0];
sp_io::default_child_storage::read(
child_info.storage_key(),
key,
&mut buffer,
0,
)
}
sp_io::default_child_storage::read(child_info.storage_key(), key, &mut buffer, 0)
},
}
}
@@ -15,11 +15,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use sp_std::prelude::*;
use sp_std::borrow::Borrow;
use codec::{FullCodec, FullEncode, Decode, Encode, EncodeLike};
use crate::{storage::{self, unhashed, KeyPrefixIterator, StorageAppend, PrefixIterator}, Never};
use crate::hash::{StorageHasher, Twox128, ReversibleStorageHasher};
use crate::{
hash::{ReversibleStorageHasher, StorageHasher, Twox128},
storage::{self, unhashed, KeyPrefixIterator, PrefixIterator, StorageAppend},
Never,
};
use codec::{Decode, Encode, EncodeLike, FullCodec, FullEncode};
use sp_std::{borrow::Borrow, prelude::*};
/// Generator for `StorageDoubleMap` used by `decl_storage`.
///
@@ -63,9 +65,8 @@ pub trait StorageDoubleMap<K1: FullEncode, K2: FullEncode, V: FullCodec> {
let module_prefix_hashed = Twox128::hash(Self::module_prefix());
let storage_prefix_hashed = Twox128::hash(Self::storage_prefix());
let mut result = Vec::with_capacity(
module_prefix_hashed.len() + storage_prefix_hashed.len()
);
let mut result =
Vec::with_capacity(module_prefix_hashed.len() + storage_prefix_hashed.len());
result.extend_from_slice(&module_prefix_hashed[..]);
result.extend_from_slice(&storage_prefix_hashed[..]);
@@ -80,7 +81,8 @@ pub trait StorageDoubleMap<K1: FullEncode, K2: FullEncode, V: FullCodec> {
fn from_query_to_optional_value(v: Self::Query) -> Option<V>;
/// Generate the first part of the key used in top storage.
fn storage_double_map_final_key1<KArg1>(k1: KArg1) -> Vec<u8> where
fn storage_double_map_final_key1<KArg1>(k1: KArg1) -> Vec<u8>
where
KArg1: EncodeLike<K1>,
{
let module_prefix_hashed = Twox128::hash(Self::module_prefix());
@@ -88,7 +90,7 @@ pub trait StorageDoubleMap<K1: FullEncode, K2: FullEncode, V: FullCodec> {
let key_hashed = k1.borrow().using_encoded(Self::Hasher1::hash);
let mut final_key = Vec::with_capacity(
module_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.as_ref().len()
module_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.as_ref().len(),
);
final_key.extend_from_slice(&module_prefix_hashed[..]);
@@ -99,7 +101,8 @@ pub trait StorageDoubleMap<K1: FullEncode, K2: FullEncode, V: FullCodec> {
}
/// Generate the full key used in top storage.
fn storage_double_map_final_key<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Vec<u8> where
fn storage_double_map_final_key<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Vec<u8>
where
KArg1: EncodeLike<K1>,
KArg2: EncodeLike<K2>,
{
@@ -109,10 +112,10 @@ pub trait StorageDoubleMap<K1: FullEncode, K2: FullEncode, V: FullCodec> {
let key2_hashed = k2.borrow().using_encoded(Self::Hasher2::hash);
let mut final_key = Vec::with_capacity(
module_prefix_hashed.len()
+ storage_prefix_hashed.len()
+ key1_hashed.as_ref().len()
+ key2_hashed.as_ref().len()
module_prefix_hashed.len() +
storage_prefix_hashed.len() +
key1_hashed.as_ref().len() +
key2_hashed.as_ref().len(),
);
final_key.extend_from_slice(&module_prefix_hashed[..]);
@@ -124,7 +127,8 @@ pub trait StorageDoubleMap<K1: FullEncode, K2: FullEncode, V: FullCodec> {
}
}
impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G
where
K1: FullEncode,
K2: FullEncode,
V: FullCodec,
@@ -132,21 +136,24 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
{
type Query = G::Query;
fn hashed_key_for<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Vec<u8> where
fn hashed_key_for<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Vec<u8>
where
KArg1: EncodeLike<K1>,
KArg2: EncodeLike<K2>,
{
Self::storage_double_map_final_key(k1, k2)
}
fn contains_key<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> bool where
fn contains_key<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> bool
where
KArg1: EncodeLike<K1>,
KArg2: EncodeLike<K2>,
{
unhashed::exists(&Self::storage_double_map_final_key(k1, k2))
}
fn get<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Self::Query where
fn get<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Self::Query
where
KArg1: EncodeLike<K1>,
KArg2: EncodeLike<K2>,
{
@@ -156,11 +163,13 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
fn try_get<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Result<V, ()>
where
KArg1: EncodeLike<K1>,
KArg2: EncodeLike<K2> {
KArg2: EncodeLike<K2>,
{
unhashed::get(&Self::storage_double_map_final_key(k1, k2)).ok_or(())
}
fn take<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Self::Query where
fn take<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Self::Query
where
KArg1: EncodeLike<K1>,
KArg2: EncodeLike<K2>,
{
@@ -170,16 +179,12 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
G::from_optional_value_to_query(value)
}
fn swap<XKArg1, XKArg2, YKArg1, YKArg2>(
x_k1: XKArg1,
x_k2: XKArg2,
y_k1: YKArg1,
y_k2: YKArg2
) where
fn swap<XKArg1, XKArg2, YKArg1, YKArg2>(x_k1: XKArg1, x_k2: XKArg2, y_k1: YKArg1, y_k2: YKArg2)
where
XKArg1: EncodeLike<K1>,
XKArg2: EncodeLike<K2>,
YKArg1: EncodeLike<K1>,
YKArg2: EncodeLike<K2>
YKArg2: EncodeLike<K2>,
{
let final_x_key = Self::storage_double_map_final_key(x_k1, x_k2);
let final_y_key = Self::storage_double_map_final_key(y_k1, y_k2);
@@ -197,7 +202,8 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
}
}
fn insert<KArg1, KArg2, VArg>(k1: KArg1, k2: KArg2, val: VArg) where
fn insert<KArg1, KArg2, VArg>(k1: KArg1, k2: KArg2, val: VArg)
where
KArg1: EncodeLike<K1>,
KArg2: EncodeLike<K2>,
VArg: EncodeLike<V>,
@@ -205,7 +211,8 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
unhashed::put(&Self::storage_double_map_final_key(k1, k2), &val.borrow())
}
fn remove<KArg1, KArg2>(k1: KArg1, k2: KArg2) where
fn remove<KArg1, KArg2>(k1: KArg1, k2: KArg2)
where
KArg1: EncodeLike<K1>,
KArg2: EncodeLike<K2>,
{
@@ -213,12 +220,15 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
}
fn remove_prefix<KArg1>(k1: KArg1, limit: Option<u32>) -> sp_io::KillStorageResult
where KArg1: EncodeLike<K1> {
where
KArg1: EncodeLike<K1>,
{
unhashed::kill_prefix(Self::storage_double_map_final_key1(k1).as_ref(), limit)
}
fn iter_prefix_values<KArg1>(k1: KArg1) -> storage::PrefixIterator<V> where
KArg1: ?Sized + EncodeLike<K1>
fn iter_prefix_values<KArg1>(k1: KArg1) -> storage::PrefixIterator<V>
where
KArg1: ?Sized + EncodeLike<K1>,
{
let prefix = Self::storage_double_map_final_key1(k1);
storage::PrefixIterator {
@@ -229,12 +239,14 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
}
}
fn mutate<KArg1, KArg2, R, F>(k1: KArg1, k2: KArg2, f: F) -> R where
fn mutate<KArg1, KArg2, R, F>(k1: KArg1, k2: KArg2, f: F) -> R
where
KArg1: EncodeLike<K1>,
KArg2: EncodeLike<K2>,
F: FnOnce(&mut Self::Query) -> R,
{
Self::try_mutate(k1, k2, |v| Ok::<R, Never>(f(v))).expect("`Never` can not be constructed; qed")
Self::try_mutate(k1, k2, |v| Ok::<R, Never>(f(v)))
.expect("`Never` can not be constructed; qed")
}
fn mutate_exists<KArg1, KArg2, R, F>(k1: KArg1, k2: KArg2, f: F) -> R
@@ -243,10 +255,12 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
KArg2: EncodeLike<K2>,
F: FnOnce(&mut Option<V>) -> R,
{
Self::try_mutate_exists(k1, k2, |v| Ok::<R, Never>(f(v))).expect("`Never` can not be constructed; qed")
Self::try_mutate_exists(k1, k2, |v| Ok::<R, Never>(f(v)))
.expect("`Never` can not be constructed; qed")
}
fn try_mutate<KArg1, KArg2, R, E, F>(k1: KArg1, k2: KArg2, f: F) -> Result<R, E> where
fn try_mutate<KArg1, KArg2, R, E, F>(k1: KArg1, k2: KArg2, f: F) -> Result<R, E>
where
KArg1: EncodeLike<K1>,
KArg2: EncodeLike<K2>,
F: FnOnce(&mut Self::Query) -> Result<R, E>,
@@ -283,11 +297,8 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
ret
}
fn append<Item, EncodeLikeItem, KArg1, KArg2>(
k1: KArg1,
k2: KArg2,
item: EncodeLikeItem,
) where
fn append<Item, EncodeLikeItem, KArg1, KArg2>(k1: KArg1, k2: KArg2, item: EncodeLikeItem)
where
KArg1: EncodeLike<K1>,
KArg2: EncodeLike<K2>,
Item: Encode,
@@ -303,7 +314,10 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
OldHasher2: StorageHasher,
KeyArg1: EncodeLike<K1>,
KeyArg2: EncodeLike<K2>,
>(key1: KeyArg1, key2: KeyArg2) -> Option<V> {
>(
key1: KeyArg1,
key2: KeyArg2,
) -> Option<V> {
let old_key = {
let module_prefix_hashed = Twox128::hash(Self::module_prefix());
let storage_prefix_hashed = Twox128::hash(Self::storage_prefix());
@@ -311,10 +325,10 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
let key2_hashed = key2.borrow().using_encoded(OldHasher2::hash);
let mut final_key = Vec::with_capacity(
module_prefix_hashed.len()
+ storage_prefix_hashed.len()
+ key1_hashed.as_ref().len()
+ key2_hashed.as_ref().len()
module_prefix_hashed.len() +
storage_prefix_hashed.len() +
key1_hashed.as_ref().len() +
key2_hashed.as_ref().len(),
);
final_key.extend_from_slice(&module_prefix_hashed[..]);
@@ -331,14 +345,11 @@ impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G where
}
}
impl<
K1: FullCodec,
K2: FullCodec,
V: FullCodec,
G: StorageDoubleMap<K1, K2, V>,
> storage::IterableStorageDoubleMap<K1, K2, V> for G where
impl<K1: FullCodec, K2: FullCodec, V: FullCodec, G: StorageDoubleMap<K1, K2, V>>
storage::IterableStorageDoubleMap<K1, K2, V> for G
where
G::Hasher1: ReversibleStorageHasher,
G::Hasher2: ReversibleStorageHasher
G::Hasher2: ReversibleStorageHasher,
{
type PartialKeyIterator = KeyPrefixIterator<K2>;
type PrefixIterator = PrefixIterator<(K2, V)>;
@@ -367,7 +378,7 @@ impl<
closure: |raw_key_without_prefix| {
let mut key_material = G::Hasher2::reverse(raw_key_without_prefix);
K2::decode(&mut key_material)
}
},
}
}
@@ -405,7 +416,7 @@ impl<
let mut k2_material = G::Hasher2::reverse(k1_k2_material);
let k2 = K2::decode(&mut k2_material)?;
Ok((k1, k2))
}
},
}
}
@@ -418,8 +429,8 @@ impl<
fn translate<O: Decode, F: FnMut(K1, K2, O) -> Option<V>>(mut f: F) {
let prefix = G::prefix_hash();
let mut previous_key = prefix.clone();
while let Some(next) = sp_io::storage::next_key(&previous_key)
.filter(|n| n.starts_with(&prefix))
while let Some(next) =
sp_io::storage::next_key(&previous_key).filter(|n| n.starts_with(&prefix))
{
previous_key = next;
let value = match unhashed::get::<O>(&previous_key) {
@@ -458,11 +469,11 @@ impl<
/// Test iterators for StorageDoubleMap
#[cfg(test)]
mod test_iterators {
use codec::{Encode, Decode};
use crate::{
hash::StorageHasher,
storage::{generator::StorageDoubleMap, IterableStorageDoubleMap, unhashed},
storage::{generator::StorageDoubleMap, unhashed, IterableStorageDoubleMap},
};
use codec::{Decode, Encode};
pub trait Config: 'static {
type Origin;
@@ -521,10 +532,7 @@ mod test_iterators {
vec![(3, 3), (0, 0), (2, 2), (1, 1)],
);
assert_eq!(
DoubleMap::iter_values().collect::<Vec<_>>(),
vec![3, 0, 2, 1],
);
assert_eq!(DoubleMap::iter_values().collect::<Vec<_>>(), vec![3, 0, 2, 1],);
assert_eq!(
DoubleMap::drain().collect::<Vec<_>>(),
@@ -551,15 +559,9 @@ mod test_iterators {
vec![(1, 1), (2, 2), (0, 0), (3, 3)],
);
assert_eq!(
DoubleMap::iter_key_prefix(k1).collect::<Vec<_>>(),
vec![1, 2, 0, 3],
);
assert_eq!(DoubleMap::iter_key_prefix(k1).collect::<Vec<_>>(), vec![1, 2, 0, 3],);
assert_eq!(
DoubleMap::iter_prefix_values(k1).collect::<Vec<_>>(),
vec![1, 2, 0, 3],
);
assert_eq!(DoubleMap::iter_prefix_values(k1).collect::<Vec<_>>(), vec![1, 2, 0, 3],);
assert_eq!(
DoubleMap::drain_prefix(k1).collect::<Vec<_>>(),
@@ -580,15 +582,12 @@ mod test_iterators {
}
// Wrong key1
unhashed::put(
&[prefix.clone(), vec![1, 2, 3]].concat(),
&3u64.encode()
);
unhashed::put(&[prefix.clone(), vec![1, 2, 3]].concat(), &3u64.encode());
// Wrong key2
unhashed::put(
&[prefix.clone(), crate::Blake2_128Concat::hash(&1u16.encode())].concat(),
&3u64.encode()
&3u64.encode(),
);
// Wrong value
@@ -597,11 +596,12 @@ mod test_iterators {
prefix.clone(),
crate::Blake2_128Concat::hash(&1u16.encode()),
crate::Twox64Concat::hash(&2u32.encode()),
].concat(),
]
.concat(),
&vec![1],
);
DoubleMap::translate(|_k1, _k2, v: u64| Some(v*2));
DoubleMap::translate(|_k1, _k2, v: u64| Some(v * 2));
assert_eq!(
DoubleMap::iter().collect::<Vec<_>>(),
vec![(3, 3, 6), (0, 0, 0), (2, 2, 4), (1, 1, 2)],
@@ -15,14 +15,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::{
hash::{ReversibleStorageHasher, StorageHasher, Twox128},
storage::{self, unhashed, KeyPrefixIterator, PrefixIterator, StorageAppend},
Never,
};
use codec::{Decode, Encode, EncodeLike, FullCodec, FullEncode};
use sp_std::borrow::Borrow;
#[cfg(not(feature = "std"))]
use sp_std::prelude::*;
use sp_std::borrow::Borrow;
use codec::{FullCodec, FullEncode, Decode, Encode, EncodeLike};
use crate::{
storage::{self, unhashed, KeyPrefixIterator, StorageAppend, PrefixIterator},
Never, hash::{StorageHasher, Twox128, ReversibleStorageHasher},
};
/// Generator for `StorageMap` used by `decl_storage`.
///
@@ -54,9 +55,8 @@ pub trait StorageMap<K: FullEncode, V: FullCodec> {
let module_prefix_hashed = Twox128::hash(Self::module_prefix());
let storage_prefix_hashed = Twox128::hash(Self::storage_prefix());
let mut result = Vec::with_capacity(
module_prefix_hashed.len() + storage_prefix_hashed.len()
);
let mut result =
Vec::with_capacity(module_prefix_hashed.len() + storage_prefix_hashed.len());
result.extend_from_slice(&module_prefix_hashed[..]);
result.extend_from_slice(&storage_prefix_hashed[..]);
@@ -71,7 +71,8 @@ pub trait StorageMap<K: FullEncode, V: FullCodec> {
fn from_query_to_optional_value(v: Self::Query) -> Option<V>;
/// Generate the full key used in top storage.
fn storage_map_final_key<KeyArg>(key: KeyArg) -> Vec<u8> where
fn storage_map_final_key<KeyArg>(key: KeyArg) -> Vec<u8>
where
KeyArg: EncodeLike<K>,
{
let module_prefix_hashed = Twox128::hash(Self::module_prefix());
@@ -79,7 +80,7 @@ pub trait StorageMap<K: FullEncode, V: FullCodec> {
let key_hashed = key.borrow().using_encoded(Self::Hasher::hash);
let mut final_key = Vec::with_capacity(
module_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.as_ref().len()
module_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.as_ref().len(),
);
final_key.extend_from_slice(&module_prefix_hashed[..]);
@@ -98,11 +99,9 @@ pub struct StorageMapIterator<K, V, Hasher> {
_phantom: ::sp_std::marker::PhantomData<(K, V, Hasher)>,
}
impl<
K: Decode + Sized,
V: Decode + Sized,
Hasher: ReversibleStorageHasher
> Iterator for StorageMapIterator<K, V, Hasher> {
impl<K: Decode + Sized, V: Decode + Sized, Hasher: ReversibleStorageHasher> Iterator
for StorageMapIterator<K, V, Hasher>
{
type Item = (K, V);
fn next(&mut self) -> Option<(K, V)> {
@@ -117,27 +116,25 @@ impl<
if self.drain {
unhashed::kill(&self.previous_key)
}
let mut key_material = Hasher::reverse(&self.previous_key[self.prefix.len()..]);
let mut key_material =
Hasher::reverse(&self.previous_key[self.prefix.len()..]);
match K::decode(&mut key_material) {
Ok(key) => Some((key, value)),
Err(_) => continue,
}
}
},
None => continue,
}
}
},
None => None,
}
}
}
}
impl<
K: FullCodec,
V: FullCodec,
G: StorageMap<K, V>,
> storage::IterableStorageMap<K, V> for G where
G::Hasher: ReversibleStorageHasher
impl<K: FullCodec, V: FullCodec, G: StorageMap<K, V>> storage::IterableStorageMap<K, V> for G
where
G::Hasher: ReversibleStorageHasher,
{
type Iterator = PrefixIterator<(K, V)>;
type KeyIterator = KeyPrefixIterator<K>;
@@ -166,7 +163,7 @@ impl<
closure: |raw_key_without_prefix| {
let mut key_material = G::Hasher::reverse(raw_key_without_prefix);
K::decode(&mut key_material)
}
},
}
}
@@ -180,8 +177,8 @@ impl<
fn translate<O: Decode, F: FnMut(K, O) -> Option<V>>(mut f: F) {
let prefix = G::prefix_hash();
let mut previous_key = prefix.clone();
while let Some(next) = sp_io::storage::next_key(&previous_key)
.filter(|n| n.starts_with(&prefix))
while let Some(next) =
sp_io::storage::next_key(&previous_key).filter(|n| n.starts_with(&prefix))
{
previous_key = next;
let value = match unhashed::get::<O>(&previous_key) {
@@ -254,16 +251,21 @@ impl<K: FullEncode, V: FullCodec, G: StorageMap<K, V>> storage::StorageMap<K, V>
}
fn mutate<KeyArg: EncodeLike<K>, R, F: FnOnce(&mut Self::Query) -> R>(key: KeyArg, f: F) -> R {
Self::try_mutate(key, |v| Ok::<R, Never>(f(v))).expect("`Never` can not be constructed; qed")
Self::try_mutate(key, |v| Ok::<R, Never>(f(v)))
.expect("`Never` can not be constructed; qed")
}
fn mutate_exists<KeyArg: EncodeLike<K>, R, F: FnOnce(&mut Option<V>) -> R>(key: KeyArg, f: F) -> R {
Self::try_mutate_exists(key, |v| Ok::<R, Never>(f(v))).expect("`Never` can not be constructed; qed")
fn mutate_exists<KeyArg: EncodeLike<K>, R, F: FnOnce(&mut Option<V>) -> R>(
key: KeyArg,
f: F,
) -> R {
Self::try_mutate_exists(key, |v| Ok::<R, Never>(f(v)))
.expect("`Never` can not be constructed; qed")
}
fn try_mutate<KeyArg: EncodeLike<K>, R, E, F: FnOnce(&mut Self::Query) -> Result<R, E>>(
key: KeyArg,
f: F
f: F,
) -> Result<R, E> {
let final_key = Self::storage_map_final_key(key);
let mut val = G::from_optional_value_to_query(unhashed::get(final_key.as_ref()));
@@ -280,7 +282,7 @@ impl<K: FullEncode, V: FullCodec, G: StorageMap<K, V>> storage::StorageMap<K, V>
fn try_mutate_exists<KeyArg: EncodeLike<K>, R, E, F: FnOnce(&mut Option<V>) -> Result<R, E>>(
key: KeyArg,
f: F
f: F,
) -> Result<R, E> {
let final_key = Self::storage_map_final_key(key);
let mut val = unhashed::get(final_key.as_ref());
@@ -319,7 +321,9 @@ impl<K: FullEncode, V: FullCodec, G: StorageMap<K, V>> storage::StorageMap<K, V>
let key_hashed = key.borrow().using_encoded(OldHasher::hash);
let mut final_key = Vec::with_capacity(
module_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.as_ref().len()
module_prefix_hashed.len() +
storage_prefix_hashed.len() +
key_hashed.as_ref().len(),
);
final_key.extend_from_slice(&module_prefix_hashed[..]);
@@ -338,11 +342,11 @@ impl<K: FullEncode, V: FullCodec, G: StorageMap<K, V>> storage::StorageMap<K, V>
/// Test iterators for StorageMap
#[cfg(test)]
mod test_iterators {
use codec::{Encode, Decode};
use crate::{
hash::StorageHasher,
storage::{generator::StorageMap, IterableStorageMap, unhashed},
storage::{generator::StorageMap, unhashed, IterableStorageMap},
};
use codec::{Decode, Encode};
pub trait Config: 'static {
type Origin;
@@ -421,7 +425,7 @@ mod test_iterators {
&vec![1],
);
Map::translate(|_k1, v: u64| Some(v*2));
Map::translate(|_k1, v: u64| Some(v * 2));
assert_eq!(Map::iter().collect::<Vec<_>>(), vec![(3, 6), (0, 0), (2, 4), (1, 2)]);
})
}
@@ -24,23 +24,25 @@
//!
//! This is internal api and is subject to change.
mod double_map;
mod map;
mod nmap;
mod double_map;
mod value;
pub use double_map::StorageDoubleMap;
pub use map::StorageMap;
pub use nmap::StorageNMap;
pub use double_map::StorageDoubleMap;
pub use value::StorageValue;
#[cfg(test)]
#[allow(dead_code)]
mod tests {
use sp_io::TestExternalities;
use crate::{
assert_noop, assert_ok,
storage::{generator::StorageValue, unhashed, IterableStorageMap},
};
use codec::Encode;
use crate::storage::{unhashed, generator::StorageValue, IterableStorageMap};
use crate::{assert_noop, assert_ok};
use sp_io::TestExternalities;
struct Runtime;
@@ -80,7 +82,7 @@ mod tests {
// translate
let translate_fn = |old: Option<u32>| -> Option<(u64, u64)> {
old.map(|o| (o.into(), (o*2).into()))
old.map(|o| (o.into(), (o * 2).into()))
};
let res = Value::translate(translate_fn);
debug_assert!(res.is_ok());
@@ -105,11 +107,16 @@ mod tests {
);
// do translation.
NumberMap::translate(|k: u32, v: u64| if k % 2 == 0 { Some((k as u64) << 32 | v) } else { None });
NumberMap::translate(
|k: u32, v: u64| if k % 2 == 0 { Some((k as u64) << 32 | v) } else { None },
);
assert_eq!(
NumberMap::iter().collect::<Vec<_>>(),
(0..50u32).map(|x| x * 2).map(|x| (x, (x as u64) << 32 | x as u64)).collect::<Vec<_>>(),
(0..50u32)
.map(|x| x * 2)
.map(|x| (x, (x as u64) << 32 | x as u64))
.collect::<Vec<_>>(),
);
})
}
@@ -123,20 +130,29 @@ mod tests {
assert_eq!(DoubleMap::get(0, 0), 0);
// `assert_noop` ensures that the state does not change
assert_noop!(Value::try_mutate(|value| -> Result<(), &'static str> {
*value = (2, 2);
Err("don't change value")
}), "don't change value");
assert_noop!(
Value::try_mutate(|value| -> Result<(), &'static str> {
*value = (2, 2);
Err("don't change value")
}),
"don't change value"
);
assert_noop!(NumberMap::try_mutate(0, |value| -> Result<(), &'static str> {
*value = 4;
Err("don't change value")
}), "don't change value");
assert_noop!(
NumberMap::try_mutate(0, |value| -> Result<(), &'static str> {
*value = 4;
Err("don't change value")
}),
"don't change value"
);
assert_noop!(DoubleMap::try_mutate(0, 0, |value| -> Result<(), &'static str> {
*value = 6;
Err("don't change value")
}), "don't change value");
assert_noop!(
DoubleMap::try_mutate(0, 0, |value| -> Result<(), &'static str> {
*value = 6;
Err("don't change value")
}),
"don't change value"
);
// Showing this explicitly for clarity
assert_eq!(Value::get(), (0, 0));
@@ -228,7 +228,7 @@ where
fn try_mutate<KArg, R, E, F>(key: KArg, f: F) -> Result<R, E>
where
KArg: EncodeLikeTuple<K::KArg> + TupleToEncodedIter,
F: FnOnce(&mut Self::Query) -> Result<R, E>
F: FnOnce(&mut Self::Query) -> Result<R, E>,
{
let final_key = Self::storage_n_map_final_key::<K, _>(key);
let mut val = G::from_optional_value_to_query(unhashed::get(final_key.as_ref()));
@@ -373,7 +373,7 @@ impl<K: ReversibleKeyGenerator, V: FullCodec, G: StorageNMap<K, V>>
closure: |raw_key_without_prefix| {
let (final_key, _) = K::decode_final_key(raw_key_without_prefix)?;
Ok(final_key)
}
},
}
}
@@ -394,16 +394,16 @@ impl<K: ReversibleKeyGenerator, V: FullCodec, G: StorageNMap<K, V>>
Some(value) => value,
None => {
log::error!("Invalid translate: fail to decode old value");
continue;
}
continue
},
};
let final_key = match K::decode_final_key(&previous_key[prefix.len()..]) {
Ok((final_key, _)) => final_key,
Err(_) => {
log::error!("Invalid translate: fail to decode key");
continue;
}
continue
},
};
match f(final_key, value) {
@@ -452,10 +452,7 @@ mod test_iterators {
fn key_after_prefix(mut prefix: Vec<u8>) -> Vec<u8> {
let last = prefix.iter_mut().last().unwrap();
assert!(
*last != 255,
"mock function not implemented for this prefix"
);
assert!(*last != 255, "mock function not implemented for this prefix");
*last += 1;
prefix
}
@@ -498,10 +495,7 @@ mod test_iterators {
vec![((3, 3), 3), ((0, 0), 0), ((2, 2), 2), ((1, 1), 1)],
);
assert_eq!(
NMap::iter_keys().collect::<Vec<_>>(),
vec![(3, 3), (0, 0), (2, 2), (1, 1)],
);
assert_eq!(NMap::iter_keys().collect::<Vec<_>>(), vec![(3, 3), (0, 0), (2, 2), (1, 1)],);
assert_eq!(NMap::iter_values().collect::<Vec<_>>(), vec![3, 0, 2, 1],);
@@ -511,10 +505,7 @@ mod test_iterators {
);
assert_eq!(NMap::iter().collect::<Vec<_>>(), vec![]);
assert_eq!(
unhashed::get(&key_before_prefix(prefix.clone())),
Some(1u64)
);
assert_eq!(unhashed::get(&key_before_prefix(prefix.clone())), Some(1u64));
assert_eq!(unhashed::get(&key_after_prefix(prefix.clone())), Some(1u64));
// Prefix iterator
@@ -533,15 +524,9 @@ mod test_iterators {
vec![(1, 1), (2, 2), (0, 0), (3, 3)],
);
assert_eq!(
NMap::iter_key_prefix((k1,)).collect::<Vec<_>>(),
vec![1, 2, 0, 3],
);
assert_eq!(NMap::iter_key_prefix((k1,)).collect::<Vec<_>>(), vec![1, 2, 0, 3],);
assert_eq!(
NMap::iter_prefix_values((k1,)).collect::<Vec<_>>(),
vec![1, 2, 0, 3],
);
assert_eq!(NMap::iter_prefix_values((k1,)).collect::<Vec<_>>(), vec![1, 2, 0, 3],);
assert_eq!(
NMap::drain_prefix((k1,)).collect::<Vec<_>>(),
@@ -549,10 +534,7 @@ mod test_iterators {
);
assert_eq!(NMap::iter_prefix((k1,)).collect::<Vec<_>>(), vec![]);
assert_eq!(
unhashed::get(&key_before_prefix(prefix.clone())),
Some(1u64)
);
assert_eq!(unhashed::get(&key_before_prefix(prefix.clone())), Some(1u64));
assert_eq!(unhashed::get(&key_after_prefix(prefix.clone())), Some(1u64));
// Translate
@@ -569,11 +551,7 @@ mod test_iterators {
// Wrong key2
unhashed::put(
&[
prefix.clone(),
crate::Blake2_128Concat::hash(&1u16.encode()),
]
.concat(),
&[prefix.clone(), crate::Blake2_128Concat::hash(&1u16.encode())].concat(),
&3u64.encode(),
);
@@ -15,12 +15,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use codec::{FullCodec, Encode, EncodeLike, Decode};
use crate::{
Never,
hash::{StorageHasher, Twox128},
storage::{self, unhashed, StorageAppend},
hash::{Twox128, StorageHasher},
Never,
};
use codec::{Decode, Encode, EncodeLike, FullCodec};
/// Generator for `StorageValue` used by `decl_storage`.
///
@@ -78,7 +78,8 @@ impl<T: FullCodec, G: StorageValue<T>> storage::StorageValue<T> for G {
// attempt to get the length directly.
let maybe_old = unhashed::get_raw(&key)
.map(|old_data| O::decode(&mut &old_data[..]).map_err(|_| ())).transpose()?;
.map(|old_data| O::decode(&mut &old_data[..]).map_err(|_| ()))
.transpose()?;
let maybe_new = f(maybe_old);
if let Some(new) = maybe_new.as_ref() {
new.using_encoded(|d| unhashed::put_raw(&key, d));
@@ -18,8 +18,8 @@
//! Operation on runtime storage using hashed keys.
use super::unhashed;
use codec::{Decode, Encode};
use sp_std::prelude::*;
use codec::{Encode, Decode};
/// Return the value of the item in storage under `key`, or `None` if there is no explicit entry.
pub fn get<T, HashFn, R>(hash: &HashFn, key: &[u8]) -> Option<T>
@@ -17,10 +17,9 @@
//! Some utilities for helping access storage with arbitrary key types.
use crate::{hash::ReversibleStorageHasher, storage::unhashed, StorageHasher, Twox128};
use codec::{Decode, Encode};
use sp_std::prelude::*;
use codec::{Encode, Decode};
use crate::{StorageHasher, Twox128, storage::unhashed};
use crate::hash::ReversibleStorageHasher;
use super::PrefixIterator;
@@ -34,14 +33,18 @@ pub struct StorageIterator<T> {
impl<T> StorageIterator<T> {
/// Construct iterator to iterate over map items in `module` for the map called `item`.
#[deprecated(note="Please use the storage_iter or storage_iter_with_suffix functions instead")]
#[deprecated(
note = "Please use the storage_iter or storage_iter_with_suffix functions instead"
)]
pub fn new(module: &[u8], item: &[u8]) -> Self {
#[allow(deprecated)]
Self::with_suffix(module, item, &[][..])
}
/// Construct iterator to iterate over map items in `module` for the map called `item`.
#[deprecated(note="Please use the storage_iter or storage_iter_with_suffix functions instead")]
#[deprecated(
note = "Please use the storage_iter or storage_iter_with_suffix functions instead"
)]
pub fn with_suffix(module: &[u8], item: &[u8], suffix: &[u8]) -> Self {
let mut prefix = Vec::new();
prefix.extend_from_slice(&Twox128::hash(module));
@@ -75,10 +78,10 @@ impl<T: Decode + Sized> Iterator for StorageIterator<T> {
frame_support::storage::unhashed::kill(&next);
}
Some((self.previous_key[self.prefix.len()..].to_vec(), value))
}
},
None => continue,
}
}
},
None => None,
}
}
@@ -95,14 +98,18 @@ pub struct StorageKeyIterator<K, T, H: ReversibleStorageHasher> {
impl<K, T, H: ReversibleStorageHasher> StorageKeyIterator<K, T, H> {
/// Construct iterator to iterate over map items in `module` for the map called `item`.
#[deprecated(note="Please use the storage_key_iter or storage_key_iter_with_suffix functions instead")]
#[deprecated(
note = "Please use the storage_key_iter or storage_key_iter_with_suffix functions instead"
)]
pub fn new(module: &[u8], item: &[u8]) -> Self {
#[allow(deprecated)]
Self::with_suffix(module, item, &[][..])
}
/// Construct iterator to iterate over map items in `module` for the map called `item`.
#[deprecated(note="Please use the storage_key_iter or storage_key_iter_with_suffix functions instead")]
#[deprecated(
note = "Please use the storage_key_iter or storage_key_iter_with_suffix functions instead"
)]
pub fn with_suffix(module: &[u8], item: &[u8], suffix: &[u8]) -> Self {
let mut prefix = Vec::new();
prefix.extend_from_slice(&Twox128::hash(module));
@@ -141,13 +148,13 @@ impl<K: Decode + Sized, T: Decode + Sized, H: ReversibleStorageHasher> Iterator
frame_support::storage::unhashed::kill(&next);
}
Some((key, value))
}
},
None => continue,
}
}
},
Err(_) => continue,
}
}
},
None => None,
}
}
@@ -187,7 +194,11 @@ pub fn storage_key_iter<K: Decode + Sized, T: Decode + Sized, H: ReversibleStora
}
/// Construct iterator to iterate over map items in `module` for the map called `item`.
pub fn storage_key_iter_with_suffix<K: Decode + Sized, T: Decode + Sized, H: ReversibleStorageHasher>(
pub fn storage_key_iter_with_suffix<
K: Decode + Sized,
T: Decode + Sized,
H: ReversibleStorageHasher,
>(
module: &[u8],
item: &[u8],
suffix: &[u8],
@@ -279,7 +290,7 @@ pub fn take_storage_item<K: Encode + Sized, T: Decode + Sized, H: StorageHasher>
pub fn move_storage_from_pallet(
storage_name: &[u8],
old_pallet_name: &[u8],
new_pallet_name: &[u8]
new_pallet_name: &[u8],
) {
let mut new_prefix = Vec::new();
new_prefix.extend_from_slice(&Twox128::hash(new_pallet_name));
@@ -347,18 +358,14 @@ pub fn move_prefix(from_prefix: &[u8], to_prefix: &[u8]) {
#[cfg(test)]
mod tests {
use super::{
move_pallet, move_prefix, move_storage_from_pallet, storage_iter, storage_key_iter,
};
use crate::{
pallet_prelude::{StorageValue, StorageMap, Twox64Concat, Twox128},
hash::StorageHasher,
pallet_prelude::{StorageMap, StorageValue, Twox128, Twox64Concat},
};
use sp_io::TestExternalities;
use super::{
move_prefix,
move_pallet,
move_storage_from_pallet,
storage_iter,
storage_key_iter,
};
struct OldPalletStorageValuePrefix;
impl frame_support::traits::StorageInstance for OldPalletStorageValuePrefix {
@@ -459,21 +466,22 @@ mod tests {
OldStorageMap::insert(3, 4);
assert_eq!(
storage_key_iter::<i32, i32, Twox64Concat>(b"my_old_pallet", b"foo_map").collect::<Vec<_>>(),
storage_key_iter::<i32, i32, Twox64Concat>(b"my_old_pallet", b"foo_map")
.collect::<Vec<_>>(),
vec![(1, 2), (3, 4)],
);
assert_eq!(
storage_iter(b"my_old_pallet", b"foo_map").drain().map(|t| t.1).collect::<Vec<i32>>(),
storage_iter(b"my_old_pallet", b"foo_map")
.drain()
.map(|t| t.1)
.collect::<Vec<i32>>(),
vec![2, 4],
);
assert_eq!(OldStorageMap::iter().collect::<Vec<_>>(), vec![]);
// Empty because storage iterator skips over the entry under the first key
assert_eq!(
storage_iter::<i32>(b"my_old_pallet", b"foo_value").drain().next(),
None
);
assert_eq!(storage_iter::<i32>(b"my_old_pallet", b"foo_value").drain().next(), None);
assert_eq!(OldStorageValue::get(), Some(3));
});
}
+84 -84
View File
@@ -17,31 +17,31 @@
//! Stuff to do with the runtime's storage.
use sp_core::storage::ChildInfo;
use sp_std::prelude::*;
use codec::{FullCodec, FullEncode, Encode, EncodeLike, Decode};
use crate::{
hash::{Twox128, StorageHasher, ReversibleStorageHasher},
hash::{ReversibleStorageHasher, StorageHasher, Twox128},
storage::types::{
EncodeLikeTuple, HasKeyPrefix, HasReversibleKeyPrefix, KeyGenerator,
ReversibleKeyGenerator, TupleToEncodedIter,
},
};
use codec::{Decode, Encode, EncodeLike, FullCodec, FullEncode};
use sp_core::storage::ChildInfo;
use sp_runtime::generic::{Digest, DigestItem};
pub use sp_runtime::TransactionOutcome;
use sp_std::prelude::*;
pub use types::Key;
pub mod unhashed;
pub mod hashed;
pub mod bounded_btree_map;
pub mod bounded_btree_set;
pub mod bounded_vec;
pub mod weak_bounded_vec;
pub mod child;
#[doc(hidden)]
pub mod generator;
pub mod hashed;
pub mod migration;
pub mod types;
pub mod unhashed;
pub mod weak_bounded_vec;
#[cfg(all(feature = "std", any(test, debug_assertions)))]
mod debug_helper {
@@ -101,9 +101,7 @@ pub fn require_transaction() {
///
/// Transactions can be nested to any depth. Commits happen to the parent transaction.
pub fn with_transaction<R>(f: impl FnOnce() -> TransactionOutcome<R>) -> R {
use sp_io::storage::{
start_transaction, commit_transaction, rollback_transaction,
};
use sp_io::storage::{commit_transaction, rollback_transaction, start_transaction};
use TransactionOutcome::*;
start_transaction();
@@ -112,8 +110,14 @@ pub fn with_transaction<R>(f: impl FnOnce() -> TransactionOutcome<R>) -> R {
let _guard = debug_helper::inc_transaction_level();
match f() {
Commit(res) => { commit_transaction(); res },
Rollback(res) => { rollback_transaction(); res },
Commit(res) => {
commit_transaction();
res
},
Rollback(res) => {
rollback_transaction();
res
},
}
}
@@ -205,7 +209,10 @@ pub trait StorageValue<T: FullCodec> {
///
/// `None` does not mean that `get()` does not return a value. The default value is completly
/// ignored by this function.
fn decode_len() -> Option<usize> where T: StorageDecodeLength {
fn decode_len() -> Option<usize>
where
T: StorageDecodeLength,
{
T::decode_len(&Self::hashed_key())
}
}
@@ -252,7 +259,10 @@ pub trait StorageMap<K: FullEncode, V: FullCodec> {
/// Mutate the value under a key.
///
/// Deletes the item if mutated to a `None`.
fn mutate_exists<KeyArg: EncodeLike<K>, R, F: FnOnce(&mut Option<V>) -> R>(key: KeyArg, f: F) -> R;
fn mutate_exists<KeyArg: EncodeLike<K>, R, F: FnOnce(&mut Option<V>) -> R>(
key: KeyArg,
f: F,
) -> R;
/// Mutate the item, only if an `Ok` value is returned. Deletes the item if mutated to a `None`.
fn try_mutate_exists<KeyArg: EncodeLike<K>, R, E, F: FnOnce(&mut Option<V>) -> Result<R, E>>(
@@ -292,7 +302,8 @@ pub trait StorageMap<K: FullEncode, V: FullCodec> {
/// `None` does not mean that `get()` does not return a value. The default value is completly
/// ignored by this function.
fn decode_len<KeyArg: EncodeLike<K>>(key: KeyArg) -> Option<usize>
where V: StorageDecodeLength,
where
V: StorageDecodeLength,
{
V::decode_len(&Self::hashed_key_for(key))
}
@@ -337,11 +348,9 @@ pub trait IterableStorageMap<K: FullEncode, V: FullCodec>: StorageMap<K, V> {
}
/// A strongly-typed double map in storage whose secondary keys and values can be iterated over.
pub trait IterableStorageDoubleMap<
K1: FullCodec,
K2: FullCodec,
V: FullCodec
>: StorageDoubleMap<K1, K2, V> {
pub trait IterableStorageDoubleMap<K1: FullCodec, K2: FullCodec, V: FullCodec>:
StorageDoubleMap<K1, K2, V>
{
/// The type that iterates over all `key2`.
type PartialKeyIterator: Iterator<Item = K2>;
@@ -401,19 +410,22 @@ pub trait IterableStorageNMap<K: ReversibleKeyGenerator, V: FullCodec>: StorageN
/// remove values whose prefix is `kp` to the map while doing this, you'll get undefined
/// results.
fn iter_prefix<KP>(kp: KP) -> PrefixIterator<(<K as HasKeyPrefix<KP>>::Suffix, V)>
where K: HasReversibleKeyPrefix<KP>;
where
K: HasReversibleKeyPrefix<KP>;
/// Enumerate all suffix keys in the map with prefix key `kp` in no particular order. If you
/// add or remove values whose prefix is `kp` to the map while doing this, you'll get undefined
/// results.
fn iter_key_prefix<KP>(kp: KP) -> KeyPrefixIterator<<K as HasKeyPrefix<KP>>::Suffix>
where K: HasReversibleKeyPrefix<KP>;
where
K: HasReversibleKeyPrefix<KP>;
/// Remove all elements from the map with prefix key `kp` and iterate through them in no
/// particular order. If you add elements with prefix key `kp` to the map while doing this,
/// you'll get undefined results.
fn drain_prefix<KP>(kp: KP) -> PrefixIterator<(<K as HasKeyPrefix<KP>>::Suffix, V)>
where K: HasReversibleKeyPrefix<KP>;
where
K: HasReversibleKeyPrefix<KP>;
/// Enumerate all elements in the map in no particular order. If you add or remove values to
/// the map while doing this, you'll get undefined results.
@@ -499,11 +511,13 @@ pub trait StorageDoubleMap<K1: FullEncode, K2: FullEncode, V: FullCodec> {
/// Remove all values under the first key.
fn remove_prefix<KArg1>(k1: KArg1, limit: Option<u32>) -> sp_io::KillStorageResult
where KArg1: ?Sized + EncodeLike<K1>;
where
KArg1: ?Sized + EncodeLike<K1>;
/// Iterate over values that share the first key.
fn iter_prefix_values<KArg1>(k1: KArg1) -> PrefixIterator<V>
where KArg1: ?Sized + EncodeLike<K1>;
where
KArg1: ?Sized + EncodeLike<K1>;
/// Mutate the value under the given keys.
fn mutate<KArg1, KArg2, R, F>(k1: KArg1, k2: KArg2, f: F) -> R
@@ -542,11 +556,8 @@ pub trait StorageDoubleMap<K1: FullEncode, K2: FullEncode, V: FullCodec> {
/// If the storage item is not encoded properly, the storage will be overwritten
/// and set to `[item]`. Any default value set for the storage item will be ignored
/// on overwrite.
fn append<Item, EncodeLikeItem, KArg1, KArg2>(
k1: KArg1,
k2: KArg2,
item: EncodeLikeItem,
) where
fn append<Item, EncodeLikeItem, KArg1, KArg2>(k1: KArg1, k2: KArg2, item: EncodeLikeItem)
where
KArg1: EncodeLike<K1>,
KArg2: EncodeLike<K2>,
Item: Encode,
@@ -566,10 +577,10 @@ pub trait StorageDoubleMap<K1: FullEncode, K2: FullEncode, V: FullCodec> {
/// `None` does not mean that `get()` does not return a value. The default value is completly
/// ignored by this function.
fn decode_len<KArg1, KArg2>(key1: KArg1, key2: KArg2) -> Option<usize>
where
KArg1: EncodeLike<K1>,
KArg2: EncodeLike<K2>,
V: StorageDecodeLength,
where
KArg1: EncodeLike<K1>,
KArg2: EncodeLike<K2>,
V: StorageDecodeLength,
{
V::decode_len(&Self::hashed_key_for(key1, key2))
}
@@ -583,7 +594,10 @@ pub trait StorageDoubleMap<K1: FullEncode, K2: FullEncode, V: FullCodec> {
OldHasher2: StorageHasher,
KeyArg1: EncodeLike<K1>,
KeyArg2: EncodeLike<K2>,
>(key1: KeyArg1, key2: KeyArg2) -> Option<V>;
>(
key1: KeyArg1,
key2: KeyArg2,
) -> Option<V>;
}
/// An implementation of a map with an arbitrary number of keys.
@@ -625,10 +639,13 @@ pub trait StorageNMap<K: KeyGenerator, V: FullCodec> {
/// Remove all values under the partial prefix key.
fn remove_prefix<KP>(partial_key: KP, limit: Option<u32>) -> sp_io::KillStorageResult
where K: HasKeyPrefix<KP>;
where
K: HasKeyPrefix<KP>;
/// Iterate over values that share the partial prefix key.
fn iter_prefix_values<KP>(partial_key: KP) -> PrefixIterator<V> where K: HasKeyPrefix<KP>;
fn iter_prefix_values<KP>(partial_key: KP) -> PrefixIterator<V>
where
K: HasKeyPrefix<KP>;
/// Mutate the value under a key.
fn mutate<KArg, R, F>(key: KArg, f: F) -> R
@@ -741,7 +758,7 @@ impl<T> Iterator for PrefixIterator<T> {
self.previous_key,
);
continue
}
},
};
if self.drain {
unhashed::kill(&self.previous_key)
@@ -756,11 +773,11 @@ impl<T> Iterator for PrefixIterator<T> {
e,
);
continue
}
},
};
Some(item)
}
},
None => None,
}
}
@@ -807,12 +824,12 @@ impl<T> Iterator for KeyPrefixIterator<T> {
Ok(item) => return Some(item),
Err(e) => {
log::error!("key failed to decode at {:?}: {:?}", self.previous_key, e);
continue;
}
continue
},
}
}
return None;
return None
}
}
}
@@ -871,7 +888,10 @@ impl<K: Decode + Sized, T: Decode + Sized> ChildTriePrefixIterator<(K, T)> {
/// Construct iterator to iterate over child trie items in `child_info` with the prefix `prefix`.
///
/// NOTE: Iterator with [`Self::drain`] will remove any key or value who failed to decode
pub fn with_prefix_over_key<H: ReversibleStorageHasher>(child_info: &ChildInfo, prefix: &[u8]) -> Self {
pub fn with_prefix_over_key<H: ReversibleStorageHasher>(
child_info: &ChildInfo,
prefix: &[u8],
) -> Self {
let prefix = prefix.to_vec();
let previous_key = prefix.clone();
let closure = |raw_key_without_prefix: &[u8], raw_value: &[u8]| {
@@ -888,7 +908,7 @@ impl<K: Decode + Sized, T: Decode + Sized> ChildTriePrefixIterator<(K, T)> {
drain: false,
fetch_previous_key: true,
closure,
}
}
}
}
@@ -905,7 +925,7 @@ impl<T> Iterator for ChildTriePrefixIterator<T> {
&self.child_info.storage_key(),
&self.previous_key,
)
.filter(|n| n.starts_with(&self.prefix))
.filter(|n| n.starts_with(&self.prefix))
};
break match maybe_next {
Some(next) => {
@@ -918,7 +938,7 @@ impl<T> Iterator for ChildTriePrefixIterator<T> {
self.previous_key,
);
continue
}
},
};
if self.drain {
child::kill(&self.child_info, &self.previous_key)
@@ -933,11 +953,11 @@ impl<T> Iterator for ChildTriePrefixIterator<T> {
e,
);
continue
}
},
};
Some(item)
}
},
None => None,
}
}
@@ -999,8 +1019,8 @@ pub trait StoragePrefixedMap<Value: FullCodec> {
fn translate_values<OldValue: Decode, F: FnMut(OldValue) -> Option<Value>>(mut f: F) {
let prefix = Self::final_prefix();
let mut previous_key = prefix.clone().to_vec();
while let Some(next) = sp_io::storage::next_key(&previous_key)
.filter(|n| n.starts_with(&prefix))
while let Some(next) =
sp_io::storage::next_key(&previous_key).filter(|n| n.starts_with(&prefix))
{
previous_key = next;
let maybe_value = unhashed::get::<OldValue>(&previous_key);
@@ -1010,10 +1030,7 @@ pub trait StoragePrefixedMap<Value: FullCodec> {
None => unhashed::kill(&previous_key),
},
None => {
log::error!(
"old key failed to decode at {:?}",
previous_key,
);
log::error!("old key failed to decode at {:?}", previous_key,);
continue
},
}
@@ -1218,13 +1235,13 @@ where
#[cfg(test)]
mod test {
use super::*;
use sp_core::hashing::twox_128;
use crate::{hash::Identity, assert_ok};
use sp_io::TestExternalities;
use generator::StorageValue as _;
use crate::{assert_ok, hash::Identity};
use bounded_vec::BoundedVec;
use weak_bounded_vec::WeakBoundedVec;
use core::convert::{TryFrom, TryInto};
use generator::StorageValue as _;
use sp_core::hashing::twox_128;
use sp_io::TestExternalities;
use weak_bounded_vec::WeakBoundedVec;
#[test]
fn prefixed_map_works() {
@@ -1363,8 +1380,7 @@ mod test {
#[test]
fn key_prefix_iterator_works() {
TestExternalities::default().execute_with(|| {
use crate::storage::generator::StorageMap;
use crate::hash::Twox64Concat;
use crate::{hash::Twox64Concat, storage::generator::StorageMap};
struct MyStorageMap;
impl StorageMap<u64, u64> for MyStorageMap {
type Query = u64;
@@ -1426,30 +1442,21 @@ mod test {
assert_eq!(
ChildTriePrefixIterator::with_prefix(&child_info_a, &[2])
.collect::<Vec<(Vec<u8>, u16)>>(),
vec![
(vec![], 8),
(vec![2, 3], 8),
],
vec![(vec![], 8), (vec![2, 3], 8),],
);
assert_eq!(
ChildTriePrefixIterator::with_prefix(&child_info_a, &[2])
.drain()
.collect::<Vec<(Vec<u8>, u16)>>(),
vec![
(vec![], 8),
(vec![2, 3], 8),
],
vec![(vec![], 8), (vec![2, 3], 8),],
);
// The only remaining is the ones outside prefix
assert_eq!(
ChildTriePrefixIterator::with_prefix(&child_info_a, &[])
.collect::<Vec<(Vec<u8>, u8)>>(),
vec![
(vec![1, 2, 3], 8),
(vec![3], 8),
],
vec![(vec![1, 2, 3], 8), (vec![3], 8),],
);
child::put(&child_info_a, &[1, 2, 3], &8u16);
@@ -1461,28 +1468,21 @@ mod test {
assert_eq!(
ChildTriePrefixIterator::with_prefix_over_key::<Identity>(&child_info_a, &[2])
.collect::<Vec<(u16, u16)>>(),
vec![
(u16::decode(&mut &[2, 3][..]).unwrap(), 8),
],
vec![(u16::decode(&mut &[2, 3][..]).unwrap(), 8),],
);
assert_eq!(
ChildTriePrefixIterator::with_prefix_over_key::<Identity>(&child_info_a, &[2])
.drain()
.collect::<Vec<(u16, u16)>>(),
vec![
(u16::decode(&mut &[2, 3][..]).unwrap(), 8),
],
vec![(u16::decode(&mut &[2, 3][..]).unwrap(), 8),],
);
// The only remaining is the ones outside prefix
assert_eq!(
ChildTriePrefixIterator::with_prefix(&child_info_a, &[])
.collect::<Vec<(Vec<u8>, u8)>>(),
vec![
(vec![1, 2, 3], 8),
(vec![3], 8),
],
vec![(vec![1, 2, 3], 8), (vec![3], 8),],
);
});
}
@@ -18,14 +18,14 @@
//! Storage map type. Implements StorageDoubleMap, StorageIterableDoubleMap,
//! StoragePrefixedDoubleMap traits and their methods directly.
use codec::{Decode, Encode, EncodeLike, FullCodec, MaxEncodedLen};
use crate::{
storage::{
StorageAppend, StorageTryAppend, StorageDecodeLength, StoragePrefixedMap,
types::{OptionQuery, QueryKindTrait, OnEmptyGetter},
types::{OnEmptyGetter, OptionQuery, QueryKindTrait},
StorageAppend, StorageDecodeLength, StoragePrefixedMap, StorageTryAppend,
},
traits::{GetDefault, StorageInstance, Get, StorageInfo},
traits::{Get, GetDefault, StorageInfo, StorageInstance},
};
use codec::{Decode, Encode, EncodeLike, FullCodec, MaxEncodedLen};
use frame_metadata::{DefaultByteGetter, StorageEntryModifier};
use sp_arithmetic::traits::SaturatedConversion;
use sp_std::prelude::*;
@@ -36,9 +36,9 @@ use sp_std::prelude::*;
/// Each value is stored at:
/// ```nocompile
/// Twox128(Prefix::pallet_prefix())
/// ++ Twox128(Prefix::STORAGE_PREFIX)
/// ++ Hasher1(encode(key1))
/// ++ Hasher2(encode(key2))
/// ++ Twox128(Prefix::STORAGE_PREFIX)
/// ++ Hasher1(encode(key1))
/// ++ Hasher2(encode(key2))
/// ```
///
/// # Warning
@@ -53,18 +53,26 @@ pub struct StorageDoubleMap<
Hasher2,
Key2,
Value,
QueryKind=OptionQuery,
OnEmpty=GetDefault,
MaxValues=GetDefault,
QueryKind = OptionQuery,
OnEmpty = GetDefault,
MaxValues = GetDefault,
>(
core::marker::PhantomData<
(Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues)
>
core::marker::PhantomData<(
Prefix,
Hasher1,
Key1,
Hasher2,
Key2,
Value,
QueryKind,
OnEmpty,
MaxValues,
)>,
);
impl<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
crate::storage::generator::StorageDoubleMap<Key1, Key2, Value> for
StorageDoubleMap<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
crate::storage::generator::StorageDoubleMap<Key1, Key2, Value>
for StorageDoubleMap<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
where
Prefix: StorageInstance,
Hasher1: crate::hash::StorageHasher,
@@ -94,8 +102,8 @@ where
}
impl<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
StoragePrefixedMap<Value> for
StorageDoubleMap<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
StoragePrefixedMap<Value>
for StorageDoubleMap<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
where
Prefix: StorageInstance,
Hasher1: crate::hash::StorageHasher,
@@ -161,7 +169,8 @@ where
pub fn try_get<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Result<Value, ()>
where
KArg1: EncodeLike<Key1>,
KArg2: EncodeLike<Key2> {
KArg2: EncodeLike<Key2>,
{
<Self as crate::storage::StorageDoubleMap<Key1, Key2, Value>>::try_get(k1, k2)
}
@@ -175,8 +184,12 @@ where
}
/// Swap the values of two key-pairs.
pub fn swap<XKArg1, XKArg2, YKArg1, YKArg2>(x_k1: XKArg1, x_k2: XKArg2, y_k1: YKArg1, y_k2: YKArg2)
where
pub fn swap<XKArg1, XKArg2, YKArg1, YKArg2>(
x_k1: XKArg1,
x_k2: XKArg2,
y_k1: YKArg1,
y_k2: YKArg2,
) where
XKArg1: EncodeLike<Key1>,
XKArg2: EncodeLike<Key2>,
YKArg1: EncodeLike<Key1>,
@@ -206,13 +219,16 @@ where
/// Remove all values under the first key.
pub fn remove_prefix<KArg1>(k1: KArg1, limit: Option<u32>) -> sp_io::KillStorageResult
where KArg1: ?Sized + EncodeLike<Key1> {
where
KArg1: ?Sized + EncodeLike<Key1>,
{
<Self as crate::storage::StorageDoubleMap<Key1, Key2, Value>>::remove_prefix(k1, limit)
}
/// Iterate over values that share the first key.
pub fn iter_prefix_values<KArg1>(k1: KArg1) -> crate::storage::PrefixIterator<Value>
where KArg1: ?Sized + EncodeLike<Key1>
where
KArg1: ?Sized + EncodeLike<Key1>,
{
<Self as crate::storage::StorageDoubleMap<Key1, Key2, Value>>::iter_prefix_values(k1)
}
@@ -266,11 +282,8 @@ where
/// If the storage item is not encoded properly, the storage will be overwritten
/// and set to `[item]`. Any default value set for the storage item will be ignored
/// on overwrite.
pub fn append<Item, EncodeLikeItem, KArg1, KArg2>(
k1: KArg1,
k2: KArg2,
item: EncodeLikeItem,
) where
pub fn append<Item, EncodeLikeItem, KArg1, KArg2>(k1: KArg1, k2: KArg2, item: EncodeLikeItem)
where
KArg1: EncodeLike<Key1>,
KArg2: EncodeLike<Key2>,
Item: Encode,
@@ -310,10 +323,16 @@ where
OldHasher2: crate::StorageHasher,
KeyArg1: EncodeLike<Key1>,
KeyArg2: EncodeLike<Key2>,
>(key1: KeyArg1, key2: KeyArg2) -> Option<Value> {
<
Self as crate::storage::StorageDoubleMap<Key1, Key2, Value>
>::migrate_keys::<OldHasher1, OldHasher2, _, _>(key1, key2)
>(
key1: KeyArg1,
key2: KeyArg2,
) -> Option<Value> {
<Self as crate::storage::StorageDoubleMap<Key1, Key2, Value>>::migrate_keys::<
OldHasher1,
OldHasher2,
_,
_,
>(key1, key2)
}
/// Remove all value of the storage.
@@ -360,9 +379,9 @@ where
EncodeLikeItem: EncodeLike<Item>,
Value: StorageTryAppend<Item>,
{
<
Self as crate::storage::TryAppendDoubleMap<Key1, Key2, Value, Item>
>::try_append(key1, key2, item)
<Self as crate::storage::TryAppendDoubleMap<Key1, Key2, Value, Item>>::try_append(
key1, key2, item,
)
}
}
@@ -401,7 +420,9 @@ where
///
/// If you add elements with first key `k1` to the map while doing this, you'll get undefined
/// results.
pub fn drain_prefix(k1: impl EncodeLike<Key1>) -> crate::storage::PrefixIterator<(Key2, Value)> {
pub fn drain_prefix(
k1: impl EncodeLike<Key1>,
) -> crate::storage::PrefixIterator<(Key2, Value)> {
<Self as crate::storage::IterableStorageDoubleMap<Key1, Key2, Value>>::drain_prefix(k1)
}
@@ -448,8 +469,8 @@ pub trait StorageDoubleMapMetadata {
}
impl<Prefix, Hasher1, Hasher2, Key1, Key2, Value, QueryKind, OnEmpty, MaxValues>
StorageDoubleMapMetadata for
StorageDoubleMap<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
StorageDoubleMapMetadata
for StorageDoubleMap<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
where
Prefix: StorageInstance,
Hasher1: crate::hash::StorageHasher,
@@ -470,8 +491,8 @@ where
}
impl<Prefix, Hasher1, Hasher2, Key1, Key2, Value, QueryKind, OnEmpty, MaxValues>
crate::traits::StorageInfoTrait for
StorageDoubleMap<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
crate::traits::StorageInfoTrait
for StorageDoubleMap<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
where
Prefix: StorageInstance,
Hasher1: crate::hash::StorageHasher,
@@ -484,27 +505,25 @@ where
MaxValues: Get<Option<u32>>,
{
fn storage_info() -> Vec<StorageInfo> {
vec![
StorageInfo {
pallet_name: Self::module_prefix().to_vec(),
storage_name: Self::storage_prefix().to_vec(),
prefix: Self::final_prefix().to_vec(),
max_values: MaxValues::get(),
max_size: Some(
Hasher1::max_len::<Key1>()
.saturating_add(Hasher2::max_len::<Key2>())
.saturating_add(Value::max_encoded_len())
.saturated_into(),
),
}
]
vec![StorageInfo {
pallet_name: Self::module_prefix().to_vec(),
storage_name: Self::storage_prefix().to_vec(),
prefix: Self::final_prefix().to_vec(),
max_values: MaxValues::get(),
max_size: Some(
Hasher1::max_len::<Key1>()
.saturating_add(Hasher2::max_len::<Key2>())
.saturating_add(Value::max_encoded_len())
.saturated_into(),
),
}]
}
}
/// It doesn't require to implement `MaxEncodedLen` and give no information for `max_size`.
impl<Prefix, Hasher1, Hasher2, Key1, Key2, Value, QueryKind, OnEmpty, MaxValues>
crate::traits::PartialStorageInfoTrait for
StorageDoubleMap<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
crate::traits::PartialStorageInfoTrait
for StorageDoubleMap<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
where
Prefix: StorageInstance,
Hasher1: crate::hash::StorageHasher,
@@ -517,29 +536,28 @@ where
MaxValues: Get<Option<u32>>,
{
fn partial_storage_info() -> Vec<StorageInfo> {
vec![
StorageInfo {
pallet_name: Self::module_prefix().to_vec(),
storage_name: Self::storage_prefix().to_vec(),
prefix: Self::final_prefix().to_vec(),
max_values: MaxValues::get(),
max_size: None
}
]
vec![StorageInfo {
pallet_name: Self::module_prefix().to_vec(),
storage_name: Self::storage_prefix().to_vec(),
prefix: Self::final_prefix().to_vec(),
max_values: MaxValues::get(),
max_size: None,
}]
}
}
#[cfg(test)]
mod test {
use super::*;
use sp_io::{TestExternalities, hashing::twox_128};
use crate::hash::*;
use crate::storage::types::ValueQuery;
use crate::{hash::*, storage::types::ValueQuery};
use frame_metadata::StorageEntryModifier;
use sp_io::{hashing::twox_128, TestExternalities};
struct Prefix;
impl StorageInstance for Prefix {
fn pallet_prefix() -> &'static str { "test" }
fn pallet_prefix() -> &'static str {
"test"
}
const STORAGE_PREFIX: &'static str = "foo";
}
@@ -552,11 +570,17 @@ mod test {
#[test]
fn test() {
type A = StorageDoubleMap<
Prefix, Blake2_128Concat, u16, Twox64Concat, u8, u32, OptionQuery
>;
type A =
StorageDoubleMap<Prefix, Blake2_128Concat, u16, Twox64Concat, u8, u32, OptionQuery>;
type AValueQueryWithAnOnEmpty = StorageDoubleMap<
Prefix, Blake2_128Concat, u16, Twox64Concat, u8, u32, ValueQuery, ADefault
Prefix,
Blake2_128Concat,
u16,
Twox64Concat,
u8,
u32,
ValueQuery,
ADefault,
>;
type B = StorageDoubleMap<Prefix, Blake2_256, u16, Twox128, u8, u32, ValueQuery>;
type C = StorageDoubleMap<Prefix, Blake2_128Concat, u16, Twox64Concat, u8, u8, ValueQuery>;
@@ -598,17 +622,20 @@ mod test {
A::remove(2, 20);
let _: Result<(), ()> = AValueQueryWithAnOnEmpty::try_mutate(2, 20, |v| {
*v = *v * 2; Ok(())
*v = *v * 2;
Ok(())
});
let _: Result<(), ()> = AValueQueryWithAnOnEmpty::try_mutate(2, 20, |v| {
*v = *v * 2; Ok(())
*v = *v * 2;
Ok(())
});
assert_eq!(A::contains_key(2, 20), true);
assert_eq!(A::get(2, 20), Some(97 * 4));
A::remove(2, 20);
let _: Result<(), ()> = AValueQueryWithAnOnEmpty::try_mutate(2, 20, |v| {
*v = *v * 2; Err(())
*v = *v * 2;
Err(())
});
assert_eq!(A::contains_key(2, 20), false);
@@ -647,7 +674,6 @@ mod test {
assert_eq!(A::contains_key(2, 20), true);
assert_eq!(A::get(2, 20), Some(100));
A::insert(2, 20, 10);
assert_eq!(A::take(2, 20), Some(10));
assert_eq!(A::contains_key(2, 20), false);
@@ -672,7 +698,7 @@ mod test {
C::insert(3, 30, 10);
C::insert(4, 40, 10);
A::translate_values::<u8,_>(|v| Some((v * 2).into()));
A::translate_values::<u8, _>(|v| Some((v * 2).into()));
assert_eq!(A::iter().collect::<Vec<_>>(), vec![(4, 40, 20), (3, 30, 20)]);
A::insert(3, 30, 10);
@@ -683,7 +709,7 @@ mod test {
C::insert(3, 30, 10);
C::insert(4, 40, 10);
A::translate::<u8,_>(|k1, k2, v| Some((k1 * k2 as u16 * v as u16).into()));
A::translate::<u8, _>(|k1, k2, v| Some((k1 * k2 as u16 * v as u16).into()));
assert_eq!(A::iter().collect::<Vec<_>>(), vec![(4, 40, 1600), (3, 30, 900)]);
assert_eq!(A::MODIFIER, StorageEntryModifier::Optional);
@@ -75,24 +75,16 @@ impl<H: StorageHasher, K: FullCodec> KeyGenerator for Key<H, K> {
const HASHER_METADATA: &'static [frame_metadata::StorageHasher] = &[H::METADATA];
fn final_key<KArg: EncodeLikeTuple<Self::KArg> + TupleToEncodedIter>(key: KArg) -> Vec<u8> {
H::hash(
&key.to_encoded_iter()
.next()
.expect("should have at least one element!"),
)
.as_ref()
.to_vec()
H::hash(&key.to_encoded_iter().next().expect("should have at least one element!"))
.as_ref()
.to_vec()
}
fn migrate_key<KArg: EncodeLikeTuple<Self::KArg> + TupleToEncodedIter>(
key: &KArg,
hash_fns: Self::HArg,
) -> Vec<u8> {
(hash_fns.0)(
&key.to_encoded_iter()
.next()
.expect("should have at least one element!"),
)
(hash_fns.0)(&key.to_encoded_iter().next().expect("should have at least one element!"))
}
}
@@ -118,9 +110,8 @@ impl KeyGenerator for Tuple {
for_tuples!( type HArg = ( #(Tuple::HashFn),* ); );
type HashFn = Box<dyn FnOnce(&[u8]) -> Vec<u8>>;
const HASHER_METADATA: &'static [frame_metadata::StorageHasher] = &[
for_tuples!( #(Tuple::Hasher::METADATA),* )
];
const HASHER_METADATA: &'static [frame_metadata::StorageHasher] =
&[for_tuples!( #(Tuple::Hasher::METADATA),* )];
fn final_key<KArg: EncodeLikeTuple<Self::KArg> + TupleToEncodedIter>(key: KArg) -> Vec<u8> {
let mut final_key = Vec::new();
@@ -210,9 +201,7 @@ pub trait TupleToEncodedIter {
#[tuple_types_custom_trait_bound(Encode)]
impl TupleToEncodedIter for Tuple {
fn to_encoded_iter(&self) -> sp_std::vec::IntoIter<Vec<u8>> {
[for_tuples!( #(self.Tuple.encode()),* )]
.to_vec()
.into_iter()
[for_tuples!( #(self.Tuple.encode()),* )].to_vec().into_iter()
}
}
@@ -246,7 +235,7 @@ impl ReversibleKeyGenerator for Tuple {
fn decode_final_key(key_material: &[u8]) -> Result<(Self::Key, &[u8]), codec::Error> {
let mut current_key_material = key_material;
Ok((
(for_tuples!{
(for_tuples! {
#({
let (key, material) = Tuple::decode_final_key(current_key_material)?;
current_key_material = material;
@@ -18,14 +18,14 @@
//! Storage map type. Implements StorageMap, StorageIterableMap, StoragePrefixedMap traits and their
//! methods directly.
use codec::{FullCodec, Decode, EncodeLike, Encode, MaxEncodedLen};
use crate::{
storage::{
StorageAppend, StorageTryAppend, StorageDecodeLength, StoragePrefixedMap,
types::{OptionQuery, QueryKindTrait, OnEmptyGetter},
types::{OnEmptyGetter, OptionQuery, QueryKindTrait},
StorageAppend, StorageDecodeLength, StoragePrefixedMap, StorageTryAppend,
},
traits::{GetDefault, StorageInstance, Get, StorageInfo},
traits::{Get, GetDefault, StorageInfo, StorageInstance},
};
use codec::{Decode, Encode, EncodeLike, FullCodec, MaxEncodedLen};
use frame_metadata::{DefaultByteGetter, StorageEntryModifier};
use sp_arithmetic::traits::SaturatedConversion;
use sp_std::prelude::*;
@@ -35,8 +35,8 @@ use sp_std::prelude::*;
/// Each value is stored at:
/// ```nocompile
/// Twox128(Prefix::pallet_prefix())
/// ++ Twox128(Prefix::STORAGE_PREFIX)
/// ++ Hasher1(encode(key))
/// ++ Twox128(Prefix::STORAGE_PREFIX)
/// ++ Hasher1(encode(key))
/// ```
///
/// # Warning
@@ -44,10 +44,14 @@ use sp_std::prelude::*;
/// If the keys are not trusted (e.g. can be set by a user), a cryptographic `hasher` such as
/// `blake2_128_concat` must be used. Otherwise, other values in storage can be compromised.
pub struct StorageMap<
Prefix, Hasher, Key, Value, QueryKind=OptionQuery, OnEmpty=GetDefault, MaxValues=GetDefault,
>(
core::marker::PhantomData<(Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues)>
);
Prefix,
Hasher,
Key,
Value,
QueryKind = OptionQuery,
OnEmpty = GetDefault,
MaxValues = GetDefault,
>(core::marker::PhantomData<(Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues)>);
impl<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
crate::storage::generator::StorageMap<Key, Value>
@@ -77,9 +81,8 @@ where
}
}
impl<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
StoragePrefixedMap<Value> for
StorageMap<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
impl<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues> StoragePrefixedMap<Value>
for StorageMap<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
where
Prefix: StorageInstance,
Hasher: crate::hash::StorageHasher,
@@ -148,7 +151,7 @@ where
/// Mutate the value under a key.
pub fn mutate<KeyArg: EncodeLike<Key>, R, F: FnOnce(&mut QueryKind::Query) -> R>(
key: KeyArg,
f: F
f: F,
) -> R {
<Self as crate::storage::StorageMap<Key, Value>>::mutate(key, f)
}
@@ -165,7 +168,7 @@ where
/// Mutate the value under a key. Deletes the item if mutated to a `None`.
pub fn mutate_exists<KeyArg: EncodeLike<Key>, R, F: FnOnce(&mut Option<Value>) -> R>(
key: KeyArg,
f: F
f: F,
) -> R {
<Self as crate::storage::StorageMap<Key, Value>>::mutate_exists(key, f)
}
@@ -198,7 +201,7 @@ where
EncodeLikeKey: EncodeLike<Key>,
Item: Encode,
EncodeLikeItem: EncodeLike<Item>,
Value: StorageAppend<Item>
Value: StorageAppend<Item>,
{
<Self as crate::storage::StorageMap<Key, Value>>::append(key, item)
}
@@ -216,7 +219,8 @@ where
/// `None` does not mean that `get()` does not return a value. The default value is completly
/// ignored by this function.
pub fn decode_len<KeyArg: EncodeLike<Key>>(key: KeyArg) -> Option<usize>
where Value: StorageDecodeLength,
where
Value: StorageDecodeLength,
{
<Self as crate::storage::StorageMap<Key, Value>>::decode_len(key)
}
@@ -225,7 +229,7 @@ where
///
/// If the key doesn't exist, then it's a no-op. If it does, then it returns its value.
pub fn migrate_key<OldHasher: crate::hash::StorageHasher, KeyArg: EncodeLike<Key>>(
key: KeyArg
key: KeyArg,
) -> Option<Value> {
<Self as crate::storage::StorageMap<Key, Value>>::migrate_key::<OldHasher, _>(key)
}
@@ -263,19 +267,14 @@ where
/// Try and append the given item to the value in the storage.
///
/// Is only available if `Value` of the storage implements [`StorageTryAppend`].
pub fn try_append<KArg, Item, EncodeLikeItem>(
key: KArg,
item: EncodeLikeItem,
) -> Result<(), ()>
pub fn try_append<KArg, Item, EncodeLikeItem>(key: KArg, item: EncodeLikeItem) -> Result<(), ()>
where
KArg: EncodeLike<Key> + Clone,
Item: Encode,
EncodeLikeItem: EncodeLike<Item>,
Value: StorageTryAppend<Item>,
{
<
Self as crate::storage::TryAppendMap<Key, Value, Item>
>::try_append(key, item)
<Self as crate::storage::TryAppendMap<Key, Value, Item>>::try_append(key, item)
}
}
@@ -332,7 +331,8 @@ pub trait StorageMapMetadata {
}
impl<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues> StorageMapMetadata
for StorageMap<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues> where
for StorageMap<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
where
Prefix: StorageInstance,
Hasher: crate::hash::StorageHasher,
Key: FullCodec,
@@ -348,9 +348,8 @@ impl<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues> StorageMapMetada
DefaultByteGetter(&OnEmptyGetter::<QueryKind::Query, OnEmpty>(core::marker::PhantomData));
}
impl<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
crate::traits::StorageInfoTrait for
StorageMap<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
impl<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues> crate::traits::StorageInfoTrait
for StorageMap<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
where
Prefix: StorageInstance,
Hasher: crate::hash::StorageHasher,
@@ -361,26 +360,24 @@ where
MaxValues: Get<Option<u32>>,
{
fn storage_info() -> Vec<StorageInfo> {
vec![
StorageInfo {
pallet_name: Self::module_prefix().to_vec(),
storage_name: Self::storage_prefix().to_vec(),
prefix: Self::final_prefix().to_vec(),
max_values: MaxValues::get(),
max_size: Some(
Hasher::max_len::<Key>()
.saturating_add(Value::max_encoded_len())
.saturated_into(),
),
}
]
vec![StorageInfo {
pallet_name: Self::module_prefix().to_vec(),
storage_name: Self::storage_prefix().to_vec(),
prefix: Self::final_prefix().to_vec(),
max_values: MaxValues::get(),
max_size: Some(
Hasher::max_len::<Key>()
.saturating_add(Value::max_encoded_len())
.saturated_into(),
),
}]
}
}
/// It doesn't require to implement `MaxEncodedLen` and give no information for `max_size`.
impl<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
crate::traits::PartialStorageInfoTrait for
StorageMap<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
crate::traits::PartialStorageInfoTrait
for StorageMap<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
where
Prefix: StorageInstance,
Hasher: crate::hash::StorageHasher,
@@ -391,29 +388,28 @@ where
MaxValues: Get<Option<u32>>,
{
fn partial_storage_info() -> Vec<StorageInfo> {
vec![
StorageInfo {
pallet_name: Self::module_prefix().to_vec(),
storage_name: Self::storage_prefix().to_vec(),
prefix: Self::final_prefix().to_vec(),
max_values: MaxValues::get(),
max_size: None,
}
]
vec![StorageInfo {
pallet_name: Self::module_prefix().to_vec(),
storage_name: Self::storage_prefix().to_vec(),
prefix: Self::final_prefix().to_vec(),
max_values: MaxValues::get(),
max_size: None,
}]
}
}
#[cfg(test)]
mod test {
use super::*;
use sp_io::{TestExternalities, hashing::twox_128};
use crate::hash::*;
use crate::storage::types::ValueQuery;
use crate::{hash::*, storage::types::ValueQuery};
use frame_metadata::StorageEntryModifier;
use sp_io::{hashing::twox_128, TestExternalities};
struct Prefix;
impl StorageInstance for Prefix {
fn pallet_prefix() -> &'static str { "test" }
fn pallet_prefix() -> &'static str {
"test"
}
const STORAGE_PREFIX: &'static str = "foo";
}
@@ -427,9 +423,8 @@ mod test {
#[test]
fn test() {
type A = StorageMap<Prefix, Blake2_128Concat, u16, u32, OptionQuery>;
type AValueQueryWithAnOnEmpty = StorageMap<
Prefix, Blake2_128Concat, u16, u32, ValueQuery, ADefault
>;
type AValueQueryWithAnOnEmpty =
StorageMap<Prefix, Blake2_128Concat, u16, u32, ValueQuery, ADefault>;
type B = StorageMap<Prefix, Blake2_256, u16, u32, ValueQuery>;
type C = StorageMap<Prefix, Blake2_128Concat, u16, u8, ValueQuery>;
type WithLen = StorageMap<Prefix, Blake2_128Concat, u16, Vec<u32>>;
@@ -471,17 +466,20 @@ mod test {
A::remove(2);
let _: Result<(), ()> = AValueQueryWithAnOnEmpty::try_mutate(2, |v| {
*v = *v * 2; Ok(())
*v = *v * 2;
Ok(())
});
let _: Result<(), ()> = AValueQueryWithAnOnEmpty::try_mutate(2, |v| {
*v = *v * 2; Ok(())
*v = *v * 2;
Ok(())
});
assert_eq!(A::contains_key(2), true);
assert_eq!(A::get(2), Some(97 * 4));
A::remove(2);
let _: Result<(), ()> = AValueQueryWithAnOnEmpty::try_mutate(2, |v| {
*v = *v * 2; Err(())
*v = *v * 2;
Err(())
});
assert_eq!(A::contains_key(2), false);
@@ -519,7 +517,6 @@ mod test {
assert_eq!(A::contains_key(2), true);
assert_eq!(A::get(2), Some(100));
A::insert(2, 10);
assert_eq!(A::take(2), Some(10));
assert_eq!(A::contains_key(2), false);
@@ -543,7 +540,7 @@ mod test {
C::insert(3, 10);
C::insert(4, 10);
A::translate_values::<u8,_>(|v| Some((v * 2).into()));
A::translate_values::<u8, _>(|v| Some((v * 2).into()));
assert_eq!(A::iter().collect::<Vec<_>>(), vec![(4, 20), (3, 20)]);
A::insert(3, 10);
@@ -554,7 +551,7 @@ mod test {
C::insert(3, 10);
C::insert(4, 10);
A::translate::<u8,_>(|k, v| Some((k * v as u16).into()));
A::translate::<u8, _>(|k, v| Some((k * v as u16).into()));
assert_eq!(A::iter().collect::<Vec<_>>(), vec![(4, 40), (3, 30)]);
assert_eq!(A::MODIFIER, StorageEntryModifier::Optional);
@@ -30,7 +30,7 @@ mod value;
pub use double_map::{StorageDoubleMap, StorageDoubleMapMetadata};
pub use key::{
EncodeLikeTuple, HasKeyPrefix, HasReversibleKeyPrefix, Key, KeyGenerator,
ReversibleKeyGenerator, TupleToEncodedIter, KeyGeneratorMaxEncodedLen,
KeyGeneratorMaxEncodedLen, ReversibleKeyGenerator, TupleToEncodedIter,
};
pub use map::{StorageMap, StorageMapMetadata};
pub use nmap::{StorageNMap, StorageNMapMetadata};
+80 -156
View File
@@ -21,12 +21,12 @@
use crate::{
storage::{
types::{
EncodeLikeTuple, HasKeyPrefix, HasReversibleKeyPrefix, OnEmptyGetter,
OptionQuery, QueryKindTrait, TupleToEncodedIter,
EncodeLikeTuple, HasKeyPrefix, HasReversibleKeyPrefix, OnEmptyGetter, OptionQuery,
QueryKindTrait, TupleToEncodedIter,
},
KeyGenerator, PrefixIterator, StorageAppend, StorageDecodeLength, StoragePrefixedMap,
},
traits::{Get, GetDefault, StorageInstance, StorageInfo},
traits::{Get, GetDefault, StorageInfo, StorageInstance},
};
use codec::{Decode, Encode, EncodeLike, FullCodec, MaxEncodedLen};
use frame_metadata::{DefaultByteGetter, StorageEntryModifier};
@@ -39,9 +39,9 @@ use sp_std::prelude::*;
/// Each value is stored at:
/// ```nocompile
/// Twox128(Prefix::pallet_prefix())
/// ++ Twox128(Prefix::STORAGE_PREFIX)
/// ++ Hasher1(encode(key1))
/// ++ Hasher2(encode(key2))
/// ++ Twox128(Prefix::STORAGE_PREFIX)
/// ++ Hasher1(encode(key1))
/// ++ Hasher2(encode(key2))
/// ++ ...
/// ++ HasherN(encode(keyN))
/// ```
@@ -52,10 +52,13 @@ use sp_std::prelude::*;
/// such as `blake2_128_concat` must be used for the key hashers. Otherwise, other values
/// in storage can be compromised.
pub struct StorageNMap<
Prefix, Key, Value, QueryKind = OptionQuery, OnEmpty = GetDefault, MaxValues=GetDefault,
>(
core::marker::PhantomData<(Prefix, Key, Value, QueryKind, OnEmpty, MaxValues)>,
);
Prefix,
Key,
Value,
QueryKind = OptionQuery,
OnEmpty = GetDefault,
MaxValues = GetDefault,
>(core::marker::PhantomData<(Prefix, Key, Value, QueryKind, OnEmpty, MaxValues)>);
impl<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues>
crate::storage::generator::StorageNMap<Key, Value>
@@ -83,8 +86,7 @@ where
}
}
impl<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues>
crate::storage::StoragePrefixedMap<Value>
impl<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues> crate::storage::StoragePrefixedMap<Value>
for StorageNMap<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues>
where
Prefix: StorageInstance,
@@ -113,7 +115,9 @@ where
MaxValues: Get<Option<u32>>,
{
/// Get the storage key used to fetch a value corresponding to a specific key.
pub fn hashed_key_for<KArg: EncodeLikeTuple<Key::KArg> + TupleToEncodedIter>(key: KArg) -> Vec<u8> {
pub fn hashed_key_for<KArg: EncodeLikeTuple<Key::KArg> + TupleToEncodedIter>(
key: KArg,
) -> Vec<u8> {
<Self as crate::storage::StorageNMap<Key, Value>>::hashed_key_for(key)
}
@@ -123,7 +127,9 @@ where
}
/// Load the value associated with the given key from the map.
pub fn get<KArg: EncodeLikeTuple<Key::KArg> + TupleToEncodedIter>(key: KArg) -> QueryKind::Query {
pub fn get<KArg: EncodeLikeTuple<Key::KArg> + TupleToEncodedIter>(
key: KArg,
) -> QueryKind::Query {
<Self as crate::storage::StorageNMap<Key, Value>>::get(key)
}
@@ -137,7 +143,9 @@ where
}
/// Take a value from storage, removing it afterwards.
pub fn take<KArg: EncodeLikeTuple<Key::KArg> + TupleToEncodedIter>(key: KArg) -> QueryKind::Query {
pub fn take<KArg: EncodeLikeTuple<Key::KArg> + TupleToEncodedIter>(
key: KArg,
) -> QueryKind::Query {
<Self as crate::storage::StorageNMap<Key, Value>>::take(key)
}
@@ -248,7 +256,9 @@ where
///
/// `None` does not mean that `get()` does not return a value. The default value is completly
/// ignored by this function.
pub fn decode_len<KArg: EncodeLikeTuple<Key::KArg> + TupleToEncodedIter>(key: KArg) -> Option<usize>
pub fn decode_len<KArg: EncodeLikeTuple<Key::KArg> + TupleToEncodedIter>(
key: KArg,
) -> Option<usize>
where
Value: StorageDecodeLength,
{
@@ -260,7 +270,7 @@ where
/// If the key doesn't exist, then it's a no-op. If it does, then it returns its value.
pub fn migrate_keys<KArg>(key: KArg, hash_fns: Key::HArg) -> Option<Value>
where
KArg: EncodeLikeTuple<Key::KArg> + TupleToEncodedIter
KArg: EncodeLikeTuple<Key::KArg> + TupleToEncodedIter,
{
<Self as crate::storage::StorageNMap<Key, Value>>::migrate_keys::<_>(key, hash_fns)
}
@@ -398,15 +408,13 @@ where
{
const MODIFIER: StorageEntryModifier = QueryKind::METADATA;
const NAME: &'static str = Prefix::STORAGE_PREFIX;
const DEFAULT: DefaultByteGetter = DefaultByteGetter(
&OnEmptyGetter::<QueryKind::Query, OnEmpty>(core::marker::PhantomData),
);
const DEFAULT: DefaultByteGetter =
DefaultByteGetter(&OnEmptyGetter::<QueryKind::Query, OnEmpty>(core::marker::PhantomData));
const HASHERS: &'static [frame_metadata::StorageHasher] = Key::HASHER_METADATA;
}
impl<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues>
crate::traits::StorageInfoTrait for
StorageNMap<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues>
impl<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues> crate::traits::StorageInfoTrait
for StorageNMap<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues>
where
Prefix: StorageInstance,
Key: super::key::KeyGenerator + super::key::KeyGeneratorMaxEncodedLen,
@@ -416,26 +424,23 @@ where
MaxValues: Get<Option<u32>>,
{
fn storage_info() -> Vec<StorageInfo> {
vec![
StorageInfo {
pallet_name: Self::module_prefix().to_vec(),
storage_name: Self::storage_prefix().to_vec(),
prefix: Self::final_prefix().to_vec(),
max_values: MaxValues::get(),
max_size: Some(
Key::key_max_encoded_len()
.saturating_add(Value::max_encoded_len())
.saturated_into(),
),
}
]
vec![StorageInfo {
pallet_name: Self::module_prefix().to_vec(),
storage_name: Self::storage_prefix().to_vec(),
prefix: Self::final_prefix().to_vec(),
max_values: MaxValues::get(),
max_size: Some(
Key::key_max_encoded_len()
.saturating_add(Value::max_encoded_len())
.saturated_into(),
),
}]
}
}
/// It doesn't require to implement `MaxEncodedLen` and give no information for `max_size`.
impl<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues>
crate::traits::PartialStorageInfoTrait for
StorageNMap<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues>
impl<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues> crate::traits::PartialStorageInfoTrait
for StorageNMap<Prefix, Key, Value, QueryKind, OnEmpty, MaxValues>
where
Prefix: StorageInstance,
Key: super::key::KeyGenerator,
@@ -445,22 +450,22 @@ where
MaxValues: Get<Option<u32>>,
{
fn partial_storage_info() -> Vec<StorageInfo> {
vec![
StorageInfo {
pallet_name: Self::module_prefix().to_vec(),
storage_name: Self::storage_prefix().to_vec(),
prefix: Self::final_prefix().to_vec(),
max_values: MaxValues::get(),
max_size: None,
}
]
vec![StorageInfo {
pallet_name: Self::module_prefix().to_vec(),
storage_name: Self::storage_prefix().to_vec(),
prefix: Self::final_prefix().to_vec(),
max_values: MaxValues::get(),
max_size: None,
}]
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::hash::*;
use crate::storage::types::{Key, ValueQuery};
use crate::{
hash::*,
storage::types::{Key, ValueQuery},
};
use frame_metadata::StorageEntryModifier;
use sp_io::{hashing::twox_128, TestExternalities};
@@ -627,15 +632,9 @@ mod test {
assert_eq!(A::iter().collect::<Vec<_>>(), vec![(4, 40), (3, 30)]);
assert_eq!(A::MODIFIER, StorageEntryModifier::Optional);
assert_eq!(
AValueQueryWithAnOnEmpty::MODIFIER,
StorageEntryModifier::Default
);
assert_eq!(AValueQueryWithAnOnEmpty::MODIFIER, StorageEntryModifier::Default);
assert_eq!(A::NAME, "Foo");
assert_eq!(
AValueQueryWithAnOnEmpty::DEFAULT.0.default_byte(),
98u32.encode()
);
assert_eq!(AValueQueryWithAnOnEmpty::DEFAULT.0.default_byte(), 98u32.encode());
assert_eq!(A::DEFAULT.0.default_byte(), Option::<u32>::None.encode());
WithLen::remove_all(None);
@@ -787,41 +786,23 @@ mod test {
C::insert((3, 30), 10);
C::insert((4, 40), 10);
A::translate_values::<u8, _>(|v| Some((v * 2).into()));
assert_eq!(
A::iter().collect::<Vec<_>>(),
vec![((4, 40), 20), ((3, 30), 20)]
);
assert_eq!(A::iter().collect::<Vec<_>>(), vec![((4, 40), 20), ((3, 30), 20)]);
A::insert((3, 30), 10);
A::insert((4, 40), 10);
assert_eq!(
A::iter().collect::<Vec<_>>(),
vec![((4, 40), 10), ((3, 30), 10)]
);
assert_eq!(
A::drain().collect::<Vec<_>>(),
vec![((4, 40), 10), ((3, 30), 10)]
);
assert_eq!(A::iter().collect::<Vec<_>>(), vec![((4, 40), 10), ((3, 30), 10)]);
assert_eq!(A::drain().collect::<Vec<_>>(), vec![((4, 40), 10), ((3, 30), 10)]);
assert_eq!(A::iter().collect::<Vec<_>>(), vec![]);
C::insert((3, 30), 10);
C::insert((4, 40), 10);
A::translate::<u8, _>(|(k1, k2), v| Some((k1 * k2 as u16 * v as u16).into()));
assert_eq!(
A::iter().collect::<Vec<_>>(),
vec![((4, 40), 1600), ((3, 30), 900)]
);
assert_eq!(A::iter().collect::<Vec<_>>(), vec![((4, 40), 1600), ((3, 30), 900)]);
assert_eq!(A::MODIFIER, StorageEntryModifier::Optional);
assert_eq!(
AValueQueryWithAnOnEmpty::MODIFIER,
StorageEntryModifier::Default
);
assert_eq!(AValueQueryWithAnOnEmpty::MODIFIER, StorageEntryModifier::Default);
assert_eq!(A::NAME, "Foo");
assert_eq!(
AValueQueryWithAnOnEmpty::DEFAULT.0.default_byte(),
98u32.encode()
);
assert_eq!(AValueQueryWithAnOnEmpty::DEFAULT.0.default_byte(), 98u32.encode());
assert_eq!(A::DEFAULT.0.default_byte(), Option::<u32>::None.encode());
WithLen::remove_all(None);
@@ -833,14 +814,8 @@ mod test {
A::insert((3, 31), 12);
A::insert((4, 40), 13);
A::insert((4, 41), 14);
assert_eq!(
A::iter_prefix_values((3,)).collect::<Vec<_>>(),
vec![12, 11]
);
assert_eq!(
A::iter_prefix_values((4,)).collect::<Vec<_>>(),
vec![13, 14]
);
assert_eq!(A::iter_prefix_values((3,)).collect::<Vec<_>>(), vec![12, 11]);
assert_eq!(A::iter_prefix_values((4,)).collect::<Vec<_>>(), vec![13, 14]);
});
}
@@ -848,52 +823,32 @@ mod test {
fn test_3_keys() {
type A = StorageNMap<
Prefix,
(
Key<Blake2_128Concat, u16>,
Key<Blake2_128Concat, u16>,
Key<Twox64Concat, u16>,
),
(Key<Blake2_128Concat, u16>, Key<Blake2_128Concat, u16>, Key<Twox64Concat, u16>),
u32,
OptionQuery,
>;
type AValueQueryWithAnOnEmpty = StorageNMap<
Prefix,
(
Key<Blake2_128Concat, u16>,
Key<Blake2_128Concat, u16>,
Key<Twox64Concat, u16>,
),
(Key<Blake2_128Concat, u16>, Key<Blake2_128Concat, u16>, Key<Twox64Concat, u16>),
u32,
ValueQuery,
ADefault,
>;
type B = StorageNMap<
Prefix,
(
Key<Blake2_256, u16>,
Key<Blake2_256, u16>,
Key<Twox128, u16>,
),
(Key<Blake2_256, u16>, Key<Blake2_256, u16>, Key<Twox128, u16>),
u32,
ValueQuery,
>;
type C = StorageNMap<
Prefix,
(
Key<Blake2_128Concat, u16>,
Key<Blake2_128Concat, u16>,
Key<Twox64Concat, u16>,
),
(Key<Blake2_128Concat, u16>, Key<Blake2_128Concat, u16>, Key<Twox64Concat, u16>),
u8,
ValueQuery,
>;
type WithLen = StorageNMap<
Prefix,
(
Key<Blake2_128Concat, u16>,
Key<Blake2_128Concat, u16>,
Key<Twox64Concat, u16>,
),
(Key<Blake2_128Concat, u16>, Key<Blake2_128Concat, u16>, Key<Twox64Concat, u16>),
Vec<u32>,
>;
@@ -916,11 +871,7 @@ mod test {
assert_eq!(AValueQueryWithAnOnEmpty::get((1, 10, 100)), 30);
A::swap::<
(
Key<Blake2_128Concat, u16>,
Key<Blake2_128Concat, u16>,
Key<Twox64Concat, u16>,
),
(Key<Blake2_128Concat, u16>, Key<Blake2_128Concat, u16>, Key<Twox64Concat, u16>),
_,
_,
>((1, 10, 100), (2, 20, 200));
@@ -1020,17 +971,11 @@ mod test {
C::insert((3, 30, 300), 10);
C::insert((4, 40, 400), 10);
A::translate_values::<u8, _>(|v| Some((v * 2).into()));
assert_eq!(
A::iter().collect::<Vec<_>>(),
vec![((4, 40, 400), 20), ((3, 30, 300), 20)]
);
assert_eq!(A::iter().collect::<Vec<_>>(), vec![((4, 40, 400), 20), ((3, 30, 300), 20)]);
A::insert((3, 30, 300), 10);
A::insert((4, 40, 400), 10);
assert_eq!(
A::iter().collect::<Vec<_>>(),
vec![((4, 40, 400), 10), ((3, 30, 300), 10)]
);
assert_eq!(A::iter().collect::<Vec<_>>(), vec![((4, 40, 400), 10), ((3, 30, 300), 10)]);
assert_eq!(
A::drain().collect::<Vec<_>>(),
vec![((4, 40, 400), 10), ((3, 30, 300), 10)]
@@ -1042,21 +987,12 @@ mod test {
A::translate::<u8, _>(|(k1, k2, k3), v| {
Some((k1 * k2 as u16 * v as u16 / k3 as u16).into())
});
assert_eq!(
A::iter().collect::<Vec<_>>(),
vec![((4, 40, 400), 4), ((3, 30, 300), 3)]
);
assert_eq!(A::iter().collect::<Vec<_>>(), vec![((4, 40, 400), 4), ((3, 30, 300), 3)]);
assert_eq!(A::MODIFIER, StorageEntryModifier::Optional);
assert_eq!(
AValueQueryWithAnOnEmpty::MODIFIER,
StorageEntryModifier::Default
);
assert_eq!(AValueQueryWithAnOnEmpty::MODIFIER, StorageEntryModifier::Default);
assert_eq!(A::NAME, "Foo");
assert_eq!(
AValueQueryWithAnOnEmpty::DEFAULT.0.default_byte(),
98u32.encode()
);
assert_eq!(AValueQueryWithAnOnEmpty::DEFAULT.0.default_byte(), 98u32.encode());
assert_eq!(A::DEFAULT.0.default_byte(), Option::<u32>::None.encode());
WithLen::remove_all(None);
@@ -1068,22 +1004,10 @@ mod test {
A::insert((3, 30, 301), 12);
A::insert((4, 40, 400), 13);
A::insert((4, 40, 401), 14);
assert_eq!(
A::iter_prefix_values((3,)).collect::<Vec<_>>(),
vec![11, 12]
);
assert_eq!(
A::iter_prefix_values((4,)).collect::<Vec<_>>(),
vec![14, 13]
);
assert_eq!(
A::iter_prefix_values((3, 30)).collect::<Vec<_>>(),
vec![11, 12]
);
assert_eq!(
A::iter_prefix_values((4, 40)).collect::<Vec<_>>(),
vec![14, 13]
);
assert_eq!(A::iter_prefix_values((3,)).collect::<Vec<_>>(), vec![11, 12]);
assert_eq!(A::iter_prefix_values((4,)).collect::<Vec<_>>(), vec![14, 13]);
assert_eq!(A::iter_prefix_values((3, 30)).collect::<Vec<_>>(), vec![11, 12]);
assert_eq!(A::iter_prefix_values((4, 40)).collect::<Vec<_>>(), vec![14, 13]);
});
}
}
@@ -17,15 +17,15 @@
//! Storage value type. Implements StorageValue trait and its method directly.
use codec::{FullCodec, Decode, EncodeLike, Encode, MaxEncodedLen};
use crate::{
storage::{
StorageAppend, StorageTryAppend, StorageDecodeLength,
types::{OptionQuery, QueryKindTrait, OnEmptyGetter},
generator::{StorageValue as StorageValueT},
generator::StorageValue as StorageValueT,
types::{OnEmptyGetter, OptionQuery, QueryKindTrait},
StorageAppend, StorageDecodeLength, StorageTryAppend,
},
traits::{GetDefault, StorageInstance, StorageInfo},
traits::{GetDefault, StorageInfo, StorageInstance},
};
use codec::{Decode, Encode, EncodeLike, FullCodec, MaxEncodedLen};
use frame_metadata::{DefaultByteGetter, StorageEntryModifier};
use sp_arithmetic::traits::SaturatedConversion;
use sp_std::prelude::*;
@@ -36,12 +36,12 @@ use sp_std::prelude::*;
/// ```nocompile
/// Twox128(Prefix::pallet_prefix()) ++ Twox128(Prefix::STORAGE_PREFIX)
/// ```
pub struct StorageValue<Prefix, Value, QueryKind=OptionQuery, OnEmpty=GetDefault>(
core::marker::PhantomData<(Prefix, Value, QueryKind, OnEmpty)>
pub struct StorageValue<Prefix, Value, QueryKind = OptionQuery, OnEmpty = GetDefault>(
core::marker::PhantomData<(Prefix, Value, QueryKind, OnEmpty)>,
);
impl<Prefix, Value, QueryKind, OnEmpty> crate::storage::generator::StorageValue<Value> for
StorageValue<Prefix, Value, QueryKind, OnEmpty>
impl<Prefix, Value, QueryKind, OnEmpty> crate::storage::generator::StorageValue<Value>
for StorageValue<Prefix, Value, QueryKind, OnEmpty>
where
Prefix: StorageInstance,
Value: FullCodec,
@@ -71,13 +71,19 @@ where
OnEmpty: crate::traits::Get<QueryKind::Query> + 'static,
{
/// Get the storage key.
pub fn hashed_key() -> [u8; 32] { <Self as crate::storage::StorageValue<Value>>::hashed_key() }
pub fn hashed_key() -> [u8; 32] {
<Self as crate::storage::StorageValue<Value>>::hashed_key()
}
/// Does the value (explicitly) exist in storage?
pub fn exists() -> bool { <Self as crate::storage::StorageValue<Value>>::exists() }
pub fn exists() -> bool {
<Self as crate::storage::StorageValue<Value>>::exists()
}
/// Load the value from the provided storage instance.
pub fn get() -> QueryKind::Query { <Self as crate::storage::StorageValue<Value>>::get() }
pub fn get() -> QueryKind::Query {
<Self as crate::storage::StorageValue<Value>>::get()
}
/// Try to get the underlying value from the provided storage instance; `Ok` if it exists,
/// `Err` if not.
@@ -120,7 +126,9 @@ where
/// Store a value under this key into the provided storage instance.
///
/// this uses the query type rather than the underlying value.
pub fn set(val: QueryKind::Query) { <Self as crate::storage::StorageValue<Value>>::set(val) }
pub fn set(val: QueryKind::Query) {
<Self as crate::storage::StorageValue<Value>>::set(val)
}
/// Mutate the value
pub fn mutate<R, F: FnOnce(&mut QueryKind::Query) -> R>(f: F) -> R {
@@ -135,10 +143,14 @@ where
}
/// Clear the storage value.
pub fn kill() { <Self as crate::storage::StorageValue<Value>>::kill() }
pub fn kill() {
<Self as crate::storage::StorageValue<Value>>::kill()
}
/// Take a value from storage, removing it afterwards.
pub fn take() -> QueryKind::Query { <Self as crate::storage::StorageValue<Value>>::take() }
pub fn take() -> QueryKind::Query {
<Self as crate::storage::StorageValue<Value>>::take()
}
/// Append the given item to the value in the storage.
///
@@ -153,7 +165,7 @@ where
where
Item: Encode,
EncodeLikeItem: EncodeLike<Item>,
Value: StorageAppend<Item>
Value: StorageAppend<Item>,
{
<Self as crate::storage::StorageValue<Value>>::append(item)
}
@@ -169,7 +181,10 @@ where
///
/// `None` does not mean that `get()` does not return a value. The default value is completly
/// ignored by this function.
pub fn decode_len() -> Option<usize> where Value: StorageDecodeLength {
pub fn decode_len() -> Option<usize>
where
Value: StorageDecodeLength,
{
<Self as crate::storage::StorageValue<Value>>::decode_len()
}
@@ -194,7 +209,8 @@ pub trait StorageValueMetadata {
}
impl<Prefix, Value, QueryKind, OnEmpty> StorageValueMetadata
for StorageValue<Prefix, Value, QueryKind, OnEmpty> where
for StorageValue<Prefix, Value, QueryKind, OnEmpty>
where
Prefix: StorageInstance,
Value: FullCodec,
QueryKind: QueryKindTrait<Value, OnEmpty>,
@@ -206,64 +222,57 @@ impl<Prefix, Value, QueryKind, OnEmpty> StorageValueMetadata
DefaultByteGetter(&OnEmptyGetter::<QueryKind::Query, OnEmpty>(core::marker::PhantomData));
}
impl<Prefix, Value, QueryKind, OnEmpty>
crate::traits::StorageInfoTrait for
StorageValue<Prefix, Value, QueryKind, OnEmpty>
impl<Prefix, Value, QueryKind, OnEmpty> crate::traits::StorageInfoTrait
for StorageValue<Prefix, Value, QueryKind, OnEmpty>
where
Prefix: StorageInstance,
Value: FullCodec + MaxEncodedLen,
QueryKind: QueryKindTrait<Value, OnEmpty>,
OnEmpty: crate::traits::Get<QueryKind::Query> + 'static
OnEmpty: crate::traits::Get<QueryKind::Query> + 'static,
{
fn storage_info() -> Vec<StorageInfo> {
vec![
StorageInfo {
pallet_name: Self::module_prefix().to_vec(),
storage_name: Self::storage_prefix().to_vec(),
prefix: Self::hashed_key().to_vec(),
max_values: Some(1),
max_size: Some(
Value::max_encoded_len()
.saturated_into(),
),
}
]
vec![StorageInfo {
pallet_name: Self::module_prefix().to_vec(),
storage_name: Self::storage_prefix().to_vec(),
prefix: Self::hashed_key().to_vec(),
max_values: Some(1),
max_size: Some(Value::max_encoded_len().saturated_into()),
}]
}
}
/// It doesn't require to implement `MaxEncodedLen` and give no information for `max_size`.
impl<Prefix, Value, QueryKind, OnEmpty>
crate::traits::PartialStorageInfoTrait for
StorageValue<Prefix, Value, QueryKind, OnEmpty>
impl<Prefix, Value, QueryKind, OnEmpty> crate::traits::PartialStorageInfoTrait
for StorageValue<Prefix, Value, QueryKind, OnEmpty>
where
Prefix: StorageInstance,
Value: FullCodec,
QueryKind: QueryKindTrait<Value, OnEmpty>,
OnEmpty: crate::traits::Get<QueryKind::Query> + 'static
OnEmpty: crate::traits::Get<QueryKind::Query> + 'static,
{
fn partial_storage_info() -> Vec<StorageInfo> {
vec![
StorageInfo {
pallet_name: Self::module_prefix().to_vec(),
storage_name: Self::storage_prefix().to_vec(),
prefix: Self::hashed_key().to_vec(),
max_values: Some(1),
max_size: None,
}
]
vec![StorageInfo {
pallet_name: Self::module_prefix().to_vec(),
storage_name: Self::storage_prefix().to_vec(),
prefix: Self::hashed_key().to_vec(),
max_values: Some(1),
max_size: None,
}]
}
}
#[cfg(test)]
mod test {
use super::*;
use sp_io::{TestExternalities, hashing::twox_128};
use crate::storage::types::ValueQuery;
use frame_metadata::StorageEntryModifier;
use sp_io::{hashing::twox_128, TestExternalities};
struct Prefix;
impl StorageInstance for Prefix {
fn pallet_prefix() -> &'static str { "test" }
fn pallet_prefix() -> &'static str {
"test"
}
const STORAGE_PREFIX: &'static str = "foo";
}
@@ -309,10 +318,16 @@ mod test {
assert_eq!(A::try_get(), Ok(4));
A::set(Some(4));
let _: Result<(), ()> = A::try_mutate(|v| { *v = Some(v.unwrap() * 2); Ok(()) });
let _: Result<(), ()> = A::try_mutate(|v| {
*v = Some(v.unwrap() * 2);
Ok(())
});
assert_eq!(A::try_get(), Ok(8));
let _: Result<(), ()> = A::try_mutate(|v| { *v = Some(v.unwrap() * 2); Err(()) });
let _: Result<(), ()> = A::try_mutate(|v| {
*v = Some(v.unwrap() * 2);
Err(())
});
assert_eq!(A::try_get(), Ok(8));
A::kill();
@@ -321,7 +336,8 @@ mod test {
AValueQueryWithAnOnEmpty::kill();
let _: Result<(), ()> = AValueQueryWithAnOnEmpty::try_mutate(|v| {
*v = *v * 2; Ok(())
*v = *v * 2;
Ok(())
});
assert_eq!(AValueQueryWithAnOnEmpty::try_get(), Ok(97 * 2));
@@ -17,8 +17,8 @@
//! Operation on unhashed runtime storage.
use codec::{Decode, Encode};
use sp_std::prelude::*;
use codec::{Encode, Decode};
/// Return the value of the item in storage under `key`, or `None` if there is no explicit entry.
pub fn get<T: Decode + Sized>(key: &[u8]) -> Option<T> {
@@ -18,17 +18,16 @@
//! Traits, types and structs to support putting a bounded vector into storage, as a raw value, map
//! or a double map.
use sp_std::prelude::*;
use sp_std::{convert::TryFrom, fmt, marker::PhantomData};
use codec::{Encode, Decode, MaxEncodedLen};
use crate::{
storage::{StorageDecodeLength, StorageTryAppend},
traits::Get,
};
use codec::{Decode, Encode, MaxEncodedLen};
use core::{
ops::{Deref, Index, IndexMut},
slice::SliceIndex,
};
use crate::{
traits::Get,
storage::{StorageDecodeLength, StorageTryAppend},
};
use sp_std::{convert::TryFrom, fmt, marker::PhantomData, prelude::*};
/// A weakly bounded vector.
///
@@ -317,9 +316,9 @@ where
#[cfg(test)]
pub mod test {
use super::*;
use crate::Twox128;
use sp_io::TestExternalities;
use sp_std::convert::TryInto;
use crate::Twox128;
crate::parameter_types! {
pub const Seven: u32 = 7;
+29 -24
View File
@@ -20,62 +20,67 @@
//! NOTE: If you're looking for `parameter_types`, it has moved in to the top-level module.
pub mod tokens;
pub use tokens::fungible;
pub use tokens::fungibles;
pub use tokens::currency::{
Currency, LockIdentifier, LockableCurrency, ReservableCurrency, NamedReservableCurrency,
VestingSchedule,
pub use tokens::{
currency::{
Currency, LockIdentifier, LockableCurrency, NamedReservableCurrency, ReservableCurrency,
VestingSchedule,
},
fungible, fungibles,
imbalance::{Imbalance, OnUnbalanced, SignedImbalance},
BalanceStatus, ExistenceRequirement, WithdrawReasons,
};
pub use tokens::imbalance::{Imbalance, OnUnbalanced, SignedImbalance};
pub use tokens::{ExistenceRequirement, WithdrawReasons, BalanceStatus};
mod members;
pub use members::{
Contains, ContainsLengthBound, SortedMembers, InitializeMembers, ChangeMembers, All, IsInVec,
AsContains,
All, AsContains, ChangeMembers, Contains, ContainsLengthBound, InitializeMembers, IsInVec,
SortedMembers,
};
mod validation;
pub use validation::{
ValidatorSet, ValidatorSetWithIdentification, OneSessionHandler, FindAuthor, VerifySeal,
EstimateNextNewSession, EstimateNextSessionRotation, KeyOwnerProofSystem, ValidatorRegistration,
Lateness,
EstimateNextNewSession, EstimateNextSessionRotation, FindAuthor, KeyOwnerProofSystem, Lateness,
OneSessionHandler, ValidatorRegistration, ValidatorSet, ValidatorSetWithIdentification,
VerifySeal,
};
mod filter;
pub use filter::{
Filter, FilterStack, FilterStackGuard, ClearFilterGuard, InstanceFilter, IntegrityTest,
AllowAll, DenyAll,
AllowAll, ClearFilterGuard, DenyAll, Filter, FilterStack, FilterStackGuard, InstanceFilter,
IntegrityTest,
};
mod misc;
pub use misc::{
Len, Get, GetDefault, HandleLifetime, TryDrop, Time, UnixTime, IsType, IsSubType, ExecuteBlock,
SameOrOther, OnNewAccount, OnKilledAccount, OffchainWorker, GetBacking, Backing, ExtrinsicCall,
EnsureInherentsAreFirst, ConstU32,
Backing, ConstU32, EnsureInherentsAreFirst, ExecuteBlock, ExtrinsicCall, Get, GetBacking,
GetDefault, HandleLifetime, IsSubType, IsType, Len, OffchainWorker, OnKilledAccount,
OnNewAccount, SameOrOther, Time, TryDrop, UnixTime,
};
mod stored_map;
pub use stored_map::{StoredMap, StorageMapShim};
pub use stored_map::{StorageMapShim, StoredMap};
mod randomness;
pub use randomness::Randomness;
mod metadata;
pub use metadata::{
CallMetadata, GetCallMetadata, GetCallName, PalletInfo, PalletVersion, GetPalletVersion,
PALLET_VERSION_STORAGE_KEY_POSTFIX, PalletInfoAccess,
CallMetadata, GetCallMetadata, GetCallName, GetPalletVersion, PalletInfo, PalletInfoAccess,
PalletVersion, PALLET_VERSION_STORAGE_KEY_POSTFIX,
};
mod hooks;
pub use hooks::{Hooks, OnGenesis, OnInitialize, OnFinalize, OnIdle, OnRuntimeUpgrade, OnTimestampSet};
#[cfg(feature = "try-runtime")]
pub use hooks::{OnRuntimeUpgradeHelpersExt, ON_RUNTIME_UPGRADE_PREFIX};
#[cfg(feature = "std")]
pub use hooks::GenesisBuild;
pub use hooks::{
Hooks, OnFinalize, OnGenesis, OnIdle, OnInitialize, OnRuntimeUpgrade, OnTimestampSet,
};
#[cfg(feature = "try-runtime")]
pub use hooks::{OnRuntimeUpgradeHelpersExt, ON_RUNTIME_UPGRADE_PREFIX};
pub mod schedule;
mod storage;
pub use storage::{Instance, PartialStorageInfoTrait, StorageInstance, StorageInfo, StorageInfoTrait};
pub use storage::{
Instance, PartialStorageInfoTrait, StorageInfo, StorageInfoTrait, StorageInstance,
};
mod dispatch;
pub use dispatch::{EnsureOrigin, OriginTrait, UnfilteredDispatchable};
+24 -7
View File
@@ -32,11 +32,15 @@ pub enum AllowAll {}
pub enum DenyAll {}
impl<T> Filter<T> for AllowAll {
fn filter(_: &T) -> bool { true }
fn filter(_: &T) -> bool {
true
}
}
impl<T> Filter<T> for DenyAll {
fn filter(_: &T) -> bool { false }
fn filter(_: &T) -> bool {
false
}
}
/// Trait to add a constraint onto the filter.
@@ -101,17 +105,28 @@ pub trait InstanceFilter<T>: Sized + Send + Sync {
fn filter(&self, _: &T) -> bool;
/// Determines whether `self` matches at least everything that `_o` does.
fn is_superset(&self, _o: &Self) -> bool { false }
fn is_superset(&self, _o: &Self) -> bool {
false
}
}
impl<T> InstanceFilter<T> for () {
fn filter(&self, _: &T) -> bool { true }
fn is_superset(&self, _o: &Self) -> bool { true }
fn filter(&self, _: &T) -> bool {
true
}
fn is_superset(&self, _o: &Self) -> bool {
true
}
}
/// Re-expected for the macro.
#[doc(hidden)]
pub use sp_std::{mem::{swap, take}, cell::RefCell, vec::Vec, boxed::Box};
pub use sp_std::{
boxed::Box,
cell::RefCell,
mem::{swap, take},
vec::Vec,
};
#[macro_export]
macro_rules! impl_filter_stack {
@@ -206,7 +221,9 @@ pub mod test_impl_filter_stack {
pub struct IsCallable;
pub struct BaseFilter;
impl Filter<u32> for BaseFilter {
fn filter(x: &u32) -> bool { x % 2 == 0 }
fn filter(x: &u32) -> bool {
x % 2 == 0
}
}
impl_filter_stack!(
crate::traits::filter::test_impl_filter_stack::IsCallable,
+20 -10
View File
@@ -17,9 +17,9 @@
//! Traits for hooking tasks to events in a blockchain's lifecycle.
use impl_trait_for_tuples::impl_for_tuples;
use sp_arithmetic::traits::Saturating;
use sp_runtime::traits::MaybeSerializeDeserialize;
use impl_trait_for_tuples::impl_for_tuples;
/// The block initialization trait.
///
@@ -33,7 +33,9 @@ pub trait OnInitialize<BlockNumber> {
/// NOTE: This function is called BEFORE ANY extrinsic in a block is applied,
/// including inherent extrinsics. Hence for instance, if you runtime includes
/// `pallet_timestamp`, the `timestamp` is not yet up to date at this point.
fn on_initialize(_n: BlockNumber) -> crate::weights::Weight { 0 }
fn on_initialize(_n: BlockNumber) -> crate::weights::Weight {
0
}
}
#[impl_for_tuples(30)]
@@ -71,7 +73,7 @@ pub trait OnIdle<BlockNumber> {
/// in a block are applied but before `on_finalize` is executed.
fn on_idle(
_n: BlockNumber,
_remaining_weight: crate::weights::Weight
_remaining_weight: crate::weights::Weight,
) -> crate::weights::Weight {
0
}
@@ -79,7 +81,7 @@ pub trait OnIdle<BlockNumber> {
#[impl_for_tuples(30)]
impl<BlockNumber: Clone> OnIdle<BlockNumber> for Tuple {
fn on_idle(n: BlockNumber, remaining_weight: crate::weights::Weight) -> crate::weights::Weight {
fn on_idle(n: BlockNumber, remaining_weight: crate::weights::Weight) -> crate::weights::Weight {
let mut weight = 0;
for_tuples!( #(
let adjusted_remaining_weight = remaining_weight.saturating_sub(weight);
@@ -170,13 +172,17 @@ pub trait OnRuntimeUpgrade {
///
/// This hook is never meant to be executed on-chain but is meant to be used by testing tools.
#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<(), &'static str> { Ok(()) }
fn pre_upgrade() -> Result<(), &'static str> {
Ok(())
}
/// Execute some post-checks after a runtime upgrade.
///
/// This hook is never meant to be executed on-chain but is meant to be used by testing tools.
#[cfg(feature = "try-runtime")]
fn post_upgrade() -> Result<(), &'static str> { Ok(()) }
fn post_upgrade() -> Result<(), &'static str> {
Ok(())
}
}
#[impl_for_tuples(30)]
@@ -214,7 +220,7 @@ pub trait Hooks<BlockNumber> {
/// and pass the result to the next `on_idle` hook if it exists.
fn on_idle(
_n: BlockNumber,
_remaining_weight: crate::weights::Weight
_remaining_weight: crate::weights::Weight,
) -> crate::weights::Weight {
0
}
@@ -222,7 +228,9 @@ pub trait Hooks<BlockNumber> {
/// The block is being initialized. Implement to have something happen.
///
/// Return the non-negotiable weight consumed in the block.
fn on_initialize(_n: BlockNumber) -> crate::weights::Weight { 0 }
fn on_initialize(_n: BlockNumber) -> crate::weights::Weight {
0
}
/// Perform a module upgrade.
///
@@ -238,7 +246,9 @@ pub trait Hooks<BlockNumber> {
/// block local data are not accessible.
///
/// Return the non-negotiable weight consumed for runtime upgrade.
fn on_runtime_upgrade() -> crate::weights::Weight { 0 }
fn on_runtime_upgrade() -> crate::weights::Weight {
0
}
/// Execute some pre-checks prior to a runtime upgrade.
///
@@ -282,7 +292,7 @@ pub trait Hooks<BlockNumber> {
/// A trait to define the build function of a genesis config, T and I are placeholder for pallet
/// trait and pallet instance.
#[cfg(feature = "std")]
pub trait GenesisBuild<T, I=()>: Default + MaybeSerializeDeserialize {
pub trait GenesisBuild<T, I = ()>: Default + MaybeSerializeDeserialize {
/// The build function is called within an externalities allowing storage APIs.
/// Thus one can write to storage using regular pallet storages.
fn build(&self);
+28 -12
View File
@@ -17,7 +17,7 @@
//! Traits for dealing with the idea of membership.
use sp_std::{prelude::*, marker::PhantomData};
use sp_std::{marker::PhantomData, prelude::*};
/// A trait for querying whether a type can be said to "contain" a value.
pub trait Contains<T> {
@@ -28,7 +28,9 @@ pub trait Contains<T> {
/// A `Contains` implementation which always returns `true`.
pub struct All<T>(PhantomData<T>);
impl<T> Contains<T> for All<T> {
fn contains(_: &T) -> bool { true }
fn contains(_: &T) -> bool {
true
}
}
#[impl_trait_for_tuples::impl_for_tuples(30)]
@@ -77,32 +79,46 @@ pub trait SortedMembers<T: Ord> {
fn sorted_members() -> Vec<T>;
/// Return `true` if this "contains" the given value `t`.
fn contains(t: &T) -> bool { Self::sorted_members().binary_search(t).is_ok() }
fn contains(t: &T) -> bool {
Self::sorted_members().binary_search(t).is_ok()
}
/// Get the number of items in the set.
fn count() -> usize { Self::sorted_members().len() }
fn count() -> usize {
Self::sorted_members().len()
}
/// Add an item that would satisfy `contains`. It does not make sure any other
/// state is correctly maintained or generated.
///
/// **Should be used for benchmarking only!!!**
#[cfg(feature = "runtime-benchmarks")]
fn add(_t: &T) { unimplemented!() }
fn add(_t: &T) {
unimplemented!()
}
}
/// Adapter struct for turning an `OrderedMembership` impl into a `Contains` impl.
pub struct AsContains<OM>(PhantomData<(OM,)>);
impl<T: Ord + Eq, OM: SortedMembers<T>> Contains<T> for AsContains<OM> {
fn contains(t: &T) -> bool { OM::contains(t) }
fn contains(t: &T) -> bool {
OM::contains(t)
}
}
/// Trivial utility for implementing `Contains`/`OrderedMembership` with a `Vec`.
pub struct IsInVec<T>(PhantomData<T>);
impl<X: Eq, T: super::Get<Vec<X>>> Contains<X> for IsInVec<T> {
fn contains(t: &X) -> bool { T::get().contains(t) }
fn contains(t: &X) -> bool {
T::get().contains(t)
}
}
impl<X: Ord + PartialOrd, T: super::Get<Vec<X>>> SortedMembers<X> for IsInVec<T> {
fn sorted_members() -> Vec<X> { let mut r = T::get(); r.sort(); r }
fn sorted_members() -> Vec<X> {
let mut r = T::get();
r.sort();
r
}
}
/// A trait for querying bound for the length of an implementation of `Contains`
@@ -174,19 +190,19 @@ pub trait ChangeMembers<AccountId: Clone + Ord> {
(Some(old), Some(new)) if old == new => {
old_i = old_iter.next();
new_i = new_iter.next();
}
},
(Some(old), Some(new)) if old < new => {
outgoing.push(old.clone());
old_i = old_iter.next();
}
},
(Some(old), None) => {
outgoing.push(old.clone());
old_i = old_iter.next();
}
},
(_, Some(new)) => {
incoming.push(new.clone());
new_i = new_iter.next();
}
},
}
}
(incoming, outgoing)
+5 -12
View File
@@ -17,7 +17,7 @@
//! Traits for managing information attached to pallets and their constituents.
use codec::{Encode, Decode};
use codec::{Decode, Encode};
use sp_runtime::RuntimeDebug;
/// Provides information about the pallet setup in the runtime.
@@ -91,11 +91,7 @@ pub struct PalletVersion {
impl PalletVersion {
/// Creates a new instance of `Self`.
pub fn new(major: u16, minor: u8, patch: u8) -> Self {
Self {
major,
minor,
patch,
}
Self { major, minor, patch }
}
/// Returns the storage key for a pallet version.
@@ -139,13 +135,10 @@ impl PalletVersion {
impl sp_std::cmp::PartialOrd for PalletVersion {
fn partial_cmp(&self, other: &Self) -> Option<sp_std::cmp::Ordering> {
let res = self.major
let res = self
.major
.cmp(&other.major)
.then_with(||
self.minor
.cmp(&other.minor)
.then_with(|| self.patch.cmp(&other.patch)
));
.then_with(|| self.minor.cmp(&other.minor).then_with(|| self.patch.cmp(&other.patch)));
Some(res)
}
+38 -16
View File
@@ -17,9 +17,9 @@
//! Smaller traits used in FRAME which don't need their own file.
use sp_runtime::{traits::Block as BlockT, DispatchError};
use sp_arithmetic::traits::AtLeast32Bit;
use crate::dispatch::Parameter;
use sp_arithmetic::traits::AtLeast32Bit;
use sp_runtime::{traits::Block as BlockT, DispatchError};
/// Anything that can have a `::len()` method.
pub trait Len {
@@ -27,7 +27,10 @@ pub trait Len {
fn len(&self) -> usize;
}
impl<T: IntoIterator + Clone,> Len for T where <T as IntoIterator>::IntoIter: ExactSizeIterator {
impl<T: IntoIterator + Clone> Len for T
where
<T as IntoIterator>::IntoIter: ExactSizeIterator,
{
fn len(&self) -> usize {
self.clone().into_iter().len()
}
@@ -42,7 +45,9 @@ pub trait Get<T> {
}
impl<T: Default> Get<T> for () {
fn get() -> T { T::default() }
fn get() -> T {
T::default()
}
}
/// Implement Get by returning Default for any type that implements Default.
@@ -123,7 +128,10 @@ impl<A, B> SameOrOther<A, B> {
}
}
pub fn same(self) -> Result<A, B> where A: Default {
pub fn same(self) -> Result<A, B>
where
A: Default,
{
match self {
SameOrOther::Same(a) => Ok(a),
SameOrOther::None => Ok(A::default()),
@@ -131,7 +139,10 @@ impl<A, B> SameOrOther<A, B> {
}
}
pub fn other(self) -> Result<B, A> where B: Default {
pub fn other(self) -> Result<B, A>
where
B: Default,
{
match self {
SameOrOther::Same(a) => Err(a),
SameOrOther::None => Ok(B::default()),
@@ -157,10 +168,14 @@ pub trait OnKilledAccount<AccountId> {
/// A simple, generic one-parameter event notifier/handler.
pub trait HandleLifetime<T> {
/// An account was created.
fn created(_t: &T) -> Result<(), DispatchError> { Ok(()) }
fn created(_t: &T) -> Result<(), DispatchError> {
Ok(())
}
/// An account was killed.
fn killed(_t: &T) -> Result<(), DispatchError> { Ok(()) }
fn killed(_t: &T) -> Result<(), DispatchError> {
Ok(())
}
}
impl<T> HandleLifetime<T> for () {}
@@ -195,10 +210,18 @@ pub trait IsType<T>: Into<T> + From<T> {
}
impl<T> IsType<T> for T {
fn from_ref(t: &T) -> &Self { t }
fn into_ref(&self) -> &T { self }
fn from_mut(t: &mut T) -> &mut Self { t }
fn into_mut(&mut self) -> &mut T { self }
fn from_ref(t: &T) -> &Self {
t
}
fn into_ref(&self) -> &T {
self
}
fn from_mut(t: &mut T) -> &mut Self {
t
}
fn into_mut(&mut self) -> &mut T {
self
}
}
/// Something that can be checked to be a of sub type `T`.
@@ -300,8 +323,6 @@ pub trait GetBacking {
fn get_backing(&self) -> Option<Backing>;
}
/// A trait to ensure the inherent are before non-inherent in a block.
///
/// This is typically implemented on runtime, through `construct_runtime!`.
@@ -319,7 +340,8 @@ pub trait ExtrinsicCall: sp_runtime::traits::Extrinsic {
}
#[cfg(feature = "std")]
impl<Call, Extra> ExtrinsicCall for sp_runtime::testing::TestXt<Call, Extra> where
impl<Call, Extra> ExtrinsicCall for sp_runtime::testing::TestXt<Call, Extra>
where
Call: codec::Codec + Sync + Send,
{
fn call(&self) -> &Self::Call {
@@ -328,7 +350,7 @@ impl<Call, Extra> ExtrinsicCall for sp_runtime::testing::TestXt<Call, Extra> whe
}
impl<Address, Call, Signature, Extra> ExtrinsicCall
for sp_runtime::generic::UncheckedExtrinsic<Address, Call, Signature, Extra>
for sp_runtime::generic::UncheckedExtrinsic<Address, Call, Signature, Extra>
where
Extra: sp_runtime::traits::SignedExtension,
{
@@ -17,9 +17,9 @@
//! Traits and associated utilities for scheduling dispatchables in FRAME.
use sp_std::{prelude::*, fmt::Debug};
use codec::{Encode, Decode, Codec, EncodeLike};
use sp_runtime::{RuntimeDebug, DispatchError};
use codec::{Codec, Decode, Encode, EncodeLike};
use sp_runtime::{DispatchError, RuntimeDebug};
use sp_std::{fmt::Debug, prelude::*};
/// Information relating to the period of a scheduled task. First item is the length of the
/// period and the second is the number of times it should be executed in total before the task
@@ -61,7 +61,7 @@ pub trait Anon<BlockNumber, Call, Origin> {
maybe_periodic: Option<Period<BlockNumber>>,
priority: Priority,
origin: Origin,
call: Call
call: Call,
) -> Result<Self::Address, DispatchError>;
/// Cancel a scheduled task. If periodic, then it will cancel all further instances of that,
@@ -107,7 +107,7 @@ pub trait Named<BlockNumber, Call, Origin> {
maybe_periodic: Option<Period<BlockNumber>>,
priority: Priority,
origin: Origin,
call: Call
call: Call,
) -> Result<Self::Address, ()>;
/// Cancel a scheduled, named task. If periodic, then it will cancel all further instances
@@ -17,10 +17,9 @@
//! Traits and associated datatypes for managing abstract stored values.
use crate::{storage::StorageMap, traits::misc::HandleLifetime};
use codec::FullCodec;
use sp_runtime::DispatchError;
use crate::storage::StorageMap;
use crate::traits::misc::HandleLifetime;
/// An abstraction of a value stored within storage, but possibly as part of a larger composite
/// item.
@@ -47,25 +46,26 @@ pub trait StoredMap<K, T: Default> {
let r = f(&mut account);
*x = Some(account);
r
}
},
})
}
/// Mutate the item, removing or resetting to default value if it has been mutated to `None`.
///
/// This is infallible as long as the value does not get destroyed.
fn mutate_exists<R>(
k: &K,
f: impl FnOnce(&mut Option<T>) -> R,
) -> Result<R, DispatchError> {
fn mutate_exists<R>(k: &K, f: impl FnOnce(&mut Option<T>) -> R) -> Result<R, DispatchError> {
Self::try_mutate_exists(k, |x| -> Result<R, DispatchError> { Ok(f(x)) })
}
/// Set the item to something new.
fn insert(k: &K, t: T) -> Result<(), DispatchError> { Self::mutate(k, |i| *i = t) }
fn insert(k: &K, t: T) -> Result<(), DispatchError> {
Self::mutate(k, |i| *i = t)
}
/// Remove the item or otherwise replace it with its default value; we don't care which.
fn remove(k: &K) -> Result<(), DispatchError> { Self::mutate_exists(k, |x| *x = None) }
fn remove(k: &K) -> Result<(), DispatchError> {
Self::mutate_exists(k, |x| *x = None)
}
}
/// A shim for placing around a storage item in order to use it as a `StoredValue`. Ideally this
@@ -81,12 +81,15 @@ pub trait StoredMap<K, T: Default> {
/// system module's `CallOnCreatedAccount` and `CallKillAccount`.
pub struct StorageMapShim<S, L, K, T>(sp_std::marker::PhantomData<(S, L, K, T)>);
impl<
S: StorageMap<K, T, Query=T>,
L: HandleLifetime<K>,
K: FullCodec,
T: FullCodec + Default,
> StoredMap<K, T> for StorageMapShim<S, L, K, T> {
fn get(k: &K) -> T { S::get(k) }
S: StorageMap<K, T, Query = T>,
L: HandleLifetime<K>,
K: FullCodec,
T: FullCodec + Default,
> StoredMap<K, T> for StorageMapShim<S, L, K, T>
{
fn get(k: &K) -> T {
S::get(k)
}
fn insert(k: &K, t: T) -> Result<(), DispatchError> {
if !S::contains_key(&k) {
L::created(k)?;
+6 -6
View File
@@ -17,15 +17,15 @@
//! Traits for working with tokens and their associated datastructures.
pub mod currency;
pub mod fungible;
pub mod fungibles;
pub mod currency;
pub mod imbalance;
mod misc;
pub mod nonfungible;
pub mod nonfungibles;
mod misc;
pub use misc::{
BalanceConversion, BalanceStatus, DepositConsequence,
ExistenceRequirement, WithdrawConsequence, WithdrawReasons,
};
pub use imbalance::Imbalance;
pub use misc::{
BalanceConversion, BalanceStatus, DepositConsequence, ExistenceRequirement,
WithdrawConsequence, WithdrawReasons,
};
@@ -17,17 +17,19 @@
//! The Currency trait and associated types.
use sp_std::fmt::Debug;
use sp_runtime::traits::MaybeSerializeDeserialize;
use crate::dispatch::{DispatchResult, DispatchError};
use super::misc::{Balance, WithdrawReasons, ExistenceRequirement};
use super::imbalance::{Imbalance, SignedImbalance};
use super::{
imbalance::{Imbalance, SignedImbalance},
misc::{Balance, ExistenceRequirement, WithdrawReasons},
};
use crate::dispatch::{DispatchError, DispatchResult};
use codec::MaxEncodedLen;
use sp_runtime::traits::MaybeSerializeDeserialize;
use sp_std::fmt::Debug;
mod reservable;
pub use reservable::{ReservableCurrency, NamedReservableCurrency};
pub use reservable::{NamedReservableCurrency, ReservableCurrency};
mod lockable;
pub use lockable::{LockableCurrency, VestingSchedule, LockIdentifier};
pub use lockable::{LockIdentifier, LockableCurrency, VestingSchedule};
/// Abstraction over a fungible assets system.
pub trait Currency<AccountId> {
@@ -36,11 +38,11 @@ pub trait Currency<AccountId> {
/// 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.
type PositiveImbalance: Imbalance<Self::Balance, Opposite=Self::NegativeImbalance>;
type PositiveImbalance: Imbalance<Self::Balance, Opposite = Self::NegativeImbalance>;
/// 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.
type NegativeImbalance: Imbalance<Self::Balance, Opposite=Self::PositiveImbalance>;
type NegativeImbalance: Imbalance<Self::Balance, Opposite = Self::PositiveImbalance>;
// PUBLIC IMMUTABLES
@@ -123,17 +125,14 @@ pub trait Currency<AccountId> {
///
/// As much funds up to `value` will be deducted as possible. If this is less than `value`,
/// then a non-zero second item will be returned.
fn slash(
who: &AccountId,
value: Self::Balance
) -> (Self::NegativeImbalance, Self::Balance);
fn slash(who: &AccountId, value: Self::Balance) -> (Self::NegativeImbalance, Self::Balance);
/// Mints `value` to the free balance of `who`.
///
/// If `who` doesn't exist, nothing is done and an Err returned.
fn deposit_into_existing(
who: &AccountId,
value: Self::Balance
value: Self::Balance,
) -> Result<Self::PositiveImbalance, DispatchError>;
/// Similar to deposit_creating, only accepts a `NegativeImbalance` and returns nothing on
@@ -152,17 +151,11 @@ pub trait Currency<AccountId> {
/// Adds up to `value` to the free balance of `who`. If `who` doesn't exist, it is created.
///
/// Infallible.
fn deposit_creating(
who: &AccountId,
value: Self::Balance,
) -> Self::PositiveImbalance;
fn deposit_creating(who: &AccountId, value: Self::Balance) -> Self::PositiveImbalance;
/// Similar to deposit_creating, only accepts a `NegativeImbalance` and returns nothing on
/// success.
fn resolve_creating(
who: &AccountId,
value: Self::NegativeImbalance,
) {
fn resolve_creating(who: &AccountId, value: Self::NegativeImbalance) {
let v = value.peek();
drop(value.offset(Self::deposit_creating(who, v)));
}
@@ -17,10 +17,8 @@
//! The lockable currency trait and some associated types.
use crate::dispatch::DispatchResult;
use crate::traits::misc::Get;
use super::Currency;
use super::super::misc::WithdrawReasons;
use super::{super::misc::WithdrawReasons, Currency};
use crate::{dispatch::DispatchResult, traits::misc::Get};
/// An identifier for a lock. Used for disambiguating different locks so that
/// they can be individually replaced or removed.
@@ -63,10 +61,7 @@ pub trait LockableCurrency<AccountId>: Currency<AccountId> {
);
/// Remove an existing lock.
fn remove_lock(
id: LockIdentifier,
who: &AccountId,
);
fn remove_lock(id: LockIdentifier, who: &AccountId);
}
/// A vesting schedule over a currency. This allows a particular currency to have vesting limits
@@ -80,7 +75,8 @@ pub trait VestingSchedule<AccountId> {
/// Get the amount that is currently being vested and cannot be transferred out of this account.
/// Returns `None` if the account has no vesting schedule.
fn vesting_balance(who: &AccountId) -> Option<<Self::Currency as Currency<AccountId>>::Balance>;
fn vesting_balance(who: &AccountId)
-> Option<<Self::Currency as Currency<AccountId>>::Balance>;
/// Adds a vesting schedule to a given account.
///
@@ -17,9 +17,8 @@
//! The reservable currency trait.
use super::Currency;
use super::super::misc::BalanceStatus;
use crate::dispatch::{DispatchResult, DispatchError};
use super::{super::misc::BalanceStatus, Currency};
use crate::dispatch::{DispatchError, DispatchResult};
/// A currency where funds can be reserved from the user.
pub trait ReservableCurrency<AccountId>: Currency<AccountId> {
@@ -33,7 +32,7 @@ pub trait ReservableCurrency<AccountId>: Currency<AccountId> {
/// is less than `value`, then a non-zero second item will be returned.
fn slash_reserved(
who: &AccountId,
value: Self::Balance
value: Self::Balance,
) -> (Self::NegativeImbalance, Self::Balance);
/// The amount of the balance of a given account that is externally reserved; this can still get
@@ -94,7 +93,7 @@ pub trait NamedReservableCurrency<AccountId>: ReservableCurrency<AccountId> {
fn slash_reserved_named(
id: &Self::ReserveIdentifier,
who: &AccountId,
value: Self::Balance
value: Self::Balance,
) -> (Self::NegativeImbalance, Self::Balance);
/// The amount of the balance of a given account that is externally reserved; this can still get
@@ -114,7 +113,11 @@ pub trait NamedReservableCurrency<AccountId>: ReservableCurrency<AccountId> {
///
/// If the free balance is lower than `value`, then no funds will be moved and an `Err` will
/// be returned to notify of this. This is different behavior than `unreserve`.
fn reserve_named(id: &Self::ReserveIdentifier, who: &AccountId, value: Self::Balance) -> DispatchResult;
fn reserve_named(
id: &Self::ReserveIdentifier,
who: &AccountId,
value: Self::Balance,
) -> DispatchResult;
/// Moves up to `value` from reserved balance to free balance. This function cannot fail.
///
@@ -126,7 +129,11 @@ pub trait NamedReservableCurrency<AccountId>: ReservableCurrency<AccountId> {
/// - This is different from `reserve`.
/// - If the remaining reserved balance is less than `ExistentialDeposit`, it will
/// invoke `on_reserved_too_low` and could reap the account.
fn unreserve_named(id: &Self::ReserveIdentifier, who: &AccountId, value: Self::Balance) -> Self::Balance;
fn unreserve_named(
id: &Self::ReserveIdentifier,
who: &AccountId,
value: Self::Balance,
) -> Self::Balance;
/// Moves up to `value` from reserved balance of account `slashed` to balance of account
/// `beneficiary`. `beneficiary` must exist for this to succeed. If it does not, `Err` will be
@@ -147,16 +154,21 @@ pub trait NamedReservableCurrency<AccountId>: ReservableCurrency<AccountId> {
///
/// This will reserve extra amount of current reserved balance is less than `value`.
/// And unreserve if current reserved balance is greater than `value`.
fn ensure_reserved_named(id: &Self::ReserveIdentifier, who: &AccountId, value: Self::Balance) -> DispatchResult {
fn ensure_reserved_named(
id: &Self::ReserveIdentifier,
who: &AccountId,
value: Self::Balance,
) -> DispatchResult {
let current = Self::reserved_balance_named(id, who);
if current > value {
if current > value {
// we always have enough balance to unreserve here
Self::unreserve_named(id, who, current - value);
Ok(())
} else if value > current {
// we checked value > current
Self::reserve_named(id, who, value - current)
} else { // current == value
} else {
// current == value
Ok(())
}
}
@@ -173,7 +185,10 @@ pub trait NamedReservableCurrency<AccountId>: ReservableCurrency<AccountId> {
/// Slash all the reserved balance, returning the negative imbalance created.
///
/// Is a no-op if the value to be slashed is zero.
fn slash_all_reserved_named(id: &Self::ReserveIdentifier, who: &AccountId) -> Self::NegativeImbalance {
fn slash_all_reserved_named(
id: &Self::ReserveIdentifier,
who: &AccountId,
) -> Self::NegativeImbalance {
let value = Self::reserved_balance_named(id, who);
Self::slash_reserved_named(id, who, value).0
}
@@ -17,16 +17,20 @@
//! The traits for dealing with a single fungible token class and any associated types.
use super::*;
use super::{
misc::{Balance, DepositConsequence, WithdrawConsequence},
*,
};
use crate::{
dispatch::{DispatchError, DispatchResult},
traits::misc::Get,
};
use sp_runtime::traits::Saturating;
use crate::traits::misc::Get;
use crate::dispatch::{DispatchResult, DispatchError};
use super::misc::{DepositConsequence, WithdrawConsequence, Balance};
mod balanced;
mod imbalance;
pub use balanced::{Balanced, Unbalanced};
pub use imbalance::{Imbalance, HandleImbalanceDrop, DebtOf, CreditOf};
pub use imbalance::{CreditOf, DebtOf, HandleImbalanceDrop, Imbalance};
/// Trait for providing balance-inspection access to a fungible asset.
pub trait Inspect<AccountId> {
@@ -84,7 +88,10 @@ pub trait Mutate<AccountId>: Inspect<AccountId> {
let extra = Self::can_withdraw(&source, amount).into_result()?;
Self::can_deposit(&dest, amount.saturating_add(extra)).into_result()?;
let actual = Self::burn_from(source, amount)?;
debug_assert!(actual == amount.saturating_add(extra), "can_withdraw must agree with withdraw; qed");
debug_assert!(
actual == amount.saturating_add(extra),
"can_withdraw must agree with withdraw; qed"
);
match Self::mint_into(dest, actual) {
Ok(_) => Ok(actual),
Err(err) => {
@@ -93,7 +100,7 @@ pub trait Mutate<AccountId>: Inspect<AccountId> {
let revert = Self::mint_into(source, actual);
debug_assert!(revert.is_ok(), "withdrew funds previously; qed");
Err(err)
}
},
}
}
}
@@ -129,8 +136,11 @@ pub trait MutateHold<AccountId>: InspectHold<AccountId> + Transfer<AccountId> {
///
/// If `best_effort` is `true`, then the amount actually unreserved and returned as the inner
/// value of `Ok` may be smaller than the `amount` passed.
fn release(who: &AccountId, amount: Self::Balance, best_effort: bool)
-> Result<Self::Balance, DispatchError>;
fn release(
who: &AccountId,
amount: Self::Balance,
best_effort: bool,
) -> Result<Self::Balance, DispatchError>;
/// Transfer held funds into a destination account.
///
@@ -160,17 +170,17 @@ pub trait BalancedHold<AccountId>: Balanced<AccountId> + MutateHold<AccountId> {
///
/// As much funds that are on hold up to `amount` will be deducted as possible. If this is less
/// than `amount`, then a non-zero second item will be returned.
fn slash_held(who: &AccountId, amount: Self::Balance)
-> (CreditOf<AccountId, Self>, Self::Balance);
fn slash_held(
who: &AccountId,
amount: Self::Balance,
) -> (CreditOf<AccountId, Self>, Self::Balance);
}
impl<
AccountId,
T: Balanced<AccountId> + MutateHold<AccountId>,
> BalancedHold<AccountId> for T {
fn slash_held(who: &AccountId, amount: Self::Balance)
-> (CreditOf<AccountId, Self>, Self::Balance)
{
impl<AccountId, T: Balanced<AccountId> + MutateHold<AccountId>> BalancedHold<AccountId> for T {
fn slash_held(
who: &AccountId,
amount: Self::Balance,
) -> (CreditOf<AccountId, Self>, Self::Balance) {
let actual = match Self::release(who, amount, true) {
Ok(x) => x,
Err(_) => return (Imbalance::default(), amount),
@@ -185,15 +195,14 @@ pub struct ItemOf<
F: fungibles::Inspect<AccountId>,
A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
AccountId,
>(
sp_std::marker::PhantomData<(F, A, AccountId)>
);
>(sp_std::marker::PhantomData<(F, A, AccountId)>);
impl<
F: fungibles::Inspect<AccountId>,
A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
AccountId,
> Inspect<AccountId> for ItemOf<F, A, AccountId> {
F: fungibles::Inspect<AccountId>,
A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
AccountId,
> Inspect<AccountId> for ItemOf<F, A, AccountId>
{
type Balance = <F as fungibles::Inspect<AccountId>>::Balance;
fn total_issuance() -> Self::Balance {
<F as fungibles::Inspect<AccountId>>::total_issuance(A::get())
@@ -216,10 +225,11 @@ impl<
}
impl<
F: fungibles::Mutate<AccountId>,
A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
AccountId,
> Mutate<AccountId> for ItemOf<F, A, AccountId> {
F: fungibles::Mutate<AccountId>,
A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
AccountId,
> Mutate<AccountId> for ItemOf<F, A, AccountId>
{
fn mint_into(who: &AccountId, amount: Self::Balance) -> DispatchResult {
<F as fungibles::Mutate<AccountId>>::mint_into(A::get(), who, amount)
}
@@ -229,22 +239,27 @@ impl<
}
impl<
F: fungibles::Transfer<AccountId>,
A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
AccountId,
> Transfer<AccountId> for ItemOf<F, A, AccountId> {
fn transfer(source: &AccountId, dest: &AccountId, amount: Self::Balance, keep_alive: bool)
-> Result<Self::Balance, DispatchError>
{
F: fungibles::Transfer<AccountId>,
A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
AccountId,
> Transfer<AccountId> for ItemOf<F, A, AccountId>
{
fn transfer(
source: &AccountId,
dest: &AccountId,
amount: Self::Balance,
keep_alive: bool,
) -> Result<Self::Balance, DispatchError> {
<F as fungibles::Transfer<AccountId>>::transfer(A::get(), source, dest, amount, keep_alive)
}
}
impl<
F: fungibles::InspectHold<AccountId>,
A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
AccountId,
> InspectHold<AccountId> for ItemOf<F, A, AccountId> {
F: fungibles::InspectHold<AccountId>,
A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
AccountId,
> InspectHold<AccountId> for ItemOf<F, A, AccountId>
{
fn balance_on_hold(who: &AccountId) -> Self::Balance {
<F as fungibles::InspectHold<AccountId>>::balance_on_hold(A::get(), who)
}
@@ -254,16 +269,19 @@ impl<
}
impl<
F: fungibles::MutateHold<AccountId>,
A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
AccountId,
> MutateHold<AccountId> for ItemOf<F, A, AccountId> {
F: fungibles::MutateHold<AccountId>,
A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
AccountId,
> MutateHold<AccountId> for ItemOf<F, A, AccountId>
{
fn hold(who: &AccountId, amount: Self::Balance) -> DispatchResult {
<F as fungibles::MutateHold<AccountId>>::hold(A::get(), who, amount)
}
fn release(who: &AccountId, amount: Self::Balance, best_effort: bool)
-> Result<Self::Balance, DispatchError>
{
fn release(
who: &AccountId,
amount: Self::Balance,
best_effort: bool,
) -> Result<Self::Balance, DispatchError> {
<F as fungibles::MutateHold<AccountId>>::release(A::get(), who, amount, best_effort)
}
fn transfer_held(
@@ -285,23 +303,30 @@ impl<
}
impl<
F: fungibles::Unbalanced<AccountId>,
A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
AccountId,
> Unbalanced<AccountId> for ItemOf<F, A, AccountId> {
F: fungibles::Unbalanced<AccountId>,
A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
AccountId,
> Unbalanced<AccountId> for ItemOf<F, A, AccountId>
{
fn set_balance(who: &AccountId, amount: Self::Balance) -> DispatchResult {
<F as fungibles::Unbalanced<AccountId>>::set_balance(A::get(), who, amount)
}
fn set_total_issuance(amount: Self::Balance) -> () {
<F as fungibles::Unbalanced<AccountId>>::set_total_issuance(A::get(), amount)
}
fn decrease_balance(who: &AccountId, amount: Self::Balance) -> Result<Self::Balance, DispatchError> {
fn decrease_balance(
who: &AccountId,
amount: Self::Balance,
) -> Result<Self::Balance, DispatchError> {
<F as fungibles::Unbalanced<AccountId>>::decrease_balance(A::get(), who, amount)
}
fn decrease_balance_at_most(who: &AccountId, amount: Self::Balance) -> Self::Balance {
<F as fungibles::Unbalanced<AccountId>>::decrease_balance_at_most(A::get(), who, amount)
}
fn increase_balance(who: &AccountId, amount: Self::Balance) -> Result<Self::Balance, DispatchError> {
fn increase_balance(
who: &AccountId,
amount: Self::Balance,
) -> Result<Self::Balance, DispatchError> {
<F as fungibles::Unbalanced<AccountId>>::increase_balance(A::get(), who, amount)
}
fn increase_balance_at_most(who: &AccountId, amount: Self::Balance) -> Self::Balance {
@@ -18,12 +18,16 @@
//! The trait and associated types for sets of fungible tokens that manage total issuance without
//! requiring atomic balanced operations.
use super::*;
use super::{super::Imbalance as ImbalanceT, *};
use crate::{
dispatch::{DispatchError, DispatchResult},
traits::misc::{SameOrOther, TryDrop},
};
use sp_runtime::{
traits::{CheckedAdd, Zero},
ArithmeticError, TokenError,
};
use sp_std::marker::PhantomData;
use sp_runtime::{TokenError, ArithmeticError, traits::{CheckedAdd, Zero}};
use super::super::Imbalance as ImbalanceT;
use crate::traits::misc::{SameOrOther, TryDrop};
use crate::dispatch::{DispatchResult, DispatchError};
/// A fungible token class where any creation and deletion of tokens is semi-explicit and where the
/// total supply is maintained automatically.
@@ -65,10 +69,7 @@ pub trait Balanced<AccountId>: Inspect<AccountId> {
///
/// As much funds up to `value` will be deducted as possible. If this is less than `value`,
/// then a non-zero second item will be returned.
fn slash(
who: &AccountId,
amount: Self::Balance,
) -> (CreditOf<AccountId, Self>, Self::Balance);
fn slash(who: &AccountId, amount: Self::Balance) -> (CreditOf<AccountId, Self>, Self::Balance);
/// Mints exactly `value` into the account of `who`.
///
@@ -90,7 +91,7 @@ pub trait Balanced<AccountId>: Inspect<AccountId> {
fn withdraw(
who: &AccountId,
value: Self::Balance,
//TODO: liveness: ExistenceRequirement,
// TODO: liveness: ExistenceRequirement,
) -> Result<CreditOf<AccountId, Self>, DispatchError>;
/// The balance of `who` is increased in order to counter `credit`. If the whole of `credit`
@@ -119,7 +120,7 @@ pub trait Balanced<AccountId>: Inspect<AccountId> {
fn settle(
who: &AccountId,
debt: DebtOf<AccountId, Self>,
//TODO: liveness: ExistenceRequirement,
// TODO: liveness: ExistenceRequirement,
) -> Result<CreditOf<AccountId, Self>, DebtOf<AccountId, Self>> {
let amount = debt.peek();
let credit = match Self::withdraw(who, amount) {
@@ -132,7 +133,7 @@ pub trait Balanced<AccountId>: Inspect<AccountId> {
SameOrOther::Other(rest) => {
debug_assert!(false, "ok withdraw return must be at least debt value; qed");
Err(rest)
}
},
}
}
}
@@ -158,9 +159,10 @@ pub trait Unbalanced<AccountId>: Inspect<AccountId> {
///
/// Minimum balance will be respected and the returned imbalance may be up to
/// `Self::minimum_balance() - 1` greater than `amount`.
fn decrease_balance(who: &AccountId, amount: Self::Balance)
-> Result<Self::Balance, DispatchError>
{
fn decrease_balance(
who: &AccountId,
amount: Self::Balance,
) -> Result<Self::Balance, DispatchError> {
let old_balance = Self::balance(who);
let (mut new_balance, mut amount) = if old_balance < amount {
Err(TokenError::NoFunds)?
@@ -182,9 +184,7 @@ pub trait Unbalanced<AccountId>: Inspect<AccountId> {
/// `Self::minimum_balance() - 1` greater than `amount`.
///
/// Return the imbalance by which the account was reduced.
fn decrease_balance_at_most(who: &AccountId, amount: Self::Balance)
-> Self::Balance
{
fn decrease_balance_at_most(who: &AccountId, amount: Self::Balance) -> Self::Balance {
let old_balance = Self::balance(who);
let (mut new_balance, mut amount) = if old_balance < amount {
(Zero::zero(), old_balance)
@@ -217,9 +217,10 @@ pub trait Unbalanced<AccountId>: Inspect<AccountId> {
///
/// Minimum balance will be respected and an error will be returned if
/// `amount < Self::minimum_balance()` when the account of `who` is zero.
fn increase_balance(who: &AccountId, amount: Self::Balance)
-> Result<Self::Balance, DispatchError>
{
fn increase_balance(
who: &AccountId,
amount: Self::Balance,
) -> Result<Self::Balance, DispatchError> {
let old_balance = Self::balance(who);
let new_balance = old_balance.checked_add(&amount).ok_or(ArithmeticError::Overflow)?;
if new_balance < Self::minimum_balance() {
@@ -237,9 +238,7 @@ pub trait Unbalanced<AccountId>: Inspect<AccountId> {
/// `amount < Self::minimum_balance()`.
///
/// Return the imbalance by which the account was increased.
fn increase_balance_at_most(who: &AccountId, amount: Self::Balance)
-> Self::Balance
{
fn increase_balance_at_most(who: &AccountId, amount: Self::Balance) -> Self::Balance {
let old_balance = Self::balance(who);
let mut new_balance = old_balance.saturating_add(amount);
let mut amount = new_balance - old_balance;
@@ -300,16 +299,12 @@ type Debt<AccountId, U> = Imbalance<
>;
/// Create some `Credit` item. Only for internal use.
fn credit<AccountId, U: Unbalanced<AccountId>>(
amount: U::Balance,
) -> Credit<AccountId, U> {
fn credit<AccountId, U: Unbalanced<AccountId>>(amount: U::Balance) -> Credit<AccountId, U> {
Imbalance::new(amount)
}
/// Create some `Debt` item. Only for internal use.
fn debt<AccountId, U: Unbalanced<AccountId>>(
amount: U::Balance,
) -> Debt<AccountId, U> {
fn debt<AccountId, U: Unbalanced<AccountId>>(amount: U::Balance) -> Debt<AccountId, U> {
Imbalance::new(amount)
}
@@ -328,10 +323,7 @@ impl<AccountId, U: Unbalanced<AccountId>> Balanced<AccountId> for U {
U::set_total_issuance(new);
credit(new - old)
}
fn slash(
who: &AccountId,
amount: Self::Balance,
) -> (Credit<AccountId, Self>, Self::Balance) {
fn slash(who: &AccountId, amount: Self::Balance) -> (Credit<AccountId, Self>, Self::Balance) {
let slashed = U::decrease_balance_at_most(who, amount);
// `slashed` could be less than, greater than or equal to `amount`.
// If slashed == amount, it means the account had at least amount in it and it could all be
@@ -344,7 +336,7 @@ impl<AccountId, U: Unbalanced<AccountId>> Balanced<AccountId> for U {
}
fn deposit(
who: &AccountId,
amount: Self::Balance
amount: Self::Balance,
) -> Result<Debt<AccountId, Self>, DispatchError> {
let increase = U::increase_balance(who, amount)?;
Ok(debt(increase))
@@ -352,7 +344,7 @@ impl<AccountId, U: Unbalanced<AccountId>> Balanced<AccountId> for U {
fn withdraw(
who: &AccountId,
amount: Self::Balance,
//TODO: liveness: ExistenceRequirement,
// TODO: liveness: ExistenceRequirement,
) -> Result<Credit<AccountId, Self>, DispatchError> {
let decrease = U::decrease_balance(who, amount)?;
Ok(credit(decrease))
@@ -18,13 +18,10 @@
//! The imbalance type and its associates, which handles keeps everything adding up properly with
//! unbalanced operations.
use super::*;
use super::{super::Imbalance as ImbalanceT, balanced::Balanced, misc::Balance, *};
use crate::traits::misc::{SameOrOther, TryDrop};
use sp_runtime::{traits::Zero, RuntimeDebug};
use sp_std::marker::PhantomData;
use sp_runtime::{RuntimeDebug, traits::Zero};
use super::misc::Balance;
use super::balanced::Balanced;
use crate::traits::misc::{TryDrop, SameOrOther};
use super::super::Imbalance as ImbalanceT;
/// Handler for when an imbalance gets dropped. This could handle either a credit (negative) or
/// debt (positive) imbalance.
@@ -49,11 +46,9 @@ pub struct Imbalance<
_phantom: PhantomData<(OnDrop, OppositeOnDrop)>,
}
impl<
B: Balance,
OnDrop: HandleImbalanceDrop<B>,
OppositeOnDrop: HandleImbalanceDrop<B>
> Drop for Imbalance<B, OnDrop, OppositeOnDrop> {
impl<B: Balance, OnDrop: HandleImbalanceDrop<B>, OppositeOnDrop: HandleImbalanceDrop<B>> Drop
for Imbalance<B, OnDrop, OppositeOnDrop>
{
fn drop(&mut self) {
if !self.amount.is_zero() {
OnDrop::handle(self.amount)
@@ -61,42 +56,34 @@ impl<
}
}
impl<
B: Balance,
OnDrop: HandleImbalanceDrop<B>,
OppositeOnDrop: HandleImbalanceDrop<B>,
> TryDrop for Imbalance<B, OnDrop, OppositeOnDrop> {
impl<B: Balance, OnDrop: HandleImbalanceDrop<B>, OppositeOnDrop: HandleImbalanceDrop<B>> TryDrop
for Imbalance<B, OnDrop, OppositeOnDrop>
{
/// Drop an instance cleanly. Only works if its value represents "no-operation".
fn try_drop(self) -> Result<(), Self> {
self.drop_zero()
}
}
impl<
B: Balance,
OnDrop: HandleImbalanceDrop<B>,
OppositeOnDrop: HandleImbalanceDrop<B>,
> Default for Imbalance<B, OnDrop, OppositeOnDrop> {
impl<B: Balance, OnDrop: HandleImbalanceDrop<B>, OppositeOnDrop: HandleImbalanceDrop<B>> Default
for Imbalance<B, OnDrop, OppositeOnDrop>
{
fn default() -> Self {
Self::zero()
}
}
impl<
B: Balance,
OnDrop: HandleImbalanceDrop<B>,
OppositeOnDrop: HandleImbalanceDrop<B>,
> Imbalance<B, OnDrop, OppositeOnDrop> {
impl<B: Balance, OnDrop: HandleImbalanceDrop<B>, OppositeOnDrop: HandleImbalanceDrop<B>>
Imbalance<B, OnDrop, OppositeOnDrop>
{
pub(crate) fn new(amount: B) -> Self {
Self { amount, _phantom: PhantomData }
}
}
impl<
B: Balance,
OnDrop: HandleImbalanceDrop<B>,
OppositeOnDrop: HandleImbalanceDrop<B>,
> ImbalanceT<B> for Imbalance<B, OnDrop, OppositeOnDrop> {
impl<B: Balance, OnDrop: HandleImbalanceDrop<B>, OppositeOnDrop: HandleImbalanceDrop<B>>
ImbalanceT<B> for Imbalance<B, OnDrop, OppositeOnDrop>
{
type Opposite = Imbalance<B, OppositeOnDrop, OnDrop>;
fn zero() -> Self {
@@ -127,9 +114,10 @@ impl<
self.amount = self.amount.saturating_add(other.amount);
sp_std::mem::forget(other);
}
fn offset(self, other: Imbalance<B, OppositeOnDrop, OnDrop>)
-> SameOrOther<Self, Imbalance<B, OppositeOnDrop, OnDrop>>
{
fn offset(
self,
other: Imbalance<B, OppositeOnDrop, OnDrop>,
) -> SameOrOther<Self, Imbalance<B, OppositeOnDrop, OnDrop>> {
let (a, b) = (self.amount, other.amount);
sp_std::mem::forget((self, other));
@@ -17,15 +17,17 @@
//! The traits for sets of fungible tokens and any associated types.
use super::*;
use super::{
misc::{AssetId, Balance},
*,
};
use crate::dispatch::{DispatchError, DispatchResult};
use super::misc::{AssetId, Balance};
use sp_runtime::traits::Saturating;
mod balanced;
pub use balanced::{Balanced, Unbalanced};
mod imbalance;
pub use imbalance::{Imbalance, HandleImbalanceDrop, DebtOf, CreditOf};
pub use imbalance::{CreditOf, DebtOf, HandleImbalanceDrop, Imbalance};
/// Trait for providing balance-inspection access to a set of named fungible assets.
pub trait Inspect<AccountId> {
@@ -48,8 +50,11 @@ pub trait Inspect<AccountId> {
fn reducible_balance(asset: Self::AssetId, who: &AccountId, keep_alive: bool) -> Self::Balance;
/// Returns `true` if the `asset` balance of `who` may be increased by `amount`.
fn can_deposit(asset: Self::AssetId, who: &AccountId, amount: Self::Balance)
-> DepositConsequence;
fn can_deposit(
asset: Self::AssetId,
who: &AccountId,
amount: Self::Balance,
) -> DepositConsequence;
/// Returns `Failed` if the `asset` balance of `who` may not be decreased by `amount`, otherwise
/// the consequence.
@@ -87,8 +92,11 @@ pub trait Mutate<AccountId>: Inspect<AccountId> {
/// Due to minimum balance requirements, it's possible that the amount withdrawn could be up to
/// `Self::minimum_balance() - 1` more than the `amount`. The total amount withdrawn is returned
/// in an `Ok` result. This may be safely ignored if you don't mind the overall supply reducing.
fn burn_from(asset: Self::AssetId, who: &AccountId, amount: Self::Balance)
-> Result<Self::Balance, DispatchError>;
fn burn_from(
asset: Self::AssetId,
who: &AccountId,
amount: Self::Balance,
) -> Result<Self::Balance, DispatchError>;
/// Attempt to reduce the `asset` balance of `who` by as much as possible up to `amount`, and
/// possibly slightly more due to minimum_balance requirements. If no decrease is possible then
@@ -97,9 +105,11 @@ pub trait Mutate<AccountId>: Inspect<AccountId> {
///
/// The default implementation just uses `withdraw` along with `reducible_balance` to ensure
/// that is doesn't fail.
fn slash(asset: Self::AssetId, who: &AccountId, amount: Self::Balance)
-> Result<Self::Balance, DispatchError>
{
fn slash(
asset: Self::AssetId,
who: &AccountId,
amount: Self::Balance,
) -> Result<Self::Balance, DispatchError> {
Self::burn_from(asset, who, Self::reducible_balance(asset, who, false).min(amount))
}
@@ -114,7 +124,10 @@ pub trait Mutate<AccountId>: Inspect<AccountId> {
let extra = Self::can_withdraw(asset, &source, amount).into_result()?;
Self::can_deposit(asset, &dest, amount.saturating_add(extra)).into_result()?;
let actual = Self::burn_from(asset, source, amount)?;
debug_assert!(actual == amount.saturating_add(extra), "can_withdraw must agree with withdraw; qed");
debug_assert!(
actual == amount.saturating_add(extra),
"can_withdraw must agree with withdraw; qed"
);
match Self::mint_into(asset, dest, actual) {
Ok(_) => Ok(actual),
Err(err) => {
@@ -123,7 +136,7 @@ pub trait Mutate<AccountId>: Inspect<AccountId> {
let revert = Self::mint_into(asset, source, actual);
debug_assert!(revert.is_ok(), "withdrew funds previously; qed");
Err(err)
}
},
}
}
}
@@ -158,8 +171,12 @@ pub trait MutateHold<AccountId>: InspectHold<AccountId> + Transfer<AccountId> {
///
/// If `best_effort` is `true`, then the amount actually released and returned as the inner
/// value of `Ok` may be smaller than the `amount` passed.
fn release(asset: Self::AssetId, who: &AccountId, amount: Self::Balance, best_effort: bool)
-> Result<Self::Balance, DispatchError>;
fn release(
asset: Self::AssetId,
who: &AccountId,
amount: Self::Balance,
best_effort: bool,
) -> Result<Self::Balance, DispatchError>;
/// Transfer held funds into a destination account.
///
@@ -190,17 +207,19 @@ pub trait BalancedHold<AccountId>: Balanced<AccountId> + MutateHold<AccountId> {
///
/// As much funds up to `amount` will be deducted as possible. If this is less than `amount`,
/// then a non-zero second item will be returned.
fn slash_held(asset: Self::AssetId, who: &AccountId, amount: Self::Balance)
-> (CreditOf<AccountId, Self>, Self::Balance);
fn slash_held(
asset: Self::AssetId,
who: &AccountId,
amount: Self::Balance,
) -> (CreditOf<AccountId, Self>, Self::Balance);
}
impl<
AccountId,
T: Balanced<AccountId> + MutateHold<AccountId>,
> BalancedHold<AccountId> for T {
fn slash_held(asset: Self::AssetId, who: &AccountId, amount: Self::Balance)
-> (CreditOf<AccountId, Self>, Self::Balance)
{
impl<AccountId, T: Balanced<AccountId> + MutateHold<AccountId>> BalancedHold<AccountId> for T {
fn slash_held(
asset: Self::AssetId,
who: &AccountId,
amount: Self::Balance,
) -> (CreditOf<AccountId, Self>, Self::Balance) {
let actual = match Self::release(asset, who, amount, true) {
Ok(x) => x,
Err(_) => return (Imbalance::zero(asset), amount),
@@ -19,11 +19,16 @@
//! requiring atomic balanced operations.
use super::*;
use sp_std::marker::PhantomData;
use sp_runtime::{ArithmeticError, TokenError, traits::{Zero, CheckedAdd}};
use crate::{
dispatch::{DispatchError, DispatchResult},
traits::misc::{SameOrOther, TryDrop},
};
use sp_arithmetic::traits::Saturating;
use crate::dispatch::{DispatchError, DispatchResult};
use crate::traits::misc::{SameOrOther, TryDrop};
use sp_runtime::{
traits::{CheckedAdd, Zero},
ArithmeticError, TokenError,
};
use sp_std::marker::PhantomData;
/// A fungible token class where any creation and deletion of tokens is semi-explicit and where the
/// total supply is maintained automatically.
@@ -55,9 +60,10 @@ pub trait Balanced<AccountId>: Inspect<AccountId> {
///
/// This is just the same as burning and issuing the same amount and has no effect on the
/// total issuance.
fn pair(asset: Self::AssetId, amount: Self::Balance)
-> (DebtOf<AccountId, Self>, CreditOf<AccountId, Self>)
{
fn pair(
asset: Self::AssetId,
amount: Self::Balance,
) -> (DebtOf<AccountId, Self>, CreditOf<AccountId, Self>) {
(Self::rescind(asset, amount), Self::issue(asset, amount))
}
@@ -96,7 +102,7 @@ pub trait Balanced<AccountId>: Inspect<AccountId> {
asset: Self::AssetId,
who: &AccountId,
value: Self::Balance,
//TODO: liveness: ExistenceRequirement,
// TODO: liveness: ExistenceRequirement,
) -> Result<CreditOf<AccountId, Self>, DispatchError>;
/// The balance of `who` is increased in order to counter `credit`. If the whole of `credit`
@@ -129,7 +135,7 @@ pub trait Balanced<AccountId>: Inspect<AccountId> {
fn settle(
who: &AccountId,
debt: DebtOf<AccountId, Self>,
//TODO: liveness: ExistenceRequirement,
// TODO: liveness: ExistenceRequirement,
) -> Result<CreditOf<AccountId, Self>, DebtOf<AccountId, Self>> {
let amount = debt.peek();
let asset = debt.asset();
@@ -143,11 +149,11 @@ pub trait Balanced<AccountId>: Inspect<AccountId> {
Ok(SameOrOther::Other(rest)) => {
debug_assert!(false, "ok withdraw return must be at least debt value; qed");
Err(rest)
}
},
Err(_) => {
debug_assert!(false, "debt.asset is credit.asset; qed");
Ok(CreditOf::<AccountId, Self>::zero(asset))
}
},
}
}
}
@@ -173,9 +179,11 @@ pub trait Unbalanced<AccountId>: Inspect<AccountId> {
///
/// Minimum balance will be respected and the returned imbalance may be up to
/// `Self::minimum_balance() - 1` greater than `amount`.
fn decrease_balance(asset: Self::AssetId, who: &AccountId, amount: Self::Balance)
-> Result<Self::Balance, DispatchError>
{
fn decrease_balance(
asset: Self::AssetId,
who: &AccountId,
amount: Self::Balance,
) -> Result<Self::Balance, DispatchError> {
let old_balance = Self::balance(asset, who);
let (mut new_balance, mut amount) = if old_balance < amount {
Err(TokenError::NoFunds)?
@@ -197,9 +205,11 @@ pub trait Unbalanced<AccountId>: Inspect<AccountId> {
/// `Self::minimum_balance() - 1` greater than `amount`.
///
/// Return the imbalance by which the account was reduced.
fn decrease_balance_at_most(asset: Self::AssetId, who: &AccountId, amount: Self::Balance)
-> Self::Balance
{
fn decrease_balance_at_most(
asset: Self::AssetId,
who: &AccountId,
amount: Self::Balance,
) -> Self::Balance {
let old_balance = Self::balance(asset, who);
let (mut new_balance, mut amount) = if old_balance < amount {
(Zero::zero(), old_balance)
@@ -232,9 +242,11 @@ pub trait Unbalanced<AccountId>: Inspect<AccountId> {
///
/// Minimum balance will be respected and an error will be returned if
/// `amount < Self::minimum_balance()` when the account of `who` is zero.
fn increase_balance(asset: Self::AssetId, who: &AccountId, amount: Self::Balance)
-> Result<Self::Balance, DispatchError>
{
fn increase_balance(
asset: Self::AssetId,
who: &AccountId,
amount: Self::Balance,
) -> Result<Self::Balance, DispatchError> {
let old_balance = Self::balance(asset, who);
let new_balance = old_balance.checked_add(&amount).ok_or(ArithmeticError::Overflow)?;
if new_balance < Self::minimum_balance(asset) {
@@ -252,9 +264,11 @@ pub trait Unbalanced<AccountId>: Inspect<AccountId> {
/// `amount < Self::minimum_balance()`.
///
/// Return the imbalance by which the account was increased.
fn increase_balance_at_most(asset: Self::AssetId, who: &AccountId, amount: Self::Balance)
-> Self::Balance
{
fn increase_balance_at_most(
asset: Self::AssetId,
who: &AccountId,
amount: Self::Balance,
) -> Self::Balance {
let old_balance = Self::balance(asset, who);
let mut new_balance = old_balance.saturating_add(amount);
let mut amount = new_balance - old_balance;
@@ -361,7 +375,7 @@ impl<AccountId, U: Unbalanced<AccountId>> Balanced<AccountId> for U {
fn deposit(
asset: Self::AssetId,
who: &AccountId,
amount: Self::Balance
amount: Self::Balance,
) -> Result<Debt<AccountId, Self>, DispatchError> {
let increase = U::increase_balance(asset, who, amount)?;
Ok(debt(asset, increase))
@@ -370,7 +384,7 @@ impl<AccountId, U: Unbalanced<AccountId>> Balanced<AccountId> for U {
asset: Self::AssetId,
who: &AccountId,
amount: Self::Balance,
//TODO: liveness: ExistenceRequirement,
// TODO: liveness: ExistenceRequirement,
) -> Result<Credit<AccountId, Self>, DispatchError> {
let decrease = U::decrease_balance(asset, who, amount)?;
Ok(credit(asset, decrease))
@@ -18,12 +18,14 @@
//! The imbalance type and its associates, which handles keeps everything adding up properly with
//! unbalanced operations.
use super::*;
use super::{
balanced::Balanced,
fungibles::{AssetId, Balance},
*,
};
use crate::traits::misc::{SameOrOther, TryDrop};
use sp_runtime::{traits::Zero, RuntimeDebug};
use sp_std::marker::PhantomData;
use sp_runtime::{RuntimeDebug, traits::Zero};
use super::fungibles::{AssetId, Balance};
use super::balanced::Balanced;
use crate::traits::misc::{TryDrop, SameOrOther};
/// Handler for when an imbalance gets dropped. This could handle either a credit (negative) or
/// debt (positive) imbalance.
@@ -50,11 +52,12 @@ pub struct Imbalance<
}
impl<
A: AssetId,
B: Balance,
OnDrop: HandleImbalanceDrop<A, B>,
OppositeOnDrop: HandleImbalanceDrop<A, B>
> Drop for Imbalance<A, B, OnDrop, OppositeOnDrop> {
A: AssetId,
B: Balance,
OnDrop: HandleImbalanceDrop<A, B>,
OppositeOnDrop: HandleImbalanceDrop<A, B>,
> Drop for Imbalance<A, B, OnDrop, OppositeOnDrop>
{
fn drop(&mut self) {
if !self.amount.is_zero() {
OnDrop::handle(self.asset, self.amount)
@@ -63,11 +66,12 @@ impl<
}
impl<
A: AssetId,
B: Balance,
OnDrop: HandleImbalanceDrop<A, B>,
OppositeOnDrop: HandleImbalanceDrop<A, B>,
> TryDrop for Imbalance<A, B, OnDrop, OppositeOnDrop> {
A: AssetId,
B: Balance,
OnDrop: HandleImbalanceDrop<A, B>,
OppositeOnDrop: HandleImbalanceDrop<A, B>,
> TryDrop for Imbalance<A, B, OnDrop, OppositeOnDrop>
{
/// Drop an instance cleanly. Only works if its value represents "no-operation".
fn try_drop(self) -> Result<(), Self> {
self.drop_zero()
@@ -75,11 +79,12 @@ impl<
}
impl<
A: AssetId,
B: Balance,
OnDrop: HandleImbalanceDrop<A, B>,
OppositeOnDrop: HandleImbalanceDrop<A, B>,
> Imbalance<A, B, OnDrop, OppositeOnDrop> {
A: AssetId,
B: Balance,
OnDrop: HandleImbalanceDrop<A, B>,
OppositeOnDrop: HandleImbalanceDrop<A, B>,
> Imbalance<A, B, OnDrop, OppositeOnDrop>
{
pub fn zero(asset: A) -> Self {
Self { asset, amount: Zero::zero(), _phantom: PhantomData }
}
@@ -122,7 +127,10 @@ impl<
Err(other)
}
}
pub fn offset(self, other: Imbalance<A, B, OppositeOnDrop, OnDrop>) -> Result<
pub fn offset(
self,
other: Imbalance<A, B, OppositeOnDrop, OnDrop>,
) -> Result<
SameOrOther<Self, Imbalance<A, B, OppositeOnDrop, OnDrop>>,
(Self, Imbalance<A, B, OppositeOnDrop, OnDrop>),
> {
@@ -18,16 +18,16 @@
//! The imbalance trait type and its associates, which handles keeps everything adding up properly
//! with unbalanced operations.
use sp_std::ops::Div;
use crate::traits::misc::{SameOrOther, TryDrop};
use sp_runtime::traits::Saturating;
use crate::traits::misc::{TryDrop, SameOrOther};
use sp_std::ops::Div;
mod split_two_ways;
mod signed_imbalance;
mod on_unbalanced;
pub use split_two_ways::SplitTwoWays;
pub use signed_imbalance::SignedImbalance;
mod signed_imbalance;
mod split_two_ways;
pub use on_unbalanced::OnUnbalanced;
pub use signed_imbalance::SignedImbalance;
pub use split_two_ways::SplitTwoWays;
/// A trait for a not-quite Linear Type that tracks an imbalance.
///
@@ -78,10 +78,13 @@ pub trait Imbalance<Balance>: Sized + TryDrop + Default {
/// NOTE: This requires up to `first + second` room for a multiply, and `first + second` should
/// fit into a `u32`. Overflow will safely saturate in both cases.
fn ration(self, first: u32, second: u32) -> (Self, Self)
where Balance: From<u32> + Saturating + Div<Output=Balance>
where
Balance: From<u32> + Saturating + Div<Output = Balance>,
{
let total: u32 = first.saturating_add(second);
if total == 0 { return (Self::zero(), Self::zero()) }
if total == 0 {
return (Self::zero(), Self::zero())
}
let amount1 = self.peek().saturating_mul(first.into()) / total.into();
self.split(amount1)
}
@@ -100,7 +103,8 @@ pub trait Imbalance<Balance>: Sized + TryDrop + Default {
///
/// A convenient replacement for `split` and `merge`.
fn ration_merge(self, first: u32, second: u32, others: (Self, Self)) -> (Self, Self)
where Balance: From<u32> + Saturating + Div<Output=Balance>
where
Balance: From<u32> + Saturating + Div<Output = Balance>,
{
let (a, b) = self.ration(first, second);
(a.merge(others.0), b.merge(others.1))
@@ -121,7 +125,8 @@ pub trait Imbalance<Balance>: Sized + TryDrop + Default {
///
/// A convenient replacement for `split` and `merge`.
fn ration_merge_into(self, first: u32, second: u32, others: &mut (Self, Self))
where Balance: From<u32> + Saturating + Div<Output=Balance>
where
Balance: From<u32> + Saturating + Div<Output = Balance>,
{
let (a, b) = self.ration(first, second);
others.0.subsume(a);
@@ -167,7 +172,7 @@ pub trait Imbalance<Balance>: Sized + TryDrop + Default {
/// greater value than the `other`. Otherwise returns `Err` with an instance of
/// the `Opposite`. In both cases the value represents the combination of `self`
/// and `other`.
fn offset(self, other: Self::Opposite)-> SameOrOther<Self, Self::Opposite>;
fn offset(self, other: Self::Opposite) -> SameOrOther<Self, Self::Opposite>;
/// The raw value of self.
fn peek(&self) -> Balance;
@@ -33,7 +33,10 @@ pub trait OnUnbalanced<Imbalance: TryDrop> {
/// Handler for some imbalances. The different imbalances might have different origins or
/// meanings, dependent on the context. Will default to simply calling on_unbalanced for all
/// of them. Infallible.
fn on_unbalanceds<B>(amounts: impl Iterator<Item=Imbalance>) where Imbalance: crate::traits::Imbalance<B> {
fn on_unbalanceds<B>(amounts: impl Iterator<Item = Imbalance>)
where
Imbalance: crate::traits::Imbalance<B>,
{
Self::on_unbalanced(amounts.fold(Imbalance::zero(), |i, x| x.merge(i)))
}
@@ -44,7 +47,9 @@ pub trait OnUnbalanced<Imbalance: TryDrop> {
/// Actually handle a non-zero imbalance. You probably want to implement this rather than
/// `on_unbalanced`.
fn on_nonzero_unbalanced(amount: Imbalance) { drop(amount); }
fn on_nonzero_unbalanced(amount: Imbalance) {
drop(amount);
}
}
impl<Imbalance: TryDrop> OnUnbalanced<Imbalance> for () {}
@@ -17,14 +17,14 @@
//! Convenience type for managing an imbalance whose sign is unknown.
use codec::FullCodec;
use sp_std::fmt::Debug;
use sp_runtime::traits::{AtLeast32BitUnsigned, MaybeSerializeDeserialize};
use crate::traits::misc::SameOrOther;
use super::super::imbalance::Imbalance;
use crate::traits::misc::SameOrOther;
use codec::FullCodec;
use sp_runtime::traits::{AtLeast32BitUnsigned, MaybeSerializeDeserialize};
use sp_std::fmt::Debug;
/// Either a positive or a negative imbalance.
pub enum SignedImbalance<B, PositiveImbalance: Imbalance<B>>{
pub enum SignedImbalance<B, PositiveImbalance: Imbalance<B>> {
/// A positive imbalance (funds have been created but none destroyed).
Positive(PositiveImbalance),
/// A negative imbalance (funds have been destroyed but none created).
@@ -32,10 +32,11 @@ pub enum SignedImbalance<B, PositiveImbalance: Imbalance<B>>{
}
impl<
P: Imbalance<B, Opposite=N>,
N: Imbalance<B, Opposite=P>,
B: AtLeast32BitUnsigned + FullCodec + Copy + MaybeSerializeDeserialize + Debug + Default,
> SignedImbalance<B, P> {
P: Imbalance<B, Opposite = N>,
N: Imbalance<B, Opposite = P>,
B: AtLeast32BitUnsigned + FullCodec + Copy + MaybeSerializeDeserialize + Debug + Default,
> SignedImbalance<B, P>
{
/// Create a `Positive` instance of `Self` whose value is zero.
pub fn zero() -> Self {
SignedImbalance::Positive(P::zero())
@@ -17,29 +17,24 @@
//! Means for splitting an imbalance into two and hanlding them differently.
use sp_std::{ops::Div, marker::PhantomData};
use super::super::imbalance::{Imbalance, OnUnbalanced};
use sp_core::u32_trait::Value as U32;
use sp_runtime::traits::Saturating;
use super::super::imbalance::{Imbalance, OnUnbalanced};
use sp_std::{marker::PhantomData, ops::Div};
/// Split an unbalanced amount two ways between a common divisor.
pub struct SplitTwoWays<
Balance,
Imbalance,
Part1,
Target1,
Part2,
Target2,
>(PhantomData<(Balance, Imbalance, Part1, Target1, Part2, Target2)>);
pub struct SplitTwoWays<Balance, Imbalance, Part1, Target1, Part2, Target2>(
PhantomData<(Balance, Imbalance, Part1, Target1, Part2, Target2)>,
);
impl<
Balance: From<u32> + Saturating + Div<Output=Balance>,
I: Imbalance<Balance>,
Part1: U32,
Target1: OnUnbalanced<I>,
Part2: U32,
Target2: OnUnbalanced<I>,
> OnUnbalanced<I> for SplitTwoWays<Balance, I, Part1, Target1, Part2, Target2>
Balance: From<u32> + Saturating + Div<Output = Balance>,
I: Imbalance<Balance>,
Part1: U32,
Target1: OnUnbalanced<I>,
Part2: U32,
Target2: OnUnbalanced<I>,
> OnUnbalanced<I> for SplitTwoWays<Balance, I, Part1, Target1, Part2, Target2>
{
fn on_nonzero_unbalanced(amount: I) {
let total: u32 = Part1::VALUE + Part2::VALUE;
@@ -17,11 +17,11 @@
//! Miscellaneous types.
use sp_std::fmt::Debug;
use codec::{Encode, Decode, FullCodec};
use codec::{Decode, Encode, FullCodec};
use sp_arithmetic::traits::{AtLeast32BitUnsigned, Zero};
use sp_core::RuntimeDebug;
use sp_arithmetic::traits::{Zero, AtLeast32BitUnsigned};
use sp_runtime::{DispatchError, ArithmeticError, TokenError};
use sp_runtime::{ArithmeticError, DispatchError, TokenError};
use sp_std::fmt::Debug;
/// One of a number of consequences of withdrawing a fungible from an account.
#[derive(Copy, Clone, Eq, PartialEq)]
@@ -150,7 +150,7 @@ impl WithdrawReasons {
/// assert_eq!(
/// WithdrawReasons::FEE | WithdrawReasons::TRANSFER | WithdrawReasons::RESERVE | WithdrawReasons::TIP,
/// WithdrawReasons::except(WithdrawReasons::TRANSACTION_PAYMENT),
/// );
/// );
/// # }
/// ```
pub fn except(one: WithdrawReasons) -> WithdrawReasons {
@@ -161,7 +161,7 @@ impl WithdrawReasons {
}
/// Simple amalgamation trait to collect together properties for an AssetId under one roof.
pub trait AssetId: FullCodec + Copy + Eq + PartialEq + Debug {}
pub trait AssetId: FullCodec + Copy + Eq + PartialEq + Debug {}
impl<T: FullCodec + Copy + Eq + PartialEq + Debug> AssetId for T {}
/// Simple amalgamation trait to collect together properties for a Balance under one roof.
@@ -24,12 +24,11 @@
//! For an NFT API which has dual-level namespacing, the traits in `nonfungibles` are better to
//! use.
use codec::{Encode, Decode};
use sp_std::prelude::*;
use sp_runtime::TokenError;
use crate::dispatch::DispatchResult;
use crate::traits::Get;
use super::nonfungibles;
use crate::{dispatch::DispatchResult, traits::Get};
use codec::{Decode, Encode};
use sp_runtime::TokenError;
use sp_std::prelude::*;
/// Trait for providing an interface to a read-only NFT-like set of asset instances.
pub trait Inspect<AccountId> {
@@ -43,7 +42,9 @@ pub trait Inspect<AccountId> {
/// Returns the attribute value of `instance` corresponding to `key`.
///
/// By default this is `None`; no attributes are defined.
fn attribute(_instance: &Self::InstanceId, _key: &[u8]) -> Option<Vec<u8>> { None }
fn attribute(_instance: &Self::InstanceId, _key: &[u8]) -> Option<Vec<u8>> {
None
}
/// Returns the strongly-typed attribute value of `instance` corresponding to `key`.
///
@@ -56,7 +57,9 @@ pub trait Inspect<AccountId> {
/// Returns `true` if the asset `instance` may be transferred.
///
/// Default implementation is that all assets are transferable.
fn can_transfer(_instance: &Self::InstanceId) -> bool { true }
fn can_transfer(_instance: &Self::InstanceId) -> bool {
true
}
}
/// Interface for enumerating assets in existence or owned by a given account over a collection
@@ -117,15 +120,14 @@ pub struct ItemOf<
F: nonfungibles::Inspect<AccountId>,
A: Get<<F as nonfungibles::Inspect<AccountId>>::ClassId>,
AccountId,
>(
sp_std::marker::PhantomData<(F, A, AccountId)>
);
>(sp_std::marker::PhantomData<(F, A, AccountId)>);
impl<
F: nonfungibles::Inspect<AccountId>,
A: Get<<F as nonfungibles::Inspect<AccountId>>::ClassId>,
AccountId,
> Inspect<AccountId> for ItemOf<F, A, AccountId> {
F: nonfungibles::Inspect<AccountId>,
A: Get<<F as nonfungibles::Inspect<AccountId>>::ClassId>,
AccountId,
> Inspect<AccountId> for ItemOf<F, A, AccountId>
{
type InstanceId = <F as nonfungibles::Inspect<AccountId>>::InstanceId;
fn owner(instance: &Self::InstanceId) -> Option<AccountId> {
<F as nonfungibles::Inspect<AccountId>>::owner(&A::get(), instance)
@@ -142,10 +144,11 @@ impl<
}
impl<
F: nonfungibles::InspectEnumerable<AccountId>,
A: Get<<F as nonfungibles::Inspect<AccountId>>::ClassId>,
AccountId,
> InspectEnumerable<AccountId> for ItemOf<F, A, AccountId> {
F: nonfungibles::InspectEnumerable<AccountId>,
A: Get<<F as nonfungibles::Inspect<AccountId>>::ClassId>,
AccountId,
> InspectEnumerable<AccountId> for ItemOf<F, A, AccountId>
{
fn instances() -> Box<dyn Iterator<Item = Self::InstanceId>> {
<F as nonfungibles::InspectEnumerable<AccountId>>::instances(&A::get())
}
@@ -155,10 +158,11 @@ impl<
}
impl<
F: nonfungibles::Mutate<AccountId>,
A: Get<<F as nonfungibles::Inspect<AccountId>>::ClassId>,
AccountId,
> Mutate<AccountId> for ItemOf<F, A, AccountId> {
F: nonfungibles::Mutate<AccountId>,
A: Get<<F as nonfungibles::Inspect<AccountId>>::ClassId>,
AccountId,
> Mutate<AccountId> for ItemOf<F, A, AccountId>
{
fn mint_into(instance: &Self::InstanceId, who: &AccountId) -> DispatchResult {
<F as nonfungibles::Mutate<AccountId>>::mint_into(&A::get(), instance, who)
}
@@ -178,10 +182,11 @@ impl<
}
impl<
F: nonfungibles::Transfer<AccountId>,
A: Get<<F as nonfungibles::Inspect<AccountId>>::ClassId>,
AccountId,
> Transfer<AccountId> for ItemOf<F, A, AccountId> {
F: nonfungibles::Transfer<AccountId>,
A: Get<<F as nonfungibles::Inspect<AccountId>>::ClassId>,
AccountId,
> Transfer<AccountId> for ItemOf<F, A, AccountId>
{
fn transfer(instance: &Self::InstanceId, destination: &AccountId) -> DispatchResult {
<F as nonfungibles::Transfer<AccountId>>::transfer(&A::get(), instance, destination)
}
@@ -27,10 +27,10 @@
//! Implementations of these traits may be converted to implementations of corresponding
//! `nonfungible` traits by using the `nonfungible::ItemOf` type adapter.
use sp_std::prelude::*;
use codec::{Encode, Decode};
use sp_runtime::TokenError;
use crate::dispatch::DispatchResult;
use codec::{Decode, Encode};
use sp_runtime::TokenError;
use sp_std::prelude::*;
/// Trait for providing an interface to many read-only NFT-like sets of asset instances.
pub trait Inspect<AccountId> {
@@ -48,14 +48,18 @@ pub trait Inspect<AccountId> {
/// Returns the owner of the asset `class`, if there is one. For many NFTs this may not make
/// any sense, so users of this API should not be surprised to find an asset class results in
/// `None` here.
fn class_owner(_class: &Self::ClassId) -> Option<AccountId> { None }
fn class_owner(_class: &Self::ClassId) -> Option<AccountId> {
None
}
/// Returns the attribute value of `instance` of `class` corresponding to `key`.
///
/// By default this is `None`; no attributes are defined.
fn attribute(_class: &Self::ClassId, _instance: &Self::InstanceId, _key: &[u8])
-> Option<Vec<u8>>
{
fn attribute(
_class: &Self::ClassId,
_instance: &Self::InstanceId,
_key: &[u8],
) -> Option<Vec<u8>> {
None
}
@@ -74,15 +78,14 @@ pub trait Inspect<AccountId> {
/// Returns the attribute value of `class` corresponding to `key`.
///
/// By default this is `None`; no attributes are defined.
fn class_attribute(_class: &Self::ClassId, _key: &[u8]) -> Option<Vec<u8>> { None }
fn class_attribute(_class: &Self::ClassId, _key: &[u8]) -> Option<Vec<u8>> {
None
}
/// Returns the strongly-typed attribute value of `class` corresponding to `key`.
///
/// By default this just attempts to use `class_attribute`.
fn typed_class_attribute<K: Encode, V: Decode>(
class: &Self::ClassId,
key: &K,
) -> Option<V> {
fn typed_class_attribute<K: Encode, V: Decode>(class: &Self::ClassId, key: &K) -> Option<V> {
key.using_encoded(|d| Self::class_attribute(class, d))
.and_then(|v| V::decode(&mut &v[..]).ok())
}
@@ -90,7 +93,9 @@ pub trait Inspect<AccountId> {
/// Returns `true` if the asset `instance` of `class` may be transferred.
///
/// Default implementation is that all assets are transferable.
fn can_transfer(_class: &Self::ClassId, _instance: &Self::InstanceId) -> bool { true }
fn can_transfer(_class: &Self::ClassId, _instance: &Self::InstanceId) -> bool {
true
}
}
/// Interface for enumerating assets in existence or owned by a given account over many collections
@@ -106,7 +111,10 @@ pub trait InspectEnumerable<AccountId>: Inspect<AccountId> {
fn owned(who: &AccountId) -> Box<dyn Iterator<Item = (Self::ClassId, Self::InstanceId)>>;
/// Returns an iterator of the asset instances of `class` owned by `who`.
fn owned_in_class(class: &Self::ClassId, who: &AccountId) -> Box<dyn Iterator<Item = Self::InstanceId>>;
fn owned_in_class(
class: &Self::ClassId,
who: &AccountId,
) -> Box<dyn Iterator<Item = Self::InstanceId>>;
}
/// Trait for providing an interface for multiple classes of NFT-like assets which may be minted,
@@ -151,19 +159,13 @@ pub trait Mutate<AccountId>: Inspect<AccountId> {
key: &K,
value: &V,
) -> DispatchResult {
key.using_encoded(|k| value.using_encoded(|v|
Self::set_attribute(class, instance, k, v)
))
key.using_encoded(|k| value.using_encoded(|v| Self::set_attribute(class, instance, k, v)))
}
/// Set attribute `value` of asset `class`'s `key`.
///
/// By default, this is not a supported operation.
fn set_class_attribute(
_class: &Self::ClassId,
_key: &[u8],
_value: &[u8],
) -> DispatchResult {
fn set_class_attribute(_class: &Self::ClassId, _key: &[u8], _value: &[u8]) -> DispatchResult {
Err(TokenError::Unsupported.into())
}
@@ -175,9 +177,7 @@ pub trait Mutate<AccountId>: Inspect<AccountId> {
key: &K,
value: &V,
) -> DispatchResult {
key.using_encoded(|k| value.using_encoded(|v|
Self::set_class_attribute(class, k, v)
))
key.using_encoded(|k| value.using_encoded(|v| Self::set_class_attribute(class, k, v)))
}
}
@@ -17,13 +17,14 @@
//! Traits for dealing with validation and validators.
use sp_std::prelude::*;
use crate::{dispatch::Parameter, weights::Weight};
use codec::{Codec, Decode};
use sp_runtime::traits::{Convert, Zero};
use sp_runtime::{BoundToRuntimeAppPublic, ConsensusEngineId, Permill, RuntimeAppPublic};
use sp_runtime::{
traits::{Convert, Zero},
BoundToRuntimeAppPublic, ConsensusEngineId, Permill, RuntimeAppPublic,
};
use sp_staking::SessionIndex;
use crate::dispatch::Parameter;
use crate::weights::Weight;
use sp_std::prelude::*;
/// A trait for online node inspection in a session.
///
@@ -54,12 +55,14 @@ pub trait ValidatorSetWithIdentification<AccountId>: ValidatorSet<AccountId> {
pub trait FindAuthor<Author> {
/// Find the author of a block based on the pre-runtime digests.
fn find_author<'a, I>(digests: I) -> Option<Author>
where I: 'a + IntoIterator<Item=(ConsensusEngineId, &'a [u8])>;
where
I: 'a + IntoIterator<Item = (ConsensusEngineId, &'a [u8])>;
}
impl<A> FindAuthor<A> for () {
fn find_author<'a, I>(_: I) -> Option<A>
where I: 'a + IntoIterator<Item=(ConsensusEngineId, &'a [u8])>
where
I: 'a + IntoIterator<Item = (ConsensusEngineId, &'a [u8])>,
{
None
}
@@ -81,7 +84,9 @@ pub trait OneSessionHandler<ValidatorId>: BoundToRuntimeAppPublic {
/// for the second session, therefore the first call to `on_new_session`
/// should provide the same validator set.
fn on_genesis_session<'a, I: 'a>(validators: I)
where I: Iterator<Item=(&'a ValidatorId, Self::Key)>, ValidatorId: 'a;
where
I: Iterator<Item = (&'a ValidatorId, Self::Key)>,
ValidatorId: 'a;
/// Session set has changed; act appropriately. Note that this can be called
/// before initialization of your module.
@@ -92,11 +97,10 @@ pub trait OneSessionHandler<ValidatorId>: BoundToRuntimeAppPublic {
///
/// The `validators` are the validators of the incoming session, and `queued_validators`
/// will follow.
fn on_new_session<'a, I: 'a>(
changed: bool,
validators: I,
queued_validators: I,
) where I: Iterator<Item=(&'a ValidatorId, Self::Key)>, ValidatorId: 'a;
fn on_new_session<'a, I: 'a>(changed: bool, validators: I, queued_validators: I)
where
I: Iterator<Item = (&'a ValidatorId, Self::Key)>,
ValidatorId: 'a;
/// A notification for end of the session.
///
+4 -3
View File
@@ -18,7 +18,7 @@
//! Traits and associated data structures concerned with voting, and moving between tokens and
//! votes.
use sp_arithmetic::traits::{UniqueSaturatedInto, UniqueSaturatedFrom, SaturatedConversion};
use sp_arithmetic::traits::{SaturatedConversion, UniqueSaturatedFrom, UniqueSaturatedInto};
/// A trait similar to `Convert` to convert values from `B` an abstract balance type
/// into u64 and back from u128. (This conversion is used in election and other places where complex
@@ -69,7 +69,6 @@ impl CurrencyToVote<u128> for U128CurrencyToVote {
}
}
/// A naive implementation of `CurrencyConvert` that simply saturates all conversions.
///
/// # Warning
@@ -77,7 +76,9 @@ impl CurrencyToVote<u128> for U128CurrencyToVote {
/// This is designed to be used mostly for testing. Use with care, and think about the consequences.
pub struct SaturatingCurrencyToVote;
impl<B: UniqueSaturatedInto<u64> + UniqueSaturatedFrom<u128>> CurrencyToVote<B> for SaturatingCurrencyToVote {
impl<B: UniqueSaturatedInto<u64> + UniqueSaturatedFrom<u128>> CurrencyToVote<B>
for SaturatingCurrencyToVote
{
fn to_vote(value: B, _: B) -> u64 {
value.unique_saturated_into()
}
+65 -74
View File
@@ -127,15 +127,20 @@
//! - Ubuntu 19.10 (GNU/Linux 5.3.0-18-generic x86_64)
//! - rustc 1.42.0 (b8cedc004 2020-03-09)
use crate::dispatch::{DispatchError, DispatchErrorWithPostInfo, DispatchResultWithPostInfo};
use codec::{Decode, Encode};
#[cfg(feature = "std")]
use serde::{Serialize, Deserialize};
use codec::{Encode, Decode};
use sp_runtime::{RuntimeDebug, traits::SignedExtension};
use sp_runtime::generic::{CheckedExtrinsic, UncheckedExtrinsic};
use crate::dispatch::{DispatchErrorWithPostInfo, DispatchResultWithPostInfo, DispatchError};
use sp_runtime::traits::SaturatedConversion;
use sp_arithmetic::{Perbill, traits::{BaseArithmetic, Saturating, Unsigned}};
use serde::{Deserialize, Serialize};
use smallvec::{smallvec, SmallVec};
use sp_arithmetic::{
traits::{BaseArithmetic, Saturating, Unsigned},
Perbill,
};
use sp_runtime::{
generic::{CheckedExtrinsic, UncheckedExtrinsic},
traits::{SaturatedConversion, SignedExtension},
RuntimeDebug,
};
/// Re-export priority as type
pub use sp_runtime::transaction_validity::TransactionPriority;
@@ -152,7 +157,7 @@ pub mod constants {
pub const WEIGHT_PER_SECOND: Weight = 1_000_000_000_000;
pub const WEIGHT_PER_MILLIS: Weight = WEIGHT_PER_SECOND / 1000; // 1_000_000_000
pub const WEIGHT_PER_MICROS: Weight = WEIGHT_PER_MILLIS / 1000; // 1_000_000
pub const WEIGHT_PER_NANOS: Weight = WEIGHT_PER_MICROS / 1000; // 1_000
pub const WEIGHT_PER_NANOS: Weight = WEIGHT_PER_MICROS / 1000; // 1_000
parameter_types! {
/// Importing a block with 0 txs takes ~5 ms
@@ -267,13 +272,17 @@ pub trait OneOrMany<T> {
}
impl OneOrMany<DispatchClass> for DispatchClass {
type Iter = sp_std::iter::Once<DispatchClass>;
fn into_iter(self) -> Self::Iter { sp_std::iter::once(self) }
type Iter = sp_std::iter::Once<DispatchClass>;
fn into_iter(self) -> Self::Iter {
sp_std::iter::once(self)
}
}
impl<'a> OneOrMany<DispatchClass> for &'a [DispatchClass] {
type Iter = sp_std::iter::Cloned<sp_std::slice::Iter<'a, DispatchClass>>;
fn into_iter(self) -> Self::Iter { self.iter().cloned() }
type Iter = sp_std::iter::Cloned<sp_std::slice::Iter<'a, DispatchClass>>;
fn into_iter(self) -> Self::Iter {
self.iter().cloned()
}
}
/// Primitives related to priority management of Frame.
@@ -365,43 +374,32 @@ pub fn extract_actual_weight(result: &DispatchResultWithPostInfo, info: &Dispatc
match result {
Ok(post_info) => &post_info,
Err(err) => &err.post_info,
}.calc_actual_weight(info)
}
.calc_actual_weight(info)
}
impl From<(Option<Weight>, Pays)> for PostDispatchInfo {
fn from(post_weight_info: (Option<Weight>, Pays)) -> Self {
let (actual_weight, pays_fee) = post_weight_info;
Self {
actual_weight,
pays_fee,
}
Self { actual_weight, pays_fee }
}
}
impl From<Pays> for PostDispatchInfo {
fn from(pays_fee: Pays) -> Self {
Self {
actual_weight: None,
pays_fee,
}
Self { actual_weight: None, pays_fee }
}
}
impl From<Option<Weight>> for PostDispatchInfo {
fn from(actual_weight: Option<Weight>) -> Self {
Self {
actual_weight,
pays_fee: Default::default(),
}
Self { actual_weight, pays_fee: Default::default() }
}
}
impl From<()> for PostDispatchInfo {
fn from(_: ()) -> Self {
Self {
actual_weight: None,
pays_fee: Default::default(),
}
Self { actual_weight: None, pays_fee: Default::default() }
}
}
@@ -434,8 +432,9 @@ pub trait WithPostDispatchInfo {
fn with_weight(self, actual_weight: Weight) -> DispatchErrorWithPostInfo;
}
impl<T> WithPostDispatchInfo for T where
T: Into<DispatchError>
impl<T> WithPostDispatchInfo for T
where
T: Into<DispatchError>,
{
fn with_weight(self, actual_weight: Weight) -> DispatchErrorWithPostInfo {
DispatchErrorWithPostInfo {
@@ -542,8 +541,9 @@ impl<Args, CD, PF> WeighData<Args> for FunctionOf<Weight, CD, PF> {
// `WeighData` as a closure
#[allow(deprecated)]
impl<Args, WD, CD, PF> WeighData<Args> for FunctionOf<WD, CD, PF> where
WD : Fn(Args) -> Weight
impl<Args, WD, CD, PF> WeighData<Args> for FunctionOf<WD, CD, PF>
where
WD: Fn(Args) -> Weight,
{
fn weigh_data(&self, args: Args) -> Weight {
(self.0)(args)
@@ -560,8 +560,9 @@ impl<Args, WD, PF> ClassifyDispatch<Args> for FunctionOf<WD, DispatchClass, PF>
// `ClassifyDispatch` as a raw value
#[allow(deprecated)]
impl<Args, WD, CD, PF> ClassifyDispatch<Args> for FunctionOf<WD, CD, PF> where
CD : Fn(Args) -> DispatchClass
impl<Args, WD, CD, PF> ClassifyDispatch<Args> for FunctionOf<WD, CD, PF>
where
CD: Fn(Args) -> DispatchClass,
{
fn classify_dispatch(&self, args: Args) -> DispatchClass {
(self.1)(args)
@@ -578,8 +579,9 @@ impl<Args, WD, CD> PaysFee<Args> for FunctionOf<WD, CD, Pays> {
// `PaysFee` as a closure
#[allow(deprecated)]
impl<Args, WD, CD, PF> PaysFee<Args> for FunctionOf<WD, CD, PF> where
PF : Fn(Args) -> Pays
impl<Args, WD, CD, PF> PaysFee<Args> for FunctionOf<WD, CD, PF>
where
PF: Fn(Args) -> Pays,
{
fn pays_fee(&self, args: Args) -> Pays {
(self.2)(args)
@@ -599,8 +601,7 @@ where
}
/// Implementation for checked extrinsic.
impl<AccountId, Call, Extra> GetDispatchInfo
for CheckedExtrinsic<AccountId, Call, Extra>
impl<AccountId, Call, Extra> GetDispatchInfo for CheckedExtrinsic<AccountId, Call, Extra>
where
Call: GetDispatchInfo,
{
@@ -614,11 +615,7 @@ where
impl<Call: Encode, Extra: Encode> GetDispatchInfo for sp_runtime::testing::TestXt<Call, Extra> {
fn get_dispatch_info(&self) -> DispatchInfo {
// for testing: weight == size.
DispatchInfo {
weight: self.encode().len() as _,
pays_fee: Pays::Yes,
..Default::default()
}
DispatchInfo { weight: self.encode().len() as _, pays_fee: Pays::Yes, ..Default::default() }
}
}
@@ -690,32 +687,35 @@ pub trait WeightToFeePolynomial {
/// This should not be overriden in most circumstances. Calculation is done in the
/// `Balance` type and never overflows. All evaluation is saturating.
fn calc(weight: &Weight) -> Self::Balance {
Self::polynomial().iter().fold(Self::Balance::saturated_from(0u32), |mut acc, args| {
let w = Self::Balance::saturated_from(*weight).saturating_pow(args.degree.into());
Self::polynomial()
.iter()
.fold(Self::Balance::saturated_from(0u32), |mut acc, args| {
let w = Self::Balance::saturated_from(*weight).saturating_pow(args.degree.into());
// The sum could get negative. Therefore we only sum with the accumulator.
// The Perbill Mul implementation is non overflowing.
let frac = args.coeff_frac * w;
let integer = args.coeff_integer.saturating_mul(w);
// The sum could get negative. Therefore we only sum with the accumulator.
// The Perbill Mul implementation is non overflowing.
let frac = args.coeff_frac * w;
let integer = args.coeff_integer.saturating_mul(w);
if args.negative {
acc = acc.saturating_sub(frac);
acc = acc.saturating_sub(integer);
} else {
acc = acc.saturating_add(frac);
acc = acc.saturating_add(integer);
}
if args.negative {
acc = acc.saturating_sub(frac);
acc = acc.saturating_sub(integer);
} else {
acc = acc.saturating_add(frac);
acc = acc.saturating_add(integer);
}
acc
})
acc
})
}
}
/// Implementor of `WeightToFeePolynomial` that maps one unit of weight to one unit of fee.
pub struct IdentityFee<T>(sp_std::marker::PhantomData<T>);
impl<T> WeightToFeePolynomial for IdentityFee<T> where
T: BaseArithmetic + From<u32> + Copy + Unsigned
impl<T> WeightToFeePolynomial for IdentityFee<T>
where
T: BaseArithmetic + From<u32> + Copy + Unsigned,
{
type Balance = T;
@@ -813,8 +813,8 @@ impl PerDispatchClass<Weight> {
#[cfg(test)]
#[allow(dead_code)]
mod tests {
use crate::{decl_module, parameter_types, traits::Get};
use super::*;
use crate::{decl_module, parameter_types, traits::Get};
pub trait Config: 'static {
type Origin;
@@ -925,24 +925,15 @@ mod tests {
#[test]
fn extract_actual_weight_works() {
let pre = DispatchInfo {
weight: 1000,
.. Default::default()
};
let pre = DispatchInfo { weight: 1000, ..Default::default() };
assert_eq!(extract_actual_weight(&Ok(Some(7).into()), &pre), 7);
assert_eq!(extract_actual_weight(&Ok(Some(1000).into()), &pre), 1000);
assert_eq!(
extract_actual_weight(&Err(DispatchError::BadOrigin.with_weight(9)), &pre),
9
);
assert_eq!(extract_actual_weight(&Err(DispatchError::BadOrigin.with_weight(9)), &pre), 9);
}
#[test]
fn extract_actual_weight_caps_at_pre_weight() {
let pre = DispatchInfo {
weight: 1000,
.. Default::default()
};
let pre = DispatchInfo { weight: 1000, ..Default::default() };
assert_eq!(extract_actual_weight(&Ok(Some(1250).into()), &pre), 1000);
assert_eq!(
extract_actual_weight(&Err(DispatchError::BadOrigin.with_weight(1300)), &pre),