Skip to content

Commit f34be4c

Browse files
Merge pull request #557 from opentensor/fix-add-adjust-senate-call-vune-devnet-companion
[devnet-companion] Fix Senate membership changes
2 parents fce53c0 + 9f09d94 commit f34be4c

File tree

6 files changed

+391
-30
lines changed

6 files changed

+391
-30
lines changed

pallets/subtensor/src/errors.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,5 +126,7 @@ mod errors {
126126
CommitRevealEnabled,
127127
/// Attemtping to commit/reveal weights when disabled.
128128
CommitRevealDisabled,
129+
/// Not able to join the senate.
130+
CouldNotJoinSenate,
129131
}
130132
}

pallets/subtensor/src/events.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,5 +132,12 @@ mod events {
132132
MinDelegateTakeSet(u16),
133133
/// the target stakes per interval is set by sudo/admin transaction
134134
TargetStakesPerIntervalSet(u64),
135+
/// a member of the senate is adjusted
136+
SenateAdjusted {
137+
/// the account ID of the old senate member, if any
138+
old_member: Option<T::AccountId>,
139+
/// the account ID of the new senate member
140+
new_member: T::AccountId,
141+
},
135142
}
136143
}

pallets/subtensor/src/lib.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1916,6 +1916,15 @@ pub mod pallet {
19161916
Self::do_root_register(origin, hotkey)
19171917
}
19181918

1919+
/// Attempt to adjust the senate membership to include a hotkey
1920+
#[pallet::call_index(63)]
1921+
#[pallet::weight((Weight::from_parts(0, 0)
1922+
.saturating_add(T::DbWeight::get().reads(0))
1923+
.saturating_add(T::DbWeight::get().writes(0)), DispatchClass::Normal, Pays::Yes))]
1924+
pub fn adjust_senate(origin: OriginFor<T>, hotkey: T::AccountId) -> DispatchResult {
1925+
Self::do_adjust_senate(origin, hotkey)
1926+
}
1927+
19191928
/// User register a new subnetwork via burning token
19201929
#[pallet::call_index(7)]
19211930
#[pallet::weight((Weight::from_parts(177_000_000, 0)

pallets/subtensor/src/root.rs

Lines changed: 127 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -567,9 +567,129 @@ impl<T: Config> Pallet<T> {
567567
);
568568
}
569569

