Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
andreea-popescu-reef committed Jan 15, 2025
1 parent 7c67ab5 commit b9c0524
Show file tree
Hide file tree
Showing 14 changed files with 577 additions and 114 deletions.
8 changes: 8 additions & 0 deletions pallets/admin-utils/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,14 @@ mod benchmarks {
_(RawOrigin::Root, 1u16/*netuid*/, 100u64/*bonds_moving_average*/)/*sudo_set_bonds_moving_average*/;
}

#[benchmark]
fn sudo_set_bonds_penalty() {
pallet_subtensor::Pallet::<T>::init_new_network(1u16 /*netuid*/, 1u16 /*tempo*/);

#[extrinsic_call]
_(RawOrigin::Root, 1u16/*netuid*/, 100u64/*bonds_penalty*/)/*sudo_set_bonds_penalty*/;
}

#[benchmark]
fn sudo_set_max_allowed_validators() {
pallet_subtensor::Pallet::<T>::init_new_network(1u16 /*netuid*/, 1u16 /*tempo*/);
Expand Down
41 changes: 41 additions & 0 deletions pallets/admin-utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,22 @@ pub mod pallet {
Ok(())
}

#[pallet::call_index(59)]
#[pallet::weight((
Weight::from_ref_time(14_000_000)
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1)),
DispatchClass::Operational,
Pays::No
))]
pub fn sudo_set_bonds_penalty(
origin: OriginFor<T>,
netuid: u16,
bonds_penalty: u16,
) -> DispatchResult {
Self::do_sudo_set_bonds_penalty(origin, netuid, bonds_penalty)
}

/// The extrinsic sets the adjustment beta for a subnet.
/// It is only callable by the root account or subnet owner.
/// The extrinsic will call the Subtensor pallet to set the adjustment beta.
Expand Down Expand Up @@ -685,6 +701,31 @@ pub mod pallet {
Ok(())
}

/// The extrinsic sets the bonds penalty for a subnet.
/// It is only callable by the root account or subnet owner.
/// The extrinsic will call the Subtensor pallet to set the bonds penalty.
#[pallet::call_index(60)]
#[pallet::weight(<T as Config>::WeightInfo::sudo_set_bonds_penalty())]
pub fn sudo_set_bonds_penalty(
origin: OriginFor<T>,
netuid: u16,
bonds_penalty: u16,
) -> DispatchResult {
pallet_subtensor::Pallet::<T>::ensure_subnet_owner_or_root(origin, netuid)?;

ensure!(
pallet_subtensor::Pallet::<T>::if_subnet_exist(netuid),
Error::<T>::SubnetDoesNotExist
);
pallet_subtensor::Pallet::<T>::set_bonds_penalty(netuid, bonds_penaltyverage);
log::debug!(
"Bondspenaltyet( netuid: {:?} bonds_penalty: {:?} ) ",
netuid,
bonds_penalty
);
Ok(())
}

/// The extrinsic sets the maximum registrations per block for a subnet.
/// It is only callable by the root account.
/// The extrinsic will call the Subtensor pallet to set the maximum registrations per block.
Expand Down
2 changes: 2 additions & 0 deletions pallets/admin-utils/src/tests/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ parameter_types! {
pub const InitialImmunityPeriod: u16 = 2;
pub const InitialMaxAllowedUids: u16 = 2;
pub const InitialBondsMovingAverage: u64 = 900_000;
pub const InitialBondsPenalty: u16 = 0;
pub const InitialStakePruningMin: u16 = 0;
pub const InitialFoundationDistribution: u64 = 0;
pub const InitialDefaultDelegateTake: u16 = 11_796; // 18% honest number.
Expand Down Expand Up @@ -163,6 +164,7 @@ impl pallet_subtensor::Config for Test {
type InitialMaxRegistrationsPerBlock = InitialMaxRegistrationsPerBlock;
type InitialPruningScore = InitialPruningScore;
type InitialBondsMovingAverage = InitialBondsMovingAverage;
type InitialBondsPenalty = InitialBondsPenalty;
type InitialMaxAllowedValidators = InitialMaxAllowedValidators;
type InitialDefaultDelegateTake = InitialDefaultDelegateTake;
type InitialMinDelegateTake = InitialMinDelegateTake;
Expand Down
33 changes: 33 additions & 0 deletions pallets/admin-utils/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -741,6 +741,39 @@ fn test_sudo_set_bonds_moving_average() {
});
}

