@@ -309,26 +309,12 @@ impl ChallengeRuntime {
309309 Ok ( ( ) )
310310 }
311311
312- /// Handle phase change
312+ /// Handle phase change - just logs, does not trigger commit/reveal
313+ ///
314+ /// Commit/reveal are triggered by Bittensor events (CommitWindowOpen, RevealWindowOpen)
315+ /// not by internal phase tracking. This ensures timing matches Bittensor exactly.
313316 async fn on_phase_change ( & self , epoch : u64 , phase : EpochPhase ) -> Result < ( ) , RuntimeError > {
314- info ! ( "Epoch {} phase: {}" , epoch, phase) ;
315-
316- match phase {
317- EpochPhase :: Commit => {
318- // Calculate and commit weights for all challenges
319- self . commit_weights ( epoch) . await ?;
320- }
321- EpochPhase :: Reveal => {
322- // Reveal weights for all challenges
323- self . reveal_weights ( epoch) . await ?;
324- }
325- EpochPhase :: Finalization => {
326- // Finalize weights
327- self . finalize_weights ( epoch) . await ?;
328- }
329- _ => { }
330- }
331-
317+ info ! ( "Epoch {} phase: {} (info only - actions triggered by Bittensor events)" , epoch, phase) ;
332318 Ok ( ( ) )
333319 }
334320
@@ -400,7 +386,9 @@ impl ChallengeRuntime {
400386 }
401387
402388 /// Commit weights for all mechanisms
403- async fn commit_weights ( & self , epoch : u64 ) -> Result < ( ) , RuntimeError > {
389+ ///
390+ /// Called when Bittensor CommitWindowOpen event fires.
391+ pub async fn commit_weights ( & self , epoch : u64 ) -> Result < ( ) , RuntimeError > {
404392 info ! ( "Committing weights for epoch {} (per mechanism)" , epoch) ;
405393
406394 // First collect weights from all challenges
@@ -449,7 +437,9 @@ impl ChallengeRuntime {
449437 }
450438
451439 /// Reveal weights for all mechanisms
452- async fn reveal_weights ( & self , epoch : u64 ) -> Result < ( ) , RuntimeError > {
440+ ///
441+ /// Called when Bittensor RevealWindowOpen event fires.
442+ pub async fn reveal_weights ( & self , epoch : u64 ) -> Result < ( ) , RuntimeError > {
453443 info ! ( "Revealing weights for epoch {} (per mechanism)" , epoch) ;
454444
455445 let all_mechanisms = self . mechanism_weights . read ( ) . list_mechanisms ( ) ;
@@ -524,10 +514,80 @@ impl ChallengeRuntime {
524514
525515 /// Get all mechanism weights for batch submission to Bittensor
526516 /// Returns Vec<(mechanism_id, uids, weights)> for use with batch_set_mechanism_weights
517+ ///
518+ /// Note: This returns revealed weights from internal commit-reveal.
519+ /// For direct weights, use collect_and_get_weights() instead.
527520 pub fn get_mechanism_weights_for_submission ( & self ) -> Vec < ( u8 , Vec < u16 > , Vec < u16 > ) > {
528521 self . mechanism_commit_reveal . get_revealed_weights ( )
529522 }
530523
524+ /// Collect weights from all challenges and return them for Bittensor submission
525+ ///
526+ /// This is the primary method for event-driven weight submission.
527+ /// Called when Bittensor CommitWindowOpen event fires.
528+ pub async fn collect_and_get_weights ( & self ) -> Vec < ( u8 , Vec < u16 > , Vec < u16 > ) > {
529+ let epoch = self . epoch_manager . current_epoch ( ) ;
530+ info ! ( "Collecting weights for epoch {} (event-driven)" , epoch) ;
531+
532+ let mut result = Vec :: new ( ) ;
533+
534+ for challenge_id in self . manager . list_challenges ( ) {
535+ let mechanism_id = match self . challenge_mechanisms . read ( ) . get ( & challenge_id) {
536+ Some ( id) => * id,
537+ None => {
538+ warn ! ( "Challenge {} has no mechanism_id, skipping" , challenge_id) ;
539+ continue ;
540+ }
541+ } ;
542+
543+ let ctx = match self . manager . get_context ( & challenge_id) {
544+ Some ( ctx) => ctx,
545+ None => continue ,
546+ } ;
547+
548+ let challenge = match self . manager . get_challenge ( & challenge_id) {
549+ Some ( c) => c,
550+ None => continue ,
551+ } ;
552+
553+ // Calculate weights from this challenge
554+ match challenge. calculate_weights ( & ctx) . await {
555+ Ok ( weights) => {
556+ if weights. is_empty ( ) {
557+ debug ! ( "Challenge {} has no weights" , challenge_id) ;
558+ continue ;
559+ }
560+
561+ info ! (
562+ "Challenge {} -> mechanism {}: {} weights" ,
563+ challenge_id,
564+ mechanism_id,
565+ weights. len( )
566+ ) ;
567+
568+ // Convert to Bittensor format (uid, weight as u16)
569+ // For now, use placeholder UIDs - actual UID mapping would come from metagraph
570+ let uids: Vec < u16 > = ( 0 ..weights. len ( ) as u16 ) . collect ( ) ;
571+ let weight_values: Vec < u16 > = weights
572+ . iter ( )
573+ . map ( |w| ( w. weight . clamp ( 0.0 , 1.0 ) * 65535.0 ) as u16 )
574+ . collect ( ) ;
575+
576+ result. push ( ( mechanism_id, uids, weight_values) ) ;
577+ }
578+ Err ( e) => {
579+ error ! (
580+ "Failed to calculate weights for challenge {}: {}" ,
581+ challenge_id, e
582+ ) ;
583+ }
584+ }
585+ }
586+
587+ info ! ( "Collected weights for {} mechanisms" , result. len( ) ) ;
588+ result
589+ }
590+
531591 /// Get all registered mechanism IDs (for initial weight submission)
532592 pub fn get_registered_mechanism_ids ( & self ) -> Vec < u8 > {
533593 self . challenge_mechanisms
0 commit comments