-
Notifications
You must be signed in to change notification settings - Fork 2
feat: WASM-based dynamic challenge loading system with term-challenge integration #6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
29d2930
22281cf
d0b8dba
1e6422b
c1a1b2c
c970a54
6fa7f69
8854480
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -10,8 +10,9 @@ use clap::Parser; | |||||||||||||||||||||||||||||||||||||||
| use parking_lot::RwLock; | ||||||||||||||||||||||||||||||||||||||||
| use platform_bittensor::{ | ||||||||||||||||||||||||||||||||||||||||
| sync_metagraph, BittensorClient, BlockSync, BlockSyncConfig, BlockSyncEvent, Metagraph, | ||||||||||||||||||||||||||||||||||||||||
| Subtensor, SubtensorClient, | ||||||||||||||||||||||||||||||||||||||||
| StorageConfig, StorageReader, Subtensor, SubtensorClient, | ||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||
| use platform_challenge_loader::{ChallengeLoader, LoaderConfig}; | ||||||||||||||||||||||||||||||||||||||||
| use platform_core::{ | ||||||||||||||||||||||||||||||||||||||||
| checkpoint::{ | ||||||||||||||||||||||||||||||||||||||||
| CheckpointData, CheckpointManager, CompletedEvaluationState, PendingEvaluationState, | ||||||||||||||||||||||||||||||||||||||||
|
|
@@ -23,6 +24,8 @@ use platform_distributed_storage::{ | |||||||||||||||||||||||||||||||||||||||
| DistributedStoreExt, LocalStorage, LocalStorageBuilder, StorageKey, | ||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||
| use platform_p2p_consensus::{ | ||||||||||||||||||||||||||||||||||||||||
| assignment::{AssignmentConfig, ValidatorAssignment}, | ||||||||||||||||||||||||||||||||||||||||
| fast_consensus::{FastConsensus, FastConsensusConfig}, | ||||||||||||||||||||||||||||||||||||||||
| ChainState, ConsensusEngine, NetworkEvent, P2PConfig, P2PMessage, P2PNetwork, StateManager, | ||||||||||||||||||||||||||||||||||||||||
| ValidatorRecord, ValidatorSet, | ||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||
|
|
@@ -159,6 +162,14 @@ struct Args { | |||||||||||||||||||||||||||||||||||||||
| /// Docker challenges support | ||||||||||||||||||||||||||||||||||||||||
| #[arg(long, default_value = "true")] | ||||||||||||||||||||||||||||||||||||||||
| docker_challenges: bool, | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| /// Challenge modules directory | ||||||||||||||||||||||||||||||||||||||||
| #[arg(long, default_value = "./challenges")] | ||||||||||||||||||||||||||||||||||||||||
| challenges_dir: PathBuf, | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| /// Enable WASM challenge loading | ||||||||||||||||||||||||||||||||||||||||
| #[arg(long, default_value = "true")] | ||||||||||||||||||||||||||||||||||||||||
| wasm_challenges: bool, | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| // ==================== Main ==================== | ||||||||||||||||||||||||||||||||||||||||
|
|
@@ -183,6 +194,33 @@ async fn main() -> Result<()> { | |||||||||||||||||||||||||||||||||||||||
| let validator_hotkey = keypair.ss58_address(); | ||||||||||||||||||||||||||||||||||||||||
| info!("Validator hotkey: {}", validator_hotkey); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| // Initialize challenge loader | ||||||||||||||||||||||||||||||||||||||||
| let challenge_loader = if args.wasm_challenges { | ||||||||||||||||||||||||||||||||||||||||
| let loader_config = LoaderConfig { | ||||||||||||||||||||||||||||||||||||||||
| challenges_dir: Some(args.challenges_dir.clone()), | ||||||||||||||||||||||||||||||||||||||||
| enable_p2p_discovery: true, | ||||||||||||||||||||||||||||||||||||||||
| max_challenges: 100, | ||||||||||||||||||||||||||||||||||||||||
| ..Default::default() | ||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| match ChallengeLoader::new(loader_config) { | ||||||||||||||||||||||||||||||||||||||||
| Ok(loader) => { | ||||||||||||||||||||||||||||||||||||||||
| info!("Challenge loader initialized"); | ||||||||||||||||||||||||||||||||||||||||
| Some(Arc::new(loader)) | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| Err(e) => { | ||||||||||||||||||||||||||||||||||||||||
| warn!( | ||||||||||||||||||||||||||||||||||||||||
| "Failed to initialize challenge loader: {}. WASM challenges disabled.", | ||||||||||||||||||||||||||||||||||||||||
| e | ||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||
| None | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||
| info!("WASM challenges disabled"); | ||||||||||||||||||||||||||||||||||||||||
| None | ||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| // Create data directory | ||||||||||||||||||||||||||||||||||||||||
| std::fs::create_dir_all(&args.data_dir)?; | ||||||||||||||||||||||||||||||||||||||||
| let data_dir = std::fs::canonicalize(&args.data_dir)?; | ||||||||||||||||||||||||||||||||||||||||
|
|
@@ -210,6 +248,19 @@ async fn main() -> Result<()> { | |||||||||||||||||||||||||||||||||||||||
| let validator_set = Arc::new(ValidatorSet::new(keypair.clone(), p2p_config.min_stake)); | ||||||||||||||||||||||||||||||||||||||||
| info!("P2P network config initialized"); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| // Initialize validator assignment | ||||||||||||||||||||||||||||||||||||||||
| let assignment_config = AssignmentConfig { | ||||||||||||||||||||||||||||||||||||||||
| min_validators: 3, | ||||||||||||||||||||||||||||||||||||||||
| max_validators: 10, | ||||||||||||||||||||||||||||||||||||||||
| stake_weighted: true, | ||||||||||||||||||||||||||||||||||||||||
| epoch_seed: [0u8; 32], // Will be updated from Bittensor | ||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||
| let validator_assignment = Arc::new(RwLock::new(ValidatorAssignment::new( | ||||||||||||||||||||||||||||||||||||||||
| validator_set.clone(), | ||||||||||||||||||||||||||||||||||||||||
| assignment_config, | ||||||||||||||||||||||||||||||||||||||||
| ))); | ||||||||||||||||||||||||||||||||||||||||
| info!("Validator assignment initialized"); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| // Initialize state manager, loading persisted state if available | ||||||||||||||||||||||||||||||||||||||||
| let state_manager = Arc::new( | ||||||||||||||||||||||||||||||||||||||||
| load_state_from_storage(&storage, args.netuid) | ||||||||||||||||||||||||||||||||||||||||
|
|
@@ -242,6 +293,19 @@ async fn main() -> Result<()> { | |||||||||||||||||||||||||||||||||||||||
| state_manager.clone(), | ||||||||||||||||||||||||||||||||||||||||
| ))); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| // Initialize fast validation consensus | ||||||||||||||||||||||||||||||||||||||||
| let fast_consensus_config = FastConsensusConfig { | ||||||||||||||||||||||||||||||||||||||||
| finality_threshold: 0.67, | ||||||||||||||||||||||||||||||||||||||||
| vote_timeout: Duration::from_secs(5), | ||||||||||||||||||||||||||||||||||||||||
| max_score_variance: 0.1, | ||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||
| let _fast_consensus = Arc::new(RwLock::new(FastConsensus::new( | ||||||||||||||||||||||||||||||||||||||||
| keypair.clone(), | ||||||||||||||||||||||||||||||||||||||||
| validator_set.clone(), | ||||||||||||||||||||||||||||||||||||||||
| fast_consensus_config, | ||||||||||||||||||||||||||||||||||||||||
| ))); | ||||||||||||||||||||||||||||||||||||||||
| info!("Fast validation consensus initialized"); | ||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+296
to
+307
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FastConsensus is created but not wired to Evaluation messages.
Also applies to: 735-742 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| // Connect to Bittensor | ||||||||||||||||||||||||||||||||||||||||
| let subtensor: Option<Arc<Subtensor>>; | ||||||||||||||||||||||||||||||||||||||||
| let subtensor_signer: Option<Arc<BittensorSigner>>; | ||||||||||||||||||||||||||||||||||||||||
|
|
@@ -338,6 +402,29 @@ async fn main() -> Result<()> { | |||||||||||||||||||||||||||||||||||||||
| bittensor_client_for_metagraph = None; | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| // Initialize storage reader for direct metagraph access | ||||||||||||||||||||||||||||||||||||||||
| let _storage_reader = if !args.no_bittensor { | ||||||||||||||||||||||||||||||||||||||||
| let storage_config = StorageConfig { | ||||||||||||||||||||||||||||||||||||||||
| endpoint: args.subtensor_endpoint.clone(), | ||||||||||||||||||||||||||||||||||||||||
| netuid: args.netuid, | ||||||||||||||||||||||||||||||||||||||||
| cache_duration_secs: 60, | ||||||||||||||||||||||||||||||||||||||||
| max_retries: 3, | ||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||
| let mut reader = StorageReader::new(storage_config); | ||||||||||||||||||||||||||||||||||||||||
| match reader.connect().await { | ||||||||||||||||||||||||||||||||||||||||
| Ok(()) => { | ||||||||||||||||||||||||||||||||||||||||
| info!("Bittensor storage reader connected"); | ||||||||||||||||||||||||||||||||||||||||
| Some(Arc::new(RwLock::new(reader))) | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| Err(e) => { | ||||||||||||||||||||||||||||||||||||||||
| warn!("Storage reader connection failed: {}", e); | ||||||||||||||||||||||||||||||||||||||||
| None | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||
| None | ||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| // Initialize shutdown handler for graceful checkpoint persistence | ||||||||||||||||||||||||||||||||||||||||
| let mut shutdown_handler = | ||||||||||||||||||||||||||||||||||||||||
| match ShutdownHandler::new(&data_dir, state_manager.clone(), args.netuid) { | ||||||||||||||||||||||||||||||||||||||||
|
|
@@ -363,6 +450,7 @@ async fn main() -> Result<()> { | |||||||||||||||||||||||||||||||||||||||
| let mut stale_check_interval = tokio::time::interval(Duration::from_secs(60)); | ||||||||||||||||||||||||||||||||||||||||
| let mut state_persist_interval = tokio::time::interval(Duration::from_secs(60)); | ||||||||||||||||||||||||||||||||||||||||
| let mut checkpoint_interval = tokio::time::interval(Duration::from_secs(300)); // 5 minutes | ||||||||||||||||||||||||||||||||||||||||
| let mut challenge_discovery_interval = tokio::time::interval(Duration::from_secs(120)); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| loop { | ||||||||||||||||||||||||||||||||||||||||
| tokio::select! { | ||||||||||||||||||||||||||||||||||||||||
|
|
@@ -389,6 +477,7 @@ async fn main() -> Result<()> { | |||||||||||||||||||||||||||||||||||||||
| &subtensor_signer, | ||||||||||||||||||||||||||||||||||||||||
| &subtensor_client, | ||||||||||||||||||||||||||||||||||||||||
| &state_manager, | ||||||||||||||||||||||||||||||||||||||||
| &validator_assignment, | ||||||||||||||||||||||||||||||||||||||||
| netuid, | ||||||||||||||||||||||||||||||||||||||||
| version_key, | ||||||||||||||||||||||||||||||||||||||||
| ).await; | ||||||||||||||||||||||||||||||||||||||||
|
|
@@ -449,6 +538,21 @@ async fn main() -> Result<()> { | |||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| // Challenge discovery check | ||||||||||||||||||||||||||||||||||||||||
| _ = challenge_discovery_interval.tick() => { | ||||||||||||||||||||||||||||||||||||||||
| if let Some(loader) = challenge_loader.as_ref() { | ||||||||||||||||||||||||||||||||||||||||
| let challenges = loader.list_challenges(); | ||||||||||||||||||||||||||||||||||||||||
| if !challenges.is_empty() { | ||||||||||||||||||||||||||||||||||||||||
| debug!("Active challenges: {}", challenges.len()); | ||||||||||||||||||||||||||||||||||||||||
| for challenge in challenges.iter().take(5) { | ||||||||||||||||||||||||||||||||||||||||
| debug!(" - {} (v{})", challenge.name, challenge.version); | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||
| debug!("No challenges loaded"); | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| // Ctrl+C | ||||||||||||||||||||||||||||||||||||||||
| _ = tokio::signal::ctrl_c() => { | ||||||||||||||||||||||||||||||||||||||||
| info!("Received shutdown signal, creating final checkpoint..."); | ||||||||||||||||||||||||||||||||||||||||
|
|
@@ -628,8 +732,16 @@ async fn handle_network_event( | |||||||||||||||||||||||||||||||||||||||
| debug!("Heartbeat update skipped: {}", e); | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| P2PMessage::Evaluation(eval_msg) => { | ||||||||||||||||||||||||||||||||||||||||
| // Handle evaluation messages which may contain validation results | ||||||||||||||||||||||||||||||||||||||||
| // These are processed through the FastConsensus module for vote aggregation | ||||||||||||||||||||||||||||||||||||||||
| debug!( | ||||||||||||||||||||||||||||||||||||||||
| "Received evaluation message for challenge {:?} from {:?}", | ||||||||||||||||||||||||||||||||||||||||
| eval_msg.challenge_id, source | ||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| _ => { | ||||||||||||||||||||||||||||||||||||||||
| debug!("Unhandled P2P message type"); | ||||||||||||||||||||||||||||||||||||||||
| debug!("Unhandled P2P message type from {:?}", source); | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||
| NetworkEvent::PeerConnected(peer_id) => { | ||||||||||||||||||||||||||||||||||||||||
|
|
@@ -661,6 +773,7 @@ async fn handle_block_event( | |||||||||||||||||||||||||||||||||||||||
| signer: &Option<Arc<BittensorSigner>>, | ||||||||||||||||||||||||||||||||||||||||
| _client: &Option<SubtensorClient>, | ||||||||||||||||||||||||||||||||||||||||
| state_manager: &Arc<StateManager>, | ||||||||||||||||||||||||||||||||||||||||
| validator_assignment: &Arc<RwLock<ValidatorAssignment>>, | ||||||||||||||||||||||||||||||||||||||||
| netuid: u16, | ||||||||||||||||||||||||||||||||||||||||
| version_key: u64, | ||||||||||||||||||||||||||||||||||||||||
| ) { | ||||||||||||||||||||||||||||||||||||||||
|
|
@@ -682,6 +795,20 @@ async fn handle_block_event( | |||||||||||||||||||||||||||||||||||||||
| old_epoch, new_epoch, block | ||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| // Update validator assignment epoch seed | ||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||
| let mut seed = [0u8; 32]; | ||||||||||||||||||||||||||||||||||||||||
| seed[..8].copy_from_slice(&new_epoch.to_le_bytes()); | ||||||||||||||||||||||||||||||||||||||||
| seed[8..16].copy_from_slice(&block.to_le_bytes()); | ||||||||||||||||||||||||||||||||||||||||
| validator_assignment | ||||||||||||||||||||||||||||||||||||||||
| .write() | ||||||||||||||||||||||||||||||||||||||||
| .update_config(AssignmentConfig { | ||||||||||||||||||||||||||||||||||||||||
| epoch_seed: seed, | ||||||||||||||||||||||||||||||||||||||||
| ..Default::default() | ||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+798
to
+808
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Find AssignmentConfig definition and related code
rg -n "struct AssignmentConfig|impl.*Default.*AssignmentConfig|fn update_config" --type rs -A 10 -B 2Repository: PlatformNetwork/platform-v2 Length of output: 97 🏁 Script executed: #!/bin/bash
# Find AssignmentConfig definition and related code
rg -n "struct AssignmentConfig|impl.*Default.*AssignmentConfig|fn update_config" crates/ -A 10 -B 2Repository: PlatformNetwork/platform-v2 Length of output: 3475 🏁 Script executed: #!/bin/bash
# Check the actual code context in the validator-node main.rs file
sed -n '790,820p' bins/validator-node/src/main.rsRepository: PlatformNetwork/platform-v2 Length of output: 1162 Preserve existing validator assignment config during epoch transitions. Calling Suggested fix- validator_assignment
- .write()
- .update_config(AssignmentConfig {
- epoch_seed: seed,
- ..Default::default()
- });
+ let mut cfg = validator_assignment.read().config().clone();
+ cfg.epoch_seed = seed;
+ validator_assignment.write().update_config(cfg);📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||
| debug!("Updated assignment epoch seed for epoch {}", new_epoch); | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| // Transition state to next epoch | ||||||||||||||||||||||||||||||||||||||||
| state_manager.apply(|state| { | ||||||||||||||||||||||||||||||||||||||||
| state.next_epoch(); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
rg -n "start_discovery" --type rsRepository: PlatformNetwork/platform-v2
Length of output: 97
🏁 Script executed:
Repository: PlatformNetwork/platform-v2
Length of output: 289
🏁 Script executed:
Repository: PlatformNetwork/platform-v2
Length of output: 53
🏁 Script executed:
Repository: PlatformNetwork/platform-v2
Length of output: 241
🏁 Script executed:
Repository: PlatformNetwork/platform-v2
Length of output: 346
🏁 Script executed:
Repository: PlatformNetwork/platform-v2
Length of output: 857
🏁 Script executed:
Repository: PlatformNetwork/platform-v2
Length of output: 5922
🏁 Script executed:
Repository: PlatformNetwork/platform-v2
Length of output: 1066
🏁 Script executed:
Repository: PlatformNetwork/platform-v2
Length of output: 926
🏁 Script executed:
Repository: PlatformNetwork/platform-v2
Length of output: 2006
🏁 Script executed:
Repository: PlatformNetwork/platform-v2
Length of output: 743
🏁 Script executed:
Repository: PlatformNetwork/platform-v2
Length of output: 136
🏁 Script executed:
Repository: PlatformNetwork/platform-v2
Length of output: 144
🏁 Script executed:
Repository: PlatformNetwork/platform-v2
Length of output: 102
🏁 Script executed:
Repository: PlatformNetwork/platform-v2
Length of output: 241
🏁 Script executed:
Repository: PlatformNetwork/platform-v2
Length of output: 2349
🏁 Script executed:
Repository: PlatformNetwork/platform-v2
Length of output: 945
🏁 Script executed:
Repository: PlatformNetwork/platform-v2
Length of output: 1680
🏁 Script executed:
Repository: PlatformNetwork/platform-v2
Length of output: 818
🏁 Script executed:
Repository: PlatformNetwork/platform-v2
Length of output: 53
🏁 Script executed:
Repository: PlatformNetwork/platform-v2
Length of output: 263
🏁 Script executed:
Repository: PlatformNetwork/platform-v2
Length of output: 2017
🏁 Script executed:
Repository: PlatformNetwork/platform-v2
Length of output: 6466
🏁 Script executed:
Repository: PlatformNetwork/platform-v2
Length of output: 768
🏁 Script executed:
Repository: PlatformNetwork/platform-v2
Length of output: 489
🏁 Script executed:
Repository: PlatformNetwork/platform-v2
Length of output: 831
🏁 Script executed:
Repository: PlatformNetwork/platform-v2
Length of output: 53
Call
start_discovery()on the ChallengeLoader after initialization.The loader is created with
enable_p2p_discovery: trueand achallenges_dir, butstart_discovery()is never invoked. Without this call, the discovery sources are never registered, no initial discovery occurs, andlist_challenges()will perpetually return an empty list. The polling in the main loop will never find any challenges.Suggested fix
match ChallengeLoader::new(loader_config) { Ok(loader) => { + if let Err(e) = loader.start_discovery().await { + warn!("Failed to start challenge discovery: {}", e); + } info!("Challenge loader initialized"); Some(Arc::new(loader)) }🤖 Prompt for AI Agents