This document describes validator-specific operations for interacting with the Bittensor network, including weight setting, staking, registration, and network serving.
- All on-chain balances and stake amounts are RAO (
u128). TAO is for display only. Convert explicitly. - Commit-reveal must match Subtensor runtime:
uids/weightsasVec<u16>,salt: Vec<u16>, andversion_keymust matchWeightsVersionfrom chain. - CRv4 timelock encryption (
commit_timelocked_weights) is the default whenCommitRevealVersion >= 4and uses chainDrand.LastStoredRoundto compute reveal rounds. - See
docs/parity_checklist.mdfor gaps and required updates.
Set validator weights for a subnet. This is the final step after commit-reveal.
pub async fn set_weights(
client: &BittensorClient,
signer: &PairSigner<DefaultConfig, Pair>,
netuid: u16,
uids: Vec<u16>,
weights: Vec<u16>,
version_key: u64
) -> Result<()>Parameters:
client: Bittensor client instancesigner: Key pair signernetuid: Subnet IDuids: Vector of u16 UIDsweights: Vector of u16 weights (scaled by u16::MAX)
Returns:
Result<()>: Success or error
Example:
use bittensor_rs::validator::set_weights;
use bittensor_rs::utils::normalize_weights;
let (uid_vals, weight_vals) = normalize_weights(&uids, &weights)?;
set_weights(&client, &signer, netuid, uid_vals, weight_vals, version_key).await?;Commit weights using a commit-reveal scheme.
pub async fn commit_weights(
client: &BittensorClient,
signer: &PairSigner<DefaultConfig, Pair>,
netuid: u16,
commitment: [u8; 32]
) -> Result<()>Parameters:
client: Bittensor client instancesigner: Key pair signernetuid: Subnet IDcommitment: 32-byte commitment hash
Returns:
Result<()>: Success or error
Example:
use bittensor_rs::validator::commit_weights;
use bittensor_rs::utils::commit_weights_hash;
let commitment = commit_weights_hash(&uids, &weights, &salt)?;
commit_weights(&client, &signer, netuid, commitment).await?;Reveal weights after committing.
pub async fn reveal_weights(
client: &BittensorClient,
signer: &PairSigner<DefaultConfig, Pair>,
netuid: u16,
uids: Vec<u16>,
weights: Vec<u16>,
salt: Vec<u16>
) -> Result<()>Parameters:
client: Bittensor client instancesigner: Key pair signernetuid: Subnet IDuids: Vector of u16 UIDsweights: Vector of u16 weightssalt: Salt used in commitment
Returns:
Result<()>: Success or error
Example:
use bittensor_rs::validator::reveal_weights;
reveal_weights(&client, &signer, netuid, uid_vals, weight_vals, salt).await?;Set mechanism-specific weights.
pub async fn set_mechanism_weights(
client: &BittensorClient,
signer: &PairSigner<DefaultConfig, Pair>,
netuid: u16,
mechanism_id: u8,
uids: Vec<u16>,
weights: Vec<u16>
) -> Result<()>Commit mechanism weights.
pub async fn commit_mechanism_weights(
client: &BittensorClient,
signer: &PairSigner<DefaultConfig, Pair>,
netuid: u16,
mechanism_id: u8,
commitment: [u8; 32]
) -> Result<()>Reveal mechanism weights.
pub async fn reveal_mechanism_weights(
client: &BittensorClient,
signer: &PairSigner<DefaultConfig, Pair>,
netuid: u16,
mechanism_id: u8,
uids: Vec<u16>,
weights: Vec<u16>,
salt: Vec<u16>
) -> Result<()>CRv4 uses timelock encryption and requires only a commit; the chain auto-reveals when drand data is available. Reveal rounds must be computed relative to the on-chain Drand.LastStoredRound, tempo, and RevealPeriodEpochs.
use bittensor_rs::crv4::prepare_and_commit_crv4_weights;
let commit = prepare_and_commit_crv4_weights(
&client,
&signer,
netuid,
&uids,
&weights,
version_key,
ExtrinsicWait::Finalized,
).await?;Add stake to a neuron on a specific subnet.
pub async fn add_stake(
client: &BittensorClient,
signer: &PairSigner<DefaultConfig, Pair>,
hotkey: &AccountId32,
netuid: u16,
amount: Rao
) -> Result<()>Parameters:
client: Bittensor client instancesigner: Key pair signerhotkey: Hotkey to stake tonetuid: Subnet IDamount: Amount to stake in RAO
Example:
use bittensor_rs::validator::add_stake;
use bittensor_rs::utils::tao_to_rao;
use bittensor_rs::Rao;
let amount_rao = Rao::from(tao_to_rao(100.0)); // 100 TAO
add_stake(&client, &signer, &hotkey, netuid, amount_rao).await?;Unstake from a neuron on a specific subnet.
pub async fn unstake(
pub async fn unstake(
client: &BittensorClient,
signer: &PairSigner<DefaultConfig, Pair>,
hotkey: &AccountId32,
netuid: u16,
amount: Rao
) -> Result<()>Move stake between subnets.
pub async fn move_stake(
pub async fn move_stake(
client: &BittensorClient,
signer: &PairSigner<DefaultConfig, Pair>,
hotkey: &AccountId32,
origin_netuid: u16,
destination_netuid: u16,
amount: Rao
) -> Result<()>Swap stake between hotkeys.
pub async fn swap_stake(
pub async fn swap_stake(
client: &BittensorClient,
signer: &PairSigner<DefaultConfig, Pair>,
hotkey: &AccountId32,
origin_netuid: u16,
destination_netuid: u16,
amount: Rao
) -> Result<()>Transfer stake to another coldkey.
pub async fn transfer_stake(
client: &BittensorClient,
signer: &PairSigner<DefaultConfig, Pair>,
destination_coldkey: &AccountId32,
hotkey: &AccountId32,
origin_netuid: u16,
destination_netuid: u16,
amount: Rao
) -> Result<()>Query stake amount for a coldkey-hotkey pair on a subnet.
pub async fn get_stake(
client: &BittensorClient,
coldkey: &AccountId32,
hotkey: &AccountId32,
netuid: u16
) -> Result<u128>Register a neuron on a subnet.
pub async fn register(
client: &BittensorClient,
signer: &PairSigner<DefaultConfig, Pair>,
netuid: u16
) -> Result<()>
pub async fn register(
client: &BittensorClient,
signer: &PairSigner<DefaultConfig, Pair>,
netuid: u16
) -> Result<()>Example:
use bittensor_rs::validator::register;
register(&client, &signer, 1).await?;Register using burned TAO (registration cost).
pub async fn burned_register(
client: &BittensorClient,
signer: &PairSigner<DefaultConfig, Pair>,
netuid: u16,
hotkey: &AccountId32
) -> Result<()>register(&client, &signer, 1).await?;
### is_registered
Check if a hotkey is registered on a subnet.
```rust
pub async fn is_registered(
client: &BittensorClient,
hotkey: &AccountId32,
netuid: u16
) -> Result<bool>
Serve axon information (TCP).
pub async fn serve_axon(
client: &BittensorClient,
signer: &PairSigner<DefaultConfig, Pair>,
netuid: u16,
version: u32,
ip: u128,
port: u16,
ip_type: u8
) -> Result<()>Parameters:
version: Protocol versionip: IP address encoded as u128port: Port numberip_type: 4 for IPv4, 6 for IPv6
Serve axon information with TLS.
pub async fn serve_axon_tls(
client: &BittensorClient,
signer: &PairSigner<DefaultConfig, Pair>,
netuid: u16,
version: u32,
ip: u128,
port: u16,
ip_type: u8
) -> Result<()>Increase delegate take percentage.
pub async fn increase_take(
client: &BittensorClient,
signer: &PairSigner<DefaultConfig, Pair>,
hotkey: &AccountId32,
take: u16
) -> Result<()>Decrease delegate take percentage.
pub async fn decrease_take(
client: &BittensorClient,
signer: &PairSigner<DefaultConfig, Pair>,
hotkey: &AccountId32,
take: u16
) -> Result<()>Enable delegate status by setting an initial take.
pub async fn become_delegate(
client: &BittensorClient,
signer: &PairSigner<DefaultConfig, Pair>,
hotkey: &AccountId32,
take: u16
) -> Result<()>Submit a governance proposal via the Triumvirate.
pub async fn propose(
client: &BittensorClient,
signer: &PairSigner<DefaultConfig, Pair>,
call_data: Vec<u8>
) -> Result<()>Close a governance proposal with a weight bound.
pub async fn close_proposal(
client: &BittensorClient,
signer: &PairSigner<DefaultConfig, Pair>,
proposal_hash: &[u8; 32],
proposal_index: u32,
weight_bound: u64
) -> Result<()>pub async fn decrease_take( client: &BittensorClient, signer: &PairSigner<DefaultConfig, Pair>, hotkey: &AccountId32, take: u16 ) -> Result<()>
## Root Operations
Root subnet operations for managing validator permissions and network governance.
See the `root` module for detailed root operations.
## Child Operations
Operations for managing child subnets and relationships.
See the `children` module for detailed child subnet operations.
## Error Handling
All validator operations return `Result<()>` types. Handle errors appropriately:
```rust
match set_weights(&client, &signer, netuid, uid_vals, weight_vals, version_key).await {
Ok(()) => println!("Weights set successfully"),
Err(e) => eprintln!("Error setting weights: {}", e),
}
All validator operations require transaction fees. Ensure sufficient balance before executing operations.
Import validator operations from the main crate:
use bittensor_rs::validator::{
set_weights, commit_weights, reveal_weights,
add_stake, unstake, move_stake,
register, is_registered,
serve_axon, serve_axon_tls,
increase_take, decrease_take, become_delegate,
propose, close_proposal
};- Weight Setting: Use commit-reveal scheme to hide weights until reveal phase
- CRv4: Prefer CRv4 timelock when enabled on chain (no manual reveal needed)
- Rate Limits: Respect weights rate limits and tempo
- RAO Units: Keep all on-chain values in RAO
- Documentation: Track parity updates in
docs/parity_checklist.md