use cosmwasm_std::StdError::GenericErr;
use cosmwasm_std::{ensure, Addr, Api, DepsMut, Env, MessageInfo, Order, StdResult, Storage};
use cw_utils::must_pay;
use cyber_std::Response;
use substrate_fixed::types::I64F64;
use crate::block_step::blocks_until_next_epoch;
use crate::epoch::get_float_kappa;
use crate::math::{inplace_normalize_64, matmul_64, vec_fixed64_to_u64};
use crate::staking::{
create_account_if_non_existent, delegate_hotkey, get_total_stake_for_hotkey, hotkey_is_delegate,
};
use crate::state::{
Metadata, ACTIVE, ACTIVITY_CUTOFF, ADJUSTMENTS_ALPHA, ADJUSTMENT_INTERVAL,
BLOCKS_SINCE_LAST_STEP, BONDS, BONDS_MOVING_AVERAGE, BURN, BURN_REGISTRATIONS_THIS_INTERVAL,
CONSENSUS, DENOM, DIFFICULTY, DIVIDENDS, EMISSION, EMISSION_VALUES, IMMUNITY_PERIOD, INCENTIVE,
KAPPA, KEYS, LAST_ADJUSTMENT_BLOCK, LAST_UPDATE, MAX_ALLOWED_UIDS, MAX_ALLOWED_VALIDATORS,
MAX_BURN, MAX_DIFFICULTY, MAX_REGISTRATION_PER_BLOCK, MAX_WEIGHTS_LIMIT, MIN_ALLOWED_WEIGHTS,
MIN_BURN, MIN_DIFFICULTY, NETWORKS_ADDED, NETWORKS_METADATA, NETWORK_IMMUNITY_PERIOD,
NETWORK_LAST_LOCK_COST, NETWORK_LAST_REGISTERED, NETWORK_LOCK_REDUCTION_INTERVAL,
NETWORK_MIN_LOCK_COST, NETWORK_MODALITY, NETWORK_RATE_LIMIT, NETWORK_REGISTERED_AT,
NETWORK_REGISTRATION_ALLOWED, PENDING_EMISSION, POW_REGISTRATIONS_THIS_INTERVAL,
PRUNING_SCORES, RANK, RAO_RECYCLED_FOR_REGISTRATION, REGISTRATIONS_THIS_BLOCK,
REGISTRATIONS_THIS_INTERVAL, RHO, SERVING_RATE_LIMIT, SUBNETWORK_N, SUBNET_LIMIT, SUBNET_OWNER,
TARGET_REGISTRATIONS_PER_INTERVAL, TEMPO, TOTAL_NETWORKS, TOTAL_REWARDS, TRUST, UIDS,
VALIDATOR_PERMIT, VALIDATOR_TRUST, WEIGHTS, WEIGHTS_SET_RATE_LIMIT, WEIGHTS_VERSION_KEY,
};
use crate::uids::{append_neuron, get_hotkey_for_net_and_uid, get_subnetwork_n, replace_neuron};
use crate::utils::{
get_block_emission, get_emission_value, get_max_allowed_uids, get_max_registrations_per_block,
get_registrations_this_block, get_registrations_this_interval, get_rho, get_subnet_owner,
get_target_registrations_per_interval, get_tempo, set_subnet_locked_balance,
};
use crate::ContractError;
pub fn get_root_netuid() -> u16 {
0
}
pub fn get_num_subnets(store: &dyn Storage) -> u16 {
TOTAL_NETWORKS.load(store).unwrap()
}
pub fn get_max_subnets(store: &dyn Storage) -> u16 {
SUBNET_LIMIT.load(store).unwrap()
}
pub fn get_num_root_validators(store: &dyn Storage) -> u16 {
get_subnetwork_n(store, get_root_netuid())
}
pub fn get_max_root_validators(store: &dyn Storage) -> u16 {
get_max_allowed_uids(store, get_root_netuid())
}
#[cfg(test)]
pub fn get_subnet_emission_value(store: &dyn Storage, netuid: u16) -> u64 {
EMISSION_VALUES.load(store, netuid).unwrap()
}
pub fn if_subnet_exist(store: &dyn Storage, netuid: u16) -> bool {
let exist = NETWORKS_ADDED.load(store, netuid);
if exist.is_ok() {
return exist.unwrap();
} else {
false
}
}
pub fn if_subnet_allows_registration(store: &dyn Storage, netuid: u16) -> bool {
NETWORK_REGISTRATION_ALLOWED.load(store, netuid).unwrap()
}
pub fn get_all_subnet_netuids(store: &dyn Storage) -> Vec<u16> {
return NETWORKS_ADDED
.range(store, None, None, Order::Ascending)
.map(|item| item.unwrap().0)
.collect();
}
pub fn contains_invalid_root_uids(store: &dyn Storage, api: &dyn Api, netuids: &Vec<u16>) -> bool {
for netuid in netuids {
if !if_subnet_exist(store, *netuid) {
api.debug(&format!(
"๐ต contains_invalid_root_uids: netuid {:?} does not exist",
netuid
));
return true;
}
}
false
}
pub fn set_emission_values(
store: &mut dyn Storage,
api: &dyn Api,
netuids: &Vec<u16>,
emission: Vec<u64>,
) -> Result<(), ContractError> {
api.debug(&format!(
"๐ต set_emission_values: netuids: {:?}, emission:{:?}",
netuids, emission
));
if contains_invalid_root_uids(store, api, netuids) {
api.debug(&format!(
"๐ต error set_emission_values: contains_invalid_root_uids"
));
return Err(ContractError::InvalidUid {});
}
if netuids.len() != emission.len() {
api.debug(&format!(
"๐ต error set_emission_values: netuids.len() != emission.len()"
));
return Err(ContractError::Std(GenericErr {
msg: "๐ต netuids and emission must have the same length".to_string(),
}));
}
for (i, netuid_i) in netuids.iter().enumerate() {
api.debug(&format!(
"๐ต set netuid:{:?}, emission:{:?}",
netuid_i, emission[i]
));
EMISSION_VALUES.save(store, *netuid_i, &emission[i])?;
}
Ok(())
}
pub fn get_root_weights(store: &dyn Storage, api: &dyn Api) -> Vec<Vec<I64F64>> {
let n: usize = get_num_root_validators(store) as usize;
let k: usize = get_num_subnets(store) as usize;
api.debug(&format!("๐ต root_validators: {:?}, subnets: {:?}", n, k));
let mut weights: Vec<Vec<I64F64>> = vec![vec![I64F64::from_num(0.0); k]; n];
let subnet_list = get_all_subnet_netuids(store);
for item in WEIGHTS
.prefix(get_root_netuid())
.range(store, None, None, Order::Ascending)
{
let (uid_i, weights_i) = item.unwrap();
for (netuid, weight_ij) in weights_i.iter() {
let option = subnet_list.iter().position(|item| item == netuid);
let idx = uid_i as usize;
if let Some(weight) = weights.get_mut(idx) {
if let Some(netuid_idx) = option {
weight[netuid_idx] = I64F64::from_num(*weight_ij);
}
}
}
}
weights
}
pub fn get_network_rate_limit(store: &dyn Storage) -> u64 {
NETWORK_RATE_LIMIT.load(store).unwrap()
}
pub fn root_epoch(
store: &mut dyn Storage,
api: &dyn Api,
block_number: u64,
) -> Result<(), ContractError> {
let root_netuid: u16 = get_root_netuid();
let blocks_until_next_epoch: u64 =
blocks_until_next_epoch(root_netuid, get_tempo(store, root_netuid), block_number);
if blocks_until_next_epoch != 0 {
api.debug(&format!(
"๐ต blocks_until_next_epoch: {:?}",
blocks_until_next_epoch
));
return Err(ContractError::Std(GenericErr {
msg: "๐ต Not the block to update emission values.".to_string(),
}));
}
let n: u16 = get_num_root_validators(store);
api.debug(&format!("root_validators: {:?}", n));
if n == 0 {
return Err(ContractError::Std(GenericErr {
msg: "๐ต No validators to validate emission values.".to_string(),
}));
}
let k: u16 = get_all_subnet_netuids(store).len() as u16;
api.debug(&format!("subnets ๐ต: {:?}", k));
if k == 0 {
return Err(ContractError::Std(GenericErr {
msg: "๐ต No networks to validate emission values.".to_string(),
}));
}
let block_emission_u64: u64 = get_block_emission(store);
let block_emission: I64F64 = I64F64::from_num(block_emission_u64);
TOTAL_REWARDS.update(store, |val| -> StdResult<_> {
let mut amount = val;
amount += block_emission_u64;
Ok(amount)
})?;
api.debug(&format!("๐ต block_emission: {:?}", block_emission));
let mut hotkeys: Vec<(u16, Addr)> = vec![];
for item in KEYS
.prefix(root_netuid)
.range(store, None, None, Order::Ascending)
{
let (uid_i, hotkey) = item?;
hotkeys.push((uid_i, hotkey));
}
api.debug(&format!("๐ต hotkeys: {:?}\n", hotkeys));
let mut stake_i64: Vec<I64F64> = vec![I64F64::from_num(0.0); n as usize];
for (uid_i, hotkey) in hotkeys.iter() {
stake_i64[*uid_i as usize] = I64F64::from_num(get_total_stake_for_hotkey(store, &hotkey));
}
inplace_normalize_64(&mut stake_i64);
api.debug(&format!("๐ต stake: {:?}\n", &stake_i64));
let weights: Vec<Vec<I64F64>> = get_root_weights(store, api);
api.debug(&format!("๐ต weights: {:?}\n", &weights));
let ranks: Vec<I64F64> = matmul_64(&weights, &stake_i64);
api.debug(&format!("๐ต ranks: {:?}\n", &ranks));
let total_networks = get_num_subnets(store);
let mut trust = vec![I64F64::from_num(0); total_networks as usize];
let mut total_stake: I64F64 = I64F64::from_num(0);
for (idx, weights) in weights.iter().enumerate() {
let hotkey_stake = stake_i64[idx];
total_stake += hotkey_stake;
for (weight_idx, weight) in weights.iter().enumerate() {
if *weight > 0 {
trust[weight_idx] += hotkey_stake;
}
}
}
api.debug(&format!("๐ต trust_nn: {:?}\n", &trust));
api.debug(&format!("๐ต total_stake: {:?}\n", &total_stake));
if total_stake == 0 {
return Err(ContractError::Std(GenericErr {
msg: "๐ต No stake on network".to_string(),
}));
}
for trust_score in trust.iter_mut() {
match trust_score.checked_div(total_stake) {
Some(quotient) => {
*trust_score = quotient;
}
None => {}
}
}
api.debug(&format!("๐ต trust_n: {:?}\n", &trust));
let one = I64F64::from_num(1);
let mut consensus = vec![I64F64::from_num(0); total_networks as usize];
for (idx, trust_score) in trust.iter_mut().enumerate() {
let shifted_trust = *trust_score - I64F64::from_num(get_float_kappa(store, 0)); let temperatured_trust = shifted_trust * I64F64::from_num(get_rho(store, 0)); let exponentiated_trust: I64F64 = substrate_fixed::transcendental::exp(-temperatured_trust)
.expect("temperatured_trust is on range( -rho * kappa, rho ( 1 - kappa ) )");
consensus[idx] = one / (one + exponentiated_trust);
}
api.debug(&format!("๐ต consensus: {:?}\n", &consensus));
let mut weighted_emission = vec![I64F64::from_num(0); total_networks as usize];
for (idx, emission) in weighted_emission.iter_mut().enumerate() {
*emission = consensus[idx] * ranks[idx];
}
inplace_normalize_64(&mut weighted_emission);
api.debug(&format!("๐ต emission_w: {:?}\n", &weighted_emission));
let emission_as_boot: Vec<I64F64> = weighted_emission
.iter()
.map(|v: &I64F64| *v * block_emission)
.collect();
let emission_u64: Vec<u64> = vec_fixed64_to_u64(emission_as_boot);
api.debug(&format!("๐ต emission_f: {:?}\n", &emission_u64));
let netuids: Vec<u16> = get_all_subnet_netuids(store);
api.debug(&format!(
"๐ต netuids: {:?}, values: {:?}",
netuids, emission_u64
));
set_emission_values(store, api, &netuids, emission_u64)?;
Ok(())
}
pub fn do_root_register(
deps: DepsMut,
env: Env,
info: MessageInfo,
hotkey_address: String,
) -> Result<Response, ContractError> {
let hotkey = deps.api.addr_validate(&hotkey_address)?;
let root_netuid: u16 = get_root_netuid();
let current_block_number: u64 = env.block.height;
ensure!(
if_subnet_exist(deps.storage, root_netuid),
ContractError::NetworkDoesNotExist {}
);
let coldkey = info.sender;
deps.api.debug(&format!(
"๐ต do_root_register ( coldkey: {:?}, hotkey: {:?} )",
coldkey,
hotkey.clone()
));
ensure!(
get_registrations_this_block(deps.storage, root_netuid)
< get_max_registrations_per_block(deps.storage, root_netuid),
ContractError::TooManyRegistrationsThisBlock {}
);
ensure!(
get_registrations_this_interval(deps.storage, root_netuid)
< get_target_registrations_per_interval(deps.storage, root_netuid) * 3,
ContractError::TooManyRegistrationsThisInterval {}
);
ensure!(
!UIDS.has(deps.storage, (root_netuid, &hotkey)),
ContractError::AlreadyRegistered {}
);
create_account_if_non_existent(deps.storage, &coldkey, &hotkey);
let current_num_root_validators: u16 = get_num_root_validators(deps.storage);
let subnetwork_uid: u16;
if current_num_root_validators < get_max_root_validators(deps.storage) {
subnetwork_uid = current_num_root_validators;
append_neuron(
deps.storage,
deps.api,
root_netuid,
&hotkey,
current_block_number,
)?;
deps.api.debug(&format!(
"๐ต add new neuron: {:?} on uid {:?}",
hotkey, subnetwork_uid
));
} else {
let mut lowest_stake: u64 = u64::MAX;
let mut lowest_uid: u16 = 0;
for item in KEYS
.prefix(root_netuid)
.range(deps.storage, None, None, Order::Ascending)
{
let (uid_i, hotkey_i) = item?;
let stake_i: u64 = get_total_stake_for_hotkey(deps.storage, &hotkey_i);
if stake_i < lowest_stake {
lowest_stake = stake_i;
lowest_uid = uid_i;
}
}
subnetwork_uid = lowest_uid;
let replaced_hotkey: Addr =
get_hotkey_for_net_and_uid(deps.storage, root_netuid, subnetwork_uid).unwrap();
ensure!(
lowest_stake < get_total_stake_for_hotkey(deps.storage, &hotkey),
ContractError::StakeTooLowForRoot {}
);
let _msgs = replace_neuron(
deps.storage,
deps.api,
root_netuid,
lowest_uid,
&hotkey,
current_block_number,
)?;
deps.api.debug(&format!(
"๐ต replace neuron: {:?} with {:?} on uid {:?}",
replaced_hotkey, hotkey, subnetwork_uid
));
}
if !hotkey_is_delegate(deps.storage, &hotkey) {
delegate_hotkey(deps.storage, &hotkey, 13107);
}
REGISTRATIONS_THIS_INTERVAL.update(deps.storage, root_netuid, |val| -> StdResult<_> {
let mut new_val = val.unwrap();
new_val += 1;
Ok(new_val)
})?;
REGISTRATIONS_THIS_BLOCK.update(deps.storage, root_netuid, |val| -> StdResult<_> {
let mut new_val = val.unwrap();
new_val += 1;
Ok(new_val)
})?;
deps.api.debug(&format!(
"๐ต RootRegistered (netuid:{:?} uid:{:?} hotkey:{:?})",
root_netuid, subnetwork_uid, hotkey
));
Ok(Response::default()
.add_attribute("active", "neuron_registered")
.add_attribute("root_netuid", format!("{}", root_netuid))
.add_attribute("subnetwork_uid", format!("{}", subnetwork_uid))
.add_attribute("hotkey", hotkey))
}
pub fn user_add_network(
deps: DepsMut,
env: Env,
info: MessageInfo,
) -> Result<Response, ContractError> {
let denom = DENOM.load(deps.storage)?;
let amount = must_pay(&info, &denom).map_err(|_| ContractError::CouldNotConvertToBalance {})?;
let coldkey = info.sender;
let current_block = env.block.height;
let last_lock_block = get_network_last_lock_block(deps.storage);
ensure!(
current_block - last_lock_block >= get_network_rate_limit(deps.storage),
ContractError::TxRateLimitExceeded {}
);
let lock_amount: u64 = get_network_lock_cost(deps.storage, deps.api, env.block.height)?;
deps.api
.debug(&format!("๐ต network lock_amount: {:?}", lock_amount));
ensure!(
amount.u128() >= lock_amount as u128,
ContractError::NotEnoughTokens {}
);
let netuid_to_register: u16 = {
deps.api.debug(&format!(
"๐ต subnet count: {:?}\nmax subnets: {:?}",
get_num_subnets(deps.storage),
get_max_subnets(deps.storage)
));
if get_num_subnets(deps.storage) - 1 < get_max_subnets(deps.storage) {
let mut next_available_netuid = 0;
loop {
next_available_netuid += 1;
if !if_subnet_exist(deps.storage, next_available_netuid) {
deps.api
.debug(&format!("got subnet id: {:?}", next_available_netuid));
break next_available_netuid;
}
}
} else {
let netuid_to_prune = get_subnet_to_prune(deps.storage, env.block.height)?;
ensure!(netuid_to_prune > 0, ContractError::AllNetworksInImmunity {});
remove_network(deps.storage, netuid_to_prune)?;
deps.api
.debug(&format!("remove_network: {:?}", netuid_to_prune));
netuid_to_prune
}
};
set_subnet_locked_balance(deps.storage, netuid_to_register, lock_amount);
set_network_last_lock(deps.storage, lock_amount);
init_new_network(deps.storage, netuid_to_register, 360)?;
deps.api
.debug(&format!("init_new_network: {:?}", netuid_to_register));
let current_block_number: u64 = env.block.height;
NETWORK_LAST_REGISTERED.save(deps.storage, ¤t_block_number)?;
NETWORK_REGISTERED_AT.save(deps.storage, netuid_to_register, ¤t_block_number)?;
SUBNET_OWNER.save(deps.storage, netuid_to_register, &coldkey)?;
deps.api.debug(&format!(
"๐ต NetworkAdded ( netuid:{:?}, modality:{:?} )",
netuid_to_register, 0
));
Ok(Response::default()
.add_attribute("active", "network_added")
.add_attribute("netuid_to_register", format!("{}", netuid_to_register)))
}
pub fn user_remove_network(
deps: DepsMut,
_env: Env,
info: MessageInfo,
netuid: u16,
) -> Result<Response, ContractError> {
let coldkey = info.sender;
ensure!(
if_subnet_exist(deps.storage, netuid),
ContractError::NetworkDoesNotExist {}
);
ensure!(
get_subnet_owner(deps.storage, netuid) == coldkey,
ContractError::NotSubnetOwner {}
);
remove_network(deps.storage, netuid)?;
deps.api
.debug(&format!("๐ต NetworkRemoved ( netuid:{:?} )", netuid));
Ok(Response::default()
.add_attribute("active", "network_removed")
.add_attribute("netuid", format!("{}", netuid)))
}
pub fn init_new_network(
store: &mut dyn Storage,
netuid: u16,
tempo: u16,
) -> Result<(), ContractError> {
SUBNETWORK_N.save(store, netuid, &0)?;
NETWORKS_ADDED.save(store, netuid, &true)?;
TEMPO.save(store, netuid, &tempo)?;
NETWORK_MODALITY.save(store, netuid, &0)?;
TOTAL_NETWORKS.update(store, |mut n| -> StdResult<_> {
n += 1;
Ok(n)
})?;
NETWORK_REGISTRATION_ALLOWED.save(store, netuid, &true)?;
MAX_ALLOWED_UIDS.save(store, netuid, &128)?;
MAX_ALLOWED_VALIDATORS.save(store, netuid, &32)?;
MIN_ALLOWED_WEIGHTS.save(store, netuid, &1)?;
MAX_WEIGHTS_LIMIT.save(store, netuid, &u16::MAX)?;
ADJUSTMENT_INTERVAL.save(store, netuid, &360)?;
TARGET_REGISTRATIONS_PER_INTERVAL.save(store, netuid, &1)?;
ADJUSTMENTS_ALPHA.save(store, netuid, &58000)?;
IMMUNITY_PERIOD.save(store, netuid, &14400)?;
DIFFICULTY.save(store, netuid, &10_000_000)?;
MIN_DIFFICULTY.save(store, netuid, &10_000_000)?;
MAX_DIFFICULTY.save(store, netuid, &(u64::MAX / 4))?;
KAPPA.save(store, netuid, &32_767)?; ACTIVITY_CUTOFF.save(store, netuid, &14400)?;
EMISSION_VALUES.save(store, netuid, &0)?;
REGISTRATIONS_THIS_INTERVAL.save(store, netuid, &0)?;
POW_REGISTRATIONS_THIS_INTERVAL.save(store, netuid, &0)?;
BURN_REGISTRATIONS_THIS_INTERVAL.save(store, netuid, &0)?;
WEIGHTS_VERSION_KEY.save(store, netuid, &0)?;
MAX_REGISTRATION_PER_BLOCK.save(store, netuid, &3)?;
WEIGHTS_SET_RATE_LIMIT.save(store, netuid, &100)?;
PENDING_EMISSION.save(store, netuid, &0)?;
BLOCKS_SINCE_LAST_STEP.save(store, netuid, &0)?;
BONDS_MOVING_AVERAGE.save(store, netuid, &900_000)?;
LAST_ADJUSTMENT_BLOCK.save(store, netuid, &0)?;
ADJUSTMENT_INTERVAL.save(store, netuid, &100)?;
BURN.save(store, netuid, &1_000_000_000)?;
MIN_BURN.save(store, netuid, &100_000_000)?;
MAX_BURN.save(store, netuid, &100_000_000_000)?;
REGISTRATIONS_THIS_BLOCK.save(store, netuid, &0)?;
KAPPA.save(store, netuid, &32_767)?;
RHO.save(store, netuid, &30)?;
RAO_RECYCLED_FOR_REGISTRATION.save(store, netuid, &0)?;
SERVING_RATE_LIMIT.save(store, netuid, &50)?;
ADJUSTMENTS_ALPHA.save(store, netuid, &0)?;
LAST_UPDATE.save(store, netuid, &vec![])?;
NETWORKS_METADATA.save(
store,
netuid,
&Metadata {
name: "empty".to_string(),
particle: "".to_string(),
description: "".to_string(),
logo: "".to_string(),
types: "".to_string(),
extra: "".to_string(),
},
)?;
Ok(())
}
pub fn remove_network(store: &mut dyn Storage, netuid: u16) -> Result<(), ContractError> {
SUBNETWORK_N.remove(store, netuid);
NETWORK_MODALITY.remove(store, netuid);
NETWORKS_ADDED.remove(store, netuid);
TOTAL_NETWORKS.update(store, |mut n| -> StdResult<_> {
n -= 1;
Ok(n)
})?;
NETWORK_REGISTERED_AT.remove(store, netuid);
UIDS.prefix(netuid).clear(store, None);
KEYS.prefix(netuid).clear(store, None);
BONDS.prefix(netuid).clear(store, None);
WEIGHTS.prefix(netuid).clear(store, None);
RANK.remove(store, netuid);
TRUST.remove(store, netuid);
ACTIVE.remove(store, netuid);
EMISSION.remove(store, netuid);
INCENTIVE.remove(store, netuid);
CONSENSUS.remove(store, netuid);
DIVIDENDS.remove(store, netuid);
PRUNING_SCORES.remove(store, netuid);
LAST_UPDATE.remove(store, netuid);
VALIDATOR_PERMIT.remove(store, netuid);
VALIDATOR_TRUST.remove(store, netuid);
TEMPO.remove(store, netuid);
KAPPA.remove(store, netuid);
DIFFICULTY.remove(store, netuid);
MAX_ALLOWED_UIDS.remove(store, netuid);
IMMUNITY_PERIOD.remove(store, netuid);
ACTIVITY_CUTOFF.remove(store, netuid);
EMISSION_VALUES.remove(store, netuid);
MAX_WEIGHTS_LIMIT.remove(store, netuid);
MIN_ALLOWED_WEIGHTS.remove(store, netuid);
REGISTRATIONS_THIS_INTERVAL.remove(store, netuid);
POW_REGISTRATIONS_THIS_INTERVAL.remove(store, netuid);
BURN_REGISTRATIONS_THIS_INTERVAL.remove(store, netuid);
set_subnet_locked_balance(store, netuid, 0);
SUBNET_OWNER.remove(store, netuid);
WEIGHTS_VERSION_KEY.remove(store, netuid);
MAX_REGISTRATION_PER_BLOCK.remove(store, netuid);
WEIGHTS_SET_RATE_LIMIT.remove(store, netuid);
PENDING_EMISSION.remove(store, netuid);
BLOCKS_SINCE_LAST_STEP.remove(store, netuid);
BONDS_MOVING_AVERAGE.remove(store, netuid);
LAST_ADJUSTMENT_BLOCK.remove(store, netuid);
ADJUSTMENT_INTERVAL.remove(store, netuid);
BURN.remove(store, netuid);
MIN_BURN.remove(store, netuid);
MAX_BURN.remove(store, netuid);
REGISTRATIONS_THIS_BLOCK.remove(store, netuid);
KAPPA.remove(store, netuid);
RHO.remove(store, netuid);
RAO_RECYCLED_FOR_REGISTRATION.remove(store, netuid);
SERVING_RATE_LIMIT.remove(store, netuid);
MIN_DIFFICULTY.remove(store, netuid);
MAX_DIFFICULTY.remove(store, netuid);
ADJUSTMENTS_ALPHA.remove(store, netuid);
NETWORK_REGISTRATION_ALLOWED.remove(store, netuid);
TARGET_REGISTRATIONS_PER_INTERVAL.remove(store, netuid);
NETWORKS_METADATA.remove(store, netuid);
Ok(())
}
pub fn get_network_lock_cost(
store: &dyn Storage,
api: &dyn Api,
current_block: u64,
) -> StdResult<u64> {
let last_lock = get_network_last_lock(store);
let min_lock = get_network_min_lock(store);
let last_lock_block = get_network_last_lock_block(store);
let lock_reduction_interval = get_lock_reduction_interval(store);
let mult = if last_lock_block == 0 { 1 } else { 2 };
let mut lock_cost = last_lock.saturating_mul(mult).saturating_sub(
last_lock
.saturating_div(lock_reduction_interval)
.saturating_mul(current_block.saturating_sub(last_lock_block)),
);
if lock_cost < min_lock {
lock_cost = min_lock;
}
api.debug(&format!("๐ต last_lock: {:?}, min_lock: {:?}, last_lock_block: {:?}, lock_reduction_interval: {:?}, current_block: {:?}, mult: {:?} lock_cost: {:?}",
last_lock, min_lock, last_lock_block, lock_reduction_interval, current_block, mult, lock_cost));
Ok(lock_cost)
}
pub fn get_subnet_to_prune(store: &dyn Storage, current_block: u64) -> Result<u16, ContractError> {
let mut min_score = 1;
let mut min_score_in_immunity_period = u64::MAX;
let mut uid_with_min_score = 1;
for netuid in 1..get_num_subnets(store) - 1 {
let emission_value: u64 = get_emission_value(store, netuid);
let block_at_registration: u64 = get_network_registered_block(store, netuid);
let immunity_period: u64 = get_network_immunity_period(store);
if min_score == emission_value {
if current_block.saturating_sub(block_at_registration) < immunity_period {
if min_score_in_immunity_period > emission_value {
min_score_in_immunity_period = emission_value;
}
} else {
min_score = emission_value;
uid_with_min_score = netuid;
}
}
else if min_score > emission_value {
if current_block.saturating_sub(block_at_registration) < immunity_period {
if min_score_in_immunity_period > emission_value {
min_score_in_immunity_period = emission_value;
}
} else {
min_score = emission_value;
uid_with_min_score = netuid;
}
}
}
if min_score == 1 {
return Ok(0);
} else {
return Ok(uid_with_min_score);
}
}
pub fn get_network_registered_block(store: &dyn Storage, netuid: u16) -> u64 {
NETWORK_REGISTERED_AT.load(store, netuid).unwrap()
}
pub fn get_network_immunity_period(store: &dyn Storage) -> u64 {
NETWORK_IMMUNITY_PERIOD.load(store).unwrap()
}
#[cfg(test)]
pub fn set_network_immunity_period(store: &mut dyn Storage, net_immunity_period: u64) {
NETWORK_IMMUNITY_PERIOD
.save(store, &net_immunity_period)
.unwrap();
}
#[cfg(test)]
pub fn set_network_min_lock(store: &mut dyn Storage, net_min_lock: u64) {
NETWORK_MIN_LOCK_COST.save(store, &net_min_lock).unwrap();
}
pub fn get_network_min_lock(store: &dyn Storage) -> u64 {
NETWORK_MIN_LOCK_COST.load(store).unwrap()
}
pub fn set_network_last_lock(store: &mut dyn Storage, net_last_lock: u64) {
NETWORK_LAST_LOCK_COST.save(store, &net_last_lock).unwrap();
}
pub fn get_network_last_lock(store: &dyn Storage) -> u64 {
NETWORK_LAST_LOCK_COST.load(store).unwrap()
}
pub fn get_network_last_lock_block(store: &dyn Storage) -> u64 {
NETWORK_LAST_REGISTERED.load(store).unwrap()
}
#[cfg(test)]
pub fn set_lock_reduction_interval(store: &mut dyn Storage, interval: u64) {
NETWORK_LOCK_REDUCTION_INTERVAL
.save(store, &interval)
.unwrap();
}
pub fn get_lock_reduction_interval(store: &dyn Storage) -> u64 {
NETWORK_LOCK_REDUCTION_INTERVAL.load(store).unwrap()
}