diff --git a/pallets/subtensor/src/benchmarks.rs b/pallets/subtensor/src/benchmarks.rs index 8a768c95a3..195331b74f 100644 --- a/pallets/subtensor/src/benchmarks.rs +++ b/pallets/subtensor/src/benchmarks.rs @@ -1225,7 +1225,7 @@ mod pallet_benchmarks { fn register_network_with_identity() { let coldkey: T::AccountId = whitelisted_caller(); let hotkey: T::AccountId = account("Alice", 0, 1); - let identity: Option = None; + let identity: Option = None; Subtensor::::set_network_registration_allowed(1.into(), true); Subtensor::::set_network_rate_limit(1); @@ -1331,6 +1331,7 @@ mod pallet_benchmarks { let descr = vec![]; let logo_url = vec![]; let add = vec![]; + let agent_docs_url = vec![]; SubnetOwner::::insert(netuid, coldkey.clone()); SubtokenEnabled::::insert(netuid, true); @@ -1347,6 +1348,7 @@ mod pallet_benchmarks { descr.clone(), logo_url.clone(), add.clone(), + agent_docs_url.clone(), ); } diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index 54ccadc1a1..e30a51742f 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -256,8 +256,8 @@ pub mod pallet { pub additional: Vec, } - /// Struct for SubnetIdentities. (DEPRECATED for V2) - pub type SubnetIdentityOf = SubnetIdentity; + /// Struct for SubnetIdentities. (DEPRECATED) + pub type SubnetIdentityOfV1 = SubnetIdentity; /// Data structure for Subnet Identities. (DEPRECATED for V2) #[crate::freeze_struct("f448dc3dad763108")] #[derive(Encode, Decode, Default, TypeInfo, Clone, PartialEq, Eq, Debug)] @@ -292,9 +292,9 @@ pub mod pallet { pub additional: Vec, } - /// Struct for SubnetIdentitiesV3. + /// Struct for SubnetIdentitiesV3. (DEPRECATED) pub type SubnetIdentityOfV3 = SubnetIdentityV3; - /// Data structure for Subnet Identities + /// Data structure for Subnet Identities (DEPRECATED) #[crate::freeze_struct("6a441335f985a0b")] #[derive( Encode, Decode, DecodeWithMemTracking, Default, TypeInfo, Clone, PartialEq, Eq, Debug, @@ -318,6 +318,35 @@ pub mod pallet { pub additional: Vec, } + /// Type alias for the current subnet identity version. + /// Update this alias when introducing a new version. + pub type SubnetIdentityOf = SubnetIdentityV4; + /// Data structure for Subnet Identities + #[crate::freeze_struct("4b9718ba1a9cb75f")] + #[derive( + Encode, Decode, DecodeWithMemTracking, Default, TypeInfo, Clone, PartialEq, Eq, Debug, + )] + pub struct SubnetIdentityV4 { + /// The name of the subnet + pub subnet_name: Vec, + /// The github repository associated with the subnet + pub github_repo: Vec, + /// The subnet's contact + pub subnet_contact: Vec, + /// The subnet's website + pub subnet_url: Vec, + /// The subnet's discord + pub discord: Vec, + /// The subnet's description + pub description: Vec, + /// The subnet's logo + pub logo_url: Vec, + /// Additional information about the subnet + pub additional: Vec, + /// The subnet's agent documentation URL + pub agent_docs_url: Vec, + } + /// Enum for recycle or burn for the owner_uid(s) #[derive(TypeInfo, Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, Eq, Debug)] pub enum RecycleOrBurnEnum { @@ -2155,10 +2184,10 @@ pub mod pallet { pub type IdentitiesV2 = StorageMap<_, Blake2_128Concat, T::AccountId, ChainIdentityOfV2, OptionQuery>; - /// --- MAP ( netuid ) --> SubnetIdentityOfV3 + /// --- MAP ( netuid ) --> SubnetIdentityOf #[pallet::storage] pub type SubnetIdentitiesV3 = - StorageMap<_, Blake2_128Concat, NetUid, SubnetIdentityOfV3, OptionQuery>; + StorageMap<_, Blake2_128Concat, NetUid, SubnetIdentityOf, OptionQuery>; /// ================================= /// ==== Axon / Promo Endpoints ===== diff --git a/pallets/subtensor/src/macros/dispatches.rs b/pallets/subtensor/src/macros/dispatches.rs index f70b83f52d..3b476a0ffe 100644 --- a/pallets/subtensor/src/macros/dispatches.rs +++ b/pallets/subtensor/src/macros/dispatches.rs @@ -1438,6 +1438,7 @@ mod dispatches { description: Vec, logo_url: Vec, additional: Vec, + agent_docs_url: Vec, ) -> DispatchResult { Self::do_set_subnet_identity( origin, @@ -1450,6 +1451,7 @@ mod dispatches { description, logo_url, additional, + agent_docs_url, ) } @@ -1461,7 +1463,7 @@ mod dispatches { pub fn register_network_with_identity( origin: OriginFor, hotkey: T::AccountId, - identity: Option, + identity: Option, ) -> DispatchResult { Self::do_register_network(origin, &hotkey, 1, identity) } diff --git a/pallets/subtensor/src/macros/hooks.rs b/pallets/subtensor/src/macros/hooks.rs index 899e8d32f2..4ebed48217 100644 --- a/pallets/subtensor/src/macros/hooks.rs +++ b/pallets/subtensor/src/macros/hooks.rs @@ -166,7 +166,9 @@ mod hooks { // Fix staking hot keys .saturating_add(migrations::migrate_fix_staking_hot_keys::migrate_fix_staking_hot_keys::()) // Migrate coldkey swap scheduled to announcements - .saturating_add(migrations::migrate_coldkey_swap_scheduled_to_announcements::migrate_coldkey_swap_scheduled_to_announcements::()); + .saturating_add(migrations::migrate_coldkey_swap_scheduled_to_announcements::migrate_coldkey_swap_scheduled_to_announcements::()) + // Migrate SubnetIdentitiesV3 entries from V3 to V4 encoding + .saturating_add(migrations::migrate_subnet_identity_v3_to_v4::migrate_subnet_identity_v3_to_v4::()); weight } diff --git a/pallets/subtensor/src/migrations/migrate_subnet_identity_v3_to_v4.rs b/pallets/subtensor/src/migrations/migrate_subnet_identity_v3_to_v4.rs new file mode 100644 index 0000000000..6eda452a3d --- /dev/null +++ b/pallets/subtensor/src/migrations/migrate_subnet_identity_v3_to_v4.rs @@ -0,0 +1,52 @@ +use super::*; +use crate::HasMigrationRun; +use frame_support::{traits::Get, weights::Weight}; +use scale_info::prelude::string::String; + +pub fn migrate_subnet_identity_v3_to_v4() -> Weight { + let migration_name = b"migrate_subnet_identity_v3_to_v4".to_vec(); + let mut weight = T::DbWeight::get().reads(1); + + if HasMigrationRun::::get(&migration_name) { + log::info!( + "Migration '{:?}' has already run. Skipping.", + String::from_utf8_lossy(&migration_name) + ); + return weight; + } + + log::info!( + "Running migration '{}'", + String::from_utf8_lossy(&migration_name), + ); + + let mut migrated_count: u64 = 0; + + // Translate V3-encoded entries to V4 in place within SubnetIdentitiesV3. + SubnetIdentitiesV3::::translate::(|_netuid, v3| { + migrated_count += 1; + Some(SubnetIdentityOf { + subnet_name: v3.subnet_name, + github_repo: v3.github_repo, + subnet_contact: v3.subnet_contact, + subnet_url: v3.subnet_url, + discord: v3.discord, + description: v3.description, + logo_url: v3.logo_url, + additional: v3.additional, + agent_docs_url: vec![], + }) + }); + + weight = weight.saturating_add(T::DbWeight::get().reads_writes(migrated_count, migrated_count)); + + HasMigrationRun::::insert(&migration_name, true); + weight = weight.saturating_add(T::DbWeight::get().writes(1)); + + log::info!( + "Migration '{:?}' completed successfully. Migrated {migrated_count:?} subnet identities.", + String::from_utf8_lossy(&migration_name) + ); + + weight +} diff --git a/pallets/subtensor/src/migrations/mod.rs b/pallets/subtensor/src/migrations/mod.rs index 23a2899b94..1923a11121 100644 --- a/pallets/subtensor/src/migrations/mod.rs +++ b/pallets/subtensor/src/migrations/mod.rs @@ -55,6 +55,7 @@ pub mod migrate_stake_threshold; pub mod migrate_subnet_limit_to_default; pub mod migrate_subnet_locked; pub mod migrate_subnet_symbols; +pub mod migrate_subnet_identity_v3_to_v4; pub mod migrate_subnet_volume; pub mod migrate_to_v1_separate_emission; pub mod migrate_to_v2_fixed_total_stake; diff --git a/pallets/subtensor/src/rpc_info/dynamic_info.rs b/pallets/subtensor/src/rpc_info/dynamic_info.rs index b143295425..7d71a2b833 100644 --- a/pallets/subtensor/src/rpc_info/dynamic_info.rs +++ b/pallets/subtensor/src/rpc_info/dynamic_info.rs @@ -6,7 +6,7 @@ use substrate_fixed::types::I96F32; use subtensor_macros::freeze_struct; use subtensor_runtime_common::{AlphaBalance, NetUid, TaoBalance}; -#[freeze_struct("cf677afa654c96a6")] +#[freeze_struct("df57c3a5e8b0100c")] #[derive(Decode, Encode, PartialEq, Eq, Clone, Debug, TypeInfo)] pub struct DynamicInfo { netuid: Compact, @@ -28,7 +28,7 @@ pub struct DynamicInfo { pending_root_emission: Compact, subnet_volume: Compact, network_registered_at: Compact, - subnet_identity: Option, + subnet_identity: Option, moving_price: I96F32, } diff --git a/pallets/subtensor/src/rpc_info/metagraph.rs b/pallets/subtensor/src/rpc_info/metagraph.rs index 4d82af629a..dfe5136887 100644 --- a/pallets/subtensor/src/rpc_info/metagraph.rs +++ b/pallets/subtensor/src/rpc_info/metagraph.rs @@ -10,7 +10,7 @@ use substrate_fixed::types::I96F32; use subtensor_macros::freeze_struct; use subtensor_runtime_common::{AlphaBalance, MechId, NetUid, NetUidStorageIndex, TaoBalance}; -#[freeze_struct("fbab6d1e7f3c69ae")] +#[freeze_struct("1db9a42935e6a1a8")] #[derive(Decode, Encode, PartialEq, Eq, Clone, Debug, TypeInfo)] pub struct Metagraph { // Subnet index @@ -19,7 +19,7 @@ pub struct Metagraph { // Name and symbol name: Vec>, // name symbol: Vec>, // token symbol - identity: Option, // identity information. + identity: Option, // identity information. network_registered_at: Compact, // block at registration // Keys for owner. @@ -110,7 +110,7 @@ pub struct Metagraph { alpha_dividends_per_hotkey: Vec<(AccountId, Compact)>, // List of dividend payout in alpha via subnet. } -#[freeze_struct("3ff2befdb7b393ea")] +#[freeze_struct("cb7d1187d7035b79")] #[derive(Decode, Encode, PartialEq, Eq, Clone, Debug, TypeInfo)] pub struct SelectiveMetagraph { // Subnet index @@ -119,7 +119,7 @@ pub struct SelectiveMetagraph { // Name and symbol name: Option>>, // name symbol: Option>>, // token symbol - identity: Option>, // identity information + identity: Option>, // identity information network_registered_at: Option>, // block at registration // Keys for owner. diff --git a/pallets/subtensor/src/rpc_info/subnet_info.rs b/pallets/subtensor/src/rpc_info/subnet_info.rs index db595eb98e..e99c6e9ff6 100644 --- a/pallets/subtensor/src/rpc_info/subnet_info.rs +++ b/pallets/subtensor/src/rpc_info/subnet_info.rs @@ -29,7 +29,7 @@ pub struct SubnetInfo { owner: AccountId, } -#[freeze_struct("e8e028bf4fbc6741")] +#[freeze_struct("c8976c0491130e76")] #[derive(Decode, Encode, PartialEq, Eq, Clone, Debug, TypeInfo)] pub struct SubnetInfov2 { netuid: Compact, @@ -50,7 +50,7 @@ pub struct SubnetInfov2 { emission_value: Compact, burn: Compact, owner: AccountId, - identity: Option, + identity: Option, } #[freeze_struct("fd2db338b156d251")] @@ -210,7 +210,7 @@ impl Pallet { let blocks_since_last_step = Self::get_blocks_since_last_step(netuid); let tempo = Self::get_tempo(netuid); let burn = Compact::from(Self::get_burn(netuid)); - let identity: Option = SubnetIdentitiesV3::::get(netuid); + let identity: Option = SubnetIdentitiesV3::::get(netuid); // DEPRECATED let network_connect: Vec<[u16; 2]> = Vec::<[u16; 2]>::new(); diff --git a/pallets/subtensor/src/subnets/subnet.rs b/pallets/subtensor/src/subnets/subnet.rs index c6a87af63a..4aabe2aeb8 100644 --- a/pallets/subtensor/src/subnets/subnet.rs +++ b/pallets/subtensor/src/subnets/subnet.rs @@ -92,7 +92,7 @@ impl Pallet { /// * **`origin`** – `T::RuntimeOrigin`  Must be **signed** by the coldkey. /// * **`hotkey`** – `&T::AccountId`  First neuron of the new subnet. /// * **`mechid`** – `u16`  Only the dynamic mechanism (`1`) is currently supported. - /// * **`identity`** – `Option`  Optional metadata for the subnet. + /// * **`identity`** – `Option`  Optional metadata for the subnet. /// /// ### Events /// * `NetworkAdded(netuid, mechid)` – always. @@ -112,7 +112,7 @@ impl Pallet { origin: OriginFor, hotkey: &T::AccountId, mechid: u16, - identity: Option, + identity: Option, ) -> DispatchResult { // --- 1. Ensure the caller is a signed user. let coldkey = ensure_signed(origin)?; diff --git a/pallets/subtensor/src/tests/migration.rs b/pallets/subtensor/src/tests/migration.rs index 7f19c96b3d..617e4cb4a4 100644 --- a/pallets/subtensor/src/tests/migration.rs +++ b/pallets/subtensor/src/tests/migration.rs @@ -3122,3 +3122,117 @@ fn test_migrate_coldkey_swap_scheduled_to_announcements() { ); }); } + +#[test] +fn test_migrate_subnet_identity_v3_to_v4() { + new_test_ext(1).execute_with(|| { + let migration_name = b"migrate_subnet_identity_v3_to_v4".to_vec(); + + // Ensure migration has not run yet + assert!( + !HasMigrationRun::::get(&migration_name), + "Migration should not have run yet" + ); + + // Build raw V3 identities and write them under the SubnetIdentitiesV3 prefix. + let v3_identity_1 = SubnetIdentityV3 { + subnet_name: b"Alpha Subnet".to_vec(), + github_repo: b"https://github.com/alpha".to_vec(), + subnet_contact: b"alpha@example.com".to_vec(), + subnet_url: b"https://alpha.example.com".to_vec(), + discord: b"alpha#1234".to_vec(), + description: b"The first subnet".to_vec(), + logo_url: b"https://alpha.example.com/logo.png".to_vec(), + additional: b"extra info".to_vec(), + }; + + let v3_identity_2 = SubnetIdentityV3 { + subnet_name: b"Beta Subnet".to_vec(), + github_repo: vec![], + subnet_contact: vec![], + subnet_url: vec![], + discord: vec![], + description: b"Minimal subnet".to_vec(), + logo_url: vec![], + additional: vec![], + }; + + let netuid_1 = NetUid::from(1); + let netuid_2 = NetUid::from(42); + + // Write raw V3-encoded bytes into the SubnetIdentitiesV3 storage prefix. + // Key layout: twox_128("SubtensorModule") ++ twox_128("SubnetIdentitiesV3") ++ Blake2_128Concat(netuid) + let pallet_prefix = twox_128(b"SubtensorModule"); + let storage_prefix = twox_128(b"SubnetIdentitiesV3"); + + for (netuid, v3_identity) in [(netuid_1, &v3_identity_1), (netuid_2, &v3_identity_2)] { + let mut key = Vec::new(); + key.extend_from_slice(&pallet_prefix); + key.extend_from_slice(&storage_prefix); + key.extend_from_slice(&frame_support::Blake2_128Concat::hash( + &netuid.encode(), + )); + put_raw(&key, &v3_identity.encode()); + } + + // Verify V3 data is present as raw bytes (cannot read via the typed + // SubnetIdentitiesV3 accessor because its value type is now V4). + { + let mut key = Vec::new(); + key.extend_from_slice(&pallet_prefix); + key.extend_from_slice(&storage_prefix); + key.extend_from_slice(&frame_support::Blake2_128Concat::hash( + &netuid_1.encode(), + )); + assert!( + get_raw(&key).is_some(), + "Raw V3 bytes should exist at storage key" + ); + } + + // Run the migration + let weight = + crate::migrations::migrate_subnet_identity_v3_to_v4::migrate_subnet_identity_v3_to_v4::< + Test, + >(); + assert!(!weight.is_zero(), "Migration weight should be non-zero"); + + // Migration should be marked as completed + assert!( + HasMigrationRun::::get(&migration_name), + "Migration should be marked as run" + ); + + // Read back via the typed storage accessor (expects V4 encoding) + let read_1 = SubnetIdentitiesV3::::get(netuid_1) + .expect("Identity 1 should exist after migration"); + assert_eq!(read_1.subnet_name, b"Alpha Subnet".to_vec()); + assert_eq!(read_1.github_repo, b"https://github.com/alpha".to_vec()); + assert_eq!(read_1.subnet_contact, b"alpha@example.com".to_vec()); + assert_eq!(read_1.subnet_url, b"https://alpha.example.com".to_vec()); + assert_eq!(read_1.discord, b"alpha#1234".to_vec()); + assert_eq!(read_1.description, b"The first subnet".to_vec()); + assert_eq!( + read_1.logo_url, + b"https://alpha.example.com/logo.png".to_vec() + ); + assert_eq!(read_1.additional, b"extra info".to_vec()); + assert_eq!(read_1.agent_docs_url, Vec::::new()); + + let read_2 = SubnetIdentitiesV3::::get(netuid_2) + .expect("Identity 2 should exist after migration"); + assert_eq!(read_2.subnet_name, b"Beta Subnet".to_vec()); + assert_eq!(read_2.description, b"Minimal subnet".to_vec()); + assert_eq!(read_2.agent_docs_url, Vec::::new()); + + // Running the migration again should be a no-op + let _weight_second = + crate::migrations::migrate_subnet_identity_v3_to_v4::migrate_subnet_identity_v3_to_v4::< + Test, + >(); + let reread_1 = SubnetIdentitiesV3::::get(netuid_1) + .expect("Identity 1 should still exist"); + assert_eq!(reread_1.subnet_name, b"Alpha Subnet".to_vec()); + assert_eq!(reread_1.agent_docs_url, Vec::::new()); + }); +} diff --git a/pallets/subtensor/src/tests/serving.rs b/pallets/subtensor/src/tests/serving.rs index 2979d4438c..66ceb78f97 100644 --- a/pallets/subtensor/src/tests/serving.rs +++ b/pallets/subtensor/src/tests/serving.rs @@ -945,6 +945,7 @@ fn test_do_set_subnet_identity() { description.clone(), logo_url.clone(), additional.clone(), + vec![], )); // Check if subnet identity is set correctly @@ -969,6 +970,7 @@ fn test_do_set_subnet_identity() { description.clone(), logo_url.clone(), additional.clone(), + vec![], ), Error::::NotSubnetOwner ); @@ -987,6 +989,7 @@ fn test_do_set_subnet_identity() { description.clone(), logo_url.clone(), additional.clone(), + vec![], )); let updated_identity = @@ -1009,6 +1012,7 @@ fn test_do_set_subnet_identity() { long_data.clone(), long_data.clone(), long_data.clone(), + long_data.clone(), ), Error::::InvalidIdentity ); @@ -1020,7 +1024,7 @@ fn test_do_set_subnet_identity() { fn test_is_valid_subnet_identity() { new_test_ext(1).execute_with(|| { // Test valid subnet identity - let valid_identity = SubnetIdentityV3 { + let valid_identity = SubnetIdentityOf { subnet_name: vec![0; 256], github_repo: vec![0; 1024], subnet_contact: vec![0; 1024], @@ -1029,11 +1033,12 @@ fn test_is_valid_subnet_identity() { description: vec![0; 1024], logo_url: vec![0; 1024], additional: vec![0; 1024], + agent_docs_url: vec![0; 1024], }; assert!(SubtensorModule::is_valid_subnet_identity(&valid_identity)); // Test subnet identity with total length exactly at the maximum - let max_length_identity = SubnetIdentityV3 { + let max_length_identity = SubnetIdentityOf { subnet_name: vec![0; 256], github_repo: vec![0; 1024], subnet_contact: vec![0; 1024], @@ -1042,13 +1047,14 @@ fn test_is_valid_subnet_identity() { description: vec![0; 1024], logo_url: vec![0; 1024], additional: vec![0; 1024], + agent_docs_url: vec![0; 1024], }; assert!(SubtensorModule::is_valid_subnet_identity( &max_length_identity )); // Test subnet identity with total length exceeding the maximum - let invalid_length_identity = SubnetIdentityV3 { + let invalid_length_identity = SubnetIdentityOf { subnet_name: vec![0; 257], github_repo: vec![0; 1024], subnet_contact: vec![0; 1024], @@ -1057,13 +1063,14 @@ fn test_is_valid_subnet_identity() { description: vec![0; 1024], logo_url: vec![0; 1024], additional: vec![0; 1024], + agent_docs_url: vec![0; 1024], }; assert!(!SubtensorModule::is_valid_subnet_identity( &invalid_length_identity )); // Test subnet identity with one field exceeding its maximum - let invalid_field_identity = SubnetIdentityV3 { + let invalid_field_identity = SubnetIdentityOf { subnet_name: vec![0; 257], github_repo: vec![0; 1024], subnet_contact: vec![0; 1024], @@ -1072,13 +1079,14 @@ fn test_is_valid_subnet_identity() { description: vec![0; 1024], logo_url: vec![0; 1024], additional: vec![0; 1024], + agent_docs_url: vec![0; 1024], }; assert!(!SubtensorModule::is_valid_subnet_identity( &invalid_field_identity )); // Test subnet identity with empty fields - let empty_identity = SubnetIdentityV3 { + let empty_identity = SubnetIdentityOf { subnet_name: vec![], github_repo: vec![], subnet_contact: vec![], @@ -1087,11 +1095,12 @@ fn test_is_valid_subnet_identity() { description: vec![], logo_url: vec![], additional: vec![], + agent_docs_url: vec![], }; assert!(SubtensorModule::is_valid_subnet_identity(&empty_identity)); // Test subnet identity with some empty and some filled fields - let mixed_identity = SubnetIdentityV3 { + let mixed_identity = SubnetIdentityOf { subnet_name: b"Test Subnet".to_vec(), github_repo: vec![], subnet_contact: b"contact@testsubnet.com".to_vec(), @@ -1100,8 +1109,25 @@ fn test_is_valid_subnet_identity() { description: b"A description".to_vec(), logo_url: vec![], additional: vec![], + agent_docs_url: vec![], }; assert!(SubtensorModule::is_valid_subnet_identity(&mixed_identity)); + + // Test subnet identity with agent_docs_url exceeding max + let invalid_agent_docs = SubnetIdentityOf { + subnet_name: vec![], + github_repo: vec![], + subnet_contact: vec![], + subnet_url: vec![], + discord: vec![], + description: vec![], + logo_url: vec![], + additional: vec![], + agent_docs_url: vec![0; 1025], + }; + assert!(!SubtensorModule::is_valid_subnet_identity( + &invalid_agent_docs + )); }); } @@ -1134,6 +1160,7 @@ fn test_set_identity_for_non_existent_subnet() { description.clone(), logo_url.clone(), additional.clone(), + vec![], ), Error::::NotSubnetOwner // Since there's no owner, it should fail ); @@ -1163,6 +1190,7 @@ fn test_set_subnet_identity_dispatch_info_ok() { description, logo_url, additional, + agent_docs_url: vec![], }); let dispatch_info: DispatchInfo = call.get_dispatch_info(); diff --git a/pallets/subtensor/src/utils/identity.rs b/pallets/subtensor/src/utils/identity.rs index c2406321ed..41f727bfaf 100644 --- a/pallets/subtensor/src/utils/identity.rs +++ b/pallets/subtensor/src/utils/identity.rs @@ -106,6 +106,7 @@ impl Pallet { description: Vec, logo_url: Vec, additional: Vec, + agent_docs_url: Vec, ) -> dispatch::DispatchResult { // Ensure the call is signed and get the signer's (coldkey) account let coldkey = ensure_signed(origin)?; @@ -117,7 +118,7 @@ impl Pallet { ); // Create the identity struct with the provided information - let identity: SubnetIdentityOfV3 = SubnetIdentityOfV3 { + let identity: SubnetIdentityOf = SubnetIdentityOf { subnet_name, github_repo, subnet_contact, @@ -126,6 +127,7 @@ impl Pallet { description, logo_url, additional, + agent_docs_url, }; // Validate the created identity @@ -188,20 +190,20 @@ impl Pallet { && identity.additional.len() <= 1024 } - /// Validates the given SubnetIdentityOfV3 struct. + /// Validates the given SubnetIdentityOf struct. /// - /// This function checks if the total length of all fields in the SubnetIdentityOfV3 struct - /// is less than or equal to 2304 bytes, and if each individual field is also - /// within its respective maximum byte limit. + /// This function checks if the total length of all fields in the SubnetIdentityOf struct + /// is within limits, and if each individual field is also within its respective maximum + /// byte limit. /// /// # Arguments /// - /// * `identity` - A reference to the SubnetIdentityOfV3 struct to be validated. + /// * `identity` - A reference to the SubnetIdentityOf struct to be validated. /// /// # Returns /// - /// * `bool` - Returns true if the SubnetIdentityV3 is valid, false otherwise. - pub fn is_valid_subnet_identity(identity: &SubnetIdentityOfV3) -> bool { + /// * `bool` - Returns true if the SubnetIdentityOf is valid, false otherwise. + pub fn is_valid_subnet_identity(identity: &SubnetIdentityOf) -> bool { let total_length = identity .subnet_name .len() @@ -215,6 +217,7 @@ impl Pallet { .saturating_add(256) .saturating_add(1024) .saturating_add(1024) + .saturating_add(1024) .saturating_add(1024); total_length <= max_length @@ -226,5 +229,6 @@ impl Pallet { && identity.description.len() <= 1024 && identity.logo_url.len() <= 1024 && identity.additional.len() <= 1024 + && identity.agent_docs_url.len() <= 1024 } } diff --git a/precompiles/src/subnet.rs b/precompiles/src/subnet.rs index 79c08c2625..5c502d8d09 100644 --- a/precompiles/src/subnet.rs +++ b/precompiles/src/subnet.rs @@ -99,7 +99,7 @@ where additional: BoundedString>, ) -> EvmResult<()> { let hotkey = R::AccountId::from(hotkey.0); - let identity = pallet_subtensor::SubnetIdentityOfV3 { + let identity = pallet_subtensor::SubnetIdentityOf { subnet_name: subnet_name.into(), github_repo: github_repo.into(), subnet_contact: subnet_contact.into(), @@ -108,6 +108,7 @@ where description: description.into(), logo_url: vec![], additional: additional.into(), + agent_docs_url: vec![], }; let call = pallet_subtensor::Call::::register_network_with_identity { @@ -139,7 +140,7 @@ where logo_url: BoundedString>, ) -> EvmResult<()> { let hotkey = R::AccountId::from(hotkey.0); - let identity = pallet_subtensor::SubnetIdentityOfV3 { + let identity = pallet_subtensor::SubnetIdentityOf { subnet_name: subnet_name.into(), github_repo: github_repo.into(), subnet_contact: subnet_contact.into(), @@ -148,6 +149,7 @@ where description: description.into(), logo_url: logo_url.into(), additional: additional.into(), + agent_docs_url: vec![], }; let call = pallet_subtensor::Call::::register_network_with_identity { diff --git a/runtime/tests/pallet_proxy.rs b/runtime/tests/pallet_proxy.rs index 1da1c4cdcc..1b01f9ffe6 100644 --- a/runtime/tests/pallet_proxy.rs +++ b/runtime/tests/pallet_proxy.rs @@ -82,6 +82,7 @@ fn call_set_subnet_identity() -> RuntimeCall { description: vec![], logo_url: vec![], additional: vec![], + agent_docs_url: vec![], }) }