@@ -350,7 +350,7 @@ pub enum LocalStateMachine {
350
350
/// A pending update for a signer state machine
351
351
#[ derive( Debug , Clone , PartialEq , Serialize , Deserialize ) ]
352
352
pub enum StateMachineUpdate {
353
- /// A new burn block at height u64 is expected
353
+ /// A new burn block is expected
354
354
BurnBlock ( NewBurnBlock ) ,
355
355
}
356
356
@@ -419,7 +419,7 @@ impl LocalStateMachine {
419
419
} ,
420
420
other => {
421
421
return Err ( CodecError :: DeserializeError ( format ! (
422
- "Active signer ptocol version is unknown: {other}"
422
+ "Active signer protocol version is unknown: {other}"
423
423
) ) )
424
424
}
425
425
} ;
@@ -780,13 +780,16 @@ impl LocalStateMachine {
780
780
if let Some ( expected_burn_block) = expected_burn_block {
781
781
// If the next height is less than the expected height, we need to wait.
782
782
// OR if the next height is the same, but with a different hash, we need to wait.
783
- if next_burn_block_height < expected_burn_block. burn_block_height || {
784
- next_burn_block_height == expected_burn_block. burn_block_height
785
- && next_burn_block_hash != expected_burn_block. consensus_hash
786
- } {
783
+ let node_behind_expected =
784
+ next_burn_block_height < expected_burn_block. burn_block_height ;
785
+ let node_on_equal_fork = next_burn_block_height
786
+ == expected_burn_block. burn_block_height
787
+ && next_burn_block_hash != expected_burn_block. consensus_hash ;
788
+ if node_behind_expected || node_on_equal_fork {
787
789
let err_msg = format ! (
788
- "Node has not processed the next burn block ({}) yet" ,
789
- expected_burn_block. burn_block_height
790
+ "Node has not processed the next burn block yet. Expected height = {}, Expected consensus hash = {}" ,
791
+ expected_burn_block. burn_block_height,
792
+ expected_burn_block. consensus_hash,
790
793
) ;
791
794
* self = Self :: Pending {
792
795
update : StateMachineUpdate :: BurnBlock ( expected_burn_block) ,
@@ -1028,62 +1031,63 @@ impl LocalStateMachine {
1028
1031
prior_state_machine : & SignerStateMachine ,
1029
1032
is_in_tx_replay_mode : bool ,
1030
1033
) -> Result < Option < Vec < StacksTransaction > > , SignerChainstateError > {
1031
- if expected_burn_block. burn_block_height <= prior_state_machine. burn_block_height
1032
- && expected_burn_block. consensus_hash != prior_state_machine. burn_block
1033
- // TODO: handle fork while still in replay
1034
- && !is_in_tx_replay_mode
1035
- {
1036
- info ! ( "Signer State: fork detected" ;
1037
- "expected_burn_block.height" => expected_burn_block. burn_block_height,
1038
- "expected_burn_block.hash" => %expected_burn_block. consensus_hash,
1039
- "prior_state_machine.burn_block_height" => prior_state_machine. burn_block_height,
1040
- "prior_state_machine.burn_block" => %prior_state_machine. burn_block,
1041
- ) ;
1042
- // Determine the tenures that were forked
1043
- let mut parent_burn_block_info =
1044
- db. get_burn_block_by_ch ( & prior_state_machine. burn_block ) ?;
1045
- let last_forked_tenure = prior_state_machine. burn_block ;
1046
- let mut first_forked_tenure = prior_state_machine. burn_block ;
1047
- let mut forked_tenures = vec ! [ (
1048
- prior_state_machine. burn_block,
1049
- prior_state_machine. burn_block_height,
1050
- ) ] ;
1051
- while parent_burn_block_info. block_height > expected_burn_block. burn_block_height {
1052
- parent_burn_block_info =
1053
- db. get_burn_block_by_hash ( & parent_burn_block_info. parent_burn_block_hash ) ?;
1054
- first_forked_tenure = parent_burn_block_info. consensus_hash ;
1055
- forked_tenures. push ( (
1056
- parent_burn_block_info. consensus_hash ,
1057
- parent_burn_block_info. block_height ,
1058
- ) ) ;
1059
- }
1060
- let fork_info =
1061
- client. get_tenure_forking_info ( & first_forked_tenure, & last_forked_tenure) ?;
1062
- let mut forked_blocks = fork_info
1063
- . iter ( )
1064
- . flat_map ( |fork_info| {
1065
- fork_info
1066
- . nakamoto_blocks
1067
- . iter ( )
1068
- . flat_map ( |blocks| blocks. iter ( ) )
1069
- } )
1070
- . collect :: < Vec < _ > > ( ) ;
1071
- forked_blocks. sort_by_key ( |block| block. header . chain_length ) ;
1072
- let forked_txs = forked_blocks
1073
- . iter ( )
1074
- . flat_map ( |block| block. txs . iter ( ) )
1075
- . filter ( |tx| match tx. payload {
1076
- // Don't include Coinbase, TenureChange, or PoisonMicroblock transactions
1077
- TransactionPayload :: TenureChange ( ..)
1078
- | TransactionPayload :: Coinbase ( ..)
1079
- | TransactionPayload :: PoisonMicroblock ( ..) => false ,
1080
- _ => true ,
1081
- } )
1082
- . cloned ( )
1083
- . collect :: < Vec < _ > > ( ) ;
1084
- Ok ( Some ( forked_txs) )
1085
- } else {
1086
- Ok ( None )
1034
+ if expected_burn_block. burn_block_height > prior_state_machine. burn_block_height {
1035
+ // no bitcoin fork, because we're advancing the burn block height
1036
+ return Ok ( None ) ;
1037
+ }
1038
+ if expected_burn_block. consensus_hash == prior_state_machine. burn_block {
1039
+ // no bitcoin fork, because we're at the same burn block hash as before
1040
+ return Ok ( None ) ;
1087
1041
}
1042
+ if is_in_tx_replay_mode {
1043
+ // TODO: handle fork while still in replay
1044
+ info ! ( "Detected bitcoin fork while in replay mode, will not try to handle the fork" ) ;
1045
+ return Ok ( None ) ;
1046
+ }
1047
+ info ! ( "Signer State: fork detected" ;
1048
+ "expected_burn_block.height" => expected_burn_block. burn_block_height,
1049
+ "expected_burn_block.hash" => %expected_burn_block. consensus_hash,
1050
+ "prior_state_machine.burn_block_height" => prior_state_machine. burn_block_height,
1051
+ "prior_state_machine.burn_block" => %prior_state_machine. burn_block,
1052
+ ) ;
1053
+ // Determine the tenures that were forked
1054
+ let mut parent_burn_block_info =
1055
+ db. get_burn_block_by_ch ( & prior_state_machine. burn_block ) ?;
1056
+ let last_forked_tenure = prior_state_machine. burn_block ;
1057
+ let mut first_forked_tenure = prior_state_machine. burn_block ;
1058
+ let mut forked_tenures = vec ! [ (
1059
+ prior_state_machine. burn_block,
1060
+ prior_state_machine. burn_block_height,
1061
+ ) ] ;
1062
+ while parent_burn_block_info. block_height > expected_burn_block. burn_block_height {
1063
+ parent_burn_block_info =
1064
+ db. get_burn_block_by_hash ( & parent_burn_block_info. parent_burn_block_hash ) ?;
1065
+ first_forked_tenure = parent_burn_block_info. consensus_hash ;
1066
+ forked_tenures. push ( (
1067
+ parent_burn_block_info. consensus_hash ,
1068
+ parent_burn_block_info. block_height ,
1069
+ ) ) ;
1070
+ }
1071
+ let fork_info =
1072
+ client. get_tenure_forking_info ( & first_forked_tenure, & last_forked_tenure) ?;
1073
+ let mut forked_blocks = fork_info
1074
+ . iter ( )
1075
+ . flat_map ( |fork_info| fork_info. nakamoto_blocks . iter ( ) . flatten ( ) )
1076
+ . collect :: < Vec < _ > > ( ) ;
1077
+ forked_blocks. sort_by_key ( |block| block. header . chain_length ) ;
1078
+ let forked_txs = forked_blocks
1079
+ . iter ( )
1080
+ . flat_map ( |block| block. txs . iter ( ) )
1081
+ . filter ( |tx|
1082
+ // Don't include Coinbase, TenureChange, or PoisonMicroblock transactions
1083
+ !matches ! (
1084
+ tx. payload,
1085
+ TransactionPayload :: TenureChange ( ..)
1086
+ | TransactionPayload :: Coinbase ( ..)
1087
+ | TransactionPayload :: PoisonMicroblock ( ..)
1088
+ ) )
1089
+ . cloned ( )
1090
+ . collect :: < Vec < _ > > ( ) ;
1091
+ Ok ( Some ( forked_txs) )
1088
1092
}
1089
1093
}
0 commit comments