mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 23:21:06 +00:00
Rename Palette to FRAME (#4182)
* palette -> frame * PALETTE, Palette -> FRAME * Move folder pallete -> frame * Update docs/Structure.adoc Co-Authored-By: Benjamin Kampmann <ben.kampmann@googlemail.com> * Update docs/README.adoc Co-Authored-By: Benjamin Kampmann <ben.kampmann@googlemail.com> * Update README.adoc
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
// Copyright 2017-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Substrate is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Address type that is union of index and id for an account.
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use std::fmt;
|
||||
use rstd::convert::TryInto;
|
||||
use crate::Member;
|
||||
use codec::{Encode, Decode, Input, Output, Error};
|
||||
|
||||
/// An indices-aware address, which can be either a direct `AccountId` or
|
||||
/// an index.
|
||||
#[derive(PartialEq, Eq, Clone, sr_primitives::RuntimeDebug)]
|
||||
#[cfg_attr(feature = "std", derive(Hash))]
|
||||
pub enum Address<AccountId, AccountIndex> where
|
||||
AccountId: Member,
|
||||
AccountIndex: Member,
|
||||
{
|
||||
/// It's an account ID (pubkey).
|
||||
Id(AccountId),
|
||||
/// It's an account index.
|
||||
Index(AccountIndex),
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<AccountId, AccountIndex> fmt::Display for Address<AccountId, AccountIndex> where
|
||||
AccountId: Member,
|
||||
AccountIndex: Member,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<AccountId, AccountIndex> From<AccountId> for Address<AccountId, AccountIndex> where
|
||||
AccountId: Member,
|
||||
AccountIndex: Member,
|
||||
{
|
||||
fn from(a: AccountId) -> Self {
|
||||
Address::Id(a)
|
||||
}
|
||||
}
|
||||
|
||||
fn need_more_than<T: PartialOrd>(a: T, b: T) -> Result<T, Error> {
|
||||
if a < b { Ok(b) } else { Err("Invalid range".into()) }
|
||||
}
|
||||
|
||||
impl<AccountId, AccountIndex> Decode for Address<AccountId, AccountIndex> where
|
||||
AccountId: Member + Decode,
|
||||
AccountIndex: Member + Decode + PartialOrd<AccountIndex> + Ord + From<u32> + Copy,
|
||||
{
|
||||
fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
|
||||
Ok(match input.read_byte()? {
|
||||
x @ 0x00..=0xef => Address::Index(AccountIndex::from(x as u32)),
|
||||
0xfc => Address::Index(AccountIndex::from(
|
||||
need_more_than(0xef, u16::decode(input)?)? as u32
|
||||
)),
|
||||
0xfd => Address::Index(AccountIndex::from(
|
||||
need_more_than(0xffff, u32::decode(input)?)?
|
||||
)),
|
||||
0xfe => Address::Index(
|
||||
need_more_than(0xffffffffu32.into(), Decode::decode(input)?)?
|
||||
),
|
||||
0xff => Address::Id(Decode::decode(input)?),
|
||||
_ => return Err("Invalid address variant".into()),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<AccountId, AccountIndex> Encode for Address<AccountId, AccountIndex> where
|
||||
AccountId: Member + Encode,
|
||||
AccountIndex: Member + Encode + PartialOrd<AccountIndex> + Ord + Copy + From<u32> + TryInto<u32>,
|
||||
{
|
||||
fn encode_to<T: Output>(&self, dest: &mut T) {
|
||||
match *self {
|
||||
Address::Id(ref i) => {
|
||||
dest.push_byte(255);
|
||||
dest.push(i);
|
||||
}
|
||||
Address::Index(i) => {
|
||||
let maybe_u32: Result<u32, _> = i.try_into();
|
||||
if let Ok(x) = maybe_u32 {
|
||||
if x > 0xffff {
|
||||
dest.push_byte(253);
|
||||
dest.push(&x);
|
||||
}
|
||||
else if x >= 0xf0 {
|
||||
dest.push_byte(252);
|
||||
dest.push(&(x as u16));
|
||||
}
|
||||
else {
|
||||
dest.push_byte(x as u8);
|
||||
}
|
||||
|
||||
} else {
|
||||
dest.push_byte(254);
|
||||
dest.push(&i);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<AccountId, AccountIndex> codec::EncodeLike for Address<AccountId, AccountIndex> where
|
||||
AccountId: Member + Encode,
|
||||
AccountIndex: Member + Encode + PartialOrd<AccountIndex> + Ord + Copy + From<u32> + TryInto<u32>,
|
||||
{}
|
||||
|
||||
impl<AccountId, AccountIndex> Default for Address<AccountId, AccountIndex> where
|
||||
AccountId: Member + Default,
|
||||
AccountIndex: Member,
|
||||
{
|
||||
fn default() -> Self {
|
||||
Address::Id(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use codec::{Encode, Decode};
|
||||
|
||||
type Address = super::Address<[u8; 8], u32>;
|
||||
fn index(i: u32) -> Address { super::Address::Index(i) }
|
||||
fn id(i: [u8; 8]) -> Address { super::Address::Id(i) }
|
||||
|
||||
fn compare(a: Option<Address>, d: &[u8]) {
|
||||
if let Some(ref a) = a {
|
||||
assert_eq!(d, &a.encode()[..]);
|
||||
}
|
||||
assert_eq!(Address::decode(&mut &d[..]).ok(), a);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_should_work() {
|
||||
compare(Some(index(2)), &[2][..]);
|
||||
compare(None, &[240][..]);
|
||||
compare(None, &[252, 239, 0][..]);
|
||||
compare(Some(index(240)), &[252, 240, 0][..]);
|
||||
compare(Some(index(304)), &[252, 48, 1][..]);
|
||||
compare(None, &[253, 255, 255, 0, 0][..]);
|
||||
compare(Some(index(0x10000)), &[253, 0, 0, 1, 0][..]);
|
||||
compare(Some(id([42, 69, 42, 69, 42, 69, 42, 69])), &[255, 42, 69, 42, 69, 42, 69, 42, 69][..]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
// Copyright 2017-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Substrate is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! An index is a short form of an address. This module handles allocation
|
||||
//! of indices for a newly created accounts.
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
use rstd::{prelude::*, marker::PhantomData, convert::TryInto};
|
||||
use codec::{Encode, Codec};
|
||||
use support::{Parameter, decl_module, decl_event, decl_storage};
|
||||
use sr_primitives::traits::{One, SimpleArithmetic, StaticLookup, Member, LookupError};
|
||||
use system::{IsDeadAccount, OnNewAccount};
|
||||
|
||||
use self::address::Address as RawAddress;
|
||||
|
||||
mod mock;
|
||||
|
||||
pub mod address;
|
||||
mod tests;
|
||||
|
||||
/// Number of account IDs stored per enum set.
|
||||
const ENUM_SET_SIZE: u32 = 64;
|
||||
|
||||
pub type Address<T> = RawAddress<<T as system::Trait>::AccountId, <T as Trait>::AccountIndex>;
|
||||
|
||||
/// Turn an Id into an Index, or None for the purpose of getting
|
||||
/// a hint at a possibly desired index.
|
||||
pub trait ResolveHint<AccountId, AccountIndex> {
|
||||
/// Turn an Id into an Index, or None for the purpose of getting
|
||||
/// a hint at a possibly desired index.
|
||||
fn resolve_hint(who: &AccountId) -> Option<AccountIndex>;
|
||||
}
|
||||
|
||||
/// Simple encode-based resolve hint implementation.
|
||||
pub struct SimpleResolveHint<AccountId, AccountIndex>(PhantomData<(AccountId, AccountIndex)>);
|
||||
impl<AccountId: Encode, AccountIndex: From<u32>>
|
||||
ResolveHint<AccountId, AccountIndex> for SimpleResolveHint<AccountId, AccountIndex>
|
||||
{
|
||||
fn resolve_hint(who: &AccountId) -> Option<AccountIndex> {
|
||||
Some(AccountIndex::from(who.using_encoded(|e| e[0] as u32 + e[1] as u32 * 256)))
|
||||
}
|
||||
}
|
||||
|
||||
/// The module's config trait.
|
||||
pub trait Trait: system::Trait {
|
||||
/// Type used for storing an account's index; implies the maximum number of accounts the system
|
||||
/// can hold.
|
||||
type AccountIndex: Parameter + Member + Codec + Default + SimpleArithmetic + Copy;
|
||||
|
||||
/// Whether an account is dead or not.
|
||||
type IsDeadAccount: IsDeadAccount<Self::AccountId>;
|
||||
|
||||
/// How to turn an id into an index.
|
||||
type ResolveHint: ResolveHint<Self::AccountId, Self::AccountIndex>;
|
||||
|
||||
/// The overarching event type.
|
||||
type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
|
||||
}
|
||||
|
||||
decl_module! {
|
||||
pub struct Module<T: Trait> for enum Call where origin: T::Origin {
|
||||
fn deposit_event() = default;
|
||||
}
|
||||
}
|
||||
|
||||
decl_event!(
|
||||
pub enum Event<T> where
|
||||
<T as system::Trait>::AccountId,
|
||||
<T as Trait>::AccountIndex
|
||||
{
|
||||
/// A new account index was assigned.
|
||||
///
|
||||
/// This event is not triggered when an existing index is reassigned
|
||||
/// to another `AccountId`.
|
||||
NewAccountIndex(AccountId, AccountIndex),
|
||||
}
|
||||
);
|
||||
|
||||
decl_storage! {
|
||||
trait Store for Module<T: Trait> as Indices {
|
||||
/// The next free enumeration set.
|
||||
pub NextEnumSet get(fn next_enum_set) build(|config: &GenesisConfig<T>| {
|
||||
(config.ids.len() as u32 / ENUM_SET_SIZE).into()
|
||||
}): T::AccountIndex;
|
||||
|
||||
/// The enumeration sets.
|
||||
pub EnumSet get(fn enum_set) build(|config: &GenesisConfig<T>| {
|
||||
(0..((config.ids.len() as u32) + ENUM_SET_SIZE - 1) / ENUM_SET_SIZE)
|
||||
.map(|i| (
|
||||
i.into(),
|
||||
config.ids[
|
||||
(i * ENUM_SET_SIZE) as usize..
|
||||
config.ids.len().min(((i + 1) * ENUM_SET_SIZE) as usize)
|
||||
].to_owned(),
|
||||
))
|
||||
.collect::<Vec<_>>()
|
||||
}): map T::AccountIndex => Vec<T::AccountId>;
|
||||
}
|
||||
add_extra_genesis {
|
||||
config(ids): Vec<T::AccountId>;
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trait> Module<T> {
|
||||
// PUBLIC IMMUTABLES
|
||||
|
||||
/// Lookup an T::AccountIndex to get an Id, if there's one there.
|
||||
pub fn lookup_index(index: T::AccountIndex) -> Option<T::AccountId> {
|
||||
let enum_set_size = Self::enum_set_size();
|
||||
let set = Self::enum_set(index / enum_set_size);
|
||||
let i: usize = (index % enum_set_size).try_into().ok()?;
|
||||
set.get(i).cloned()
|
||||
}
|
||||
|
||||
/// `true` if the account `index` is ready for reclaim.
|
||||
pub fn can_reclaim(try_index: T::AccountIndex) -> bool {
|
||||
let enum_set_size = Self::enum_set_size();
|
||||
let try_set = Self::enum_set(try_index / enum_set_size);
|
||||
let maybe_usize: Result<usize, _> = (try_index % enum_set_size).try_into();
|
||||
if let Ok(i) = maybe_usize {
|
||||
i < try_set.len() && T::IsDeadAccount::is_dead_account(&try_set[i])
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Lookup an address to get an Id, if there's one there.
|
||||
pub fn lookup_address(
|
||||
a: address::Address<T::AccountId, T::AccountIndex>
|
||||
) -> Option<T::AccountId> {
|
||||
match a {
|
||||
address::Address::Id(i) => Some(i),
|
||||
address::Address::Index(i) => Self::lookup_index(i),
|
||||
}
|
||||
}
|
||||
|
||||
// PUBLIC MUTABLES (DANGEROUS)
|
||||
|
||||
fn enum_set_size() -> T::AccountIndex {
|
||||
ENUM_SET_SIZE.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trait> OnNewAccount<T::AccountId> for Module<T> {
|
||||
// Implementation of the config type managing the creation of new accounts.
|
||||
// See Balances module for a concrete example.
|
||||
//
|
||||
// # <weight>
|
||||
// - Independent of the arguments.
|
||||
// - Given the correct value of `Self::next_enum_set`, it always has a limited
|
||||
// number of reads and writes and no complex computation.
|
||||
//
|
||||
// As for storage, calling this function with _non-dead-indices_ will linearly grow the length of
|
||||
// of `Self::enum_set`. Appropriate economic incentives should exist to make callers of this
|
||||
// function provide a `who` argument that reclaims a dead account.
|
||||
//
|
||||
// At the time of this writing, only the Balances module calls this function upon creation
|
||||
// of new accounts.
|
||||
// # </weight>
|
||||
fn on_new_account(who: &T::AccountId) {
|
||||
let enum_set_size = Self::enum_set_size();
|
||||
let next_set_index = Self::next_enum_set();
|
||||
|
||||
if let Some(try_index) = T::ResolveHint::resolve_hint(who) {
|
||||
// then check to see if this account id identifies a dead account index.
|
||||
let set_index = try_index / enum_set_size;
|
||||
let mut try_set = Self::enum_set(set_index);
|
||||
if let Ok(item_index) = (try_index % enum_set_size).try_into() {
|
||||
if item_index < try_set.len() {
|
||||
if T::IsDeadAccount::is_dead_account(&try_set[item_index]) {
|
||||
// yup - this index refers to a dead account. can be reused.
|
||||
try_set[item_index] = who.clone();
|
||||
<EnumSet<T>>::insert(set_index, try_set);
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// insert normally as a back up
|
||||
let mut set_index = next_set_index;
|
||||
// defensive only: this loop should never iterate since we keep NextEnumSet up to date
|
||||
// later.
|
||||
let mut set = loop {
|
||||
let set = Self::enum_set(set_index);
|
||||
if set.len() < ENUM_SET_SIZE as usize {
|
||||
break set;
|
||||
}
|
||||
set_index += One::one();
|
||||
};
|
||||
|
||||
let index = set_index * enum_set_size + T::AccountIndex::from(set.len() as u32);
|
||||
|
||||
// update set.
|
||||
set.push(who.clone());
|
||||
|
||||
// keep NextEnumSet up to date
|
||||
if set.len() == ENUM_SET_SIZE as usize {
|
||||
<NextEnumSet<T>>::put(set_index + One::one());
|
||||
}
|
||||
|
||||
// write set.
|
||||
<EnumSet<T>>::insert(set_index, set);
|
||||
|
||||
Self::deposit_event(RawEvent::NewAccountIndex(who.clone(), index));
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trait> StaticLookup for Module<T> {
|
||||
type Source = address::Address<T::AccountId, T::AccountIndex>;
|
||||
type Target = T::AccountId;
|
||||
|
||||
fn lookup(a: Self::Source) -> Result<T::AccountId, LookupError> {
|
||||
Self::lookup_address(a).ok_or(LookupError)
|
||||
}
|
||||
|
||||
fn unlookup(a: Self::Target) -> Self::Source {
|
||||
address::Address::Id(a)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
// Copyright 2018-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Substrate is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Test utilities
|
||||
|
||||
#![cfg(test)]
|
||||
|
||||
use std::collections::HashSet;
|
||||
use ref_thread_local::{ref_thread_local, RefThreadLocal};
|
||||
use sr_primitives::testing::Header;
|
||||
use sr_primitives::Perbill;
|
||||
use primitives::H256;
|
||||
use support::{impl_outer_origin, parameter_types};
|
||||
use {runtime_io, system};
|
||||
use crate::{GenesisConfig, Module, Trait, IsDeadAccount, OnNewAccount, ResolveHint};
|
||||
|
||||
impl_outer_origin!{
|
||||
pub enum Origin for Runtime {}
|
||||
}
|
||||
|
||||
ref_thread_local! {
|
||||
static managed ALIVE: HashSet<u64> = HashSet::new();
|
||||
}
|
||||
|
||||
pub fn make_account(who: u64) {
|
||||
ALIVE.borrow_mut().insert(who);
|
||||
Indices::on_new_account(&who);
|
||||
}
|
||||
|
||||
pub fn kill_account(who: u64) {
|
||||
ALIVE.borrow_mut().remove(&who);
|
||||
}
|
||||
|
||||
pub struct TestIsDeadAccount {}
|
||||
impl IsDeadAccount<u64> for TestIsDeadAccount {
|
||||
fn is_dead_account(who: &u64) -> bool {
|
||||
!ALIVE.borrow_mut().contains(who)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TestResolveHint;
|
||||
impl ResolveHint<u64, u64> for TestResolveHint {
|
||||
fn resolve_hint(who: &u64) -> Option<u64> {
|
||||
if *who < 256 {
|
||||
None
|
||||
} else {
|
||||
Some(*who - 256)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted.
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub struct Runtime;
|
||||
parameter_types! {
|
||||
pub const BlockHashCount: u64 = 250;
|
||||
pub const MaximumBlockWeight: u32 = 1024;
|
||||
pub const MaximumBlockLength: u32 = 2 * 1024;
|
||||
pub const AvailableBlockRatio: Perbill = Perbill::one();
|
||||
}
|
||||
impl system::Trait for Runtime {
|
||||
type Origin = Origin;
|
||||
type Index = u64;
|
||||
type BlockNumber = u64;
|
||||
type Call = ();
|
||||
type Hash = H256;
|
||||
type Hashing = ::sr_primitives::traits::BlakeTwo256;
|
||||
type AccountId = u64;
|
||||
type Lookup = Indices;
|
||||
type Header = Header;
|
||||
type Event = ();
|
||||
type BlockHashCount = BlockHashCount;
|
||||
type MaximumBlockWeight = MaximumBlockWeight;
|
||||
type MaximumBlockLength = MaximumBlockLength;
|
||||
type AvailableBlockRatio = AvailableBlockRatio;
|
||||
type Version = ();
|
||||
}
|
||||
impl Trait for Runtime {
|
||||
type AccountIndex = u64;
|
||||
type IsDeadAccount = TestIsDeadAccount;
|
||||
type ResolveHint = TestResolveHint;
|
||||
type Event = ();
|
||||
}
|
||||
|
||||
pub fn new_test_ext() -> runtime_io::TestExternalities {
|
||||
{
|
||||
let mut h = ALIVE.borrow_mut();
|
||||
h.clear();
|
||||
for i in 1..5 { h.insert(i); }
|
||||
}
|
||||
|
||||
let mut t = system::GenesisConfig::default().build_storage::<Runtime>().unwrap();
|
||||
GenesisConfig::<Runtime> {
|
||||
ids: vec![1, 2, 3, 4]
|
||||
}.assimilate_storage(&mut t).unwrap();
|
||||
t.into()
|
||||
}
|
||||
|
||||
pub type Indices = Module<Runtime>;
|
||||
@@ -0,0 +1,67 @@
|
||||
// Copyright 2017-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Substrate is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Tests for the module.
|
||||
|
||||
#![cfg(test)]
|
||||
|
||||
use super::*;
|
||||
use crate::mock::{Indices, new_test_ext, make_account, kill_account, TestIsDeadAccount};
|
||||
|
||||
#[test]
|
||||
fn indexing_lookup_should_work() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_eq!(Indices::lookup_index(0), Some(1));
|
||||
assert_eq!(Indices::lookup_index(1), Some(2));
|
||||
assert_eq!(Indices::lookup_index(2), Some(3));
|
||||
assert_eq!(Indices::lookup_index(3), Some(4));
|
||||
assert_eq!(Indices::lookup_index(4), None);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_indexing_on_new_accounts_should_work() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_eq!(Indices::lookup_index(4), None);
|
||||
make_account(5);
|
||||
assert_eq!(Indices::lookup_index(4), Some(5));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reclaim_indexing_on_new_accounts_should_work() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_eq!(Indices::lookup_index(1), Some(2));
|
||||
assert_eq!(Indices::lookup_index(4), None);
|
||||
|
||||
kill_account(2); // index 1 no longer locked to id 2
|
||||
|
||||
make_account(1 + 256); // id 257 takes index 1.
|
||||
assert_eq!(Indices::lookup_index(1), Some(257));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn alive_account_should_prevent_reclaim() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert!(!TestIsDeadAccount::is_dead_account(&2));
|
||||
assert_eq!(Indices::lookup_index(1), Some(2));
|
||||
assert_eq!(Indices::lookup_index(4), None);
|
||||
|
||||
make_account(1 + 256); // id 257 takes index 1.
|
||||
assert_eq!(Indices::lookup_index(4), Some(257));
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user