@@ -35,15 +35,15 @@ use clarity::util::sleep_ms;
35
35
use clarity:: util:: tests:: TestFlag ;
36
36
use libsigner:: v0:: messages:: {
37
37
BlockAccepted , BlockRejection , BlockResponse , MessageSlotID , MockProposal , MockSignature ,
38
- RejectReason , RejectReasonPrefix , SignerMessage ,
38
+ RejectReason , RejectReasonPrefix , SignerMessage , StateMachineUpdate ,
39
39
} ;
40
40
use libsigner:: { BlockProposal , SignerEvent } ;
41
41
use stacks_common:: types:: chainstate:: { StacksAddress , StacksPublicKey } ;
42
42
use stacks_common:: util:: get_epoch_time_secs;
43
43
use stacks_common:: util:: secp256k1:: MessageSignature ;
44
44
use stacks_common:: { debug, error, info, warn} ;
45
45
46
- use super :: signer_state:: LocalStateMachine ;
46
+ use super :: signer_state:: { GlobalStateEvaluator , LocalStateMachine } ;
47
47
use crate :: chainstate:: { ProposalEvalConfig , SortitionMinerStatus , SortitionsView } ;
48
48
use crate :: client:: { ClientError , SignerSlotID , StackerDB , StacksClient } ;
49
49
use crate :: config:: { SignerConfig , SignerConfigMode } ;
@@ -109,6 +109,8 @@ pub struct Signer {
109
109
pub block_proposal_max_age_secs : u64 ,
110
110
/// The signer's local state machine used in signer set agreement
111
111
pub local_state_machine : LocalStateMachine ,
112
+ /// The signer's global state evaluator
113
+ pub global_state_evaluator : GlobalStateEvaluator ,
112
114
}
113
115
114
116
impl std:: fmt:: Display for SignerMode {
@@ -137,7 +139,7 @@ impl SignerTrait<SignerMessage> for Signer {
137
139
138
140
debug ! ( "Reward cycle #{} {mode}" , signer_config. reward_cycle) ;
139
141
140
- let signer_db =
142
+ let mut signer_db =
141
143
SignerDb :: new ( & signer_config. db_path ) . expect ( "Failed to connect to signer Db" ) ;
142
144
let proposal_config = ProposalEvalConfig :: from ( & signer_config) ;
143
145
@@ -150,6 +152,17 @@ impl SignerTrait<SignerMessage> for Signer {
150
152
signer_config. mainnet ,
151
153
& StacksPublicKey :: from_private ( & signer_config. stacks_private_key ) ,
152
154
) ;
155
+
156
+ let updates = signer_db
157
+ . get_signer_state_machine_updates ( signer_config. reward_cycle )
158
+ . inspect_err ( |e| {
159
+ warn ! ( "An error occurred retrieving state machine updates from the db: {e}" )
160
+ } )
161
+ . unwrap_or_default ( ) ;
162
+ let global_state_evaluator = GlobalStateEvaluator :: new (
163
+ updates,
164
+ signer_config. signer_entries . signer_addr_to_weight . clone ( ) ,
165
+ ) ;
153
166
Self {
154
167
private_key : signer_config. stacks_private_key ,
155
168
stacks_address,
@@ -166,6 +179,7 @@ impl SignerTrait<SignerMessage> for Signer {
166
179
block_proposal_validation_timeout : signer_config. block_proposal_validation_timeout ,
167
180
block_proposal_max_age_secs : signer_config. block_proposal_max_age_secs ,
168
181
local_state_machine : signer_state,
182
+ global_state_evaluator,
169
183
}
170
184
}
171
185
@@ -246,21 +260,7 @@ impl SignerTrait<SignerMessage> for Signer {
246
260
sortition_state,
247
261
) ,
248
262
SignerMessage :: StateMachineUpdate ( update) => {
249
- // TODO: should make note of this update view point to determine if there is an agreed upon global state
250
- // We don't need to check the message parity again because of the check at the start of process_event
251
- if let Err ( e) = self . signer_db . insert_state_machine_update (
252
- self . reward_cycle ,
253
- & StacksAddress :: p2pkh ( self . mainnet , signer_public_key) ,
254
- update,
255
- ) {
256
- warn ! ( "{self}: Failed to update global state in signerdb: {e}" ) ;
257
- }
258
- self . local_state_machine . capitulate_miner_view (
259
- & mut self . signer_db ,
260
- self . reward_cycle ,
261
- self . stacks_address ,
262
- & self . signer_weights ,
263
- ) ;
263
+ self . handle_state_machine_update ( signer_public_key, update) ;
264
264
}
265
265
_ => { }
266
266
}
@@ -584,6 +584,31 @@ impl Signer {
584
584
self . impl_send_block_response ( block_response)
585
585
}
586
586
587
+ /// Handle signer state update message
588
+ fn handle_state_machine_update (
589
+ & mut self ,
590
+ signer_public_key : & Secp256k1PublicKey ,
591
+ update : & StateMachineUpdate ,
592
+ ) {
593
+ let address = StacksAddress :: p2pkh ( self . mainnet , signer_public_key) ;
594
+ // Store the state machine update so we can reload it if we crash
595
+ if let Err ( e) =
596
+ self . signer_db
597
+ . insert_state_machine_update ( self . reward_cycle , & address, update)
598
+ {
599
+ warn ! ( "{self}: Failed to update global state in signerdb: {e}" ) ;
600
+ }
601
+ self . global_state_evaluator
602
+ . insert_update ( address, update. clone ( ) ) ;
603
+
604
+ // See if this update means we should capitulate our viewpoint...
605
+ self . local_state_machine . capitulate_viewpoint (
606
+ & mut self . signer_db ,
607
+ & mut self . global_state_evaluator ,
608
+ self . stacks_address ,
609
+ ) ;
610
+ }
611
+
587
612
/// Handle block proposal messages submitted to signers stackerdb
588
613
fn handle_block_proposal (
589
614
& mut self ,
0 commit comments