Skip to content

Commit 8c17cfd

Browse files
authored
Merge pull request opentensor#736 from opentensor/subnet-identities
Subnet Identities
2 parents 3496c34 + 2c2a15d commit 8c17cfd

File tree

12 files changed

+488
-39
lines changed

12 files changed

+488
-39
lines changed

pallets/admin-utils/tests/tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1243,7 +1243,7 @@ fn test_sudo_get_set_alpha() {
12431243
DispatchError::BadOrigin
12441244
);
12451245

1246-
assert_ok!(SubtensorModule::register_network(signer.clone()));
1246+
assert_ok!(SubtensorModule::register_network(signer.clone(), None));
12471247

12481248
assert_ok!(AdminUtils::sudo_set_alpha_values(
12491249
signer.clone(),

pallets/subtensor/src/benchmarks.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ benchmarks! {
299299
let amount: u64 = 1;
300300
let amount_to_be_staked = 100_000_000_000_000u64;
301301
Subtensor::<T>::add_balance_to_coldkey_account(&coldkey.clone(), amount_to_be_staked);
302-
}: register_network(RawOrigin::Signed(coldkey))
302+
}: register_network(RawOrigin::Signed(coldkey), None)
303303

304304
benchmark_dissolve_network {
305305
let seed : u32 = 1;
@@ -311,8 +311,9 @@ benchmarks! {
311311
let amount: u64 = 1;
312312
let amount_to_be_staked = 100_000_000_000_000u64;
313313
Subtensor::<T>::add_balance_to_coldkey_account(&coldkey.clone(), amount_to_be_staked);
314-
assert_ok!(Subtensor::<T>::register_network(RawOrigin::Signed(coldkey.clone()).into()));
315-
}: dissolve_network(RawOrigin::Root, coldkey, 1)
314+
assert_ok!(Subtensor::<T>::register_network(RawOrigin::Signed(coldkey.clone()).into(), None));
315+
}: dissolve_network(RawOrigin::Signed(coldkey), 1)
316+
316317

317318
// swap_hotkey {
318319
// let seed: u32 = 1;

pallets/subtensor/src/coinbase/root.rs

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -894,17 +894,24 @@ impl<T: Config> Pallet<T> {
894894
/// Facilitates user registration of a new subnetwork.
895895
///
896896
/// # Args:
897-
/// * 'origin': ('T::RuntimeOrigin'): The calling origin. Must be signed.
897+
/// * `origin` (`T::RuntimeOrigin`): The calling origin. Must be signed.
898+
/// * `identity` (`Option<SubnetIdentityOf>`): Optional identity to be associated with the new subnetwork.
898899
///
899-
/// # Event:
900-
/// * 'NetworkAdded': Emitted when a new network is successfully added.
900+
/// # Events:
901+
/// * `NetworkAdded(netuid, modality)`: Emitted when a new network is successfully added.
902+
/// * `SubnetIdentitySet(netuid)`: Emitted when a custom identity is set for a new subnetwork.
903+
/// * `NetworkRemoved(netuid)`: Emitted when an existing network is removed to make room for the new one.
904+
/// * `SubnetIdentityRemoved(netuid)`: Emitted when the identity of a removed network is also deleted.
901905
///
902906
/// # Raises:
903907
/// * 'TxRateLimitExceeded': If the rate limit for network registration is exceeded.
904908
/// * 'NotEnoughBalanceToStake': If there isn't enough balance to stake for network registration.
905909
/// * 'BalanceWithdrawalError': If an error occurs during balance withdrawal for network registration.
906910
///
907-
pub fn user_add_network(origin: T::RuntimeOrigin) -> dispatch::DispatchResult {
911+
pub fn user_add_network(
912+
origin: T::RuntimeOrigin,
913+
identity: Option<SubnetIdentityOf>,
914+
) -> dispatch::DispatchResult {
908915
// --- 0. Ensure the caller is a signed user.
909916
let coldkey = ensure_signed(origin)?;
910917

@@ -948,6 +955,11 @@ impl<T: Config> Pallet<T> {
948955
Self::remove_network(netuid_to_prune);
949956
log::debug!("remove_network: {:?}", netuid_to_prune,);
950957
Self::deposit_event(Event::NetworkRemoved(netuid_to_prune));
958+
959+
if SubnetIdentities::<T>::take(netuid_to_prune).is_some() {
960+
Self::deposit_event(Event::SubnetIdentityRemoved(netuid_to_prune));
961+
}
962+
951963
netuid_to_prune
952964
}
953965
};
@@ -961,21 +973,32 @@ impl<T: Config> Pallet<T> {
961973
Self::init_new_network(netuid_to_register, 360);
962974
log::debug!("init_new_network: {:?}", netuid_to_register,);
963975

964-
// --- 7. Set netuid storage.
976+
// --- 7. Add the identity if it exists
977+
if let Some(identity_value) = identity {
978+
ensure!(
979+
Self::is_valid_subnet_identity(&identity_value),
980+
Error::<T>::InvalidIdentity
981+
);
982+
983+
SubnetIdentities::<T>::insert(netuid_to_register, identity_value);
984+
Self::deposit_event(Event::SubnetIdentitySet(netuid_to_register));
985+
}
986+
987+
// --- 8. Set netuid storage.
965988
let current_block_number: u64 = Self::get_current_block_as_u64();
966989
NetworkLastRegistered::<T>::set(current_block_number);
967990
NetworkRegisteredAt::<T>::insert(netuid_to_register, current_block_number);
968991
SubnetOwner::<T>::insert(netuid_to_register, coldkey);
969992

970-
// --- 8. Emit the NetworkAdded event.
993+
// --- 9. Emit the NetworkAdded event.
971994
log::debug!(
972995
"NetworkAdded( netuid:{:?}, modality:{:?} )",
973996
netuid_to_register,
974997
0
975998
);
976999
Self::deposit_event(Event::NetworkAdded(netuid_to_register, 0));
9771000

978-
// --- 9. Return success.
1001+
// --- 10. Return success.
9791002
Ok(())
9801003
}
9811004

@@ -1005,14 +1028,19 @@ impl<T: Config> Pallet<T> {
10051028
Error::<T>::NotSubnetOwner
10061029
);
10071030

1008-
// --- 2. Explicitly erase the network and all its parameters.
1031+
// --- 4. Remove the subnet identity if it exists.
1032+
if SubnetIdentities::<T>::take(netuid).is_some() {
1033+
Self::deposit_event(Event::SubnetIdentityRemoved(netuid));
1034+
}
1035+
1036+
// --- 5. Explicitly erase the network and all its parameters.
10091037
Self::remove_network(netuid);
10101038

1011-
// --- 3. Emit the NetworkRemoved event.
1039+
// --- 6. Emit the NetworkRemoved event.
10121040
log::debug!("NetworkRemoved( netuid:{:?} )", netuid);
10131041
Self::deposit_event(Event::NetworkRemoved(netuid));
10141042

1015-
// --- 5. Return success.
1043+
// --- 7. Return success.
10161044
Ok(())
10171045
}
10181046

pallets/subtensor/src/lib.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,10 +148,10 @@ pub mod pallet {
148148
pub ip_type: u8,
149149
}
150150

151-
/// Struct for Prometheus.
151+
/// Struct for ChainIdentities.
152152
pub type ChainIdentityOf = ChainIdentity;
153153

154-
/// Data structure for Prometheus information.
154+
/// Data structure for Chain Identities.
155155
#[crate::freeze_struct("bbfd00438dbe2b58")]
156156
#[derive(Encode, Decode, Default, TypeInfo, Clone, PartialEq, Eq, Debug)]
157157
pub struct ChainIdentity {
@@ -169,6 +169,19 @@ pub mod pallet {
169169
pub additional: Vec<u8>,
170170
}
171171

172+
/// Struct for SubnetIdentities.
173+
pub type SubnetIdentityOf = SubnetIdentity;
174+
/// Data structure for Subnet Identities
175+
#[crate::freeze_struct("f448dc3dad763108")]
176+
#[derive(Encode, Decode, Default, TypeInfo, Clone, PartialEq, Eq, Debug)]
177+
pub struct SubnetIdentity {
178+
/// The name of the subnet
179+
pub subnet_name: Vec<u8>,
180+
/// The github repository associated with the chain identity
181+
pub github_repo: Vec<u8>,
182+
/// The subnet's contact
183+
pub subnet_contact: Vec<u8>,
184+
}
172185
/// ============================
173186
/// ==== Staking + Accounts ====
174187
/// ============================
@@ -1164,6 +1177,10 @@ pub mod pallet {
11641177
pub type Identities<T: Config> =
11651178
StorageMap<_, Blake2_128Concat, T::AccountId, ChainIdentityOf, OptionQuery>;
11661179

1180+
#[pallet::storage] // --- MAP ( netuid ) --> identity
1181+
pub type SubnetIdentities<T: Config> =
1182+
StorageMap<_, Blake2_128Concat, u16, SubnetIdentityOf, OptionQuery>;
1183+
11671184
/// =================================
11681185
/// ==== Axon / Promo Endpoints =====
11691186
/// =================================

pallets/subtensor/src/macros/dispatches.rs

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -901,8 +901,11 @@ mod dispatches {
901901
#[pallet::weight((Weight::from_parts(157_000_000, 0)
902902
.saturating_add(T::DbWeight::get().reads(16))
903903
.saturating_add(T::DbWeight::get().writes(30)), DispatchClass::Operational, Pays::No))]
904-
pub fn register_network(origin: OriginFor<T>) -> DispatchResult {
905-
Self::user_add_network(origin)
904+
pub fn register_network(
905+
origin: OriginFor<T>,
906+
identity: Option<SubnetIdentityOf>,
907+
) -> DispatchResult {
908+
Self::user_add_network(origin, identity)
906909
}
907910

908911
/// Facility extrinsic for user to get taken from faucet
@@ -1168,5 +1171,35 @@ mod dispatches {
11681171
) -> DispatchResult {
11691172
Self::do_set_identity(origin, name, url, image, discord, description, additional)
11701173
}
1174+
1175+
/// ---- Set the identity information for a subnet.
1176+
/// # Args:
1177+
/// * `origin` - (<T as frame_system::Config>::Origin):
1178+
/// - The signature of the calling coldkey, which must be the owner of the subnet.
1179+
///
1180+
/// * `netuid` (u16):
1181+
/// - The unique network identifier of the subnet.
1182+
///
1183+
/// * `subnet_name` (Vec<u8>):
1184+
/// - The name of the subnet.
1185+
///
1186+
/// * `github_repo` (Vec<u8>):
1187+
/// - The GitHub repository associated with the subnet identity.
1188+
///
1189+
/// * `subnet_contact` (Vec<u8>):
1190+
/// - The contact information for the subnet.
1191+
#[pallet::call_index(78)]
1192+
#[pallet::weight((Weight::from_parts(45_000_000, 0)
1193+
.saturating_add(T::DbWeight::get().reads(4))
1194+
.saturating_add(T::DbWeight::get().writes(1)), DispatchClass::Normal, Pays::Yes))]
1195+
pub fn set_subnet_identity(
1196+
origin: OriginFor<T>,
1197+
netuid: u16,
1198+
subnet_name: Vec<u8>,
1199+
github_repo: Vec<u8>,
1200+
subnet_contact: Vec<u8>,
1201+
) -> DispatchResult {
1202+
Self::do_set_subnet_identity(origin, netuid, subnet_name, github_repo, subnet_contact)
1203+
}
11711204
}
11721205
}

