@@ -5384,3 +5384,377 @@ fn test_reveal_crv3_commits_removes_past_epoch_commits() {
5384
5384
) ;
5385
5385
} ) ;
5386
5386
}
5387
+
5388
+ #[ test]
5389
+ fn test_reveal_crv3_commits_multiple_valid_commits_all_processed ( ) {
5390
+ new_test_ext ( 100 ) . execute_with ( || {
5391
+ use ark_serialize:: CanonicalSerialize ;
5392
+
5393
+ let netuid: u16 = 1 ;
5394
+ let reveal_round: u64 = 1000 ;
5395
+
5396
+ // Initialize the network
5397
+ add_network ( netuid, 5 , 0 ) ;
5398
+ SubtensorModule :: set_commit_reveal_weights_enabled ( netuid, true ) ;
5399
+ SubtensorModule :: set_reveal_period ( netuid, 1 ) ;
5400
+ SubtensorModule :: set_weights_set_rate_limit ( netuid, 0 ) ;
5401
+ SubtensorModule :: set_max_registrations_per_block ( netuid, 100 ) ;
5402
+ SubtensorModule :: set_target_registrations_per_interval ( netuid, 100 ) ;
5403
+
5404
+ // Register multiple neurons (e.g., 5 neurons)
5405
+ let num_neurons = 5 ;
5406
+ let mut hotkeys = Vec :: new ( ) ;
5407
+ let mut neuron_uids = Vec :: new ( ) ;
5408
+ for i in 0 ..num_neurons {
5409
+ let hotkey: AccountId = U256 :: from ( i + 1 ) ;
5410
+ register_ok_neuron ( netuid, hotkey, U256 :: from ( i + 100 ) , 100_000 ) ;
5411
+ SubtensorModule :: set_validator_permit_for_uid ( netuid, i as u16 , true ) ;
5412
+ hotkeys. push ( hotkey) ;
5413
+ neuron_uids. push (
5414
+ SubtensorModule :: get_uid_for_net_and_hotkey ( netuid, & hotkey)
5415
+ . expect ( "Failed to get neuron UID" ) ,
5416
+ ) ;
5417
+ }
5418
+
5419
+ let version_key = SubtensorModule :: get_weights_version_key ( netuid) ;
5420
+
5421
+ // Prepare payloads and commits for each hotkey
5422
+ let esk = [ 2 ; 32 ] ;
5423
+ let pk_bytes = hex:: decode ( "83cf0f2896adee7eb8b5f01fcad3912212c437e0073e911fb90022d3e760183c8c4b450b6a0a6c3ac6a5776a2d1064510d1fec758c921cc22b0e17e63aaf4bcb5ed66304de9cf809bd274ca73bab4af5a6e9c76a4bc09e76eae8991ef5ece45a" )
5424
+ . expect ( "Failed to decode public key bytes" ) ;
5425
+ let pub_key = <TinyBLS381 as EngineBLS >:: PublicKeyGroup :: deserialize_compressed ( & * pk_bytes)
5426
+ . expect ( "Failed to deserialize public key" ) ;
5427
+
5428
+ let message = {
5429
+ let mut hasher = sha2:: Sha256 :: new ( ) ;
5430
+ hasher. update ( reveal_round. to_be_bytes ( ) ) ;
5431
+ hasher. finalize ( ) . to_vec ( )
5432
+ } ;
5433
+ let identity = Identity :: new ( b"" , vec ! [ message] ) ;
5434
+
5435
+ let mut commits = Vec :: new ( ) ;
5436
+ for ( i, hotkey) in hotkeys. iter ( ) . enumerate ( ) {
5437
+ // Each neuron will assign weights to all neurons, including itself
5438
+ let values: Vec < u16 > = ( 0 ..num_neurons as u16 )
5439
+ . map ( |v| ( v + i as u16 + 1 ) * 10 )
5440
+ . collect ( ) ;
5441
+ let payload = WeightsTlockPayload {
5442
+ values : values. clone ( ) ,
5443
+ uids : neuron_uids. clone ( ) ,
5444
+ version_key,
5445
+ } ;
5446
+ let serialized_payload = payload. encode ( ) ;
5447
+
5448
+ let rng = ChaCha20Rng :: seed_from_u64 ( i as u64 ) ;
5449
+
5450
+ let ct = tle :: < TinyBLS381 , AESGCMStreamCipherProvider , ChaCha20Rng > (
5451
+ pub_key,
5452
+ esk,
5453
+ & serialized_payload,
5454
+ identity. clone ( ) ,
5455
+ rng,
5456
+ )
5457
+ . expect ( "Encryption failed" ) ;
5458
+
5459
+ let mut commit_bytes = Vec :: new ( ) ;
5460
+ ct. serialize_compressed ( & mut commit_bytes)
5461
+ . expect ( "Failed to serialize commit" ) ;
5462
+
5463
+ // Submit the commit
5464
+ assert_ok ! ( SubtensorModule :: do_commit_crv3_weights(
5465
+ RuntimeOrigin :: signed( * hotkey) ,
5466
+ netuid,
5467
+ commit_bytes
5468
+ . try_into( )
5469
+ . expect( "Failed to convert commit data" ) ,
5470
+ reveal_round
5471
+ ) ) ;
5472
+
5473
+ // Store the expected weights for later comparison
5474
+ commits. push ( ( hotkey, payload) ) ;
5475
+ }
5476
+
5477
+ // Insert the pulse
5478
+ let sig_bytes = hex:: decode ( "b44679b9a59af2ec876b1a6b1ad52ea9b1615fc3982b19576350f93447cb1125e342b73a8dd2bacbe47e4b6b63ed5e39" )
5479
+ . expect ( "Failed to decode signature bytes" ) ;
5480
+
5481
+ pallet_drand:: Pulses :: < Test > :: insert (
5482
+ reveal_round,
5483
+ Pulse {
5484
+ round : reveal_round,
5485
+ randomness : vec ! [ 0 ; 32 ]
5486
+ . try_into ( )
5487
+ . expect ( "Failed to convert randomness vector" ) ,
5488
+ signature : sig_bytes
5489
+ . try_into ( )
5490
+ . expect ( "Failed to convert signature bytes" ) ,
5491
+ } ,
5492
+ ) ;
5493
+
5494
+ // Advance epoch to trigger reveal
5495
+ step_epochs ( 1 , netuid) ;
5496
+
5497
+ // Verify weights for all hotkeys
5498
+ let weights_sparse = SubtensorModule :: get_weights_sparse ( netuid) ;
5499
+
5500
+ // Set acceptable delta for `I32F32` weights
5501
+ let delta = I32F32 :: from_num ( 0.0001 ) ;
5502
+
5503
+ for ( hotkey, expected_payload) in commits {
5504
+ let neuron_uid = SubtensorModule :: get_uid_for_net_and_hotkey ( netuid, hotkey)
5505
+ . expect ( "Failed to get neuron UID for hotkey" ) as usize ;
5506
+ let weights = weights_sparse
5507
+ . get ( neuron_uid)
5508
+ . cloned ( )
5509
+ . unwrap_or_default ( ) ;
5510
+
5511
+ assert ! (
5512
+ !weights. is_empty( ) ,
5513
+ "Weights for neuron_uid {} should be set" ,
5514
+ neuron_uid
5515
+ ) ;
5516
+
5517
+ // Normalize expected weights
5518
+ let expected_weights: Vec < ( u16 , I32F32 ) > = expected_payload
5519
+ . uids
5520
+ . iter ( )
5521
+ . zip ( expected_payload. values . iter ( ) )
5522
+ . map ( |( & uid, & value) | ( uid, I32F32 :: from_num ( value) ) )
5523
+ . collect ( ) ;
5524
+
5525
+ let total_expected_weight: I32F32 =
5526
+ expected_weights. iter ( ) . map ( |& ( _, w) | w) . sum ( ) ;
5527
+
5528
+ let normalized_expected_weights: Vec < ( u16 , I32F32 ) > = expected_weights
5529
+ . iter ( )
5530
+ . map ( |& ( uid, w) | ( uid, w / total_expected_weight * I32F32 :: from_num ( 30 ) ) )
5531
+ . collect ( ) ;
5532
+
5533
+ // Normalize actual weights
5534
+ let total_weight: I32F32 = weights. iter ( ) . map ( |& ( _, w) | w) . sum ( ) ;
5535
+
5536
+ let normalized_weights: Vec < ( u16 , I32F32 ) > = weights
5537
+ . iter ( )
5538
+ . map ( |& ( uid, w) | ( uid, w / total_weight * I32F32 :: from_num ( 30 ) ) )
5539
+ . collect ( ) ;
5540
+
5541
+ // Compare expected and actual weights with acceptable delta
5542
+ for ( ( uid_expected, weight_expected) , ( uid_actual, weight_actual) ) in
5543
+ normalized_expected_weights. iter ( ) . zip ( normalized_weights. iter ( ) )
5544
+ {
5545
+ assert_eq ! (
5546
+ uid_expected, uid_actual,
5547
+ "UID mismatch: expected {}, got {}" ,
5548
+ uid_expected, uid_actual
5549
+ ) ;
5550
+
5551
+ let diff = ( * weight_expected - * weight_actual) . abs ( ) ;
5552
+ assert ! (
5553
+ diff <= delta,
5554
+ "Weight mismatch for uid {}: expected {}, got {}, diff {}" ,
5555
+ uid_expected,
5556
+ weight_expected,
5557
+ weight_actual,
5558
+ diff
5559
+ ) ;
5560
+ }
5561
+ }
5562
+
5563
+ // Verify that commits storage is empty
5564
+ let cur_epoch = SubtensorModule :: get_epoch_index (
5565
+ netuid,
5566
+ SubtensorModule :: get_current_block_as_u64 ( ) ,
5567
+ ) ;
5568
+ let commits = CRV3WeightCommits :: < Test > :: get ( netuid, cur_epoch) ;
5569
+ assert ! (
5570
+ commits. is_empty( ) ,
5571
+ "Expected no commits left in storage after reveal"
5572
+ ) ;
5573
+ } ) ;
5574
+ }
5575
+
5576
+ #[ test]
5577
+ fn test_reveal_crv3_commits_max_neurons ( ) {
5578
+ new_test_ext ( 100 ) . execute_with ( || {
5579
+ use ark_serialize:: CanonicalSerialize ;
5580
+
5581
+ let netuid: u16 = 1 ;
5582
+ let reveal_round: u64 = 1000 ;
5583
+
5584
+ add_network ( netuid, 5 , 0 ) ;
5585
+ SubtensorModule :: set_commit_reveal_weights_enabled ( netuid, true ) ;
5586
+ SubtensorModule :: set_reveal_period ( netuid, 1 ) ;
5587
+ SubtensorModule :: set_weights_set_rate_limit ( netuid, 0 ) ;
5588
+ SubtensorModule :: set_max_registrations_per_block ( netuid, 10000 ) ;
5589
+ SubtensorModule :: set_target_registrations_per_interval ( netuid, 10000 ) ;
5590
+ SubtensorModule :: set_max_allowed_uids ( netuid, 10024 ) ;
5591
+
5592
+ let num_neurons = 1_024 ;
5593
+ let mut hotkeys = Vec :: new ( ) ;
5594
+ let mut neuron_uids = Vec :: new ( ) ;
5595
+ for i in 0 ..num_neurons {
5596
+ let hotkey: AccountId = U256 :: from ( i + 1 ) ;
5597
+ register_ok_neuron ( netuid, hotkey, U256 :: from ( i + 100 ) , 100_000 ) ;
5598
+ SubtensorModule :: set_validator_permit_for_uid ( netuid, i as u16 , true ) ;
5599
+ hotkeys. push ( hotkey) ;
5600
+ neuron_uids. push (
5601
+ SubtensorModule :: get_uid_for_net_and_hotkey ( netuid, & hotkey)
5602
+ . expect ( "Failed to get neuron UID" ) ,
5603
+ ) ;
5604
+ }
5605
+
5606
+ let version_key = SubtensorModule :: get_weights_version_key ( netuid) ;
5607
+
5608
+ // Prepare payloads and commits for 3 hotkeys
5609
+ let esk = [ 2 ; 32 ] ;
5610
+ let pk_bytes = hex:: decode ( "83cf0f2896adee7eb8b5f01fcad3912212c437e0073e911fb90022d3e760183c8c4b450b6a0a6c3ac6a5776a2d1064510d1fec758c921cc22b0e17e63aaf4bcb5ed66304de9cf809bd274ca73bab4af5a6e9c76a4bc09e76eae8991ef5ece45a" )
5611
+ . expect ( "Failed to decode public key bytes" ) ;
5612
+ let pub_key = <TinyBLS381 as EngineBLS >:: PublicKeyGroup :: deserialize_compressed ( & * pk_bytes)
5613
+ . expect ( "Failed to deserialize public key" ) ;
5614
+
5615
+ let message = {
5616
+ let mut hasher = sha2:: Sha256 :: new ( ) ;
5617
+ hasher. update ( reveal_round. to_be_bytes ( ) ) ;
5618
+ hasher. finalize ( ) . to_vec ( )
5619
+ } ;
5620
+ let identity = Identity :: new ( b"" , vec ! [ message] ) ;
5621
+
5622
+ let hotkeys_to_commit = & hotkeys[ 0 ..3 ] ; // First 3 hotkeys will submit weight commits
5623
+ let mut commits = Vec :: new ( ) ;
5624
+ for ( i, hotkey) in hotkeys_to_commit. iter ( ) . enumerate ( ) {
5625
+ // Each neuron will assign weights to all neurons
5626
+ let values: Vec < u16 > = vec ! [ 10 ; num_neurons] ; // Assign weight of 10 to each neuron
5627
+ let payload = WeightsTlockPayload {
5628
+ values : values. clone ( ) ,
5629
+ uids : neuron_uids. clone ( ) ,
5630
+ version_key,
5631
+ } ;
5632
+ let serialized_payload = payload. encode ( ) ;
5633
+
5634
+ let rng = ChaCha20Rng :: seed_from_u64 ( i as u64 ) ;
5635
+
5636
+ let ct = tle :: < TinyBLS381 , AESGCMStreamCipherProvider , ChaCha20Rng > (
5637
+ pub_key,
5638
+ esk,
5639
+ & serialized_payload,
5640
+ identity. clone ( ) ,
5641
+ rng,
5642
+ )
5643
+ . expect ( "Encryption failed" ) ;
5644
+
5645
+ let mut commit_bytes = Vec :: new ( ) ;
5646
+ ct. serialize_compressed ( & mut commit_bytes)
5647
+ . expect ( "Failed to serialize commit" ) ;
5648
+
5649
+ // Submit the commit
5650
+ assert_ok ! ( SubtensorModule :: do_commit_crv3_weights(
5651
+ RuntimeOrigin :: signed( * hotkey) ,
5652
+ netuid,
5653
+ commit_bytes
5654
+ . try_into( )
5655
+ . expect( "Failed to convert commit data" ) ,
5656
+ reveal_round
5657
+ ) ) ;
5658
+
5659
+ // Store the expected weights for later comparison
5660
+ commits. push ( ( hotkey, payload) ) ;
5661
+ }
5662
+
5663
+ // Insert the pulse
5664
+ let sig_bytes = hex:: decode ( "b44679b9a59af2ec876b1a6b1ad52ea9b1615fc3982b19576350f93447cb1125e342b73a8dd2bacbe47e4b6b63ed5e39" )
5665
+ . expect ( "Failed to decode signature bytes" ) ;
5666
+
5667
+ pallet_drand:: Pulses :: < Test > :: insert (
5668
+ reveal_round,
5669
+ Pulse {
5670
+ round : reveal_round,
5671
+ randomness : vec ! [ 0 ; 32 ]
5672
+ . try_into ( )
5673
+ . expect ( "Failed to convert randomness vector" ) ,
5674
+ signature : sig_bytes
5675
+ . try_into ( )
5676
+ . expect ( "Failed to convert signature bytes" ) ,
5677
+ } ,
5678
+ ) ;
5679
+
5680
+ // Advance epoch to trigger reveal
5681
+ step_epochs ( 1 , netuid) ;
5682
+
5683
+ // Verify weights for the hotkeys that submitted commits
5684
+ let weights_sparse = SubtensorModule :: get_weights_sparse ( netuid) ;
5685
+
5686
+ // Set acceptable delta for `I32F32` weights
5687
+ let delta = I32F32 :: from_num ( 0.0001 ) ; // Adjust delta as needed
5688
+
5689
+ for ( hotkey, expected_payload) in commits {
5690
+ let neuron_uid = SubtensorModule :: get_uid_for_net_and_hotkey ( netuid, hotkey)
5691
+ . expect ( "Failed to get neuron UID for hotkey" ) as usize ;
5692
+ let weights = weights_sparse
5693
+ . get ( neuron_uid)
5694
+ . cloned ( )
5695
+ . unwrap_or_default ( ) ;
5696
+
5697
+ assert ! (
5698
+ !weights. is_empty( ) ,
5699
+ "Weights for neuron_uid {} should be set" ,
5700
+ neuron_uid
5701
+ ) ;
5702
+
5703
+ // Normalize expected weights
5704
+ let expected_weights: Vec < ( u16 , I32F32 ) > = expected_payload
5705
+ . uids
5706
+ . iter ( )
5707
+ . zip ( expected_payload. values . iter ( ) )
5708
+ . map ( |( & uid, & value) | ( uid, I32F32 :: from_num ( value) ) )
5709
+ . collect ( ) ;
5710
+
5711
+ let total_expected_weight: I32F32 =
5712
+ expected_weights. iter ( ) . map ( |& ( _, w) | w) . sum ( ) ;
5713
+
5714
+ let normalized_expected_weights: Vec < ( u16 , I32F32 ) > = expected_weights
5715
+ . iter ( )
5716
+ . map ( |& ( uid, w) | ( uid, w / total_expected_weight * I32F32 :: from_num ( 30 ) ) )
5717
+ . collect ( ) ;
5718
+
5719
+ // Normalize actual weights
5720
+ let total_weight: I32F32 = weights. iter ( ) . map ( |& ( _, w) | w) . sum ( ) ;
5721
+
5722
+ let normalized_weights: Vec < ( u16 , I32F32 ) > = weights
5723
+ . iter ( )
5724
+ . map ( |& ( uid, w) | ( uid, w / total_weight * I32F32 :: from_num ( 30 ) ) )
5725
+ . collect ( ) ;
5726
+
5727
+ // Compare expected and actual weights with acceptable delta
5728
+ for ( ( uid_expected, weight_expected) , ( uid_actual, weight_actual) ) in
5729
+ normalized_expected_weights. iter ( ) . zip ( normalized_weights. iter ( ) )
5730
+ {
5731
+ assert_eq ! (
5732
+ uid_expected, uid_actual,
5733
+ "UID mismatch: expected {}, got {}" ,
5734
+ uid_expected, uid_actual
5735
+ ) ;
5736
+
5737
+ let diff = ( * weight_expected - * weight_actual) . abs ( ) ;
5738
+ assert ! (
5739
+ diff <= delta,
5740
+ "Weight mismatch for uid {}: expected {}, got {}, diff {}" ,
5741
+ uid_expected,
5742
+ weight_expected,
5743
+ weight_actual,
5744
+ diff
5745
+ ) ;
5746
+ }
5747
+ }
5748
+
5749
+ // Verify that commits storage is empty
5750
+ let cur_epoch = SubtensorModule :: get_epoch_index (
5751
+ netuid,
5752
+ SubtensorModule :: get_current_block_as_u64 ( ) ,
5753
+ ) ;
5754
+ let commits = CRV3WeightCommits :: < Test > :: get ( netuid, cur_epoch) ;
5755
+ assert ! (
5756
+ commits. is_empty( ) ,
5757
+ "Expected no commits left in storage after reveal"
5758
+ ) ;
5759
+ } ) ;
5760
+ }
0 commit comments