@@ -33,8 +33,10 @@ pub struct GovernanceConfig {
33
33
/// Minimum waiting time in seconds for a transaction to be executed after proposal is voted on
34
34
pub min_transaction_hold_up_time : u32 ,
35
35
36
- /// Time limit in seconds for proposal to be open for voting
37
- pub max_voting_time : u32 ,
36
+ /// The base voting time in seconds for proposal to be open for voting
37
+ /// Voting is unrestricted during the base voting time and any vote types can be cast
38
+ /// The base voting time can be extend by optional cool off time when only negative votes (Veto and Deny) are allowed
39
+ pub voting_base_time : u32 ,
38
40
39
41
/// Conditions under which a Community vote will complete early
40
42
pub community_vote_tipping : VoteTipping ,
@@ -55,8 +57,11 @@ pub struct GovernanceConfig {
55
57
/// The threshold for Community Veto votes
56
58
pub community_veto_vote_threshold : VoteThreshold ,
57
59
60
+ /// Voting cool of time
61
+ pub voting_cool_off_time : u32 ,
62
+
58
63
/// Reserved space for future versions
59
- pub reserved : [ u8 ; 5 ] ,
64
+ pub reserved : u8 ,
60
65
}
61
66
62
67
/// Governance Account
@@ -178,7 +183,7 @@ impl GovernanceV2 {
178
183
} else if is_governance_v1_account_type ( & self . account_type ) {
179
184
// V1 account can't be resized and we have to translate it back to the original format
180
185
181
- // If reserved_v2 is used it must be individually assesed for v1 backward compatibility impact
186
+ // If reserved_v2 is used it must be individually assessed for v1 backward compatibility impact
182
187
if self . reserved_v2 != [ 0 ; 128 ] {
183
188
panic ! ( "Extended data not supported by GovernanceV1" )
184
189
}
@@ -288,13 +293,14 @@ pub fn get_governance_data(
288
293
289
294
// In previous versions of spl-gov (< 3) we had config.proposal_cool_off_time:u32 which was unused and always 0
290
295
// In version 3.0.0 proposal_cool_off_time was replaced with council_vote_threshold:VoteThreshold and council_veto_vote_threshold:VoteThreshold
291
- //
292
296
// If we read a legacy account then council_vote_threshold == VoteThreshold::YesVotePercentage(0)
293
- // and we coerce it to be equal to community_vote_threshold which was used for both council and community thresholds before
294
297
//
295
298
// Note: assert_is_valid_governance_config() prevents setting council_vote_threshold to VoteThreshold::YesVotePercentage(0)
296
299
// which gives as guarantee that it is a legacy account layout set with proposal_cool_off_time = 0
300
+ //
301
+ // Note: All the settings below are one time config migration from V1 & V2 account data to V3
297
302
if governance_data. config . council_vote_threshold == VoteThreshold :: YesVotePercentage ( 0 ) {
303
+ // Set council_vote_threshold to community_vote_threshold which was used for both council and community thresholds before
298
304
governance_data. config . council_vote_threshold =
299
305
governance_data. config . community_vote_threshold . clone ( ) ;
300
306
@@ -309,8 +315,9 @@ pub fn get_governance_data(
309
315
// For legacy accounts set the community Veto threshold to Disabled
310
316
governance_data. config . community_veto_vote_threshold = VoteThreshold :: Disabled ;
311
317
312
- // Reset reserved space previously used for voting_proposal_count
313
- governance_data. config . reserved = [ 0 ; 5 ] ;
318
+ // Reset voting_cool_off_time and reserved space previously used for voting_proposal_count
319
+ governance_data. config . voting_cool_off_time = 0 ;
320
+ governance_data. config . reserved = 0 ;
314
321
}
315
322
316
323
Ok ( governance_data)
@@ -478,6 +485,10 @@ pub fn assert_is_valid_governance_config(
478
485
return Err ( GovernanceError :: AtLeastOneVoteThresholdRequired . into ( ) ) ;
479
486
}
480
487
488
+ if governance_config. reserved != 0 {
489
+ return Err ( GovernanceError :: ReservedBufferMustBeEmpty . into ( ) ) ;
490
+ }
491
+
481
492
Ok ( ( ) )
482
493
}
483
494
@@ -506,17 +517,18 @@ mod test {
506
517
507
518
fn create_test_governance_config ( ) -> GovernanceConfig {
508
519
GovernanceConfig {
520
+ community_vote_threshold : VoteThreshold :: YesVotePercentage ( 60 ) ,
509
521
min_community_weight_to_create_proposal : 5 ,
510
- min_council_weight_to_create_proposal : 1 ,
511
522
min_transaction_hold_up_time : 10 ,
512
- max_voting_time : 5 ,
513
- community_vote_threshold : VoteThreshold :: YesVotePercentage ( 60 ) ,
523
+ voting_base_time : 5 ,
514
524
community_vote_tipping : VoteTipping :: Strict ,
515
525
council_vote_threshold : VoteThreshold :: YesVotePercentage ( 60 ) ,
516
526
council_veto_vote_threshold : VoteThreshold :: YesVotePercentage ( 50 ) ,
527
+ min_council_weight_to_create_proposal : 1 ,
517
528
council_vote_tipping : VoteTipping :: Strict ,
518
529
community_veto_vote_threshold : VoteThreshold :: YesVotePercentage ( 40 ) ,
519
- reserved : [ 0 ; 5 ] ,
530
+ voting_cool_off_time : 2 ,
531
+ reserved : 0 ,
520
532
}
521
533
}
522
534
@@ -621,25 +633,15 @@ mod test {
621
633
governance. config. community_vote_tipping
622
634
) ;
623
635
624
- assert_eq ! ( governance. config. reserved, [ 0 ; 5 ] ) ;
636
+ assert_eq ! ( governance. config. reserved, 0 ) ;
637
+ assert_eq ! ( governance. config. voting_cool_off_time, 0 ) ;
625
638
}
626
639
627
640
#[ test]
628
641
fn test_assert_config_invalid_with_council_zero_yes_vote_threshold ( ) {
629
642
// Arrange
630
- let governance_config = GovernanceConfig {
631
- community_vote_threshold : VoteThreshold :: YesVotePercentage ( 1 ) ,
632
- min_community_weight_to_create_proposal : 1 ,
633
- min_transaction_hold_up_time : 1 ,
634
- max_voting_time : 1 ,
635
- community_vote_tipping : VoteTipping :: Strict ,
636
- council_vote_threshold : VoteThreshold :: YesVotePercentage ( 0 ) ,
637
- council_veto_vote_threshold : VoteThreshold :: YesVotePercentage ( 1 ) ,
638
- min_council_weight_to_create_proposal : 1 ,
639
- council_vote_tipping : VoteTipping :: Strict ,
640
- community_veto_vote_threshold : VoteThreshold :: YesVotePercentage ( 1 ) ,
641
- reserved : [ 0 ; 5 ] ,
642
- } ;
643
+ let mut governance_config = create_test_governance_config ( ) ;
644
+ governance_config. council_vote_threshold = VoteThreshold :: YesVotePercentage ( 0 ) ;
643
645
644
646
// Act
645
647
let err = assert_is_valid_governance_config ( & governance_config)
@@ -650,22 +652,77 @@ mod test {
650
652
assert_eq ! ( err, GovernanceError :: InvalidVoteThresholdPercentage . into( ) ) ;
651
653
}
652
654
655
+ #[ test]
656
+ fn test_migrate_governance_config_from_legacy_data_to_v3 ( ) {
657
+ // Arrange
658
+ let mut governance_legacy_data = create_test_governance ( ) ;
659
+
660
+ governance_legacy_data. config . community_vote_threshold =
661
+ VoteThreshold :: YesVotePercentage ( 60 ) ;
662
+
663
+ // council_vote_threshold == YesVotePercentage(0) indicates legacy account from V1 & V2 program versions
664
+ governance_legacy_data. config . council_vote_threshold = VoteThreshold :: YesVotePercentage ( 0 ) ;
665
+
666
+ governance_legacy_data. config . council_veto_vote_threshold =
667
+ VoteThreshold :: YesVotePercentage ( 0 ) ;
668
+ governance_legacy_data. config . council_vote_tipping = VoteTipping :: Disabled ;
669
+ governance_legacy_data. config . community_veto_vote_threshold =
670
+ VoteThreshold :: YesVotePercentage ( 0 ) ;
671
+ governance_legacy_data. config . voting_cool_off_time = 1 ;
672
+ governance_legacy_data. config . voting_base_time = 36000 ;
673
+
674
+ let mut legacy_data = vec ! [ ] ;
675
+ governance_legacy_data. serialize ( & mut legacy_data) . unwrap ( ) ;
676
+
677
+ let program_id = Pubkey :: new_unique ( ) ;
678
+
679
+ let info_key = Pubkey :: new_unique ( ) ;
680
+ let mut lamports = 10u64 ;
681
+
682
+ let legacy_account_info = AccountInfo :: new (
683
+ & info_key,
684
+ false ,
685
+ false ,
686
+ & mut lamports,
687
+ & mut legacy_data[ ..] ,
688
+ & program_id,
689
+ false ,
690
+ Epoch :: default ( ) ,
691
+ ) ;
692
+ // Act
693
+ let governance_v3 = get_governance_data ( & program_id, & legacy_account_info) . unwrap ( ) ;
694
+
695
+ // Assert
696
+ assert_eq ! (
697
+ governance_v3. config. council_vote_threshold,
698
+ VoteThreshold :: YesVotePercentage ( 60 )
699
+ ) ;
700
+
701
+ assert_eq ! (
702
+ governance_v3. config. council_veto_vote_threshold,
703
+ VoteThreshold :: YesVotePercentage ( 60 )
704
+ ) ;
705
+
706
+ assert_eq ! (
707
+ governance_v3. config. community_veto_vote_threshold,
708
+ VoteThreshold :: Disabled
709
+ ) ;
710
+
711
+ assert_eq ! (
712
+ governance_v3. config. council_vote_tipping,
713
+ VoteTipping :: Strict
714
+ ) ;
715
+
716
+ assert_eq ! ( governance_v3. config. voting_cool_off_time, 0 ) ;
717
+
718
+ assert_eq ! ( governance_v3. config. reserved, 0 ) ;
719
+ }
720
+
653
721
#[ test]
654
722
fn test_assert_config_invalid_with_community_zero_yes_vote_threshold ( ) {
655
723
// Arrange
656
- let governance_config = GovernanceConfig {
657
- community_vote_threshold : VoteThreshold :: YesVotePercentage ( 0 ) ,
658
- min_community_weight_to_create_proposal : 1 ,
659
- min_transaction_hold_up_time : 1 ,
660
- max_voting_time : 1 ,
661
- community_vote_tipping : VoteTipping :: Strict ,
662
- council_vote_threshold : VoteThreshold :: YesVotePercentage ( 1 ) ,
663
- council_veto_vote_threshold : VoteThreshold :: YesVotePercentage ( 1 ) ,
664
- min_council_weight_to_create_proposal : 1 ,
665
- council_vote_tipping : VoteTipping :: Strict ,
666
- community_veto_vote_threshold : VoteThreshold :: YesVotePercentage ( 1 ) ,
667
- reserved : [ 0 ; 5 ] ,
668
- } ;
724
+ let mut governance_config = create_test_governance_config ( ) ;
725
+ governance_config. community_vote_threshold = VoteThreshold :: YesVotePercentage ( 0 ) ;
669
726
670
727
// Act
671
728
let err = assert_is_valid_governance_config ( & governance_config)
@@ -679,19 +736,9 @@ mod test {
679
736
#[ test]
680
737
fn test_assert_config_invalid_with_all_vote_thresholds_disabled ( ) {
681
738
// Arrange
682
- let governance_config = GovernanceConfig {
683
- community_vote_threshold : VoteThreshold :: Disabled ,
684
- min_community_weight_to_create_proposal : 1 ,
685
- min_transaction_hold_up_time : 1 ,
686
- max_voting_time : 1 ,
687
- community_vote_tipping : VoteTipping :: Strict ,
688
- council_vote_threshold : VoteThreshold :: Disabled ,
689
- council_veto_vote_threshold : VoteThreshold :: YesVotePercentage ( 1 ) ,
690
- min_council_weight_to_create_proposal : 1 ,
691
- council_vote_tipping : VoteTipping :: Strict ,
692
- community_veto_vote_threshold : VoteThreshold :: YesVotePercentage ( 1 ) ,
693
- reserved : [ 0 ; 5 ] ,
694
- } ;
739
+ let mut governance_config = create_test_governance_config ( ) ;
740
+ governance_config. community_vote_threshold = VoteThreshold :: Disabled ;
741
+ governance_config. council_vote_threshold = VoteThreshold :: Disabled ;
695
742
696
743
// Act
697
744
let err = assert_is_valid_governance_config ( & governance_config)
@@ -705,19 +752,8 @@ mod test {
705
752
#[ test]
706
753
fn test_assert_config_invalid_with_council_zero_yes_veto_vote_threshold ( ) {
707
754
// Arrange
708
- let governance_config = GovernanceConfig {
709
- community_vote_threshold : VoteThreshold :: YesVotePercentage ( 1 ) ,
710
- min_community_weight_to_create_proposal : 1 ,
711
- min_transaction_hold_up_time : 1 ,
712
- max_voting_time : 1 ,
713
- community_vote_tipping : VoteTipping :: Strict ,
714
- council_vote_threshold : VoteThreshold :: YesVotePercentage ( 1 ) ,
715
- council_veto_vote_threshold : VoteThreshold :: YesVotePercentage ( 0 ) ,
716
- min_council_weight_to_create_proposal : 1 ,
717
- council_vote_tipping : VoteTipping :: Strict ,
718
- community_veto_vote_threshold : VoteThreshold :: YesVotePercentage ( 1 ) ,
719
- reserved : [ 0 ; 5 ] ,
720
- } ;
755
+ let mut governance_config = create_test_governance_config ( ) ;
756
+ governance_config. council_veto_vote_threshold = VoteThreshold :: YesVotePercentage ( 0 ) ;
721
757
722
758
// Act
723
759
let err = assert_is_valid_governance_config ( & governance_config)
@@ -731,19 +767,8 @@ mod test {
731
767
#[ test]
732
768
fn test_assert_config_invalid_with_community_zero_yes_veto_vote_threshold ( ) {
733
769
// Arrange
734
- let governance_config = GovernanceConfig {
735
- community_vote_threshold : VoteThreshold :: YesVotePercentage ( 1 ) ,
736
- min_community_weight_to_create_proposal : 1 ,
737
- min_transaction_hold_up_time : 1 ,
738
- max_voting_time : 1 ,
739
- council_vote_tipping : VoteTipping :: Strict ,
740
- council_vote_threshold : VoteThreshold :: YesVotePercentage ( 1 ) ,
741
- council_veto_vote_threshold : VoteThreshold :: YesVotePercentage ( 1 ) ,
742
- min_council_weight_to_create_proposal : 1 ,
743
- community_veto_vote_threshold : VoteThreshold :: YesVotePercentage ( 0 ) ,
744
- community_vote_tipping : VoteTipping :: Strict ,
745
- reserved : [ 0 ; 5 ] ,
746
- } ;
770
+ let mut governance_config = create_test_governance_config ( ) ;
771
+ governance_config. community_veto_vote_threshold = VoteThreshold :: YesVotePercentage ( 0 ) ;
747
772
748
773
// Act
749
774
let err = assert_is_valid_governance_config ( & governance_config)
0 commit comments