Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add set_root_weights() #335

Merged
merged 9 commits into from
May 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions pallets/subtensor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -986,6 +986,8 @@ pub mod pallet {
StakeTooLowForRoot, // --- Thrown when a hotkey attempts to join the root subnet with too little stake
AllNetworksInImmunity, // --- Thrown when all subnets are in the immunity period
NotEnoughBalance,
NotRootSubnet,
IsRoot,
NoNeuronIdAvailable, // -- Thrown when no neuron id is available
/// Thrown a stake would be below the minimum threshold for nominator validations
NomStakeBelowMinimumThreshold,
Expand Down Expand Up @@ -1305,6 +1307,81 @@ pub mod pallet {
Self::do_set_weights(origin, netuid, dests, weights, version_key)
}

// # Args:
// * `origin`: (<T as frame_system::Config>Origin):
// - The caller, a hotkey who wishes to set their weights.
//
// * `netuid` (u16):
// - The network uid we are setting these weights on.
//
// * `hotkey` (T::AccountId):
// - The hotkey associated with the operation and the calling coldkey.
//
// * `dests` (Vec<u16>):
// - The edge endpoint for the weight, i.e. j for w_ij.
//
// * 'weights' (Vec<u16>):
// - The u16 integer encoded weights. Interpreted as rational
// values in the range [0,1]. They must sum to in32::MAX.
//
// * 'version_key' ( u64 ):
// - The network version key to check if the validator is up to date.
//
// # Event:
JohnReedV marked this conversation as resolved.
Show resolved Hide resolved
//
// * WeightsSet;
// - On successfully setting the weights on chain.
//
// # Raises:
//
// * NonAssociatedColdKey;
// - Attempting to set weights on a non-associated cold key.
//
// * 'NetworkDoesNotExist':
// - Attempting to set weights on a non-existent network.
//
// * 'NotRootSubnet':
// - Attempting to set weights on a subnet that is not the root network.
//
// * 'WeightVecNotEqualSize':
// - Attempting to set weights with uids not of same length.
//
// * 'InvalidUid':
// - Attempting to set weights with invalid uids.
//
// * 'NotRegistered':
// - Attempting to set weights from a non registered account.
//
// * 'NotSettingEnoughWeights':
// - Attempting to set weights with fewer weights than min.
//
// * 'IncorrectNetworkVersionKey':
// - Attempting to set weights with the incorrect network version key.
//
// * 'SettingWeightsTooFast':
// - Attempting to set weights too fast.
//
// * 'NotSettingEnoughWeights':
// - Attempting to set weights with fewer weights than min.
//
// * 'MaxWeightExceeded':
// - Attempting to set weights with max value exceeding limit.
//
#[pallet::call_index(8)]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know we haven't really started doing this yet but ideally these should be doc comments

#[pallet::weight((Weight::from_parts(10_151_000_000, 0)
.saturating_add(T::DbWeight::get().reads(4104))
.saturating_add(T::DbWeight::get().writes(2)), DispatchClass::Normal, Pays::No))]
pub fn set_root_weights(
origin: OriginFor<T>,
netuid: u16,
hotkey: T::AccountId,
dests: Vec<u16>,
weights: Vec<u16>,
version_key: u64,
) -> DispatchResult {
Self::do_set_root_weights(origin, netuid, hotkey, dests, weights, version_key)
}

