-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Lazy reaping #4895
Lazy reaping #4895
Changes from 13 commits
9027e19
1081058
30cf0f3
644a1a4
11cd085
8de91c4
33d1a8d
c9c8e5f
9f18519
572efb3
4de443a
9e2fe29
603b194
2d8f05e
1181bc2
3c22d02
3741e90
6c0c845
e6c09eb
c2b6076
562f87d
f07b8e1
6de2216
9c59bcd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -159,6 +159,7 @@ mod benchmarking; | |
|
|
||
| use sp_std::prelude::*; | ||
| use sp_std::{cmp, result, mem, fmt::Debug, ops::BitOr, convert::Infallible}; | ||
| use sp_io::hashing::twox_64; | ||
| use codec::{Codec, Encode, Decode}; | ||
| use frame_support::{ | ||
| StorageValue, Parameter, decl_event, decl_storage, decl_module, decl_error, ensure, | ||
|
|
@@ -178,7 +179,7 @@ use sp_runtime::{ | |
| }; | ||
| use frame_system::{self as system, ensure_signed, ensure_root}; | ||
| use frame_support::storage::migration::{ | ||
| get_storage_value, take_storage_value, put_storage_value, StorageIterator | ||
| get_storage_value, take_storage_value, put_storage_value, StorageIterator, have_storage_value | ||
| }; | ||
|
|
||
| pub use self::imbalances::{PositiveImbalance, NegativeImbalance}; | ||
|
|
@@ -609,7 +610,16 @@ impl<T: Trait<I>, I: Instance> Module<T, I> { | |
|
|
||
| for (hash, balances) in StorageIterator::<AccountData<T::Balance>>::new(b"Balances", b"Account").drain() { | ||
| let nonce = take_storage_value::<T::Index>(b"System", b"AccountNonce", &hash).unwrap_or_default(); | ||
| put_storage_value(b"System", b"Account", &hash, (nonce, balances)); | ||
| let mut refs: system::RefCount = 0; | ||
| // The items in Kusama that would result in a ref count being incremented. | ||
| if have_storage_value(b"Democracy", b"Proxy", &hash) { refs += 1 } | ||
| // We skip Recovered since it's being replaced anyway. | ||
| let mut prefixed_hash = twox_64(&b":session:keys"[..]).to_vec(); | ||
| prefixed_hash.extend(&b":session:keys"[..]); | ||
| prefixed_hash.extend(&hash[..]); | ||
| if have_storage_value(b"Session", b"NextKeys", &prefixed_hash) { refs += 1 } | ||
| if have_storage_value(b"Staking", b"Bonded", &hash) { refs += 1 } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I understand that we don't have an easy and better choice here, but maybe we should document the rules of these references somewhere in a very strict way. The pattern in staking/session of
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are these the kind of rules would you be looking for? If a module wants to "keep alive" an account until it is done with it, it should put a reference counter on it. When it is done with it, it should remove that reference counter. It should only happen once each way. (But I guess there is nothing that would stop a module from managing multiple reference counters in both directions.) |
||
| put_storage_value(b"System", b"Account", &hash, (nonce, refs, &balances)); | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -721,14 +731,21 @@ impl<T: Trait<I>, I: Instance> Module<T, I> { | |
| } | ||
| } | ||
| }); | ||
| Locks::<T, I>::insert(who, locks); | ||
| } | ||
| } | ||
|
|
||
| impl<T: Trait<I>, I: Instance> OnReapAccount<T::AccountId> for Module<T, I> { | ||
| fn on_reap_account(who: &T::AccountId) { | ||
| Locks::<T, I>::remove(who); | ||
| Account::<T, I>::remove(who); | ||
| let existed = Locks::<T, I>::contains_key(who); | ||
| if locks.is_empty() { | ||
| Locks::<T, I>::remove(who); | ||
| if existed { | ||
| // TODO: use Locks::<T, I>::hashed_key | ||
gavofyork marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| // https://github.com/paritytech/substrate/issues/4969 | ||
| system::Module::<T>::dec_ref(who); | ||
| } | ||
| } else { | ||
| Locks::<T, I>::insert(who, locks); | ||
| if !existed { | ||
| system::Module::<T>::inc_ref(who); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -1040,6 +1057,7 @@ impl<T: Trait<I>, I: Instance> Currency<T::AccountId> for Module<T, I> where | |
| )?; | ||
|
|
||
| let allow_death = existence_requirement == ExistenceRequirement::AllowDeath; | ||
| let allow_death = allow_death && system::Module::<T>::allow_death(transactor); | ||
| ensure!(allow_death || from_account.free >= ed, Error::<T, I>::KeepAlive); | ||
|
|
||
| Ok(()) | ||
|
|
@@ -1283,6 +1301,17 @@ impl<T: Trait<I>, I: Instance> ReservableCurrency<T::AccountId> for Module<T, I> | |
| } | ||
| } | ||
|
|
||
| /// Implement `OnReapAccount` to remove the local account, if using local account storage. | ||
| /// | ||
| /// NOTE: You probably won't need to use this! This only needs to be "wired in" to System module | ||
| /// if you're using the local balance storage. **If you're using the composite system account | ||
| /// storage (which is the default in most examples and tests) then there's no need.** | ||
| impl<T: Trait<I>, I: Instance> OnReapAccount<T::AccountId> for Module<T, I> { | ||
shawntabrizi marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| fn on_reap_account(who: &T::AccountId) { | ||
| Account::<T, I>::remove(who); | ||
| } | ||
| } | ||
|
|
||
| impl<T: Trait<I>, I: Instance> LockableCurrency<T::AccountId> for Module<T, I> | ||
| where | ||
| T::Balance: MaybeSerializeDeserialize + Debug | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.