#[test]
fn test_sudo_set_bonds_penalty() {
new_test_ext().execute_with(|| {
let netuid: u16 = 1;
let to_be_set: u16 = 10;
let init_value: u16 = SubtensorModule::get_bonds_penalty(netuid);
add_network(netuid, 10, 0);
assert_eq!(
SubtensorModule::sudo_set_bonds_penalty(
<<Test as Config>::RuntimeOrigin>::signed(U256::from(0)),
netuid,
to_be_set
),
Err(DispatchError::BadOrigin.into())
);
assert_eq!(
SubtensorModule::sudo_set_bonds_penalty(
<<Test as Config>::RuntimeOrigin>::root(),
netuid + 1,
to_be_set
),
Err(Error::<Test>::NetworkDoesNotExist.into())
);
assert_eq!(SubtensorModule::get_bonds_penalty(netuid), init_value);
assert_ok!(SubtensorModule::sudo_set_bonds_penalty(
<<Test as Config>::RuntimeOrigin>::root(),
netuid,
to_be_set
));
assert_eq!(SubtensorModule::get_bonds_penalty(netuid), to_be_set);
});
}

#[test]
fn test_sudo_set_rao_recycled() {
new_test_ext().execute_with(|| {
Expand Down
73 changes: 73 additions & 0 deletions pallets/subtensor/src/epoch/math.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1022,6 +1022,79 @@ pub fn weighted_median_col_sparse(
median
}

// Element-wise interpolation of two matrices: Result = A + ratio * (B - A).
// ratio is has intended range [0, 1]
// ratio=0: Result = A
// ratio=1: Result = B
#[allow(dead_code)]
pub fn interpolate(
mat1: &Vec<Vec<I32F32>>,
mat2: &Vec<Vec<I32F32>>,
ratio: I32F32,
) -> Vec<Vec<I32F32>> {
if ratio == I32F32::from_num(0) {
return mat1.clone();
}
if ratio == I32F32::from_num(1) {
return mat2.clone();
}
assert!(mat1.len() == mat2.len());
if mat1.len() == 0 {
return vec![vec![]; 1];
}
if mat1[0].len() == 0 {
return vec![vec![]; 1];
}
let mut result: Vec<Vec<I32F32>> = vec![vec![I32F32::from_num(0); mat1[0].len()]; mat1.len()];
for i in 0..mat1.len() {
assert!(mat1[i].len() == mat2[i].len());
for j in 0..mat1[i].len() {
result[i][j] = mat1[i][j] + ratio * (mat2[i][j] - mat1[i][j]);
}
}
result
}

// Element-wise interpolation of two sparse matrices: Result = A + ratio * (B - A).
// ratio is has intended range [0, 1]
// ratio=0: Result = A
// ratio=1: Result = B
#[allow(dead_code)]
pub fn interpolate_sparse(
mat1: &Vec<Vec<(u16, I32F32)>>,
mat2: &Vec<Vec<(u16, I32F32)>>,
columns: u16,
ratio: I32F32,
) -> Vec<Vec<(u16, I32F32)>> {
if ratio == I32F32::from_num(0) {
return mat1.clone();
}
if ratio == I32F32::from_num(1) {
return mat2.clone();
}
assert!(mat1.len() == mat2.len());
let rows = mat1.len();
let zero: I32F32 = I32F32::from_num(0);
let mut result: Vec<Vec<(u16, I32F32)>> = vec![vec![]; rows];
for i in 0..rows {
let mut row1: Vec<I32F32> = vec![zero; columns as usize];
for (j, value) in mat1[i].iter() {
row1[*j as usize] = *value;
}
let mut row2: Vec<I32F32> = vec![zero; columns as usize];
for (j, value) in mat2[i].iter() {
row2[*j as usize] = *value;
}
for j in 0..columns as usize {
let interp: I32F32 = row1[j] + ratio * (row2[j] - row1[j]);
if zero < interp {
result[i].push((j as u16, interp))
}
}
}
result
}

// Element-wise product of two matrices.
#[allow(dead_code)]
pub fn hadamard(mat1: &[Vec<I32F32>], mat2: &[Vec<I32F32>]) -> Vec<Vec<I32F32>> {
Expand Down
53 changes: 40 additions & 13 deletions pallets/subtensor/src/epoch/run_epoch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,18 +137,22 @@ impl<T: Config> Pallet<T> {
// Compute preranks: r_j = SUM(i) w_ij * s_i
let preranks: Vec<I32F32> = matmul(&weights, &active_stake);

// Clip weights at majority consensus
let kappa: I32F32 = Self::get_float_kappa(netuid); // consensus majority ratio, e.g. 51%.
// Consensus majority ratio, e.g. 51%.
let kappa: I32F32 = Self::get_float_kappa(netuid);
// Calculate consensus as stake-weighted median of weights.
let consensus: Vec<I32F32> = weighted_median_col(&active_stake, &weights, kappa);
inplace_col_clip(&mut weights, &consensus);
let validator_trust: Vec<I32F32> = row_sum(&weights);
// Clip weights at majority consensus.
let mut clipped_weights: Vec<Vec<I32F32>> = weights.clone();
inplace_col_clip(&mut clipped_weights, &consensus);
// Calculate validator trust as sum of clipped weights set by validator.
let validator_trust: Vec<I32F32> = row_sum(&clipped_weights);

// ====================================
// == Ranks, Server Trust, Incentive ==
// ====================================

// Compute ranks: r_j = SUM(i) w_ij * s_i
let mut ranks: Vec<I32F32> = matmul(&weights, &active_stake);
let mut ranks: Vec<I32F32> = matmul(&clipped_weights, &active_stake);

// Compute server trust: ratio of rank after vs. rank before.
let trust: Vec<I32F32> = vecdiv(&ranks, &preranks);
Expand All @@ -161,14 +165,22 @@ impl<T: Config> Pallet<T> {
// == Bonds and Dividends ==
// =========================

// Get validator bonds penalty in [0, 1].
let bonds_penalty: I32F32 = Self::get_float_bonds_penalty(netuid);
// Calculate weights for bonds, apply bonds penalty to weights.
// bonds_penalty = 0: weights_for_bonds = weights.clone()
// bonds_penalty = 1: weights_for_bonds = clipped_weights.clone()
let weights_for_bonds: Vec<Vec<I32F32>> =
interpolate(&weights, &clipped_weights, bonds_penalty);

// Access network bonds.
let mut bonds: Vec<Vec<I32F32>> = Self::get_bonds(netuid);
inplace_mask_matrix(&outdated, &mut bonds); // mask outdated bonds
inplace_col_normalize(&mut bonds); // sum_i b_ij = 1
log::trace!("B:\n{:?}\n", &bonds);

// Compute bonds delta column normalized.
let mut bonds_delta: Vec<Vec<I32F32>> = row_hadamard(&weights, &active_stake); // ΔB = W◦S
let mut bonds_delta: Vec<Vec<I32F32>> = row_hadamard(&weights_for_bonds, &active_stake); // ΔB = W◦S
inplace_col_normalize(&mut bonds_delta); // sum_i b_ij = 1
log::trace!("ΔB:\n{:?}\n", &bonds_delta);
// Compute the Exponential Moving Average (EMA) of bonds.
Expand Down Expand Up @@ -474,23 +486,26 @@ impl<T: Config> Pallet<T> {
let preranks: Vec<I32F32> = matmul_sparse(&weights, &active_stake, n);
log::trace!("Ranks (before): {:?}", &preranks);

// Clip weights at majority consensus
let kappa: I32F32 = Self::get_float_kappa(netuid); // consensus majority ratio, e.g. 51%.
// Consensus majority ratio, e.g. 51%.
let kappa: I32F32 = Self::get_float_kappa(netuid);
// Calculate consensus as stake-weighted median of weights.
let consensus: Vec<I32F32> = weighted_median_col_sparse(&active_stake, &weights, n, kappa);
log::trace!("Consensus: {:?}", &consensus);

weights = col_clip_sparse(&weights, &consensus);
log::trace!("Weights: {:?}", &weights);
// Clip weights at majority consensus.
let clipped_weights: Vec<Vec<(u16, I32F32)>> = col_clip_sparse(&weights, &consensus);
log::trace!("Clipped Weights: {:?}", &clipped_weights);

let validator_trust: Vec<I32F32> = row_sum_sparse(&weights);
// Calculate validator trust as sum of clipped weights set by validator.
let validator_trust: Vec<I32F32> = row_sum_sparse(&clipped_weights);
log::trace!("Validator Trust: {:?}", &validator_trust);

// =============================
// == Ranks, Trust, Incentive ==
// =============================

// Compute ranks: r_j = SUM(i) w_ij * s_i.
let mut ranks: Vec<I32F32> = matmul_sparse(&weights, &active_stake, n);
let mut ranks: Vec<I32F32> = matmul_sparse(&clipped_weights, &active_stake, n);
log::trace!("Ranks (after): {:?}", &ranks);

// Compute server trust: ratio of rank after vs. rank before.
Expand All @@ -505,6 +520,14 @@ impl<T: Config> Pallet<T> {
// == Bonds and Dividends ==
// =========================

// Get validator bonds penalty in [0, 1].
let bonds_penalty: I32F32 = Self::get_float_bonds_penalty(netuid);
// Calculate weights for bonds, apply bonds penalty to weights.
// bonds_penalty = 0: weights_for_bonds = weights.clone()
// bonds_penalty = 1: weights_for_bonds = clipped_weights.clone()
let weights_for_bonds: Vec<Vec<(u16, I32F32)>> =
interpolate_sparse(&weights, &clipped_weights, n, bonds_penalty);

// Access network bonds.
let mut bonds: Vec<Vec<(u16, I32F32)>> = Self::get_bonds_sparse(netuid);
log::trace!("B: {:?}", &bonds);
Expand All @@ -523,7 +546,8 @@ impl<T: Config> Pallet<T> {
log::trace!("B (mask+norm): {:?}", &bonds);

// Compute bonds delta column normalized.
let mut bonds_delta: Vec<Vec<(u16, I32F32)>> = row_hadamard_sparse(&weights, &active_stake); // ΔB = W◦S (outdated W masked)
let mut bonds_delta: Vec<Vec<(u16, I32F32)>> =
row_hadamard_sparse(&weights_for_bonds, &active_stake); // ΔB = W◦S (outdated W masked)
log::trace!("ΔB: {:?}", &bonds_delta);

// Normalize bonds delta.
Expand Down Expand Up @@ -713,6 +737,9 @@ impl<T: Config> Pallet<T> {
pub fn get_float_kappa(netuid: u16) -> I32F32 {
I32F32::from_num(Self::get_kappa(netuid)).saturating_div(I32F32::from_num(u16::MAX))
}
pub fn get_float_bonds_penalty(netuid: u16) -> I32F32 {
I32F32::from_num(Self::get_bonds_penalty(netuid)) / I32F32::from_num(u16::MAX)
}

pub fn get_block_at_registration(netuid: u16) -> Vec<u64> {
let n = Self::get_subnetwork_n(netuid);
Expand Down
9 changes: 9 additions & 0 deletions pallets/subtensor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,11 @@ pub mod pallet {
pub fn DefaultBondsMovingAverage<T: Config>() -> u64 {
T::InitialBondsMovingAverage::get()
}
/// Default bonds penalty.
#[pallet::type_value]
pub fn DefaultBondsPenalty<T: Config>() -> u16 {
T::InitialBondsPenalty::get()
}
#[pallet::type_value]
/// Default validator prune length.
pub fn DefaultValidatorPruneLen<T: Config>() -> u64 {
Expand Down Expand Up @@ -1171,6 +1176,10 @@ pub mod pallet {
/// --- MAP ( netuid ) --> bonds_moving_average
pub type BondsMovingAverage<T> =
StorageMap<_, Identity, u16, u64, ValueQuery, DefaultBondsMovingAverage<T>>;
#[pallet::storage]
/// --- MAP ( netuid ) --> bonds_penalty
pub type BondsPenalty<T> =
StorageMap<_, Identity, u16, u16, ValueQuery, DefaultBondsPenalty<T>>;
/// --- MAP ( netuid ) --> weights_set_rate_limit
#[pallet::storage]
pub type WeightsSetRateLimit<T> =
Expand Down
3 changes: 3 additions & 0 deletions pallets/subtensor/src/macros/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ mod config {
/// Initial bonds moving average.
#[pallet::constant]
type InitialBondsMovingAverage: Get<u64>;
/// Initial bonds penalty.
#[pallet::constant]
type InitialBondsPenalty: Get<u16>;
/// Initial target registrations per interval.
#[pallet::constant]
type InitialTargetRegistrationsPerInterval: Get<u16>;
Expand Down
2 changes: 2 additions & 0 deletions pallets/subtensor/src/macros/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ mod events {
ImmunityPeriodSet(u16, u16),
/// bonds moving average is set for a subnet.
BondsMovingAverageSet(u16, u64),
/// bonds penalty is set for a subnet.
BondsPenaltySet(u16, u16),
/// setting the max number of allowed validators on a subnet.
MaxAllowedValidatorsSet(u16, u16),
/// the axon server information is added to the network.
Expand Down
Loading

0 comments on commit b9c0524

Please sign in to comment.