@@ -162,9 +162,9 @@ impl GlobalStateEvaluator {
162
162
None
163
163
}
164
164
165
- /// Determines whether a signer with the `local_address` and `local_update` should
166
- /// should capitulate its current miner view to a new state. This is not necessarily the same as the current global view
167
- /// of the miner as it is up to signers to capitulate before this becomes the finalized view.
165
+ /// Determines whether a signer with the `local_address` and `local_update` should capitulate
166
+ /// its current miner view to a new state. This is not necessarily the same as the current global
167
+ /// view of the miner as it is up to signers to capitulate before this becomes the finalized view.
168
168
pub fn capitulate_miner_view (
169
169
& mut self ,
170
170
signerdb : & mut SignerDb ,
@@ -825,6 +825,7 @@ mod tests {
825
825
use libsigner:: v0:: messages:: { StateMachineUpdateContent , StateMachineUpdateMinerState } ;
826
826
827
827
use super :: * ;
828
+ use crate :: signerdb:: tests:: { create_block_override, tmp_db_path} ;
828
829
829
830
fn generate_global_state_evaluator ( num_addresses : u32 ) -> GlobalStateEvaluator {
830
831
let address_weights = generate_random_address_with_equal_weights ( num_addresses) ;
@@ -1094,4 +1095,91 @@ mod tests {
1094
1095
state_machine
1095
1096
)
1096
1097
}
1098
+
1099
+ #[ test]
1100
+ fn check_capitulate_miner_view ( ) {
1101
+ let mut global_eval = generate_global_state_evaluator ( 5 ) ;
1102
+
1103
+ let addresses: Vec < _ > = global_eval. address_weights . keys ( ) . cloned ( ) . collect ( ) ;
1104
+ let local_address = addresses[ 0 ] ;
1105
+ let local_update = global_eval
1106
+ . address_updates
1107
+ . get ( & local_address)
1108
+ . unwrap ( )
1109
+ . clone ( ) ;
1110
+ let StateMachineUpdateMessage {
1111
+ active_signer_protocol_version,
1112
+ local_supported_signer_protocol_version,
1113
+ content :
1114
+ StateMachineUpdateContent :: V0 {
1115
+ burn_block,
1116
+ burn_block_height,
1117
+ current_miner,
1118
+ } ,
1119
+ ..
1120
+ } = local_update. clone ( ) ;
1121
+ // Let's create a new miner view
1122
+ let new_tenure_id = ConsensusHash ( [ 0x00 ; 20 ] ) ;
1123
+ let new_miner = StateMachineUpdateMinerState :: ActiveMiner {
1124
+ current_miner_pkh : Hash160 ( [ 0x00 ; 20 ] ) ,
1125
+ tenure_id : new_tenure_id,
1126
+ parent_tenure_id : ConsensusHash ( [ 0x22 ; 20 ] ) ,
1127
+ parent_tenure_last_block : StacksBlockId ( [ 0x33 ; 32 ] ) ,
1128
+ parent_tenure_last_block_height : 1 ,
1129
+ } ;
1130
+
1131
+ let new_update = StateMachineUpdateMessage :: new (
1132
+ active_signer_protocol_version,
1133
+ local_supported_signer_protocol_version,
1134
+ StateMachineUpdateContent :: V0 {
1135
+ burn_block,
1136
+ burn_block_height,
1137
+ current_miner : new_miner. clone ( ) ,
1138
+ } ,
1139
+ )
1140
+ . unwrap ( ) ;
1141
+
1142
+ let db_path = tmp_db_path ( ) ;
1143
+ let mut db = SignerDb :: new ( db_path) . expect ( "Failed to create signer db" ) ;
1144
+ let ( mut block_info_1, _block_proposal) = create_block_override ( |b| {
1145
+ b. block . header . consensus_hash = new_tenure_id;
1146
+ b. block . header . miner_signature = MessageSignature ( [ 0x01 ; 65 ] ) ;
1147
+ b. block . header . chain_length = 1 ;
1148
+ b. burn_height = 1 ;
1149
+ } ) ;
1150
+
1151
+ db. insert_block ( & block_info_1) . unwrap ( ) ;
1152
+ // Let's update only our own view: the evaluator will tell me to revert my viewpoint to the original miner
1153
+ assert_eq ! (
1154
+ global_eval
1155
+ . capitulate_miner_view( & mut db, local_address, new_update. clone( ) )
1156
+ . unwrap( ) ,
1157
+ current_miner
1158
+ ) ;
1159
+
1160
+ // Let's set a blocking minority to this different view: evaluator should see no global blocks for the blocking majority and return none
1161
+ // I.e. only if the blocking minority is attempting to reject an reorg should it take priority over the rest.
1162
+ // Let's update 1 other signer to some new miner key (60 percent)
1163
+ for address in addresses. into_iter ( ) . skip ( 1 ) . take ( 1 ) {
1164
+ global_eval. insert_update ( address, new_update. clone ( ) ) ;
1165
+ }
1166
+ assert ! (
1167
+ global_eval
1168
+ . capitulate_miner_view( & mut db, local_address, new_update. clone( ) )
1169
+ . is_none( ) ,
1170
+ "Evaluator should have been unable to determine a majority view and return none"
1171
+ ) ;
1172
+
1173
+ db. mark_block_globally_accepted ( & mut block_info_1) . unwrap ( ) ;
1174
+
1175
+ db. insert_block ( & block_info_1) . unwrap ( ) ;
1176
+
1177
+ // Now that the blocking minority references a tenure which would actually get reorged, lets capitulate to their view
1178
+ assert_eq ! (
1179
+ global_eval
1180
+ . capitulate_miner_view( & mut db, local_address, new_update)
1181
+ . unwrap( ) ,
1182
+ new_miner
1183
+ ) ;
1184
+ }
1097
1185
}
0 commit comments