Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
unconst committed Jul 24, 2024
1 parent a1e2287 commit dd938c2
Show file tree
Hide file tree
Showing 13 changed files with 1,015 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .rustfmt.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
##
# rustup run nightly -- rustfmt node/src/main.rs

# max_width = 100
# max_width = 180
# hard_tabs = false
# tab_spaces = 4
# newline_style = "Auto"
Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

394 changes: 394 additions & 0 deletions docs/delegate-info.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions pallets/subtensor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ frame-support = { workspace = true }
frame-system = { workspace = true }
sp-io = { workspace = true }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
serde-tuple-vec-map = { workspace = true }
serde_bytes = { workspace = true, features = ["alloc"] }
serde_with = { workspace = true, features = ["macros"] }
Expand Down
22 changes: 22 additions & 0 deletions pallets/subtensor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,25 @@ pub mod pallet {
pub ip_type: u8,
}

/// Struct for Prometheus.
pub type ChainIdentityOf = ChainIdentity;
/// Data structure for Prometheus information.
#[derive(Encode, Decode, Default, TypeInfo, Clone, PartialEq, Eq, Debug)]
pub struct ChainIdentity {
/// The name of the chain identity
pub name: Vec<u8>,
/// The URL associated with the chain identity
pub url: Vec<u8>,
/// The image representation of the chain identity
pub image: Vec<u8>,
/// The Discord information for the chain identity
pub discord: Vec<u8>,
/// A description of the chain identity
pub description: Vec<u8>,
/// Additional information about the chain identity
pub additional: Vec<u8>,
}

/// ============================
/// ==== Staking + Accounts ====
/// ============================
Expand Down Expand Up @@ -1057,6 +1076,9 @@ pub mod pallet {
PrometheusInfoOf,
OptionQuery,
>;
#[pallet::storage] // --- MAP ( coldkey ) --> identity
pub type Identities<T: Config> =
StorageMap<_, Blake2_128Concat, T::AccountId, ChainIdentityOf, OptionQuery>;

/// =================================
/// ==== Axon / Promo Endpoints =====
Expand Down
36 changes: 36 additions & 0 deletions pallets/subtensor/src/macros/dispatches.rs
Original file line number Diff line number Diff line change
Expand Up @@ -901,5 +901,41 @@ mod dispatches {
Self::do_set_children(origin, hotkey, netuid, children)?;
Ok(().into())
}

/// ---- Set prometheus information for the neuron.
/// # Args:
/// * 'origin': (<T as frame_system::Config>Origin):
/// - The signature of the calling hotkey.
///
/// * 'netuid' (u16):
/// - The u16 network identifier.
///
/// * 'version' (u16):
/// - The bittensor version identifier.
///
/// * 'ip' (u128):
/// - The prometheus ip information as a u128 encoded integer.
///
/// * 'port' (u16):
/// - The prometheus port information as a u16 encoded integer.
///
/// * 'ip_type' (u8):
/// - The ip type v4 or v6.
///
#[pallet::call_index(68)]
#[pallet::weight((Weight::from_parts(45_000_000, 0)
.saturating_add(T::DbWeight::get().reads(4))
.saturating_add(T::DbWeight::get().writes(1)), DispatchClass::Normal, Pays::Yes))]
pub fn set_identity(
origin: OriginFor<T>,
name: Vec<u8>,
url: Vec<u8>,
image: Vec<u8>,
discord: Vec<u8>,
description: Vec<u8>,
additional: Vec<u8>,
) -> DispatchResult {
Self::do_set_identity(origin, name, url, image, discord, description, additional)
}
}
}
2 changes: 2 additions & 0 deletions pallets/subtensor/src/macros/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,5 +168,7 @@ mod errors {
TooManyChildren,
/// Default transaction rate limit exceeded.
TxRateLimitExceeded,
/// Invalid identity.
InvalidIdentity,
}
}
2 changes: 2 additions & 0 deletions pallets/subtensor/src/macros/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,5 +177,7 @@ mod events {
HotkeyEmissionTempoSet(u64),
/// The network maximum stake has been set
NetworkMaxStakeSet(u16, u64),
/// The identity of a coldkey has been set
ChainIdentitySet(T::AccountId),
}
}
166 changes: 166 additions & 0 deletions pallets/subtensor/src/migrations/migrate_chain_identity.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
use crate::alloc::borrow::ToOwned;
use codec::Decode;
use scale_info::prelude::{string::String, vec::Vec};
use serde::Deserialize;
use sp_core::{crypto::Ss58Codec, ConstU32};
use sp_runtime::{AccountId32, BoundedVec};

use super::*;
use frame_support::{traits::Get, weights::Weight};
use log;

#[derive(Deserialize, Debug)]
struct RegistrationRecordJSON {
address: String,
name: String,
url: String,
description: String,
}

fn string_to_bounded_vec(input: &str) -> Result<BoundedVec<u8, ConstU32<1024>>, &'static str> {
let vec_u8: Vec<u8> = input.to_owned().into_bytes();

// Check if the length is within bounds
if vec_u8.len() > 64 {
return Err("Input string is too long");
}

