Skip to content

Commit

Permalink
initialise total issuance with a migration
Browse files Browse the repository at this point in the history
initialise total issuance with a migration
  • Loading branch information
orriin committed Jul 24, 2024
1 parent b34c052 commit 64993cc
Show file tree
Hide file tree
Showing 9 changed files with 118 additions and 180 deletions.
12 changes: 0 additions & 12 deletions pallets/admin-utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1035,18 +1035,6 @@ pub mod pallet {
T::Subtensor::ensure_subnet_owner_or_root(origin.clone(), netuid)?;
T::Subtensor::do_set_alpha_values(origin, netuid, alpha_low, alpha_high)
}

/// Sets the [`pallet_subtensor::TotalSubnetLocked`] value.
#[pallet::call_index(52)]
#[pallet::weight(T::WeightInfo::sudo_set_commit_reveal_weights_enabled())]
pub fn sudo_set_total_subnet_locked(origin: OriginFor<T>, amount: u64) -> DispatchResult {
ensure_root(origin)?;

pallet_subtensor::TotalSubnetLocked::<T>::put(amount);

log::info!("Set pallet_subtensor::TotalSubnetLocked to {}", amount);
Ok(())
}
}
}

Expand Down
31 changes: 0 additions & 31 deletions pallets/admin-utils/tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1183,22 +1183,6 @@ fn test_sudo_set_target_stakes_per_interval() {
});
}

#[test]
fn test_set_total_subnet_locked_ok() {
new_test_ext().execute_with(|| {
// Setup
let before = pallet_subtensor::TotalSubnetLocked::<Test>::get();
let new = 1000u64;
assert_ne!(before, new);
assert_ok!(AdminUtils::sudo_set_total_subnet_locked(
RuntimeOrigin::root(),
new
));
let after = pallet_subtensor::TotalSubnetLocked::<Test>::get();
assert_eq!(after, new);
});
}

