Skip to content

Commit

Permalink
move block emission adjustment to explicit step
Browse files Browse the repository at this point in the history
  • Loading branch information
camfairchild committed Dec 20, 2024
1 parent 170a5aa commit 1a3e3f9
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 24 deletions.
27 changes: 16 additions & 11 deletions pallets/subtensor/src/coinbase/block_emission.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use substrate_fixed::transcendental::log2;
use substrate_fixed::types::I96F32;

impl<T: Config> Pallet<T> {
/// Calculates the block emission based on the total issuance.
/// Calculates the block emission based on the total issuance and updates the chain if applicable.
///
/// This function computes the block emission by applying a logarithmic function
/// to the total issuance of the network. The formula used takes into account
Expand All @@ -15,9 +15,21 @@ impl<T: Config> Pallet<T> {
/// # Returns
/// * 'Result<u64, &'static str>': The calculated block emission rate or error.
///
pub fn get_block_emission() -> Result<u64, &'static str> {
// Convert the total issuance to a fixed-point number for calculation.
Self::get_block_emission_for_issuance(Self::get_total_issuance())
pub fn block_emission_step() -> Result<u64, &'static str> {
let issuance = Self::get_total_issuance();
Self::block_emission_step_with_issuance(issuance)
}

pub fn block_emission_step_with_issuance(issuance: u64) -> Result<u64, &'static str> {
let block_emission: u64 = Self::get_block_emission_for_issuance(issuance)?;

// Update the BlockEmission storage if the calculated emission is different from the current value
if BlockEmission::<T>::get() != block_emission {
// Call the on_halving hook.
Self::on_halving(block_emission);
}

Ok(block_emission)
}