// --- Sets the key as a delegate.
//
// # Args:
Expand Down Expand Up @@ -1866,6 +1943,18 @@ where
Err(InvalidTransaction::Call.into())
}
}
Some(Call::set_root_weights { netuid, .. }) => {
if Self::check_weights_min_stake(who) {
let priority: u64 = Self::get_priority_set_weights(who, *netuid);
Ok(ValidTransaction {
priority: priority,
longevity: 1,
..Default::default()
})
} else {
return Err(InvalidTransaction::Call.into());
}
}
Some(Call::add_stake { .. }) => Ok(ValidTransaction {
priority: Self::get_priority_vanilla(),
..Default::default()
Expand Down
117 changes: 117 additions & 0 deletions pallets/subtensor/src/root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,123 @@ impl<T: Config> Pallet<T> {
Ok(())
}

pub fn do_set_root_weights(
origin: T::RuntimeOrigin,
netuid: u16,
hotkey: T::AccountId,
uids: Vec<u16>,
values: Vec<u16>,
version_key: u64,
) -> dispatch::DispatchResult {
// --- 1. Check the caller's signature. This is the coldkey of a registered account.
let coldkey = ensure_signed(origin)?;
log::info!(
distributedstatemachine marked this conversation as resolved.
Show resolved Hide resolved
"do_set_root_weights( origin:{:?} netuid:{:?}, uids:{:?}, values:{:?})",
coldkey,
netuid,
uids,
values
);

// --- 2. Check that the signer coldkey owns the hotkey
ensure!(
Self::coldkey_owns_hotkey(&coldkey, &hotkey)
&& Self::get_owning_coldkey_for_hotkey(&hotkey) == coldkey,
Error::<T>::NonAssociatedColdKey
);

// --- 3. Check to see if this is a valid network.
ensure!(
Self::if_subnet_exist(netuid),
Error::<T>::NetworkDoesNotExist
);

// --- 4. Check that this is the root network.
ensure!(netuid == Self::get_root_netuid(), Error::<T>::NotRootSubnet);

// --- 5. Check that the length of uid list and value list are equal for this network.
ensure!(
Self::uids_match_values(&uids, &values),
Error::<T>::WeightVecNotEqualSize
);

// --- 6. Check to see if the number of uids is within the max allowed uids for this network.
// For the root network this number is the number of subnets.
ensure!(
!Self::contains_invalid_root_uids(&uids),
Error::<T>::InvalidUid
);

// --- 7. Check to see if the hotkey is registered to the passed network.
ensure!(
Self::is_hotkey_registered_on_network(netuid, &hotkey),
Error::<T>::NotRegistered
);

// --- 8. Check to see if the hotkey has enough stake to set weights.
ensure!(
Self::get_total_stake_for_hotkey(&hotkey) >= Self::get_weights_min_stake(),
Error::<T>::NotEnoughStakeToSetWeights
);

// --- 9. Ensure version_key is up-to-date.
ensure!(
Self::check_version_key(netuid, version_key),
Error::<T>::IncorrectNetworkVersionKey
);

// --- 10. Get the neuron uid of associated hotkey on network netuid.
let neuron_uid = Self::get_uid_for_net_and_hotkey(netuid, &hotkey)?;

// --- 11. Ensure the uid is not setting weights faster than the weights_set_rate_limit.
let current_block: u64 = Self::get_current_block_as_u64();
ensure!(
Self::check_rate_limit(netuid, neuron_uid, current_block),
Error::<T>::SettingWeightsTooFast
);

// --- 12. Ensure the passed uids contain no duplicates.
ensure!(!Self::has_duplicate_uids(&uids), Error::<T>::DuplicateUids);

// --- 13. Ensure that the weights have the required length.
ensure!(
Self::check_length(netuid, neuron_uid, &uids, &values),
Error::<T>::NotSettingEnoughWeights
);

// --- 14. Max-upscale the weights.
let max_upscaled_weights: Vec<u16> = vec_u16_max_upscale_to_u16(&values);

// --- 15. Ensure the weights are max weight limited
ensure!(
Self::max_weight_limited(netuid, neuron_uid, &uids, &max_upscaled_weights),
Error::<T>::MaxWeightExceeded
);

// --- 16. Zip weights for sinking to storage map.
let mut zipped_weights: Vec<(u16, u16)> = vec![];
for (uid, val) in uids.iter().zip(max_upscaled_weights.iter()) {
zipped_weights.push((*uid, *val))
}

// --- 17. Set weights under netuid, uid double map entry.
Weights::<T>::insert(netuid, neuron_uid, zipped_weights);

// --- 18. Set the activity for the weights on this network.
Self::set_last_update_for_uid(netuid, neuron_uid, current_block);

// --- 19. Emit the tracking event.
log::info!(
"RootWeightsSet( netuid:{:?}, neuron_uid:{:?} )",
netuid,
neuron_uid
);
Self::deposit_event(Event::WeightsSet(netuid, neuron_uid));

// --- 20. Return ok.
Ok(())
}

pub fn do_vote_root(
origin: T::RuntimeOrigin,
hotkey: &T::AccountId,
Expand Down
45 changes: 16 additions & 29 deletions pallets/subtensor/src/weights.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ impl<T: Config> Pallet<T> {
values
);

// --- Check that the netuid is not the root network.
ensure!(netuid != Self::get_root_netuid(), Error::<T>::IsRoot);

// --- 2. Check that the length of uid list and value list are equal for this network.
ensure!(
Self::uids_match_values(&uids, &values),
Expand All @@ -89,19 +92,10 @@ impl<T: Config> Pallet<T> {
);

// --- 4. Check to see if the number of uids is within the max allowed uids for this network.
// For the root network this number is the number of subnets.
if netuid == Self::get_root_netuid() {
// --- 4.a. Ensure that the passed uids are valid for the network.
ensure!(
!Self::contains_invalid_root_uids(&uids),
Error::<T>::InvalidUid
);
} else {
ensure!(
Self::check_len_uids_within_allowed(netuid, &uids),
Error::<T>::TooManyUids
);
}
ensure!(
Self::check_len_uids_within_allowed(netuid, &uids),
Error::<T>::TooManyUids
);

// --- 5. Check to see if the hotkey is registered to the passed network.
ensure!(
Expand All @@ -121,35 +115,28 @@ impl<T: Config> Pallet<T> {
Error::<T>::IncorrectNetworkVersionKey
);

// --- 8. Get the neuron uid of associated hotkey on network netuid.

let neuron_uid = Self::get_uid_for_net_and_hotkey(netuid, &hotkey)?;

// --- 9. Ensure the uid is not setting weights faster than the weights_set_rate_limit.
let neuron_uid = Self::get_uid_for_net_and_hotkey(netuid, &hotkey)?;
let current_block: u64 = Self::get_current_block_as_u64();
ensure!(
Self::check_rate_limit(netuid, neuron_uid, current_block),
Error::<T>::SettingWeightsTooFast
);

// --- 10. Check that the neuron uid is an allowed validator permitted to set non-self weights.
if netuid != Self::get_root_netuid() {
ensure!(
Self::check_validator_permit(netuid, neuron_uid, &uids, &values),
Error::<T>::NoValidatorPermit
);
}
ensure!(
Self::check_validator_permit(netuid, neuron_uid, &uids, &values),
Error::<T>::NoValidatorPermit
);

// --- 11. Ensure the passed uids contain no duplicates.
ensure!(!Self::has_duplicate_uids(&uids), Error::<T>::DuplicateUids);

// --- 12. Ensure that the passed uids are valid for the network.
if netuid != Self::get_root_netuid() {
ensure!(
!Self::contains_invalid_uids(netuid, &uids),
Error::<T>::InvalidUid
);
}
ensure!(
!Self::contains_invalid_uids(netuid, &uids),
Error::<T>::InvalidUid
);

// --- 13. Ensure that the weights have the required length.
ensure!(
Expand Down
Loading
Loading