570-
let current_stake = Self::get_total_stake_for_hotkey(&hotkey);
570+
// --- 13. Join the Senate if eligible.
571+
// Returns the replaced member, if any.
572+
let _ = Self::join_senate_if_eligible(&hotkey)?;
573+
574+
// --- 14. Force all members on root to become a delegate.
575+
if !Self::hotkey_is_delegate(&hotkey) {
576+
Self::delegate_hotkey(&hotkey, 11_796); // 18% cut defaulted.
577+
}
578+
579+
// --- 15. Update the registration counters for both the block and interval.
580+
RegistrationsThisInterval::<T>::mutate(root_netuid, |val| val.saturating_inc());
581+
RegistrationsThisBlock::<T>::mutate(root_netuid, |val| val.saturating_inc());
582+
583+
// --- 16. Log and announce the successful registration.
584+
log::info!(
585+
"RootRegistered(netuid:{:?} uid:{:?} hotkey:{:?})",
586+
root_netuid,
587+
subnetwork_uid,
588+
hotkey
589+
);
590+
Self::deposit_event(Event::NeuronRegistered(root_netuid, subnetwork_uid, hotkey));
591+
592+
// --- 17. Finish and return success.
593+
Ok(())
594+
}
595+
596+
// Checks if a hotkey should be a member of the Senate, and if so, adds them.
597+
//
598+
// This function is responsible for adding a hotkey to the Senate if they meet the requirements.
599+
// The root key with the least stake is pruned in the event of a filled membership.
600+
//
601+
// # Arguments:
602+
// * 'origin': Represents the origin of the call.
603+
// * 'hotkey': The hotkey that the user wants to register to the root network.
604+
//
605+
// # Returns:
606+
// * 'DispatchResult': A result type indicating success or failure of the registration.
607+
//
608+
pub fn do_adjust_senate(origin: T::RuntimeOrigin, hotkey: T::AccountId) -> DispatchResult {
609+
// --- 0. Get the unique identifier (UID) for the root network.
610+
let root_netuid: u16 = Self::get_root_netuid();
611+
ensure!(
612+
Self::if_subnet_exist(root_netuid),
613+
Error::<T>::RootNetworkDoesNotExist
614+
);
615+
616+
// --- 1. Ensure that the call originates from a signed source and retrieve the caller's account ID (coldkey).
617+
let coldkey = ensure_signed(origin)?;
618+
log::info!(
619+
"do_root_register( coldkey: {:?}, hotkey: {:?} )",
620+
coldkey,
621+
hotkey
622+
);
623+
624+
// --- 2. Check if the hotkey is already registered to the root network. If not, error out.
625+
ensure!(
626+
Uids::<T>::contains_key(root_netuid, &hotkey),
627+
Error::<T>::HotKeyNotRegisteredInSubNet
628+
);
629+
630+
// --- 3. Create a network account for the user if it doesn't exist.
631+
Self::create_account_if_non_existent(&coldkey, &hotkey);
632+
633+
// --- 4. Join the Senate if eligible.
634+
// Returns the replaced member, if any.
635+
let replaced = Self::join_senate_if_eligible(&hotkey)?;
636+
637+
if replaced.is_none() {
638+
// Not eligible to join the Senate, or no replacement needed.
639+
// Check if the hotkey is *now* a member of the Senate.
640+
// Otherwise, error out.
641+
ensure!(
642+
T::SenateMembers::is_member(&hotkey),
643+
Error::<T>::StakeTooLowForRoot, // Had less stake than the lowest stake incumbent.
644+
);
645+
}
646+
647+
// --- 5. Log and announce the successful Senate adjustment.
648+
log::info!(
649+
"SenateAdjusted(old_hotkey:{:?} hotkey:{:?})",
650+
replaced,
651+
hotkey
652+
);
653+
Self::deposit_event(Event::SenateAdjusted {
654+
old_member: replaced.cloned(),
655+
new_member: hotkey,
656+
});
657+
658+
// --- 6. Finish and return success.
659+
Ok(())
660+
}
661+
662+
// Checks if a hotkey should be a member of the Senate, and if so, adds them.
663+
//
664+
// # Arguments:
665+
// * 'hotkey': The hotkey that the user wants to register to the root network.
666+
//
667+
// # Returns:
668+
// * 'Result<Option<&T::AccountId>, Error<T>>': A result containing the replaced member, if any.
669+
//
670+
fn join_senate_if_eligible(hotkey: &T::AccountId) -> Result<Option<&T::AccountId>, Error<T>> {
671+
// Get the root network UID.
672+
let root_netuid: u16 = Self::get_root_netuid();
673+
674+
// --- 1. Check the hotkey is registered in the root network.
675+
ensure!(
676+
Uids::<T>::contains_key(root_netuid, hotkey),
677+
Error::<T>::HotKeyNotRegisteredInSubNet
678+
);
679+
680+
// --- 2. Verify the hotkey is NOT already a member of the Senate.
681+
ensure!(
682+
!T::SenateMembers::is_member(hotkey),
683+
Error::<T>::HotKeyAlreadyRegisteredInSubNet
684+
);
685+
686+
// --- 3. Grab the hotkey's stake.
687+
let current_stake = Self::get_total_stake_for_hotkey(hotkey);
688+
689+
// Add the hotkey to the Senate.
571690
// If we're full, we'll swap out the lowest stake member.
572691
let members = T::SenateMembers::members();
692+
let last: Option<&T::AccountId> = None;
573693
if (members.len() as u32) == T::SenateMembers::max_members() {
574694
let mut sorted_members = members.clone();
575695
sorted_members.sort_by(|a, b| {
@@ -583,34 +703,17 @@ impl<T: Config> Pallet<T> {
583703
let last_stake = Self::get_total_stake_for_hotkey(last);
584704

585705
if last_stake < current_stake {
586-
T::SenateMembers::swap_member(last, &hotkey).map_err(|e| e.error)?;
587-
T::TriumvirateInterface::remove_votes(last)?;
706+
// Swap the member with the lowest stake.
707+
T::SenateMembers::swap_member(last, hotkey)
708+
.map_err(|_| Error::<T>::CouldNotJoinSenate)?;
588709
}
589710
}
590711
} else {
591-
T::SenateMembers::add_member(&hotkey).map_err(|e| e.error)?;
592-
}
593-
594-
// --- 13. Force all members on root to become a delegate.
595-
if !Self::hotkey_is_delegate(&hotkey) {
596-
Self::delegate_hotkey(&hotkey, 11_796); // 18% cut defaulted.
712+
T::SenateMembers::add_member(hotkey).map_err(|_| Error::<T>::CouldNotJoinSenate)?;
597713
}
598714

599-
// --- 14. Update the registration counters for both the block and interval.
600-
RegistrationsThisInterval::<T>::mutate(root_netuid, |val| val.saturating_inc());
601-
RegistrationsThisBlock::<T>::mutate(root_netuid, |val| val.saturating_inc());
602-
603-
// --- 15. Log and announce the successful registration.
604-
log::info!(
605-
"RootRegistered(netuid:{:?} uid:{:?} hotkey:{:?})",
606-
root_netuid,
607-
subnetwork_uid,
608-
hotkey
609-
);
610-
Self::deposit_event(Event::NeuronRegistered(root_netuid, subnetwork_uid, hotkey));
611-
612-
// --- 16. Finish and return success.
613-
Ok(())
715+
// Return the swapped out member, if any.
716+
Ok(last)
614717
}
615718

616719
pub fn do_set_root_weights(

pallets/subtensor/tests/mock.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -194,23 +194,29 @@ use pallet_subtensor::{CollectiveInterface, MemberManagement};
194194
pub struct ManageSenateMembers;
195195
impl MemberManagement<AccountId> for ManageSenateMembers {
196196
fn add_member(account: &AccountId) -> DispatchResultWithPostInfo {
197-
SenateMembers::add_member(RawOrigin::Root.into(), *account)
197+
let who = *account;
198+
SenateMembers::add_member(RawOrigin::Root.into(), who)
198199
}
199200

200201
fn remove_member(account: &AccountId) -> DispatchResultWithPostInfo {
201-
SenateMembers::remove_member(RawOrigin::Root.into(), *account)
202+
let who = *account;
203+
SenateMembers::remove_member(RawOrigin::Root.into(), who)
202204
}
203205

204-
fn swap_member(remove: &AccountId, add: &AccountId) -> DispatchResultWithPostInfo {
205-
SenateMembers::swap_member(RawOrigin::Root.into(), *remove, *add)
206+
fn swap_member(rm: &AccountId, add: &AccountId) -> DispatchResultWithPostInfo {
207+
let remove = *rm;
208+
let add = *add;
209+
210+
Triumvirate::remove_votes(rm)?;
211+
SenateMembers::swap_member(RawOrigin::Root.into(), remove, add)
206212
}
207213

208214
fn is_member(account: &AccountId) -> bool {
209-
Senate::is_member(account)
215+
SenateMembers::members().contains(account)
210216
}
211217

212218
fn members() -> Vec<AccountId> {
213-
Senate::members()
219+
SenateMembers::members().into()
214220
}
215221

216222
fn max_members() -> u32 {

0 commit comments

Comments
 (0)