#[test]
fn test_sudo_set_liquid_alpha_enabled() {
new_test_ext().execute_with(|| {
Expand Down Expand Up @@ -1235,21 +1219,6 @@ fn test_set_alpha_values_dispatch_info_ok() {
});
}

#[test]
fn test_set_total_subnet_locked_not_sudo() {
new_test_ext().execute_with(|| {
// Setup
let before = pallet_subtensor::TotalSubnetLocked::<Test>::get();
let new = 1000u64;
let who = U256::from(1);
assert_ne!(before, new);
assert_err!(
AdminUtils::sudo_set_total_subnet_locked(RuntimeOrigin::signed(who), new),
DispatchError::BadOrigin
);
})
}

#[test]
fn test_sudo_get_set_alpha() {
new_test_ext().execute_with(|| {
Expand Down
15 changes: 0 additions & 15 deletions pallets/subtensor/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,21 +132,6 @@ mod events {
MinDelegateTakeSet(u16),
/// the target stakes per interval is set by sudo/admin transaction
TargetStakesPerIntervalSet(u64),
/// Total issuance was rejigged
TotalIssuanceRejigged {
/// If Some a signed account, or root
who: Option<T::AccountId>,
/// The previous pallet total issuance
prev_total_issuance: u64,
/// The new pallet total issuance
new_total_issuance: u64,
/// The total amount of tokens staked
total_stake: u64,
/// The total amount of tokens in accounts
total_account_balances: u64,
/// The total amount of tokens locked in subnets
total_subnet_locked: u64,
},
/// a member of the senate is adjusted
SenateAdjusted {
/// the account ID of the old senate member, if any
Expand Down
110 changes: 41 additions & 69 deletions pallets/subtensor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1445,39 +1445,7 @@ pub mod pallet {

#[cfg(feature = "try-runtime")]
fn try_state(_n: BlockNumberFor<T>) -> Result<(), sp_runtime::TryRuntimeError> {
use frame_support::traits::fungible::Inspect;
use sp_runtime::Saturating;

// Assert [`TotalStake`] accounting is correct
let mut total_staked = 0;
for stake in Stake::<T>::iter() {
total_staked.saturating_accrue(stake.2);
}
ensure!(
total_staked == TotalStake::<T>::get(),
"TotalStake does not match total staked"
);

// Assert [`TotalSubnetLocked`] accounting is correct
let mut total_subnet_locked = 0;
for (_, locked) in SubnetLocked::<T>::iter() {
total_subnet_locked.saturating_accrue(locked);
}
ensure!(
total_subnet_locked == TotalSubnetLocked::<T>::get(),
"TotalSubnetLocked does not match total subnet locked"
);

// Assert [`TotalIssuance`] accounting is correct
let currency_issuance = T::Currency::total_issuance();
ensure!(
TotalIssuance::<T>::get()
== currency_issuance
.saturating_add(total_staked)
.saturating_add(total_subnet_locked),
"TotalIssuance accounting discrepancy"
);

Self::check_accounting_invariants()?;
Ok(())
}
}
Expand Down Expand Up @@ -2321,42 +2289,6 @@ pub mod pallet {
) -> DispatchResult {
Ok(())
}

/// Set the [`TotalIssuance`] storage value to the total account balances issued + the
/// total amount staked + the total amount locked in subnets.
#[pallet::call_index(67)]
#[pallet::weight((
Weight::default()
.saturating_add(T::DbWeight::get().reads(3))
.saturating_add(T::DbWeight::get().writes(1)),
DispatchClass::Normal,
Pays::Yes
))]
pub fn rejig_total_issuance(origin: OriginFor<T>) -> DispatchResult {
let who = ensure_signed_or_root(origin)?;

let total_account_balances =
<T::Currency as fungible::Inspect<T::AccountId>>::total_issuance();
let total_stake = TotalStake::<T>::get();
let total_subnet_locked = TotalSubnetLocked::<T>::get();

let prev_total_issuance = TotalIssuance::<T>::get();
let new_total_issuance = total_account_balances
.saturating_add(total_stake)
.saturating_add(total_subnet_locked);
TotalIssuance::<T>::put(new_total_issuance);

Self::deposit_event(Event::TotalIssuanceRejigged {
who,
prev_total_issuance,
new_total_issuance,
total_stake,
total_account_balances,
total_subnet_locked,
});

Ok(())
}
}

// ---- Subtensor helper functions.
Expand Down Expand Up @@ -2402,6 +2334,46 @@ pub mod pallet {
}
true
}

#[cfg(feature = "try-runtime")]
/// Assets [`TotalStake`], [`TotalSubnetLocked`], and [`TotalIssuance`] accounting invariants
/// are correct.
pub fn check_accounting_invariants() -> Result<(), sp_runtime::TryRuntimeError> {
use frame_support::traits::fungible::Inspect;
use sp_runtime::Saturating;

// Assert [`TotalStake`] accounting is correct
let mut total_staked = 0;
for stake in Stake::<T>::iter() {
total_staked.saturating_accrue(stake.2);
}
ensure!(
total_staked == TotalStake::<T>::get(),
"TotalStake does not match total staked"
);

// Assert [`TotalSubnetLocked`] accounting is correct
let mut total_subnet_locked = 0;
for (_, locked) in SubnetLocked::<T>::iter() {
total_subnet_locked.saturating_accrue(locked);
}
ensure!(
total_subnet_locked == TotalSubnetLocked::<T>::get(),
"TotalSubnetLocked does not match total subnet locked"
);

// Assert [`TotalIssuance`] accounting is correct
let currency_issuance = T::Currency::total_issuance();
ensure!(
TotalIssuance::<T>::get()
== currency_issuance
.saturating_add(total_staked)
.saturating_add(total_subnet_locked),
"TotalIssuance accounting discrepancy"
);

Ok(())
}
}
}

Expand Down
50 changes: 50 additions & 0 deletions pallets/subtensor/src/migration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -690,3 +690,53 @@ pub fn migrate_populate_staking_hotkeys<T: Config>() -> Weight {
Weight::zero()
}
}

pub mod initialise_total_issuance {
use frame_support::pallet_prelude::Weight;
use frame_support::traits::{fungible, OnRuntimeUpgrade};
use sp_core::Get;

use crate::*;

pub struct Migration<T: Config>(PhantomData<T>);

impl<T: Config> OnRuntimeUpgrade for Migration<T> {
fn on_runtime_upgrade() -> Weight {
// First, we need to initialize the TotalSubnetLocked
let subnets_len = crate::SubnetLocked::<T>::iter().count() as u64;
let total_subnet_locked: u64 =
crate::SubnetLocked::<T>::iter().fold(0, |acc, (_, v)| acc.saturating_add(v));
crate::TotalSubnetLocked::<T>::put(total_subnet_locked);

// Now, we can rejig the total issuance
let total_account_balances = <<T as crate::Config>::Currency as fungible::Inspect<
<T as frame_system::Config>::AccountId,
>>::total_issuance();
let total_stake = crate::TotalStake::<T>::get();
let total_subnet_locked = crate::TotalSubnetLocked::<T>::get();

let prev_total_issuance = crate::TotalIssuance::<T>::get();
let new_total_issuance = total_account_balances
.saturating_add(total_stake)
.saturating_add(total_subnet_locked);
crate::TotalIssuance::<T>::put(new_total_issuance);

log::info!(
"Subtensor Pallet TI Rejigged: previously: {:?}, new: {:?}",
prev_total_issuance,
new_total_issuance
);

<T as frame_system::Config>::DbWeight::get()
.reads_writes(subnets_len.saturating_add(5), 1)
}

#[cfg(feature = "try-runtime")]
fn post_upgrade(_state: Vec<u8>) -> Result<(), sp_runtime::TryRuntimeError> {
// These are usually checked anyway by try-runtime-cli, but just in case check them again
// explicitly here.
crate::Pallet::<T>::check_accounting_invariants()?;
Ok(())
}
}
}
25 changes: 25 additions & 0 deletions pallets/subtensor/tests/migration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -422,3 +422,28 @@ fn run_migration_and_check(migration_name: &'static str) -> frame_support::weigh
// Return the weight of the executed migration
weight
}

