From 5f988efdb1b3d218d6617d18778b195d9875fe48 Mon Sep 17 00:00:00 2001 From: Gav Date: Wed, 30 Nov 2022 20:06:03 +0100 Subject: [PATCH 1/6] API for registering inactive funds --- frame/balances/src/lib.rs | 32 +++++++++++++++++++- frame/support/src/traits/tokens/currency.rs | 19 ++++++++++++ frame/support/src/traits/tokens/fungible.rs | 19 ++++++++++++ frame/support/src/traits/tokens/fungibles.rs | 10 ++++++ frame/treasury/src/lib.rs | 15 +++++++++ 5 files changed, 94 insertions(+), 1 deletion(-) diff --git a/frame/balances/src/lib.rs b/frame/balances/src/lib.rs index d3085152eba6c..51b7a13ff5a7f 100644 --- a/frame/balances/src/lib.rs +++ b/frame/balances/src/lib.rs @@ -161,6 +161,7 @@ mod tests_local; #[cfg(test)] mod tests_reentrancy; pub mod weights; +pub mod migration; pub use self::imbalances::{NegativeImbalance, PositiveImbalance}; use codec::{Codec, Decode, Encode, MaxEncodedLen}; @@ -497,6 +498,12 @@ pub mod pallet { #[pallet::whitelist_storage] pub type TotalIssuance, I: 'static = ()> = StorageValue<_, T::Balance, ValueQuery>; + /// The total units of outstanding deactivated balance in the system. + #[pallet::storage] + #[pallet::getter(fn inactive_issuance)] + #[pallet::whitelist_storage] + pub type InactiveIssuance, I: 'static = ()> = StorageValue<_, T::Balance, ValueQuery>; + /// The Balances pallet example of storing the balance of an account. /// /// # Example @@ -1067,6 +1074,9 @@ impl, I: 'static> fungible::Inspect for Pallet fn total_issuance() -> Self::Balance { TotalIssuance::::get() } + fn active_issuance() -> Self::Balance { + TotalIssuance::::get().saturating_sub(InactiveIssuance::::get()) + } fn minimum_balance() -> Self::Balance { T::ExistentialDeposit::get() } @@ -1145,6 +1155,14 @@ impl, I: 'static> fungible::Transfer for Pallet let er = if keep_alive { KeepAlive } else { AllowDeath }; >::transfer(source, dest, amount, er).map(|_| amount) } + + fn deactivate(amount: Self::Balance) { + InactiveIssuance::::mutate(|b| b.saturating_accrue(amount)); + } + + fn reactivate(amount: Self::Balance) { + InactiveIssuance::::mutate(|b| b.saturating_reduce(amount)); + } } impl, I: 'static> fungible::Unbalanced for Pallet { @@ -1418,7 +1436,19 @@ where } fn total_issuance() -> Self::Balance { - >::get() + TotalIssuance::::get() + } + + fn active_issuance() -> Self::Balance { + ::active_issuance() + } + + fn deactivate(amount: Self::Balance) { + ::deactivate(amount); + } + + fn reactivate(amount: Self::Balance) { + ::reactivate(amount); } fn minimum_balance() -> Self::Balance { diff --git a/frame/support/src/traits/tokens/currency.rs b/frame/support/src/traits/tokens/currency.rs index d0beb66d34923..55ae4545a9240 100644 --- a/frame/support/src/traits/tokens/currency.rs +++ b/frame/support/src/traits/tokens/currency.rs @@ -59,6 +59,16 @@ pub trait Currency { /// The total amount of issuance in the system. fn total_issuance() -> Self::Balance; + /// The total amount of issuance in the system excluding those which are controlled by the + /// system. + fn active_issuance() -> Self::Balance { Self::total_issuance() } + + /// Reduce the active issuance by some amount. + fn deactivate(_: Self::Balance) {} + + /// Increase the active issuance by some amount, up to the outstanding amount reduced. + fn reactivate(_: Self::Balance) {} + /// The minimum balance any single account may have. This is equivalent to the `Balances` /// module's `ExistentialDeposit`. fn minimum_balance() -> Self::Balance; @@ -212,6 +222,15 @@ impl, A> Get for TotalIssuanceOf { } } +/// A non-const `Get` implementation parameterised by a `Currency` impl which provides the result +/// of `active_issuance`. +pub struct ActiveIssuanceOf, A>(sp_std::marker::PhantomData<(C, A)>); +impl, A> Get for ActiveIssuanceOf { + fn get() -> C::Balance { + C::active_issuance() + } +} + #[cfg(feature = "std")] impl Currency for () { type Balance = u32; diff --git a/frame/support/src/traits/tokens/fungible.rs b/frame/support/src/traits/tokens/fungible.rs index 90aadb6d8daa6..1fae8e14a56be 100644 --- a/frame/support/src/traits/tokens/fungible.rs +++ b/frame/support/src/traits/tokens/fungible.rs @@ -40,6 +40,10 @@ pub trait Inspect { /// The total amount of issuance in the system. fn total_issuance() -> Self::Balance; + /// The total amount of issuance in the system excluding those which are controlled by the + /// system. + fn active_issuance() -> Self::Balance { Self::total_issuance() } + /// The minimum balance any single account may have. fn minimum_balance() -> Self::Balance; @@ -120,6 +124,12 @@ pub trait Transfer: Inspect { amount: Self::Balance, keep_alive: bool, ) -> Result; + + /// Reduce the active issuance by some amount. + fn deactivate(_: Self::Balance) {} + + /// Increase the active issuance by some amount, up to the outstanding amount reduced. + fn reactivate(_: Self::Balance) {} } /// Trait for inspecting a fungible asset which can be reserved. @@ -213,6 +223,9 @@ impl< fn total_issuance() -> Self::Balance { >::total_issuance(A::get()) } + fn active_issuance() -> Self::Balance { + >::active_issuance(A::get()) + } fn minimum_balance() -> Self::Balance { >::minimum_balance(A::get()) } @@ -258,6 +271,12 @@ impl< ) -> Result { >::transfer(A::get(), source, dest, amount, keep_alive) } + fn deactivate(amount: Self::Balance) { + >::deactivate(A::get(), amount) + } + fn reactivate(amount: Self::Balance) { + >::reactivate(A::get(), amount) + } } impl< diff --git a/frame/support/src/traits/tokens/fungibles.rs b/frame/support/src/traits/tokens/fungibles.rs index 8c370e9a0d8b5..c8939114c9818 100644 --- a/frame/support/src/traits/tokens/fungibles.rs +++ b/frame/support/src/traits/tokens/fungibles.rs @@ -46,6 +46,10 @@ pub trait Inspect { /// The total amount of issuance in the system. fn total_issuance(asset: Self::AssetId) -> Self::Balance; + /// The total amount of issuance in the system excluding those which are controlled by the + /// system. + fn active_issuance(asset: Self::AssetId) -> Self::Balance { Self::total_issuance(asset) } + /// The minimum balance any single account may have. fn minimum_balance(asset: Self::AssetId) -> Self::Balance; @@ -177,6 +181,12 @@ pub trait Transfer: Inspect { amount: Self::Balance, keep_alive: bool, ) -> Result; + + /// Reduce the active issuance by some amount. + fn deactivate(_: Self::AssetId, _: Self::Balance) {} + + /// Increase the active issuance by some amount, up to the outstanding amount reduced. + fn reactivate(_: Self::AssetId, _: Self::Balance) {} } /// Trait for inspecting a set of named fungible assets which can be placed on hold. diff --git a/frame/treasury/src/lib.rs b/frame/treasury/src/lib.rs index 21b4d2b769c8b..6a1354dc87ffd 100644 --- a/frame/treasury/src/lib.rs +++ b/frame/treasury/src/lib.rs @@ -62,6 +62,7 @@ mod benchmarking; #[cfg(test)] mod tests; pub mod weights; +pub mod migration; use codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; @@ -138,6 +139,7 @@ pub mod pallet { use super::*; use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; +use sp_runtime::traits::CheckedSub; #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] @@ -229,6 +231,11 @@ pub mod pallet { pub type Approvals, I: 'static = ()> = StorageValue<_, BoundedVec, ValueQuery>; + /// The amount which has been reported as inactive to Currency. + #[pallet::storage] + pub type Deactivated, I: 'static = ()> = + StorageValue<_, BalanceOf, ValueQuery>; + #[pallet::genesis_config] pub struct GenesisConfig; @@ -322,6 +329,14 @@ pub mod pallet { } else { Weight::zero() } + let pot = Self::pot(); + let deactivated = Deactivated::::get(); + if let Some(v) = pot.checked_sub(&deactivated) { + T::Currency::deactivate(v) + } + else if let Some(v) = deactivated.checked_sub(&pot) { + T::Currency::reactivate(v) + } } } From 3654fcbdfc99715944789406ed484ffaaa3782dd Mon Sep 17 00:00:00 2001 From: Gav Date: Thu, 1 Dec 2022 08:52:15 +0100 Subject: [PATCH 2/6] Build fixes. --- frame/balances/src/lib.rs | 6 ++-- frame/balances/src/migration.rs | 50 +++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 frame/balances/src/migration.rs diff --git a/frame/balances/src/lib.rs b/frame/balances/src/lib.rs index 51b7a13ff5a7f..60c49dd64a9ad 100644 --- a/frame/balances/src/lib.rs +++ b/frame/balances/src/lib.rs @@ -1440,15 +1440,15 @@ where } fn active_issuance() -> Self::Balance { - ::active_issuance() + >::active_issuance() } fn deactivate(amount: Self::Balance) { - ::deactivate(amount); + >::deactivate(amount); } fn reactivate(amount: Self::Balance) { - ::reactivate(amount); + >::reactivate(amount); } fn minimum_balance() -> Self::Balance { diff --git a/frame/balances/src/migration.rs b/frame/balances/src/migration.rs new file mode 100644 index 0000000000000..212e238ffe404 --- /dev/null +++ b/frame/balances/src/migration.rs @@ -0,0 +1,50 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +use super::*; +use frame_support::{storage_alias, Twox64Concat, traits::OnRuntimeUpgrade, weights::Weight}; +use frame_support::pallet_prelude::*; + +// NOTE: This must be used alongside any accounts whose balances are expected to be inactive. +// Generally this will be used for the XCM teleport checking account. +pub struct MigrateToTrackInactive>(sp_std::marker::PhantomData<(T, A)>); +impl> OnRuntimeUpgrade for MigrateToTrackInactive { + fn on_runtime_upgrade() -> Weight { + let current_version = Pallet::::current_storage_version(); + let onchain_version = Pallet::::on_chain_storage_version(); + + if onchain_version == 0 && current_version == 1 { + let b = Pallet::::total_balance(&A::get()); + Pallet::::deactivate(b); + current_version.put::>(); + log::info!(target: "runtime::balances", "Storage to version {:?}", current_version); + T::DbWeight::get().reads_writes(3, 3) + } else { + log::info!(target: "runtime::balances", "Migration did not execute. This probably should be removed"); + T::DbWeight::get().reads(1) + } + } + + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, &'static str> { + Ok(vec![]) + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(total: Vec) -> Result<(), &'static str> { + Ok(()) + } +} From f41d727ea77fcf2915f468b4da64df380e3a37d1 Mon Sep 17 00:00:00 2001 From: Gavin Wood Date: Thu, 1 Dec 2022 16:26:30 +0100 Subject: [PATCH 3/6] Update frame/treasury/src/lib.rs --- frame/treasury/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/frame/treasury/src/lib.rs b/frame/treasury/src/lib.rs index 6a1354dc87ffd..de524c08842c4 100644 --- a/frame/treasury/src/lib.rs +++ b/frame/treasury/src/lib.rs @@ -62,7 +62,6 @@ mod benchmarking; #[cfg(test)] mod tests; pub mod weights; -pub mod migration; use codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; From d9fcabcd1f5018eb6aa74fa0cfeb05411ac77481 Mon Sep 17 00:00:00 2001 From: Gav Date: Thu, 1 Dec 2022 16:39:09 +0100 Subject: [PATCH 4/6] Fix --- frame/balances/src/lib.rs | 5 ++-- frame/balances/src/migration.rs | 7 +++-- frame/support/src/traits/tokens/currency.rs | 4 ++- frame/support/src/traits/tokens/fungible.rs | 4 ++- frame/support/src/traits/tokens/fungibles.rs | 4 ++- frame/treasury/src/lib.rs | 29 ++++++++++---------- 6 files changed, 31 insertions(+), 22 deletions(-) diff --git a/frame/balances/src/lib.rs b/frame/balances/src/lib.rs index 60c49dd64a9ad..c4a8456c22c67 100644 --- a/frame/balances/src/lib.rs +++ b/frame/balances/src/lib.rs @@ -156,12 +156,12 @@ #[macro_use] mod tests; mod benchmarking; +pub mod migration; mod tests_composite; mod tests_local; #[cfg(test)] mod tests_reentrancy; pub mod weights; -pub mod migration; pub use self::imbalances::{NegativeImbalance, PositiveImbalance}; use codec::{Codec, Decode, Encode, MaxEncodedLen}; @@ -502,7 +502,8 @@ pub mod pallet { #[pallet::storage] #[pallet::getter(fn inactive_issuance)] #[pallet::whitelist_storage] - pub type InactiveIssuance, I: 'static = ()> = StorageValue<_, T::Balance, ValueQuery>; + pub type InactiveIssuance, I: 'static = ()> = + StorageValue<_, T::Balance, ValueQuery>; /// The Balances pallet example of storing the balance of an account. /// diff --git a/frame/balances/src/migration.rs b/frame/balances/src/migration.rs index 212e238ffe404..ddbd3f55b15af 100644 --- a/frame/balances/src/migration.rs +++ b/frame/balances/src/migration.rs @@ -15,12 +15,13 @@ // along with Polkadot. If not, see . use super::*; -use frame_support::{storage_alias, Twox64Concat, traits::OnRuntimeUpgrade, weights::Weight}; -use frame_support::pallet_prelude::*; +use frame_support::{pallet_prelude::*, traits::OnRuntimeUpgrade, weights::Weight}; // NOTE: This must be used alongside any accounts whose balances are expected to be inactive. // Generally this will be used for the XCM teleport checking account. -pub struct MigrateToTrackInactive>(sp_std::marker::PhantomData<(T, A)>); +pub struct MigrateToTrackInactive>( + sp_std::marker::PhantomData<(T, A)>, +); impl> OnRuntimeUpgrade for MigrateToTrackInactive { fn on_runtime_upgrade() -> Weight { let current_version = Pallet::::current_storage_version(); diff --git a/frame/support/src/traits/tokens/currency.rs b/frame/support/src/traits/tokens/currency.rs index 55ae4545a9240..48247b6021798 100644 --- a/frame/support/src/traits/tokens/currency.rs +++ b/frame/support/src/traits/tokens/currency.rs @@ -61,7 +61,9 @@ pub trait Currency { /// The total amount of issuance in the system excluding those which are controlled by the /// system. - fn active_issuance() -> Self::Balance { Self::total_issuance() } + fn active_issuance() -> Self::Balance { + Self::total_issuance() + } /// Reduce the active issuance by some amount. fn deactivate(_: Self::Balance) {} diff --git a/frame/support/src/traits/tokens/fungible.rs b/frame/support/src/traits/tokens/fungible.rs index 1fae8e14a56be..7b1ec0f434382 100644 --- a/frame/support/src/traits/tokens/fungible.rs +++ b/frame/support/src/traits/tokens/fungible.rs @@ -42,7 +42,9 @@ pub trait Inspect { /// The total amount of issuance in the system excluding those which are controlled by the /// system. - fn active_issuance() -> Self::Balance { Self::total_issuance() } + fn active_issuance() -> Self::Balance { + Self::total_issuance() + } /// The minimum balance any single account may have. fn minimum_balance() -> Self::Balance; diff --git a/frame/support/src/traits/tokens/fungibles.rs b/frame/support/src/traits/tokens/fungibles.rs index c8939114c9818..0743e3031c467 100644 --- a/frame/support/src/traits/tokens/fungibles.rs +++ b/frame/support/src/traits/tokens/fungibles.rs @@ -48,7 +48,9 @@ pub trait Inspect { /// The total amount of issuance in the system excluding those which are controlled by the /// system. - fn active_issuance(asset: Self::AssetId) -> Self::Balance { Self::total_issuance(asset) } + fn active_issuance(asset: Self::AssetId) -> Self::Balance { + Self::total_issuance(asset) + } /// The minimum balance any single account may have. fn minimum_balance(asset: Self::AssetId) -> Self::Balance; diff --git a/frame/treasury/src/lib.rs b/frame/treasury/src/lib.rs index de524c08842c4..5d4b162dcd2d9 100644 --- a/frame/treasury/src/lib.rs +++ b/frame/treasury/src/lib.rs @@ -138,7 +138,7 @@ pub mod pallet { use super::*; use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; -use sp_runtime::traits::CheckedSub; + use sp_runtime::traits::CheckedSub; #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] @@ -224,17 +224,16 @@ use sp_runtime::traits::CheckedSub; OptionQuery, >; + /// The amount which has been reported as inactive to Currency. + #[pallet::storage] + pub type Inactive, I: 'static = ()> = StorageValue<_, BalanceOf, ValueQuery>; + /// Proposal indices that have been approved but not yet awarded. #[pallet::storage] #[pallet::getter(fn approvals)] pub type Approvals, I: 'static = ()> = StorageValue<_, BoundedVec, ValueQuery>; - /// The amount which has been reported as inactive to Currency. - #[pallet::storage] - pub type Deactivated, I: 'static = ()> = - StorageValue<_, BalanceOf, ValueQuery>; - #[pallet::genesis_config] pub struct GenesisConfig; @@ -322,20 +321,22 @@ use sp_runtime::traits::CheckedSub; /// - The weight is overestimated if some approvals got missed. /// # fn on_initialize(n: T::BlockNumber) -> Weight { + let pot = Self::pot(); + let deactivated = Inactive::::get(); + match pot.checked_sub(&deactivated) { + Some(x) if !x.is_zero() => T::Currency::deactivate(x), + _ => match deactivated.checked_sub(&pot) { + Some(x) if !x.is_zero() => T::Currency::reactivate(x), + _ => {}, + }, + } + // Check to see if we should spend some funds! if (n % T::SpendPeriod::get()).is_zero() { Self::spend_funds() } else { Weight::zero() } - let pot = Self::pot(); - let deactivated = Deactivated::::get(); - if let Some(v) = pot.checked_sub(&deactivated) { - T::Currency::deactivate(v) - } - else if let Some(v) = deactivated.checked_sub(&pot) { - T::Currency::reactivate(v) - } } } From cb94357c41fd793b4b6eecd82a6cfccd55bf7854 Mon Sep 17 00:00:00 2001 From: Gav Date: Fri, 2 Dec 2022 14:16:29 +0100 Subject: [PATCH 5/6] Fixes --- frame/balances/src/migration.rs | 4 ++-- frame/treasury/src/lib.rs | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/frame/balances/src/migration.rs b/frame/balances/src/migration.rs index ddbd3f55b15af..e27efc217407a 100644 --- a/frame/balances/src/migration.rs +++ b/frame/balances/src/migration.rs @@ -17,7 +17,7 @@ use super::*; use frame_support::{pallet_prelude::*, traits::OnRuntimeUpgrade, weights::Weight}; -// NOTE: This must be used alongside any accounts whose balances are expected to be inactive. +// NOTE: This must be used alongside the account whose balance is expected to be inactive. // Generally this will be used for the XCM teleport checking account. pub struct MigrateToTrackInactive>( sp_std::marker::PhantomData<(T, A)>, @@ -35,7 +35,7 @@ impl> OnRuntimeUpgrade for MigrateToTrackInactiv T::DbWeight::get().reads_writes(3, 3) } else { log::info!(target: "runtime::balances", "Migration did not execute. This probably should be removed"); - T::DbWeight::get().reads(1) + T::DbWeight::get().reads(2) } } diff --git a/frame/treasury/src/lib.rs b/frame/treasury/src/lib.rs index 5d4b162dcd2d9..a9c1230c1cf09 100644 --- a/frame/treasury/src/lib.rs +++ b/frame/treasury/src/lib.rs @@ -323,12 +323,12 @@ pub mod pallet { fn on_initialize(n: T::BlockNumber) -> Weight { let pot = Self::pot(); let deactivated = Inactive::::get(); - match pot.checked_sub(&deactivated) { - Some(x) if !x.is_zero() => T::Currency::deactivate(x), - _ => match deactivated.checked_sub(&pot) { - Some(x) if !x.is_zero() => T::Currency::reactivate(x), - _ => {}, - }, + if pot != deactivated { + match (pot > deactivated, pot.max(deactivated) - pot.min(deactivated)) { + (true, delta) => T::Currency::deactivate(delta), + (false, delta) => T::Currency::reactivate(delta), + } + Inactive::::put(&pot); } // Check to see if we should spend some funds! From a6a026f741d2b1c47f85823b50eddfaa171efefe Mon Sep 17 00:00:00 2001 From: Gav Date: Sat, 3 Dec 2022 08:48:53 +0100 Subject: [PATCH 6/6] Fixes --- frame/treasury/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/frame/treasury/src/lib.rs b/frame/treasury/src/lib.rs index a9c1230c1cf09..4aa00c348585c 100644 --- a/frame/treasury/src/lib.rs +++ b/frame/treasury/src/lib.rs @@ -138,7 +138,6 @@ pub mod pallet { use super::*; use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; - use sp_runtime::traits::CheckedSub; #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)]