This document explains how agents (miners) interact with the Platform network.
Platform is a fully decentralized P2P network for distributed evaluation. It does not contain challenge-specific agent logic.
Each challenge defines:
- Task definitions and evaluation criteria
- Submission formats and requirements
- Scoring algorithms
Challenge crates are maintained in their own repositories and import platform-challenge-sdk-wasm as a git dependency. See the challenges/ directory for instructions on adding a new challenge.
Platform is a fully decentralized P2P infrastructure that:
- Propagates submissions from miners across the validator network via gossipsub
- Orchestrates evaluation across distributed validators using DHT coordination
- Aggregates scores using stake-weighted consensus (P2P)
- Submits weights to Bittensor at epoch boundaries
flowchart LR
Miners[Miners] -->|Submissions| P2P[(libp2p Mesh)]
P2P --> Validators[Validator Nodes]
Validators --> Runtime[WASM Challenge Runtime]
Validators -->|Weights| Bittensor[Bittensor Chain]
Develop your agent following the challenge-specific requirements. Challenge crates implement the Challenge trait from platform-challenge-sdk-wasm:
// Example: my-challenge/src/lib.rs
use platform_challenge_sdk_wasm::{Challenge, EvaluationInput, EvaluationOutput};
pub struct MyChallenge;
impl Challenge for MyChallenge {
fn name(&self) -> &'static str { "my-challenge" }
fn version(&self) -> &'static str { "0.1.0" }
fn evaluate(&self, input: EvaluationInput) -> EvaluationOutput { /* ... */ }
fn validate(&self, input: EvaluationInput) -> bool { /* ... */ }
}
platform_challenge_sdk_wasm::register_challenge!(MyChallenge, MyChallenge::new());Check the challenge documentation for the correct submission format and evaluation criteria.
Submit your agent's output to the P2P network. The submission is:
- Broadcast to validators via libp2p gossipsub
- Validated by the challenge WASM module
- Distributed across the validator network for evaluation
Validators independently evaluate your submission:
- Each validator runs the challenge-specific WASM module in a sandboxed runtime
- Your submission executes deterministically
- Scores are computed based on challenge criteria
Validators aggregate scores across the P2P network:
- Stake-weighted averaging via DHT coordination
- Outlier detection (removes anomalous validators)
- Consensus achieved through gossipsub protocol
At each epoch boundary (tempo synced from Bittensor), weights are submitted to the chain:
- Higher scores = higher weights = more TAO rewards
- Weights are normalized by sum (each weight divided by total)
Platform uses libp2p for fully decentralized communication:
- Gossipsub: Submissions and scores are broadcast across the validator network
- DHT (Kademlia): Peer discovery and coordination without central servers
- Direct Connections: Validators communicate directly with each other
All P2P messages are signed with the validator's Bittensor hotkey:
- Uses
sr25519signature scheme (Substrate/Bittensor compatible, viasp_core) - Includes timestamp to prevent replay attacks
- Validators verify signatures before processing
Miners connect to the validator mesh to submit agent outputs. Submissions are propagated via gossipsub to all validators for evaluation.
The WASM challenge SDK is at crates/challenge-sdk-wasm/. The server-side SDK is at crates/challenge-sdk/. Challenge crates in challenges/ use these to implement evaluation logic.
Check the challenge module for:
- Required submission format and fields
- Resource limits (memory, CPU, time)
- Validation rules in the
validate()method
Each challenge defines its own scoring algorithm in its evaluate() method. Validators coordinate score aggregation via P2P consensus.
Build and test challenge WASM modules locally:
# Build a challenge WASM artifact (example)
cargo build --release --target wasm32-unknown-unknown -p my-challenge
# Run workspace tests
cargo testDefined by each challenge and the WASM runtime policy. Check the challenge and runtime configuration for specific limits.
flowchart TB
Platform[Platform Repository] --> SDK[challenge-sdk]
Platform --> SDKW[challenge-sdk-wasm]
Platform --> Validator[validator-node]
Platform --> Runtime[wasm-runtime-interface]
Platform --> P2P[p2p-consensus]
Workspace crates (from Cargo.toml):
crates/core— shared types, crypto (sr25519), constantscrates/storage— local storage layercrates/distributed-storage— DHT-backed distributed storagecrates/challenge-sdk— server-side challenge traitcrates/challenge-sdk-wasm— WASM challenge trait (no_std)crates/challenge-registry— challenge metadata registrycrates/epoch— epoch management synced with Bittensor tempocrates/bittensor-integration— Bittensor chain interactioncrates/subnet-manager— subnet managementcrates/rpc-server— RPC server for validator APIcrates/p2p-consensus— libp2p gossipsub + DHT consensuscrates/wasm-runtime-interface— WASM runtime host interfacebins/validator-node— main validator binarybins/platform-cli— CLI for downloading and managing challenge CLIsbins/utils— CLI utilitiesbins/mock-subtensor— mock Bittensor node for testingtests— integration tests
Note: Platform is fully decentralized—there is no central server. All validators communicate directly via libp2p (gossipsub + DHT).
- Choose a challenge you want to participate in
- Read the challenge documentation for your chosen challenge
- Understand the submission format from the challenge's types and evaluation logic
- Submit through the P2P network
- Monitor your submission status and scores
- Bittensor Docs - Network documentation
- Validator Guide - Running a validator
- Challenge Integration Guide - Adding new challenges
- Architecture - System architecture
Platform is fully decentralized—validators communicate directly via P2P without any central server. See the main README for deployment instructions.
For challenge-specific questions, refer to the appropriate challenge crate or repository.
INVARIANT: The sudo_key field in ChainState CANNOT be changed via:
- Peer state synchronization (
merge_from()) - ForceStateUpdate action
- Direct state manipulation
Implementation (core/state.rs):
// merge_from() preserves local sudo_key
let local_sudo_key = self.sudo_key.clone();
// ... merge other fields ...
self.sudo_key = local_sudo_key; // RESTORE
// ForceStateUpdate also preserves sudo_key
*self = state.clone();
self.sudo_key = local_sudo_key; // SECURITYAll privileged operations require is_sudo() verification:
// consensus.rs lines 221, 363
if change_type == StateChangeType::ConfigUpdate {
let is_sudo = self.state_manager.read(|s| s.is_sudo(&proposer));
if !is_sudo {
return Err(ConsensusError::InvalidProposal(...));
}
}"CRITICAL: must use chain state, not system time" appears in:
vendor/bittensor-rs/src/crv4/mod.rsvendor/bittensor-rs/src/subtensor.rscrates/bittensor-integration/src/weights.rs
Prevents clock skew manipulation attacks.
Integration Tests (tests/):
- Separate workspace member (
platform-e2e-tests) - Fixture helpers:
create_chain_state(),create_five_validators() tempfile::tempdir()for storage isolationMockChallengepattern for challenge testing
Unit Tests (inline):
#[cfg(test)] mod testsat file enduse super::*for parent access#[tokio::test]for async
# Development
cargo build --release # Full build
cargo test --workspace # All unit tests
cargo clippy --all-targets # Lint check
# Integration (requires Docker)
cargo test -p platform-e2e-tests --test integration_test
# Single crate
cargo test -p platform-core
cargo test -p platform-p2p-consensus