#[test]
fn test_initialise_ti() {
use frame_support::traits::OnRuntimeUpgrade;

new_test_ext(1).execute_with(|| {
pallet_subtensor::SubnetLocked::<Test>::insert(1, 100);
pallet_subtensor::SubnetLocked::<Test>::insert(2, 5);
pallet_balances::TotalIssuance::<Test>::put(1000);
pallet_subtensor::TotalStake::<Test>::put(25);

// Ensure values are NOT initialized prior to running migration
assert!(pallet_subtensor::TotalIssuance::<Test>::get() == 0);
assert!(pallet_subtensor::TotalSubnetLocked::<Test>::get() == 0);

pallet_subtensor::migration::initialise_total_issuance::Migration::<Test>::on_runtime_upgrade();

// Ensure values were initialized correctly
assert!(pallet_subtensor::TotalSubnetLocked::<Test>::get() == 105);
assert!(
pallet_subtensor::TotalIssuance::<Test>::get()
== 105u64.saturating_add(1000).saturating_add(25)
);
});
}
52 changes: 0 additions & 52 deletions pallets/subtensor/tests/root.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#![allow(clippy::indexing_slicing, clippy::unwrap_used)]

use crate::mock::*;
use frame_support::traits::fungible::Mutate;
use frame_support::{assert_err, assert_ok};
use frame_system::Config;
use frame_system::{EventRecord, Phase};
Expand Down Expand Up @@ -976,57 +975,6 @@ fn test_dissolve_network_does_not_exist_err() {
});
}

#[test]
fn test_rejig_total_issuance_ok() {
new_test_ext(1).execute_with(|| {
// Setup
let who = U256::from(1);
Balances::set_balance(&who, 100);
let balances_total_issuance = Balances::total_issuance();
assert!(balances_total_issuance > 0);
let total_stake = 100;
let total_subnet_locked = 1000;
pallet_subtensor::TotalSubnetLocked::<Test>::put(total_subnet_locked);
pallet_subtensor::TotalStake::<Test>::put(total_stake);

let expected_total_issuance = balances_total_issuance + total_stake + total_subnet_locked;

// Rejig total issuance
let total_issuance_before = pallet_subtensor::TotalIssuance::<Test>::get();
assert_ne!(total_issuance_before, expected_total_issuance);
assert_ok!(SubtensorModule::rejig_total_issuance(
RuntimeOrigin::signed(who)
));
let total_issuance_after = pallet_subtensor::TotalIssuance::<Test>::get();

// Rejigged
assert_eq!(total_issuance_after, expected_total_issuance);
System::assert_last_event(RuntimeEvent::SubtensorModule(
pallet_subtensor::Event::TotalIssuanceRejigged {
who: Some(who),
new_total_issuance: total_issuance_after,
prev_total_issuance: total_issuance_before,
total_account_balances: balances_total_issuance,
total_stake,
total_subnet_locked,
},
));

// Works with root
assert_ok!(SubtensorModule::rejig_total_issuance(RuntimeOrigin::root()));
System::assert_last_event(RuntimeEvent::SubtensorModule(
pallet_subtensor::Event::TotalIssuanceRejigged {
who: None,
new_total_issuance: total_issuance_after,
prev_total_issuance: total_issuance_after,
total_account_balances: balances_total_issuance,
total_stake,
total_subnet_locked,
},
));
});
}

#[test]
fn test_set_subnet_locked_balance_adjusts_total_subnet_locked_correctly() {
new_test_ext(1).execute_with(|| {
Expand Down
2 changes: 1 addition & 1 deletion runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1297,7 +1297,7 @@ pub type SignedExtra = (
pallet_commitments::CommitmentsSignedExtension<Runtime>,
);

type Migrations = pallet_grandpa::migrations::MigrateV4ToV5<Runtime>;
type Migrations = pallet_subtensor::migration::initialise_total_issuance::Migration<Runtime>;

// Unchecked extrinsic type as expected by this runtime.
pub type UncheckedExtrinsic =
Expand Down
1 change: 1 addition & 0 deletions runtime/src/migrations/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
//! Export migrations from here.

0 comments on commit 64993cc

Please sign in to comment.