@@ -15,6 +15,7 @@ use sp_runtime::{
1515} ;
1616use sp_std:: collections:: vec_deque:: VecDeque ;
1717use substrate_fixed:: types:: I32F32 ;
18+ use scale_info:: prelude:: collections:: HashMap ;
1819
1920/***************************
2021 pub fn set_weights() tests
@@ -3675,3 +3676,281 @@ fn test_batch_reveal_with_out_of_order_commits() {
36753676 assert ! ( commits. is_none( ) ) ;
36763677 } ) ;
36773678}
3679+
3680+ #[ test]
3681+ fn test_highly_concurrent_commits_and_reveals_with_multiple_hotkeys ( ) {
3682+ new_test_ext ( 1 ) . execute_with ( || {
3683+ // ==== Test Configuration ====
3684+ let netuid: u16 = 1 ;
3685+ let num_hotkeys: usize = 10 ;
3686+ let max_unrevealed_commits: usize = 10 ;
3687+ let commits_per_hotkey: usize = 20 ;
3688+ let initial_reveal_period: u64 = 5 ;
3689+ let initial_tempo: u16 = 100 ;
3690+
3691+ // ==== Setup Network ====
3692+ add_network ( netuid, initial_tempo, 0 ) ;
3693+ SubtensorModule :: set_commit_reveal_weights_enabled ( netuid, true ) ;
3694+ SubtensorModule :: set_weights_set_rate_limit ( netuid, 0 ) ;
3695+ SubtensorModule :: set_reveal_period ( netuid, initial_reveal_period) ;
3696+ SubtensorModule :: set_max_registrations_per_block ( netuid, u16:: MAX ) ;
3697+ SubtensorModule :: set_target_registrations_per_interval ( netuid, u16:: MAX ) ;
3698+
3699+ // ==== Register Validators ====
3700+ for uid in 0 ..5 {
3701+ let validator_id = U256 :: from ( 100 + uid as u64 ) ;
3702+ register_ok_neuron ( netuid, validator_id, U256 :: from ( 200 + uid as u64 ) , 300_000 ) ;
3703+ SubtensorModule :: set_validator_permit_for_uid ( netuid, uid, true ) ;
3704+ }
3705+
3706+ // ==== Register Hotkeys ====
3707+ let mut hotkeys: Vec < <Test as frame_system:: Config >:: AccountId > = Vec :: new ( ) ;
3708+ for i in 0 ..num_hotkeys {
3709+ let hotkey_id = U256 :: from ( 1000 + i as u64 ) ;
3710+ register_ok_neuron ( netuid, hotkey_id, U256 :: from ( 2000 + i as u64 ) , 100_000 ) ;
3711+ hotkeys. push ( hotkey_id) ;
3712+ }
3713+
3714+ // ==== Initialize Commit Information ====
3715+ let mut commit_info_map: HashMap <
3716+ <Test as frame_system:: Config >:: AccountId ,
3717+ Vec < ( H256 , Vec < u16 > , Vec < u16 > , Vec < u16 > , u64 ) > ,
3718+ > = HashMap :: new ( ) ;
3719+
3720+ // Initialize the map
3721+ for hotkey in & hotkeys {
3722+ commit_info_map. insert ( * hotkey, Vec :: new ( ) ) ;
3723+ }
3724+
3725+ // ==== Function to Generate Unique Data ====
3726+ fn generate_unique_data ( index : usize ) -> ( Vec < u16 > , Vec < u16 > , Vec < u16 > , u64 ) {
3727+ let uids = vec ! [ index as u16 , ( index + 1 ) as u16 ] ;
3728+ let values = vec ! [ ( index * 10 ) as u16 , ( ( index + 1 ) * 10 ) as u16 ] ;
3729+ let salt = vec ! [ ( index % 100 ) as u16 ; 8 ] ;
3730+ let version_key = index as u64 ;
3731+ ( uids, values, salt, version_key)
3732+ }
3733+
3734+ // ==== Simulate Concurrent Commits and Reveals ====
3735+ for i in 0 ..commits_per_hotkey {
3736+ for hotkey in & hotkeys {
3737+
3738+ let current_commits = pallet_subtensor:: WeightCommits :: < Test > :: get ( netuid, hotkey)
3739+ . unwrap_or_default ( ) ;
3740+ if current_commits. len ( ) >= max_unrevealed_commits {
3741+ continue ;
3742+ }
3743+
3744+ let ( uids, values, salt, version_key) = generate_unique_data ( i) ;
3745+ let commit_hash: H256 = BlakeTwo256 :: hash_of ( & (
3746+ * hotkey,
3747+ netuid,
3748+ uids. clone ( ) ,
3749+ values. clone ( ) ,
3750+ salt. clone ( ) ,
3751+ version_key,
3752+ ) ) ;
3753+
3754+ if let Some ( commits) = commit_info_map. get_mut ( hotkey) {
3755+ commits. push ( ( commit_hash, salt. clone ( ) , uids. clone ( ) , values. clone ( ) , version_key) ) ;
3756+ }
3757+
3758+ assert_ok ! ( SubtensorModule :: commit_weights(
3759+ RuntimeOrigin :: signed( * hotkey) ,
3760+ netuid,
3761+ commit_hash
3762+ ) ) ;
3763+ }
3764+
3765+ // ==== Reveal Phase ====
3766+ for hotkey in & hotkeys {
3767+ if let Some ( commits) = commit_info_map. get_mut ( hotkey) {
3768+ if commits. is_empty ( ) {
3769+ continue ; // No commits to reveal
3770+ }
3771+
3772+ let ( _commit_hash, salt, uids, values, version_key) = commits. first ( ) . expect ( "expected a value" ) ;
3773+
3774+ let reveal_result = SubtensorModule :: reveal_weights (
3775+ RuntimeOrigin :: signed ( * hotkey) ,
3776+ netuid,
3777+ uids. clone ( ) ,
3778+ values. clone ( ) ,
3779+ salt. clone ( ) ,
3780+ * version_key,
3781+ ) ;
3782+
3783+ match reveal_result {
3784+ Ok ( _) => {
3785+ commits. remove ( 0 ) ;
3786+ }
3787+ Err ( e) => {
3788+ if e == Error :: < Test > :: RevealTooEarly . into ( )
3789+ || e == Error :: < Test > :: ExpiredWeightCommit . into ( )
3790+ || e == Error :: < Test > :: InvalidRevealCommitHashNotMatch . into ( )
3791+ {
3792+ log:: info!( "Expected error during reveal after epoch advancement: {:?}" , e) ;
3793+ } else {
3794+ panic ! (
3795+ "Unexpected error during reveal: {:?}, expected RevealTooEarly, ExpiredWeightCommit, or InvalidRevealCommitHashNotMatch" ,
3796+ e
3797+ ) ;
3798+ }
3799+ }
3800+ }
3801+ }
3802+ }
3803+ }
3804+
3805+ // ==== Modify Network Parameters During Commits ====
3806+ SubtensorModule :: set_tempo ( netuid, 150 ) ;
3807+ SubtensorModule :: set_reveal_period ( netuid, 7 ) ;
3808+ log:: info!( "Changed tempo to 150 and reveal_period to 7 during commits." ) ;
3809+
3810+ step_epochs ( 3 , netuid) ;
3811+
3812+ // ==== Continue Reveals After Epoch Advancement ====
3813+ for hotkey in & hotkeys {
3814+ if let Some ( commits) = commit_info_map. get_mut ( hotkey) {
3815+ while !commits. is_empty ( ) {
3816+ let ( _commit_hash, salt, uids, values, version_key) = & commits[ 0 ] ;
3817+
3818+ // Attempt to reveal
3819+ let reveal_result = SubtensorModule :: reveal_weights (
3820+ RuntimeOrigin :: signed ( * hotkey) ,
3821+ netuid,
3822+ uids. clone ( ) ,
3823+ values. clone ( ) ,
3824+ salt. clone ( ) ,
3825+ * version_key,
3826+ ) ;
3827+
3828+ match reveal_result {
3829+ Ok ( _) => {
3830+ commits. remove ( 0 ) ;
3831+ }
3832+ Err ( e) => {
3833+ // Check if the error is due to reveal being too early or commit expired
3834+ if e == Error :: < Test > :: RevealTooEarly . into ( )
3835+ || e == Error :: < Test > :: ExpiredWeightCommit . into ( )
3836+ || e == Error :: < Test > :: InvalidRevealCommitHashNotMatch . into ( )
3837+ {
3838+ log:: info!( "Expected error during reveal after epoch advancement: {:?}" , e) ;
3839+ break ;
3840+ } else {
3841+ panic ! (
3842+ "Unexpected error during reveal after epoch advancement: {:?}, expected RevealTooEarly, ExpiredWeightCommit, or InvalidRevealCommitHashNotMatch" ,
3843+ e
3844+ ) ;
3845+ }
3846+ }
3847+ }
3848+ }
3849+ }
3850+ }
3851+
3852+ // ==== Change Network Parameters Again ====
3853+ SubtensorModule :: set_tempo ( netuid, 200 ) ;
3854+ SubtensorModule :: set_reveal_period ( netuid, 10 ) ;
3855+ log:: info!( "Changed tempo to 200 and reveal_period to 10 after initial reveals." ) ;
3856+
3857+ step_epochs ( 10 , netuid) ;
3858+
3859+ // ==== Final Reveal Attempts ====
3860+ for ( hotkey, commits) in commit_info_map. iter_mut ( ) {
3861+ for ( _commit_hash, salt, uids, values, version_key) in commits. iter ( ) {
3862+ let reveal_result = SubtensorModule :: reveal_weights (
3863+ RuntimeOrigin :: signed ( * hotkey) ,
3864+ netuid,
3865+ uids. clone ( ) ,
3866+ values. clone ( ) ,
3867+ salt. clone ( ) ,
3868+ * version_key,
3869+ ) ;
3870+
3871+ assert_eq ! (
3872+ reveal_result,
3873+ Err ( Error :: <Test >:: ExpiredWeightCommit . into( ) ) ,
3874+ "Expected ExpiredWeightCommit error, got {:?}" ,
3875+ reveal_result
3876+ ) ;
3877+ }
3878+ }
3879+
3880+ for hotkey in & hotkeys {
3881+ commit_info_map. insert ( * hotkey, Vec :: new ( ) ) ;
3882+
3883+ for i in 0 ..max_unrevealed_commits {
3884+ let ( uids, values, salt, version_key) = generate_unique_data ( i + commits_per_hotkey) ;
3885+ let commit_hash: H256 = BlakeTwo256 :: hash_of ( & (
3886+ * hotkey,
3887+ netuid,
3888+ uids. clone ( ) ,
3889+ values. clone ( ) ,
3890+ salt. clone ( ) ,
3891+ version_key,
3892+ ) ) ;
3893+
3894+ assert_ok ! ( SubtensorModule :: commit_weights(
3895+ RuntimeOrigin :: signed( * hotkey) ,
3896+ netuid,
3897+ commit_hash
3898+ ) ) ;
3899+ }
3900+
3901+ let ( uids, values, salt, version_key) = generate_unique_data ( max_unrevealed_commits + commits_per_hotkey) ;
3902+ let commit_hash: H256 = BlakeTwo256 :: hash_of ( & (
3903+ * hotkey,
3904+ netuid,
3905+ uids. clone ( ) ,
3906+ values. clone ( ) ,
3907+ salt. clone ( ) ,
3908+ version_key,
3909+ ) ) ;
3910+
3911+ assert_err ! (
3912+ SubtensorModule :: commit_weights(
3913+ RuntimeOrigin :: signed( * hotkey) ,
3914+ netuid,
3915+ commit_hash
3916+ ) ,
3917+ Error :: <Test >:: TooManyUnrevealedCommits
3918+ ) ;
3919+ }
3920+
3921+ // Attempt unauthorized reveal
3922+ let unauthorized_hotkey = hotkeys[ 0 ] ;
3923+ let target_hotkey = hotkeys[ 1 ] ;
3924+ if let Some ( commits) = commit_info_map. get ( & target_hotkey) {
3925+ if let Some ( ( _commit_hash, salt, uids, values, version_key) ) = commits. first ( ) {
3926+ assert_err ! (
3927+ SubtensorModule :: reveal_weights(
3928+ RuntimeOrigin :: signed( unauthorized_hotkey) ,
3929+ netuid,
3930+ uids. clone( ) ,
3931+ values. clone( ) ,
3932+ salt. clone( ) ,
3933+ * version_key,
3934+ ) ,
3935+ Error :: <Test >:: InvalidRevealCommitHashNotMatch
3936+ ) ;
3937+ }
3938+ }
3939+
3940+ let non_committing_hotkey: <Test as frame_system:: Config >:: AccountId = U256 :: from ( 9999 ) ;
3941+ assert_err ! (
3942+ SubtensorModule :: reveal_weights(
3943+ RuntimeOrigin :: signed( non_committing_hotkey) ,
3944+ netuid,
3945+ vec![ 0 , 1 ] ,
3946+ vec![ 10 , 20 ] ,
3947+ vec![ 0 ; 8 ] ,
3948+ 0 ,
3949+ ) ,
3950+ Error :: <Test >:: NoWeightsCommitFound
3951+ ) ;
3952+
3953+ assert_eq ! ( SubtensorModule :: get_reveal_period( netuid) , 10 ) ;
3954+ assert_eq ! ( SubtensorModule :: get_tempo( netuid) , 200 ) ;
3955+ } )
3956+ }
0 commit comments