@@ -997,40 +997,20 @@ impl LocalStateMachine {
997
997
replay_state : & ReplayState ,
998
998
) -> Result < Option < ReplayState > , SignerChainstateError > {
999
999
if expected_burn_block. burn_block_height > prior_state_machine. burn_block_height {
1000
- // prevent too large of a loop
1001
- if expected_burn_block
1002
- . burn_block_height
1003
- . saturating_sub ( prior_state_machine. burn_block_height )
1004
- > 10
1005
- {
1006
- return Ok ( None ) ;
1007
- }
1008
- // are we building on top of this prior tip?
1009
- let mut parent_burn_block_info =
1010
- db. get_burn_block_by_ch ( & expected_burn_block. consensus_hash ) ?;
1011
-
1012
- while parent_burn_block_info. block_height > prior_state_machine. burn_block_height {
1013
- let Ok ( parent_info) =
1014
- db. get_burn_block_by_hash ( & parent_burn_block_info. parent_burn_block_hash )
1015
- else {
1016
- warn ! (
1017
- "Failed to get parent burn block info for {}" ,
1018
- parent_burn_block_info. parent_burn_block_hash
1019
- ) ;
1020
- return Ok ( None ) ;
1021
- } ;
1022
- parent_burn_block_info = parent_info;
1023
- }
1024
- if parent_burn_block_info. consensus_hash == prior_state_machine. burn_block {
1025
- // no bitcoin fork, because we're building on the parent
1026
- return Ok ( None ) ;
1027
- } else {
1000
+ if Self :: new_burn_block_fork_descendency_check (
1001
+ db,
1002
+ expected_burn_block,
1003
+ prior_state_machine. burn_block_height ,
1004
+ prior_state_machine. burn_block ,
1005
+ ) ? {
1028
1006
info ! ( "Detected bitcoin fork - prior tip is not parent of new tip." ;
1029
1007
"new_tip.burn_block_height" => expected_burn_block. burn_block_height,
1030
1008
"new_tip.consensus_hash" => %expected_burn_block. consensus_hash,
1031
1009
"prior_tip.burn_block_height" => prior_state_machine. burn_block_height,
1032
1010
"prior_tip.consensus_hash" => %prior_state_machine. burn_block,
1033
1011
) ;
1012
+ } else {
1013
+ return Ok ( None ) ;
1034
1014
}
1035
1015
}
1036
1016
if expected_burn_block. consensus_hash == prior_state_machine. burn_block {
@@ -1273,4 +1253,53 @@ impl LocalStateMachine {
1273
1253
1274
1254
Ok ( new_burn_block. burn_block_height > failsafe_height)
1275
1255
}
1256
+
1257
+ /// Check if the new burn block is a fork, by checking if the new burn block
1258
+ /// is a descendant of the prior burn block
1259
+ fn new_burn_block_fork_descendency_check (
1260
+ db : & SignerDb ,
1261
+ new_burn_block : & NewBurnBlock ,
1262
+ prior_burn_block_height : u64 ,
1263
+ prior_burn_block_ch : ConsensusHash ,
1264
+ ) -> Result < bool , SignerChainstateError > {
1265
+ let max_height_delta = 10 ;
1266
+ let height_delta = match new_burn_block
1267
+ . burn_block_height
1268
+ . checked_sub ( prior_burn_block_height)
1269
+ {
1270
+ None | Some ( 0 ) => return Ok ( false ) , // same height or older
1271
+ Some ( d) if d > max_height_delta => return Ok ( false ) , // too far apart
1272
+ Some ( d) => d,
1273
+ } ;
1274
+
1275
+ let Ok ( mut parent_burn_block_info) =
1276
+ db. get_burn_block_by_ch ( & new_burn_block. consensus_hash )
1277
+ else {
1278
+ warn ! (
1279
+ "Failed to get parent burn block info for {}" ,
1280
+ new_burn_block. consensus_hash
1281
+ ) ;
1282
+ return Ok ( false ) ;
1283
+ } ;
1284
+
1285
+ for _ in 0 ..height_delta {
1286
+ if parent_burn_block_info. block_height == prior_burn_block_height {
1287
+ return Ok ( parent_burn_block_info. consensus_hash != prior_burn_block_ch) ;
1288
+ }
1289
+
1290
+ parent_burn_block_info =
1291
+ match db. get_burn_block_by_hash ( & parent_burn_block_info. parent_burn_block_hash ) {
1292
+ Ok ( bi) => bi,
1293
+ Err ( e) => {
1294
+ warn ! (
1295
+ "Failed to get parent burn block info for {}. Error: {e}" ,
1296
+ parent_burn_block_info. parent_burn_block_hash
1297
+ ) ;
1298
+ return Ok ( false ) ;
1299
+ }
1300
+ } ;
1301
+ }
1302
+
1303
+ Ok ( false )
1304
+ }
1276
1305
}
0 commit comments