/// Returns the block emission for an issuance value.
Expand Down Expand Up @@ -76,13 +88,6 @@ impl<T: Config> Pallet<T> {
// Convert the calculated emission to u64
let block_emission_u64: u64 = block_emission.to_num::<u64>();

// Update the BlockEmission storage if the calculated emission is different from the current value
if BlockEmission::<T>::get() != block_emission_u64 {
log::debug!("Updating BlockEmission storage");
BlockEmission::<T>::put(block_emission_u64);
Self::on_halving(block_emission_u64);
}

// Return the calculated block emission
Ok(block_emission_u64)
}
Expand Down
3 changes: 3 additions & 0 deletions pallets/subtensor/src/coinbase/block_step.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,9 @@ impl<T: Config + pallet_drand::Config> Pallet<T> {

/// Called when the network emission is halved.
pub fn on_halving(new_emission: u64) {
log::debug!("Updating BlockEmission storage");
BlockEmission::<T>::put(new_emission);

let current_block: u64 = Self::get_current_block_as_u64();
HalvingBlock::<T>::insert(current_block, new_emission);

Expand Down
2 changes: 1 addition & 1 deletion pallets/subtensor/src/coinbase/run_coinbase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ impl<T: Config> Pallet<T> {
// replaces root epoch and uses a different algorithm to calculate EmissionValues and
// PendingEmission for each subnet.
// --- 2. Get the current coinbase emission.
let block_emission: I96F32 = I96F32::from_num(Self::get_block_emission().unwrap_or(0));
let block_emission: I96F32 = I96F32::from_num(Self::block_emission_step().unwrap_or(0));
log::debug!("Block emission: {:?}", block_emission);

// --- 3. Total subnet TAO.
Expand Down
28 changes: 20 additions & 8 deletions pallets/subtensor/src/tests/block_emission.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ fn test_minimum_non_zero_issuance() {
#[allow(clippy::unwrap_used)]
fn test_default_block_emission() {
new_test_ext(1).execute_with(|| {
let result = SubtensorModule::get_block_emission();
let result = SubtensorModule::block_emission_step();
assert!(result.is_ok());
let emission = result.unwrap();
assert!(emission > 0);
Expand Down Expand Up @@ -221,8 +221,8 @@ fn test_block_emission_storage_update() {
let initial_emission = BlockEmission::<Test>::get();
let new_issuance = TotalSupply::<Test>::get() / 2;

// Call get_block_emission_for_issuance to trigger an update
let _ = SubtensorModule::get_block_emission_for_issuance(new_issuance).unwrap();
// Call the block_emission_step_with_issuance to trigger an update
let _ = SubtensorModule::block_emission_step_with_issuance(new_issuance).unwrap();

let updated_emission = BlockEmission::<Test>::get();
assert_ne!(
Expand All @@ -231,7 +231,7 @@ fn test_block_emission_storage_update() {
);

// Call again with the same issuance to ensure no unnecessary updates
let _ = SubtensorModule::get_block_emission_for_issuance(new_issuance).unwrap();
let _ = SubtensorModule::block_emission_step_with_issuance(new_issuance).unwrap();
assert_eq!(
updated_emission,
BlockEmission::<Test>::get(),
Expand All @@ -240,19 +240,19 @@ fn test_block_emission_storage_update() {
});
}

// 15. Test Consistency Between get_block_emission() and get_block_emission_for_issuance()
// 15. Test Consistency Between block_emission_step() and block_emission_step_with_issuance()
// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test block_emission test_emission_consistency -- --exact --nocapture
#[test]
#[allow(clippy::unwrap_used)]
fn test_emission_consistency() {
new_test_ext(1).execute_with(|| {
let emission_from_get = SubtensorModule::get_block_emission().unwrap();
let emission_no_params = SubtensorModule::block_emission_step().unwrap();
let total_issuance = SubtensorModule::get_total_issuance();
let emission_for_issuance =
SubtensorModule::get_block_emission_for_issuance(total_issuance).unwrap();
SubtensorModule::block_emission_step_with_issuance(total_issuance).unwrap();

assert_eq!(
emission_from_get, emission_for_issuance,
emission_no_params, emission_for_issuance,
"Emissions should be consistent between methods"
);
});
Expand Down Expand Up @@ -594,3 +594,15 @@ fn test_floating_point_precision_impact() {
}
});
}

#[test]
fn test_block_emission_step_updates_halving_block_storage() {
new_test_ext(1).execute_with(|| {
let total_supply = TotalSupply::<Test>::get();
let issuance = total_supply / 2;
let emission = SubtensorModule::block_emission_step_with_issuance(issuance).unwrap();
assert!(emission > 0, "Emission should be positive");
let curr_block = SubtensorModule::get_current_block_as_u64();
assert_eq!(HalvingBlock::<Test>::get(curr_block), emission, "Halving block should be updated");
});
}
8 changes: 4 additions & 4 deletions pallets/subtensor/src/tests/coinbase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ fn test_coinbase_basic() {
assert_eq!(get_total_stake_for_hotkey(hotkey), stake);

// Ensure that subnet PendingEmission accumulates
let block_emission = SubtensorModule::get_block_emission();
let block_emission = SubtensorModule::block_emission_step();
let subnet_emission_before = SubtensorModule::get_pending_emission(netuid);
step_block(1);
assert_eq!(
Expand Down Expand Up @@ -191,7 +191,7 @@ fn test_run_coinbase_single_subnet() {
// Set initial values
let initial_issuance = 1_000_000;
TotalIssuance::<Test>::put(initial_issuance);
let block_emission = SubtensorModule::get_block_emission().unwrap();
let block_emission = SubtensorModule::block_emission_step().unwrap();
SubnetTAO::<Test>::insert(netuid, initial_issuance);

// Run coinbase
Expand Down Expand Up @@ -225,7 +225,7 @@ fn test_run_coinbase_multiple_subnets() {
// Set initial values
let initial_issuance = 1_000_000;
TotalIssuance::<Test>::put(initial_issuance);
let block_emission = SubtensorModule::get_block_emission().unwrap();
let block_emission = SubtensorModule::block_emission_step().unwrap();
let subnet_emission = block_emission / netuids.len() as u64;

for netuid in &netuids {
Expand Down Expand Up @@ -303,7 +303,7 @@ fn test_run_coinbase_different_mechanisms() {

// Set initial values
let initial_issuance = 1_000_000;
let block_emission = SubtensorModule::get_block_emission().unwrap();
let block_emission = SubtensorModule::block_emission_step().unwrap();
TotalIssuance::<Test>::put(initial_issuance);
SubnetTAO::<Test>::insert(netuid1, initial_issuance / 2);
SubnetTAO::<Test>::insert(netuid2, initial_issuance / 2);
Expand Down

0 comments on commit 1a3e3f9

Please sign in to comment.