pallets/subtensor/src/macros/events.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,10 @@ mod events {
187187
NetworkMaxStakeSet(u16, u64),
188188
/// The identity of a coldkey has been set
189189
ChainIdentitySet(T::AccountId),
190+
/// The identity of a subnet has been set
191+
SubnetIdentitySet(u16),
192+
/// The identity of a subnet has been removed
193+
SubnetIdentityRemoved(u16),
190194
/// A dissolve network extrinsic scheduled.
191195
DissolveNetworkScheduled {
192196
/// The account ID schedule the dissolve network extrisnic

pallets/subtensor/src/rpc_info/subnet_info.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use frame_support::storage::IterableStorageMap;
44
extern crate alloc;
55
use codec::Compact;
66

7-
#[freeze_struct("fe79d58173da662a")]
7+
#[freeze_struct("ccca539640c3f631")]
88
#[derive(Decode, Encode, PartialEq, Eq, Clone, Debug)]
99
pub struct SubnetInfo<T: Config> {
1010
netuid: Compact<u16>,
@@ -25,6 +25,7 @@ pub struct SubnetInfo<T: Config> {
2525
emission_values: Compact<u64>,
2626
burn: Compact<u64>,
2727
owner: T::AccountId,
28+
identity: Option<SubnetIdentity>,
2829
}
2930

3031
#[freeze_struct("55b472510f10e76a")]
@@ -80,6 +81,7 @@ impl<T: Config> Pallet<T> {
8081
let network_modality = <NetworkModality<T>>::get(netuid);
8182
let emission_values = Self::get_emission_value(netuid);
8283
let burn: Compact<u64> = Self::get_burn_as_u64(netuid).into();
84+
let identity: Option<SubnetIdentity> = SubnetIdentities::<T>::get(netuid);
8385

8486
// DEPRECATED
8587
let network_connect: Vec<[u16; 2]> = Vec::<[u16; 2]>::new();
@@ -106,6 +108,7 @@ impl<T: Config> Pallet<T> {
106108
emission_values: emission_values.into(),
107109
burn,
108110
owner: Self::get_subnet_owner(netuid),
111+
identity,
109112
})
110113
}
111114

pallets/subtensor/src/utils/identity.rs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,65 @@ impl<T: Config> Pallet<T> {
7575
Ok(())
7676
}
7777

78+
/// Sets the identity for a subnet.
79+
///
80+
/// This function allows the owner of a subnet to set or update the identity information associated with the subnet.
81+
/// It verifies that the caller is the owner of the specified subnet, validates the provided identity information,
82+
/// and then stores it in the blockchain state.
83+
///
84+
/// # Arguments
85+
///
86+
/// * `origin` - The origin of the call, which should be a signed extrinsic.
87+
/// * `netuid` - The unique identifier for the subnet.
88+
/// * `subnet_name` - The name of the subnet to be associated with the identity.
89+
/// * `github_repo` - The GitHub repository URL associated with the subnet identity.
90+
/// * `subnet_contact` - Contact information for the subnet.
91+
///
92+
/// # Returns
93+
///
94+
/// Returns `Ok(())` if the subnet identity is successfully set, otherwise returns an error.
95+
pub fn do_set_subnet_identity(
96+
origin: T::RuntimeOrigin,
97+
netuid: u16,
98+
subnet_name: Vec<u8>,
99+
github_repo: Vec<u8>,
100+
subnet_contact: Vec<u8>,
101+
) -> dispatch::DispatchResult {
102+
// Ensure the call is signed and get the signer's (coldkey) account
103+
let coldkey = ensure_signed(origin)?;
104+
105+
// Ensure that the coldkey owns the subnet
106+
ensure!(
107+
Self::get_subnet_owner(netuid) == coldkey,
108+
Error::<T>::NotSubnetOwner
109+
);
110+
111+
// Create the identity struct with the provided information
112+
let identity: SubnetIdentityOf = SubnetIdentityOf {
113+
subnet_name,
114+
github_repo,
115+
subnet_contact,
116+
};
117+
118+
// Validate the created identity
119+
ensure!(
120+
Self::is_valid_subnet_identity(&identity),
121+
Error::<T>::InvalidIdentity
122+
);
123+
124+
// Store the validated identity in the blockchain state
125+
SubnetIdentities::<T>::insert(netuid, identity.clone());
126+
127+
// Log the identity set event
128+
log::info!("SubnetIdentitySet( netuid:{:?} ) ", netuid);
129+
130+
// Emit an event to notify that an identity has been set
131+
Self::deposit_event(Event::SubnetIdentitySet(netuid));
132+
133+
// Return Ok to indicate successful execution
134+
Ok(())
135+
}
136+
78137
/// Validates the given ChainIdentityOf struct.
79138
///
80139
/// This function checks if the total length of all fields in the ChainIdentityOf struct
@@ -106,4 +165,30 @@ impl<T: Config> Pallet<T> {
106165
&& identity.description.len() <= 1024
107166
&& identity.additional.len() <= 1024
108167
}
168+
169+
/// Validates the given SubnetIdentityOf struct.
170+
///
171+
/// This function checks if the total length of all fields in the SubnetIdentityOf struct
172+
/// is less than or equal to 2304 bytes, and if each individual field is also
173+
/// within its respective maximum byte limit.
174+
///
175+
/// # Arguments
176+
///
177+
/// * `identity` - A reference to the SubnetIdentityOf struct to be validated.
178+
///
179+
/// # Returns
180+
///
181+
/// * `bool` - Returns true if the SubnetIdentity is valid, false otherwise.
182+
pub fn is_valid_subnet_identity(identity: &SubnetIdentityOf) -> bool {
183+
let total_length = identity
184+
.subnet_name
185+
.len()
186+
.saturating_add(identity.github_repo.len())
187+
.saturating_add(identity.subnet_contact.len());
188+
189+
total_length <= 256 + 1024 + 1024
190+
&& identity.subnet_name.len() <= 256
191+
&& identity.github_repo.len() <= 1024
192+
&& identity.subnet_contact.len() <= 1024
193+
}
109194
}

pallets/subtensor/tests/epoch.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1501,7 +1501,7 @@ fn test_set_alpha_disabled() {
15011501
assert_ok!(SubtensorModule::root_register(signer.clone(), hotkey,));
15021502
assert_ok!(SubtensorModule::add_stake(signer.clone(), hotkey, 1000));
15031503
// Only owner can set alpha values
1504-
assert_ok!(SubtensorModule::register_network(signer.clone()));
1504+
assert_ok!(SubtensorModule::register_network(signer.clone(), None));
15051505

15061506
// Explicitly set to false
15071507
SubtensorModule::set_liquid_alpha_enabled(netuid, false);
@@ -2584,7 +2584,7 @@ fn test_get_set_alpha() {
25842584
DispatchError::BadOrigin
25852585
);
25862586

2587-
assert_ok!(SubtensorModule::register_network(signer.clone()));
2587+
assert_ok!(SubtensorModule::register_network(signer.clone(), None));
25882588

25892589
assert_ok!(SubtensorModule::do_set_alpha_values(
25902590
signer.clone(),

pallets/subtensor/tests/migration.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,8 @@ fn test_total_issuance_global() {
170170
SubtensorModule::add_balance_to_coldkey_account(&owner, lockcost); // Add a balance of 20000 to the coldkey account.
171171
assert_eq!(SubtensorModule::get_total_issuance(), 0); // initial is zero.
172172
assert_ok!(SubtensorModule::register_network(
173-
<<Test as Config>::RuntimeOrigin>::signed(owner)
173+
<<Test as Config>::RuntimeOrigin>::signed(owner),
174+
None
174175
));
175176
SubtensorModule::set_max_allowed_uids(netuid, 1); // Set the maximum allowed unique identifiers for the network to 1.
176177
assert_eq!(SubtensorModule::get_total_issuance(), 0); // initial is zero.

0 commit comments

Comments
 (0)