@@ -115,7 +115,9 @@ impl GlobalStateEvaluator {
115
115
..
116
116
} = update. content ;
117
117
118
- let entry = burn_blocks. entry ( burn_block) . or_insert_with ( || 0 ) ;
118
+ let entry = burn_blocks
119
+ . entry ( ( burn_block, burn_block_height) )
120
+ . or_insert_with ( || 0 ) ;
119
121
* entry += weight;
120
122
if self . reached_agreement ( * entry) {
121
123
return Some ( ( burn_block, burn_block_height) ) ;
@@ -160,38 +162,6 @@ impl GlobalStateEvaluator {
160
162
None
161
163
}
162
164
163
- /// Check if there is an agreed upon global current miner viewpoint
164
- pub fn determine_global_current_miner (
165
- & mut self ,
166
- local_address : StacksAddress ,
167
- local_update : StateMachineUpdateMessage ,
168
- ) -> Option < StateMachineUpdateMinerState > {
169
- let ( global_burn_block, _) =
170
- self . determine_global_burn_view ( local_address, local_update) ?;
171
- let mut miner_views = HashMap :: new ( ) ;
172
- for ( address, update) in & self . address_updates {
173
- let Some ( weight) = self . address_weights . get ( address) else {
174
- continue ;
175
- } ;
176
- let StateMachineUpdateContent :: V0 {
177
- burn_block,
178
- current_miner,
179
- ..
180
- } = & update. content ;
181
-
182
- if * burn_block != global_burn_block {
183
- continue ;
184
- }
185
-
186
- let entry = miner_views. entry ( current_miner) . or_insert_with ( || 0 ) ;
187
- * entry += weight;
188
- if self . reached_agreement ( * entry) {
189
- return Some ( current_miner. clone ( ) ) ;
190
- }
191
- }
192
- None
193
- }
194
-
195
165
/// Determines whether a signer with the `local_address` and `local_update` should
196
166
/// should capitulate its current miner view to a new state. This is not necessarily the same as the current global view
197
167
/// of the miner as it is up to signers to capitulate before this becomes the finalized view.
@@ -856,30 +826,12 @@ mod tests {
856
826
857
827
use super :: * ;
858
828
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 ) ;
829
+ fn generate_global_state_evaluator ( num_addresses : u32 ) -> GlobalStateEvaluator {
830
+ let address_weights = generate_random_address_with_equal_weights ( num_addresses) ;
876
831
let active_protocol_version = 0 ;
877
832
let local_supported_signer_protocol_version = 1 ;
878
833
879
- let addresses: Vec < _ > = address_weights. keys ( ) . cloned ( ) . collect ( ) ;
880
- let local_address = addresses[ 0 ] ;
881
-
882
- let local_update = StateMachineUpdateMessage :: new (
834
+ let update = StateMachineUpdateMessage :: new (
883
835
active_protocol_version,
884
836
local_supported_signer_protocol_version,
885
837
StateMachineUpdateContent :: V0 {
@@ -897,37 +849,74 @@ mod tests {
897
849
. unwrap ( ) ;
898
850
899
851
let mut address_updates = HashMap :: new ( ) ;
900
- for address in & addresses {
901
- address_updates. insert ( * address, local_update . clone ( ) ) ;
852
+ for address in address_weights . keys ( ) {
853
+ address_updates. insert ( * address, update . clone ( ) ) ;
902
854
}
855
+ GlobalStateEvaluator :: new ( address_updates, address_weights)
856
+ }
903
857
904
- let mut global_eval = GlobalStateEvaluator :: new ( address_updates, address_weights) ;
858
+ fn generate_random_address_with_equal_weights (
859
+ num_addresses : u32 ,
860
+ ) -> HashMap < StacksAddress , u32 > {
861
+ let mut address_weights = HashMap :: new ( ) ;
862
+ for _ in 0 ..num_addresses {
863
+ let stacks_address = StacksAddress :: p2pkh (
864
+ false ,
865
+ & StacksPublicKey :: from_private ( & StacksPrivateKey :: random ( ) ) ,
866
+ ) ;
867
+ address_weights. insert ( stacks_address, 10 ) ;
868
+ }
869
+ address_weights
870
+ }
871
+
872
+ #[ test]
873
+ fn determine_latest_supported_signer_protocol_versions ( ) {
874
+ let mut global_eval = generate_global_state_evaluator ( 5 ) ;
875
+
876
+ let addresses: Vec < _ > = global_eval. address_weights . keys ( ) . cloned ( ) . collect ( ) ;
877
+ let local_address = addresses[ 0 ] ;
878
+
879
+ let local_update = global_eval
880
+ . address_updates
881
+ . get ( & local_address)
882
+ . unwrap ( )
883
+ . clone ( ) ;
905
884
assert_eq ! (
906
885
global_eval
907
886
. determine_latest_supported_signer_protocol_version(
908
887
local_address,
909
- local_update. clone( )
888
+ global_eval
889
+ . address_updates
890
+ . get( & local_address)
891
+ . unwrap( )
892
+ . clone( ) ,
910
893
)
911
894
. unwrap( ) ,
912
- local_supported_signer_protocol_version
895
+ local_update . local_supported_signer_protocol_version
913
896
) ;
914
897
898
+ let StateMachineUpdateMessage {
899
+ active_signer_protocol_version,
900
+ local_supported_signer_protocol_version,
901
+ content :
902
+ StateMachineUpdateContent :: V0 {
903
+ burn_block,
904
+ burn_block_height,
905
+ current_miner,
906
+ } ,
907
+ ..
908
+ } = local_update. clone ( ) ;
909
+
915
910
// Let's update 3 signers (60 percent) to support seperate but greater protocol versions
916
911
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 ;
912
+ let new_version = local_update . local_supported_signer_protocol_version + i as u64 + 1 ;
918
913
let new_update = StateMachineUpdateMessage :: new (
919
- 0 ,
914
+ active_signer_protocol_version ,
920
915
new_version,
921
916
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
- } ,
917
+ burn_block,
918
+ burn_block_height,
919
+ current_miner : current_miner. clone ( ) ,
931
920
} ,
932
921
)
933
922
. unwrap ( ) ;
@@ -944,18 +933,12 @@ mod tests {
944
933
// Let's tip the scales over to version number 2 by updating the local signer's version...
945
934
// i.e. > 70% will have version 2 or higher in their map
946
935
let local_update = StateMachineUpdateMessage :: new (
947
- active_protocol_version ,
936
+ active_signer_protocol_version ,
948
937
3 ,
949
938
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
- } ,
939
+ burn_block,
940
+ burn_block_height,
941
+ current_miner,
959
942
} ,
960
943
)
961
944
. unwrap ( ) ;
@@ -967,4 +950,148 @@ mod tests {
967
950
local_supported_signer_protocol_version + 1
968
951
) ;
969
952
}
953
+
954
+ #[ test]
955
+ fn determine_global_burn_views ( ) {
956
+ let mut global_eval = generate_global_state_evaluator ( 5 ) ;
957
+
958
+ let addresses: Vec < _ > = global_eval. address_weights . keys ( ) . cloned ( ) . collect ( ) ;
959
+ let local_address = addresses[ 0 ] ;
960
+ let local_update = global_eval
961
+ . address_updates
962
+ . get ( & local_address)
963
+ . unwrap ( )
964
+ . clone ( ) ;
965
+ let StateMachineUpdateMessage {
966
+ active_signer_protocol_version,
967
+ local_supported_signer_protocol_version,
968
+ content :
969
+ StateMachineUpdateContent :: V0 {
970
+ burn_block,
971
+ burn_block_height,
972
+ current_miner,
973
+ } ,
974
+ ..
975
+ } = local_update. clone ( ) ;
976
+
977
+ assert_eq ! (
978
+ global_eval
979
+ . determine_global_burn_view( local_address, local_update. clone( ) , )
980
+ . unwrap( ) ,
981
+ ( burn_block, burn_block_height)
982
+ ) ;
983
+
984
+ // Let's update 3 signers (60 percent) to support a new burn block view
985
+ let new_update = StateMachineUpdateMessage :: new (
986
+ active_signer_protocol_version,
987
+ local_supported_signer_protocol_version,
988
+ StateMachineUpdateContent :: V0 {
989
+ burn_block,
990
+ burn_block_height : burn_block_height. wrapping_add ( 1 ) ,
991
+ current_miner : current_miner. clone ( ) ,
992
+ } ,
993
+ )
994
+ . unwrap ( ) ;
995
+ for address in addresses. into_iter ( ) . skip ( 1 ) . take ( 3 ) {
996
+ global_eval. insert_update ( address, new_update. clone ( ) ) ;
997
+ }
998
+
999
+ assert ! (
1000
+ global_eval
1001
+ . determine_global_burn_view( local_address, local_update, )
1002
+ . is_none( ) ,
1003
+ "We should not have reached agreement on the burn block height"
1004
+ ) ;
1005
+
1006
+ // Let's tip the scales over to burn block height + 1
1007
+ assert_eq ! (
1008
+ global_eval
1009
+ . determine_global_burn_view( local_address, new_update, )
1010
+ . unwrap( ) ,
1011
+ ( burn_block, burn_block_height. wrapping_add( 1 ) )
1012
+ ) ;
1013
+ }
1014
+
1015
+ #[ test]
1016
+ fn determine_global_states ( ) {
1017
+ let mut global_eval = generate_global_state_evaluator ( 5 ) ;
1018
+
1019
+ let addresses: Vec < _ > = global_eval. address_weights . keys ( ) . cloned ( ) . collect ( ) ;
1020
+ let local_address = addresses[ 0 ] ;
1021
+ let local_update = global_eval
1022
+ . address_updates
1023
+ . get ( & local_address)
1024
+ . unwrap ( )
1025
+ . clone ( ) ;
1026
+ let StateMachineUpdateMessage {
1027
+ active_signer_protocol_version,
1028
+ local_supported_signer_protocol_version,
1029
+ content :
1030
+ StateMachineUpdateContent :: V0 {
1031
+ burn_block,
1032
+ burn_block_height,
1033
+ current_miner,
1034
+ } ,
1035
+ ..
1036
+ } = local_update. clone ( ) ;
1037
+
1038
+ let state_machine = SignerStateMachine {
1039
+ burn_block,
1040
+ burn_block_height,
1041
+ current_miner : ( & current_miner) . into ( ) ,
1042
+ active_signer_protocol_version : local_supported_signer_protocol_version, // a majority of signers are saying they support version the same local_supported_signer_protocol_version, so update it here...
1043
+ } ;
1044
+
1045
+ assert_eq ! (
1046
+ global_eval
1047
+ . determine_global_state( local_address, local_update. clone( ) , )
1048
+ . unwrap( ) ,
1049
+ state_machine
1050
+ ) ;
1051
+ let new_miner = StateMachineUpdateMinerState :: ActiveMiner {
1052
+ current_miner_pkh : Hash160 ( [ 0x00 ; 20 ] ) ,
1053
+ tenure_id : ConsensusHash ( [ 0x44 ; 20 ] ) ,
1054
+ parent_tenure_id : ConsensusHash ( [ 0x22 ; 20 ] ) ,
1055
+ parent_tenure_last_block : StacksBlockId ( [ 0x33 ; 32 ] ) ,
1056
+ parent_tenure_last_block_height : 1 ,
1057
+ } ;
1058
+
1059
+ let new_update = StateMachineUpdateMessage :: new (
1060
+ active_signer_protocol_version,
1061
+ local_supported_signer_protocol_version,
1062
+ StateMachineUpdateContent :: V0 {
1063
+ burn_block,
1064
+ burn_block_height,
1065
+ current_miner : new_miner. clone ( ) ,
1066
+ } ,
1067
+ )
1068
+ . unwrap ( ) ;
1069
+
1070
+ // Let's update 3 signers to some new miner key (60 percent)
1071
+ for address in addresses. into_iter ( ) . skip ( 1 ) . take ( 3 ) {
1072
+ global_eval. insert_update ( address, new_update. clone ( ) ) ;
1073
+ }
1074
+
1075
+ assert ! (
1076
+ global_eval
1077
+ . determine_global_state( local_address, local_update, )
1078
+ . is_none( ) ,
1079
+ "We should have a disagreement about the current miner"
1080
+ ) ;
1081
+
1082
+ let state_machine = SignerStateMachine {
1083
+ burn_block,
1084
+ burn_block_height,
1085
+ current_miner : ( & new_miner) . into ( ) ,
1086
+ active_signer_protocol_version : local_supported_signer_protocol_version, // a majority of signers are saying they support version the same local_supported_signer_protocol_version, so update it here...
1087
+ } ;
1088
+
1089
+ // Let's tip the scales over to a different miner
1090
+ assert_eq ! (
1091
+ global_eval
1092
+ . determine_global_state( local_address, new_update, )
1093
+ . unwrap( ) ,
1094
+ state_machine
1095
+ )
1096
+ }
970
1097
}
0 commit comments