// Convert to BoundedVec
BoundedVec::<u8, ConstU32<1024>>::try_from(vec_u8)
.map_err(|_| "Failed to convert to BoundedVec")
}

pub fn migrate_set_hotkey_identities<T: Config>() -> Weight {
let migration_name = b"fix_total_coldkey_stake_v7".to_vec();

// Initialize the weight with one read operation.
let mut weight = T::DbWeight::get().reads(1);

// Check if the migration has already run
if HasMigrationRun::<T>::get(&migration_name) {
log::info!(
"Migration '{:?}' has already run. Skipping.",
migration_name
);
return weight;
}
log::info!(
"Running migration '{}'",
String::from_utf8_lossy(&migration_name)
);

// Include the JSON file with delegate info
let data = include_str!("../../../../docs/delegate-info.json");

// Iterate over all the delegate records
if let Ok(delegates) = serde_json::from_str::<Vec<RegistrationRecordJSON>>(data) {
// Iterate through the delegates
for delegate in delegates.iter() {
// Convert fields to bounded vecs
let name_result = string_to_bounded_vec(&delegate.name);
let desc_result = string_to_bounded_vec(&delegate.description);
let url_result = string_to_bounded_vec(&delegate.url);
let hotkey: AccountId32 = match AccountId32::from_ss58check(&delegate.address) {
Ok(account) => account,
Err(_) => {
log::warn!(
"Invalid SS58 address: {:?}. Skipping this delegate.",
delegate.address
);
continue;
}
};
let decoded_hotkey: T::AccountId = match T::AccountId::decode(&mut hotkey.as_ref()) {
Ok(decoded) => decoded,
Err(e) => {
log::warn!("Failed to decode hotkey: {:?}. Skipping this delegate.", e);
continue;
}
};
log::info!("Hotkey unwrapped: {:?}", decoded_hotkey);

// If we should continue with real values.
let mut name: BoundedVec<u8, ConstU32<1024>> = BoundedVec::default();
let mut description: BoundedVec<u8, ConstU32<1024>> = BoundedVec::default();
let mut url: BoundedVec<u8, ConstU32<1024>> = BoundedVec::default();
if let Ok(n) = name_result {
name = n;
}
if let Ok(d) = desc_result {
description = d;
}
if let Ok(u) = url_result {
url = u;
}

// Unwrap the real values.
let image: BoundedVec<u8, ConstU32<1024>> = BoundedVec::default();
let discord: BoundedVec<u8, ConstU32<1024>> = BoundedVec::default();
let additional: BoundedVec<u8, ConstU32<1024>> = BoundedVec::default();

// Create the chain identity.
let identity = ChainIdentityOf {
name: name.into(),
url: url.into(),
image: image.into(),
discord: discord.into(),
description: description.into(),
additional: additional.into(),
};

// Log the identity details
log::info!("Setting identity for hotkey: {:?}", hotkey);
log::info!("Name: {:?}", String::from_utf8_lossy(&identity.name));
log::info!("URL: {:?}", String::from_utf8_lossy(&identity.url));
log::info!("Image: {:?}", String::from_utf8_lossy(&identity.image));
log::info!("Discord: {:?}", String::from_utf8_lossy(&identity.discord));
log::info!(
"Description: {:?}",
String::from_utf8_lossy(&identity.description)
);
log::info!(
"Additional: {:?}",
String::from_utf8_lossy(&identity.additional)
);

// Check validation.
let total_length = identity
.name
.len()
.saturating_add(identity.url.len())
.saturating_add(identity.image.len())
.saturating_add(identity.discord.len())
.saturating_add(identity.description.len())
.saturating_add(identity.additional.len());
let is_valid: bool = total_length <= 256 + 256 + 1024 + 256 + 1024 + 1024
&& identity.name.len() <= 256
&& identity.url.len() <= 256
&& identity.image.len() <= 1024
&& identity.discord.len() <= 256
&& identity.description.len() <= 1024
&& identity.additional.len() <= 1024;
if !is_valid {
continue;
}

// Get the owning coldkey.
let coldkey = Owner::<T>::get(decoded_hotkey.clone());
weight = weight.saturating_add(T::DbWeight::get().reads(1));

// Sink into the map.
Identities::<T>::insert(coldkey.clone(), identity.clone());
weight = weight.saturating_add(T::DbWeight::get().writes(1));
}
}
// Mark the migration as completed
HasMigrationRun::<T>::insert(&migration_name, true);
weight = weight.saturating_add(T::DbWeight::get().writes(1));

log::info!(
"Migration '{:?}' completed. Storage version set to 7.",
String::from_utf8_lossy(&migration_name)
);

// Return the migration weight.
weight
}
1 change: 1 addition & 0 deletions pallets/subtensor/src/migrations/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use super::*;
pub mod migrate_chain_identity;
pub mod migrate_create_root_network;
pub mod migrate_delete_subnet_21;
pub mod migrate_delete_subnet_3;
Expand Down
Loading

0 comments on commit dd938c2

Please sign in to comment.