@@ -67,8 +67,8 @@ impl GlobalStateEvaluator {
67
67
}
68
68
}
69
69
70
- /// Determine what the active signer protocol version should be
71
- fn determine_active_signer_protocol_version (
70
+ /// Determine what the maximum signer protocol version that a majority of signers can support
71
+ fn determine_latest_supported_signer_protocol_version (
72
72
& mut self ,
73
73
local_address : StacksAddress ,
74
74
local_update : StateMachineUpdateMessage ,
@@ -131,7 +131,7 @@ impl GlobalStateEvaluator {
131
131
local_update : StateMachineUpdateMessage ,
132
132
) -> Option < SignerStateMachine > {
133
133
let active_signer_protocol_version =
134
- self . determine_active_signer_protocol_version ( local_address, local_update) ?;
134
+ self . determine_latest_supported_signer_protocol_version ( local_address, local_update) ?;
135
135
let mut state_views = HashMap :: new ( ) ;
136
136
for ( address, update) in & self . address_updates {
137
137
let Some ( weight) = self . address_weights . get ( address) else {
@@ -792,7 +792,7 @@ impl LocalStateMachine {
792
792
let old_protocol_version = local_update. active_signer_protocol_version ;
793
793
// First check if we should update our active protocol version
794
794
let active_signer_protocol_version = eval
795
- . determine_active_signer_protocol_version ( local_address, local_update. clone ( ) )
795
+ . determine_latest_supported_signer_protocol_version ( local_address, local_update. clone ( ) )
796
796
. unwrap_or ( old_protocol_version) ;
797
797
798
798
let StateMachineUpdateContent :: V0 {
@@ -846,3 +846,125 @@ impl LocalStateMachine {
846
846
}
847
847
}
848
848
}
849
+
850
+ /// Tests for SignerDb
851
+ #[ cfg( test) ]
852
+ mod tests {
853
+ use clarity:: types:: chainstate:: { StacksBlockId , StacksPrivateKey , StacksPublicKey } ;
854
+ use clarity:: util:: hash:: Hash160 ;
855
+ use libsigner:: v0:: messages:: { StateMachineUpdateContent , StateMachineUpdateMinerState } ;
856
+
857
+ use super :: * ;
858
+
859
+ fn generate_random_address_with_equal_weights (
860
+ num_addresses : u32 ,
861
+ ) -> HashMap < StacksAddress , u32 > {
862
+ let mut address_weights = HashMap :: new ( ) ;
863
+ for _ in 0 ..num_addresses {
864
+ let stacks_address = StacksAddress :: p2pkh (
865
+ false ,
866
+ & StacksPublicKey :: from_private ( & StacksPrivateKey :: random ( ) ) ,
867
+ ) ;
868
+ address_weights. insert ( stacks_address, 10 ) ;
869
+ }
870
+ address_weights
871
+ }
872
+
873
+ #[ test]
874
+ fn determine_latest_supported_signer_protocol_versions ( ) {
875
+ let address_weights = generate_random_address_with_equal_weights ( 5 ) ;
876
+ let active_protocol_version = 0 ;
877
+ let local_supported_signer_protocol_version = 1 ;
878
+
879
+ let addresses: Vec < _ > = address_weights. keys ( ) . cloned ( ) . collect ( ) ;
880
+ let local_address = addresses[ 0 ] ;
881
+
882
+ let local_update = StateMachineUpdateMessage :: new (
883
+ active_protocol_version,
884
+ local_supported_signer_protocol_version,
885
+ StateMachineUpdateContent :: V0 {
886
+ burn_block : ConsensusHash ( [ 0x55 ; 20 ] ) ,
887
+ burn_block_height : 100 ,
888
+ current_miner : StateMachineUpdateMinerState :: ActiveMiner {
889
+ current_miner_pkh : Hash160 ( [ 0xab ; 20 ] ) ,
890
+ tenure_id : ConsensusHash ( [ 0x44 ; 20 ] ) ,
891
+ parent_tenure_id : ConsensusHash ( [ 0x22 ; 20 ] ) ,
892
+ parent_tenure_last_block : StacksBlockId ( [ 0x33 ; 32 ] ) ,
893
+ parent_tenure_last_block_height : 1 ,
894
+ } ,
895
+ } ,
896
+ )
897
+ . unwrap ( ) ;
898
+
899
+ let mut address_updates = HashMap :: new ( ) ;
900
+ for address in & addresses {
901
+ address_updates. insert ( * address, local_update. clone ( ) ) ;
902
+ }
903
+
904
+ let mut global_eval = GlobalStateEvaluator :: new ( address_updates, address_weights) ;
905
+ assert_eq ! (
906
+ global_eval
907
+ . determine_latest_supported_signer_protocol_version(
908
+ local_address,
909
+ local_update. clone( )
910
+ )
911
+ . unwrap( ) ,
912
+ local_supported_signer_protocol_version
913
+ ) ;
914
+
915
+ // Let's update 3 signers (60 percent) to support seperate but greater protocol versions
916
+ for ( i, address) in addresses. into_iter ( ) . skip ( 1 ) . take ( 3 ) . enumerate ( ) {
917
+ let new_version = local_supported_signer_protocol_version + i as u64 + 1 ;
918
+ let new_update = StateMachineUpdateMessage :: new (
919
+ 0 ,
920
+ new_version,
921
+ StateMachineUpdateContent :: V0 {
922
+ burn_block : ConsensusHash ( [ 0x55 ; 20 ] ) ,
923
+ burn_block_height : 100 ,
924
+ current_miner : StateMachineUpdateMinerState :: ActiveMiner {
925
+ current_miner_pkh : Hash160 ( [ 0xab ; 20 ] ) ,
926
+ tenure_id : ConsensusHash ( [ 0x44 ; 20 ] ) ,
927
+ parent_tenure_id : ConsensusHash ( [ 0x22 ; 20 ] ) ,
928
+ parent_tenure_last_block : StacksBlockId ( [ 0x33 ; 32 ] ) ,
929
+ parent_tenure_last_block_height : 1 ,
930
+ } ,
931
+ } ,
932
+ )
933
+ . unwrap ( ) ;
934
+ global_eval. insert_update ( address, new_update) ;
935
+ }
936
+
937
+ assert_eq ! (
938
+ global_eval
939
+ . determine_latest_supported_signer_protocol_version( local_address, local_update)
940
+ . unwrap( ) ,
941
+ local_supported_signer_protocol_version
942
+ ) ;
943
+
944
+ // Let's tip the scales over to version number 2 by updating the local signer's version...
945
+ // i.e. > 70% will have version 2 or higher in their map
946
+ let local_update = StateMachineUpdateMessage :: new (
947
+ active_protocol_version,
948
+ 3 ,
949
+ StateMachineUpdateContent :: V0 {
950
+ burn_block : ConsensusHash ( [ 0x55 ; 20 ] ) ,
951
+ burn_block_height : 100 ,
952
+ current_miner : StateMachineUpdateMinerState :: ActiveMiner {
953
+ current_miner_pkh : Hash160 ( [ 0xab ; 20 ] ) ,
954
+ tenure_id : ConsensusHash ( [ 0x44 ; 20 ] ) ,
955
+ parent_tenure_id : ConsensusHash ( [ 0x22 ; 20 ] ) ,
956
+ parent_tenure_last_block : StacksBlockId ( [ 0x33 ; 32 ] ) ,
957
+ parent_tenure_last_block_height : 1 ,
958
+ } ,
959
+ } ,
960
+ )
961
+ . unwrap ( ) ;
962
+
963
+ assert_eq ! (
964
+ global_eval
965
+ . determine_latest_supported_signer_protocol_version( local_address, local_update)
966
+ . unwrap( ) ,
967
+ local_supported_signer_protocol_version + 1
968
+ ) ;
969
+ }
970
+ }
0 commit comments