diff --git a/runtime/src/precompiles/metagraph.rs b/runtime/src/precompiles/metagraph.rs new file mode 100644 index 000000000..28bf664b8 --- /dev/null +++ b/runtime/src/precompiles/metagraph.rs @@ -0,0 +1,360 @@ +extern crate alloc; +use crate::precompiles::{get_method_id, get_slice}; +use crate::Runtime; +use fp_evm::{ + ExitError, ExitSucceed, PrecompileFailure, PrecompileHandle, PrecompileOutput, PrecompileResult, +}; +use sp_core::{ByteArray, U256}; +use sp_std::vec; +pub const METAGRAPH_PRECOMPILE_INDEX: u64 = 2050; +pub struct MetagraphPrecompile; + +const NO_HOTKEY: &str = "no hotkey"; + +impl MetagraphPrecompile { + pub fn execute(handle: &mut impl PrecompileHandle) -> PrecompileResult { + let txdata = handle.input(); + let method_id = get_slice(txdata, 0, 4)?; + let method_input = txdata + .get(4..) + .map_or_else(vec::Vec::new, |slice| slice.to_vec()); // Avoiding borrowing conflicts + + match method_id { + id if id == get_method_id("getUidCount(uint16)") => Self::get_uid_count(&method_input), + id if id == get_method_id("getStake(uint16,uint16)") => Self::get_stake(&method_input), + id if id == get_method_id("getRank(uint16,uint16)") => Self::get_rank(&method_input), + id if id == get_method_id("getTrust(uint16,uint16)") => Self::get_trust(&method_input), + id if id == get_method_id("getConsensus(uint16,uint16)") => { + Self::get_consensus(&method_input) + } + id if id == get_method_id("getIncentive(uint16,uint16)") => { + Self::get_incentive(&method_input) + } + id if id == get_method_id("getDividends(uint16,uint16)") => { + Self::get_dividends(&method_input) + } + id if id == get_method_id("getEmission(uint16,uint16)") => { + Self::get_emission(&method_input) + } + id if id == get_method_id("getVtrust(uint16,uint16)") => { + Self::get_vtrust(&method_input) + } + id if id == get_method_id("getValidatorStatus(uint16,uint16)") => { + Self::get_validator_status(&method_input) + } + id if id == get_method_id("getLastUpdate(uint16,uint16)") => { + Self::get_last_update(&method_input) + } + id if id == get_method_id("getIsActive(uint16,uint16)") => { + Self::get_is_active(&method_input) + } + id if id == get_method_id("getAxon(uint16,uint16)") => Self::get_axon(&method_input), + id if id == get_method_id("getHotkey(uint16,uint16)") => { + Self::get_hotkey(&method_input) + } + id if id == get_method_id("getColdkey(uint16,uint16)") => { + Self::get_coldkey(&method_input) + } + + _ => Err(PrecompileFailure::Error { + exit_status: ExitError::InvalidRange, + }), + } + } + + fn get_uid_count(data: &[u8]) -> PrecompileResult { + let netuid = Self::parse_netuid(data)?; + let uid_count = pallet_subtensor::SubnetworkN::::get(netuid); + + let uid_count_u256 = U256::from(uid_count); + let mut result = [0_u8; 32]; + U256::to_big_endian(&uid_count_u256, &mut result); + + Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + output: result.into(), + }) + } + + fn get_stake(data: &[u8]) -> PrecompileResult { + let netuid = Self::parse_netuid(data)?; + let uid = Self::parse_uid(get_slice(data, 32, 64)?)?; + let hotkey = pallet_subtensor::Pallet::::get_hotkey_for_net_and_uid(netuid, uid) + .map_err(|_| PrecompileFailure::Error { + exit_status: ExitError::InvalidRange, + })?; + + let stake = pallet_subtensor::TotalHotkeyStake::::get(&hotkey); + let result_u256 = U256::from(stake); + let mut result = [0_u8; 32]; + U256::to_big_endian(&result_u256, &mut result); + + Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + output: result.into(), + }) + } + + fn get_rank(data: &[u8]) -> PrecompileResult { + let netuid = Self::parse_netuid(data)?; + let uid = Self::parse_uid(get_slice(data, 32, 64)?)?; + let rank = pallet_subtensor::Pallet::::get_rank_for_uid(netuid, uid); + + let result_u256 = U256::from(rank); + let mut result = [0_u8; 32]; + U256::to_big_endian(&result_u256, &mut result); + + Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + output: result.into(), + }) + } + + fn get_trust(data: &[u8]) -> PrecompileResult { + let netuid = Self::parse_netuid(data)?; + let uid = Self::parse_uid(get_slice(data, 32, 64)?)?; + + let trust = pallet_subtensor::Pallet::::get_trust_for_uid(netuid, uid); + + let result_u256 = U256::from(trust); + let mut result = [0_u8; 32]; + U256::to_big_endian(&result_u256, &mut result); + + Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + output: result.into(), + }) + } + + fn get_consensus(data: &[u8]) -> PrecompileResult { + let netuid = Self::parse_netuid(data)?; + let uid = Self::parse_uid(get_slice(data, 32, 64)?)?; + + let consensus = pallet_subtensor::Pallet::::get_consensus_for_uid(netuid, uid); + + let result_u256 = U256::from(consensus); + let mut result = [0_u8; 32]; + U256::to_big_endian(&result_u256, &mut result); + + Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + output: result.into(), + }) + } + + fn get_incentive(data: &[u8]) -> PrecompileResult { + let netuid = Self::parse_netuid(data)?; + let uid = Self::parse_uid(get_slice(data, 32, 64)?)?; + + let incentive = pallet_subtensor::Pallet::::get_incentive_for_uid(netuid, uid); + + let result_u256 = U256::from(incentive); + let mut result = [0_u8; 32]; + U256::to_big_endian(&result_u256, &mut result); + + Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + output: result.into(), + }) + } + + fn get_dividends(data: &[u8]) -> PrecompileResult { + let netuid = Self::parse_netuid(data)?; + let uid = Self::parse_uid(get_slice(data, 32, 64)?)?; + + let dividends = pallet_subtensor::Pallet::::get_dividends_for_uid(netuid, uid); + + let result_u256 = U256::from(dividends); + let mut result = [0_u8; 32]; + U256::to_big_endian(&result_u256, &mut result); + + Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + output: result.into(), + }) + } + + fn get_emission(data: &[u8]) -> PrecompileResult { + let netuid = Self::parse_netuid(data)?; + let uid = Self::parse_uid(get_slice(data, 32, 64)?)?; + + let emission = pallet_subtensor::Pallet::::get_emission_for_uid(netuid, uid); + + let result_u256 = U256::from(emission); + let mut result = [0_u8; 32]; + U256::to_big_endian(&result_u256, &mut result); + + Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + output: result.into(), + }) + } + + fn get_vtrust(data: &[u8]) -> PrecompileResult { + let netuid = Self::parse_netuid(data)?; + let uid = Self::parse_uid(get_slice(data, 32, 64)?)?; + + let vtrust = pallet_subtensor::Pallet::::get_validator_trust_for_uid(netuid, uid); + + let result_u256 = U256::from(vtrust); + let mut result = [0_u8; 32]; + U256::to_big_endian(&result_u256, &mut result); + + Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + output: result.into(), + }) + } + + fn get_validator_status(data: &[u8]) -> PrecompileResult { + let netuid = Self::parse_netuid(data)?; + let uid = Self::parse_uid(get_slice(data, 32, 64)?)?; + + let validator_permit = + pallet_subtensor::Pallet::::get_validator_permit_for_uid(netuid, uid); + + let result_u256 = if validator_permit { + U256::from(1) + } else { + U256::from(0) + }; + let mut result = [0_u8; 32]; + U256::to_big_endian(&result_u256, &mut result); + + Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + output: result.into(), + }) + } + + fn get_last_update(data: &[u8]) -> PrecompileResult { + let netuid = Self::parse_netuid(data)?; + let uid = Self::parse_uid(get_slice(data, 32, 64)?)?; + + let last_update = pallet_subtensor::Pallet::::get_last_update_for_uid(netuid, uid); + + let result_u256 = U256::from(last_update); + let mut result = [0_u8; 32]; + U256::to_big_endian(&result_u256, &mut result); + + Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + output: result.into(), + }) + } + + fn get_is_active(data: &[u8]) -> PrecompileResult { + let netuid = Self::parse_netuid(data)?; + let uid = Self::parse_uid(get_slice(data, 32, 64)?)?; + + let active = pallet_subtensor::Pallet::::get_active_for_uid(netuid, uid); + + let result_u256 = if active { U256::from(1) } else { U256::from(0) }; + let mut result = [0_u8; 32]; + U256::to_big_endian(&result_u256, &mut result); + + Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + output: result.into(), + }) + } + + fn get_axon(data: &[u8]) -> PrecompileResult { + let netuid = Self::parse_netuid(data)?; + let uid = Self::parse_uid(get_slice(data, 32, 64)?)?; + + let hotkey = pallet_subtensor::Pallet::::get_hotkey_for_net_and_uid(netuid, uid) + .map_err(|_| PrecompileFailure::Error { + exit_status: ExitError::Other(sp_version::Cow::Borrowed(NO_HOTKEY)), + })?; + + let axon = pallet_subtensor::Pallet::::get_axon_info(netuid, &hotkey); + + let mut block_result = [0_u8; 32]; + U256::to_big_endian(&U256::from(axon.block), &mut block_result); + + let mut version_result = [0_u8; 32]; + U256::to_big_endian(&U256::from(axon.version), &mut version_result); + + let mut ip_result = [0_u8; 32]; + U256::to_big_endian(&U256::from(axon.ip), &mut ip_result); + + let mut port_result = [0_u8; 32]; + U256::to_big_endian(&U256::from(axon.port), &mut port_result); + + let mut ip_type_result = [0_u8; 32]; + U256::to_big_endian(&U256::from(axon.ip_type), &mut ip_type_result); + + let mut protocol_result = [0_u8; 32]; + U256::to_big_endian(&U256::from(axon.protocol), &mut protocol_result); + + let mut result = [0_u8; 192]; + result[..32].copy_from_slice(&block_result); + result[32..64].copy_from_slice(&version_result); + result[64..96].copy_from_slice(&ip_result); + result[96..128].copy_from_slice(&port_result); + result[128..160].copy_from_slice(&ip_type_result); + result[160..].copy_from_slice(&protocol_result); + + Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + output: result.into(), + }) + } + + fn get_hotkey(data: &[u8]) -> PrecompileResult { + let netuid = Self::parse_netuid(data)?; + let uid = Self::parse_uid(get_slice(data, 32, 64)?)?; + + let hotkey = pallet_subtensor::Pallet::::get_hotkey_for_net_and_uid(netuid, uid) + .map_err(|_| PrecompileFailure::Error { + exit_status: ExitError::InvalidRange, + })?; + + Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + output: hotkey.as_slice().into(), + }) + } + + fn get_coldkey(data: &[u8]) -> PrecompileResult { + let netuid = Self::parse_netuid(data)?; + let uid = Self::parse_uid(get_slice(data, 32, 64)?)?; + + let hotkey = pallet_subtensor::Pallet::::get_hotkey_for_net_and_uid(netuid, uid) + .map_err(|_| PrecompileFailure::Error { + exit_status: ExitError::InvalidRange, + })?; + + let coldkey = pallet_subtensor::Owner::::get(&hotkey); + + Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + output: coldkey.as_slice().into(), + }) + } + + fn parse_netuid(data: &[u8]) -> Result { + if data.len() < 32 { + return Err(PrecompileFailure::Error { + exit_status: ExitError::InvalidRange, + }); + } + let mut netuid = [0u8; 2]; + netuid.copy_from_slice(get_slice(data, 30, 32)?); + let result = u16::from_be_bytes(netuid); + Ok(result) + } + + fn parse_uid(data: &[u8]) -> Result { + if data.len() < 32 { + return Err(PrecompileFailure::Error { + exit_status: ExitError::InvalidRange, + }); + } + let mut uid = [0u8; 2]; + uid.copy_from_slice(get_slice(data, 30, 32)?); + let result = u16::from_be_bytes(uid); + Ok(result) + } +} diff --git a/runtime/src/precompiles/mod.rs b/runtime/src/precompiles/mod.rs index 22f2a4881..e13516e95 100644 --- a/runtime/src/precompiles/mod.rs +++ b/runtime/src/precompiles/mod.rs @@ -13,10 +13,12 @@ use pallet_evm_precompile_simple::{ECRecover, ECRecoverPublicKey, Identity, Ripe // Include custom precompiles mod balance_transfer; mod ed25519; +mod metagraph; mod staking; use balance_transfer::*; use ed25519::*; +use metagraph::*; use staking::*; pub struct FrontierPrecompiles(PhantomData); @@ -37,7 +39,7 @@ where pub fn new() -> Self { Self(Default::default()) } - pub fn used_addresses() -> [H160; 10] { + pub fn used_addresses() -> [H160; 11] { [ hash(1), hash(2), @@ -49,6 +51,7 @@ where hash(EDVERIFY_PRECOMPILE_INDEX), hash(BALANCE_TRANSFER_INDEX), hash(STAKING_PRECOMPILE_INDEX), + hash(METAGRAPH_PRECOMPILE_INDEX), ] } } @@ -73,6 +76,10 @@ where Some(BalanceTransferPrecompile::execute(handle)) } a if a == hash(STAKING_PRECOMPILE_INDEX) => Some(StakingPrecompile::execute(handle)), + a if a == hash(METAGRAPH_PRECOMPILE_INDEX) => { + Some(MetagraphPrecompile::execute(handle)) + } + _ => None, } } diff --git a/runtime/src/precompiles/solidity/metagraph.abi b/runtime/src/precompiles/solidity/metagraph.abi new file mode 100644 index 000000000..eb4b9be6a --- /dev/null +++ b/runtime/src/precompiles/solidity/metagraph.abi @@ -0,0 +1,389 @@ +[ + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + } + ], + "name": "getAxon", + "outputs": [ + { + "components": [ + { + "internalType": "uint64", + "name": "block", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "version", + "type": "uint32" + }, + { + "internalType": "uint128", + "name": "ip", + "type": "uint128" + }, + { + "internalType": "uint16", + "name": "port", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "ip_type", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "protocol", + "type": "uint8" + } + ], + "internalType": "struct AxonInfo", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + } + ], + "name": "getColdkey", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + } + ], + "name": "getConsensus", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + } + ], + "name": "getDividends", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + } + ], + "name": "getEmission", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + } + ], + "name": "getHotkey", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + } + ], + "name": "getIncentive", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + } + ], + "name": "getIsActive", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + } + ], + "name": "getLastUpdate", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + } + ], + "name": "getRank", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + } + ], + "name": "getStake", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + } + ], + "name": "getTrust", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getUidCount", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + } + ], + "name": "getValidatorStatus", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + } + ], + "name": "getVtrust", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/runtime/src/precompiles/solidity/metagraph.sol b/runtime/src/precompiles/solidity/metagraph.sol new file mode 100644 index 000000000..3a19281a5 --- /dev/null +++ b/runtime/src/precompiles/solidity/metagraph.sol @@ -0,0 +1,134 @@ +pragma solidity ^0.8.0; + +address constant IMetagraph_ADDRESS = 0x0000000000000000000000000000000000000802; + +struct AxonInfo { + uint64 block; + uint32 version; + uint128 ip; + uint16 port; + uint8 ip_type; + uint8 protocol; +} + +interface IMetagraph { + + /** + * @dev Returns the count of unique identifiers (UIDs) associated with a given network identifier (netuid). + * @param netuid The network identifier for which to retrieve the UID count. + * @return The count of UIDs associated with the specified netuid. + */ + function getUidCount(uint16 netuid) external view returns (uint16); + + /** + * @dev Retrieves the stake amount associated with a given network identifier (netuid) and unique identifier (uid). + * @param netuid The network identifier for which to retrieve the stake. + * @param uid The unique identifier for which to retrieve the stake. + * @return The stake amount associated with the specified netuid and uid. + */ + function getStake(uint16 netuid, uint16 uid) external view returns (uint64); + + /** + * @dev Retrieves the rank of a node with a given network identifier (netuid) and unique identifier (uid). + * @param netuid The network identifier for which to retrieve the rank. + * @param uid The unique identifier for which to retrieve the rank. + * @return The rank of the node with the specified netuid and uid. + */ + function getRank(uint16 netuid, uint16 uid) external view returns (uint16); + + /** + * @dev Retrieves the trust value of a node with a given network identifier (netuid) and unique identifier (uid). + * @param netuid The network identifier for which to retrieve the trust value. + * @param uid The unique identifier for which to retrieve the trust value. + * @return The trust value of the node with the specified netuid and uid. + */ + function getTrust(uint16 netuid, uint16 uid) external view returns (uint16); + + /** + * @dev Retrieves the consensus value of a node with a given network identifier (netuid) and unique identifier (uid). + * @param netuid The network identifier for which to retrieve the consensus value. + * @param uid The unique identifier for which to retrieve the consensus value. + * @return The consensus value of the node with the specified netuid and uid. + */ + function getConsensus(uint16 netuid, uint16 uid) external view returns (uint16); + + /** + * @dev Retrieves the incentive value of a node with a given network identifier (netuid) and unique identifier (uid). + * @param netuid The network identifier for which to retrieve the incentive value. + * @param uid The unique identifier for which to retrieve the incentive value. + * @return The incentive value of the node with the specified netuid and uid. + */ + function getIncentive(uint16 netuid, uint16 uid) external view returns (uint16); + + /** + * @dev Retrieves the dividend value of a node with a given network identifier (netuid) and unique identifier (uid). + * @param netuid The network identifier for which to retrieve the dividend value. + * @param uid The unique identifier for which to retrieve the dividend value. + * @return The dividend value of the node with the specified netuid and uid. + */ + function getDividends(uint16 netuid, uint16 uid) external view returns (uint16); + + /** + * @dev Retrieves the emission value of a node with a given network identifier (netuid) and unique identifier (uid). + * @param netuid The network identifier for which to retrieve the emission value. + * @param uid The unique identifier for which to retrieve the emission value. + * @return The emission value of the node with the specified netuid and uid. + */ + function getEmission(uint16 netuid, uint16 uid) external view returns (uint64); + + /** + * @dev Retrieves the v-trust value of a node with a given network identifier (netuid) and unique identifier (uid). + * @param netuid The network identifier for which to retrieve the v-trust value. + * @param uid The unique identifier for which to retrieve the v-trust value. + * @return The v-trust value of the node with the specified netuid and uid. + */ + function getVtrust(uint16 netuid, uint16 uid) external view returns (uint16); + + /** + * @dev Checks the validator status of a node with a given network identifier (netuid) and unique identifier (uid). + * @param netuid The network identifier for which to check the validator status. + * @param uid The unique identifier for which to check the validator status. + * @return Returns true if the node is a validator, false otherwise. + */ + function getValidatorStatus(uint16 netuid, uint16 uid) external view returns (bool); + + /** + * @dev Retrieves the last update timestamp of a node with a given network identifier (netuid) and unique identifier (uid). + * @param netuid The network identifier for which to retrieve the last update timestamp. + * @param uid The unique identifier for which to retrieve the last update timestamp. + * @return The last update timestamp of the node with the specified netuid and uid. + */ + function getLastUpdate(uint16 netuid, uint16 uid) external view returns (uint64); + + /** + * @dev Checks if a node with a given network identifier (netuid) and unique identifier (uid) is active. + * @param netuid The network identifier for which to check the node's activity. + * @param uid The unique identifier for which to check the node's activity. + * @return Returns true if the node is active, false otherwise. + */ + function getIsActive(uint16 netuid, uint16 uid) external view returns (bool); + + /** + * @dev Retrieves the axon information of a node with a given network identifier (netuid) and unique identifier (uid). + * @param netuid The network identifier for which to retrieve the axon information. + * @param uid The unique identifier for which to retrieve the axon information. + * @return The axon information of the node with the specified netuid and uid. + */ + function getAxon(uint16 netuid, uint16 uid) external view returns (AxonInfo memory); + + /** + * @dev Retrieves the hotkey of a node with a given network identifier (netuid) and unique identifier (uid). + * @param netuid The network identifier for which to retrieve the hotkey. + * @param uid The unique identifier for which to retrieve the hotkey. + * @return The hotkey of the node with the specified netuid and uid. + */ + function getHotkey(uint16 netuid, uint16 uid) external view returns (bytes32); + + /** + * @dev Retrieves the coldkey of a node with a given network identifier (netuid) and unique identifier (uid). + * @param netuid The network identifier for which to retrieve the coldkey. + * @param uid The unique identifier for which to retrieve the coldkey. + * @return The coldkey of the node with the specified netuid and uid. + */ + function getColdkey(uint16 netuid, uint16 uid) external view returns (bytes32); +}