@@ -157,7 +157,7 @@ impl P2Chain {
157
157
. get ( usize:: try_from ( index?) . expect ( "32 bit systems not supported" ) )
158
158
}
159
159
160
- fn get_block_at_height ( & self , height : u64 , hash : & FixedHash ) -> Option < & Arc < P2Block > > {
160
+ pub fn get_block_at_height ( & self , height : u64 , hash : & FixedHash ) -> Option < & Arc < P2Block > > {
161
161
let level = self . level_at_height ( height) ?;
162
162
level. blocks . get ( hash)
163
163
}
@@ -201,11 +201,11 @@ impl P2Chain {
201
201
self . levels . len ( ) as u64 >= self . total_size + SAFETY_MARGIN + MAX_EXTRA_SYNC
202
202
}
203
203
204
- fn cleanup_chain ( & mut self ) -> Result < ( ) , ShareChainError > {
204
+ fn cleanup_chain ( & mut self ) -> Result < ( ) , ShareChainError > {
205
205
let mut first_index = self . levels . back ( ) . map ( |level| level. height ) . unwrap_or ( 0 ) ;
206
206
let mut current_chain_length = self . current_tip . saturating_sub ( first_index) ;
207
207
// let see if we are the limit for the current chain
208
- while current_chain_length > self . total_size + SAFETY_MARGIN {
208
+ while current_chain_length > self . total_size + SAFETY_MARGIN {
209
209
self . levels . pop_back ( ) . ok_or ( ShareChainError :: BlockLevelNotFound ) ?;
210
210
first_index = self . levels . back ( ) . map ( |level| level. height ) . unwrap_or ( 0 ) ;
211
211
current_chain_length = self . current_tip . saturating_sub ( first_index) ;
@@ -1368,6 +1368,131 @@ mod test {
1368
1368
chain. assert_share_window_verified ( ) ;
1369
1369
}
1370
1370
1371
+ #[ test]
1372
+ fn add_blocks_missing_block ( ) {
1373
+ // this test will verify that we reorg to a completely new chain
1374
+ let mut chain = P2Chain :: new_empty ( 50 , 25 , 20 ) ;
1375
+
1376
+ let mut prev_block = None ;
1377
+ let mut tari_block = Block :: new ( BlockHeader :: new ( 0 ) , AggregateBody :: empty ( ) ) ;
1378
+ let mut blocks = Vec :: new ( ) ;
1379
+ for i in 0 ..50 {
1380
+ tari_block. header . nonce = i;
1381
+ let address = new_random_address ( ) ;
1382
+ let block = P2BlockBuilder :: new ( prev_block. as_ref ( ) )
1383
+ . with_timestamp ( EpochTime :: now ( ) )
1384
+ . with_height ( i)
1385
+ . with_tari_block ( tari_block. clone ( ) )
1386
+ . unwrap ( )
1387
+ . with_miner_wallet_address ( address. clone ( ) )
1388
+ . with_target_difficulty ( Difficulty :: from_u64 ( 10 ) . unwrap ( ) )
1389
+ . unwrap ( )
1390
+ . build ( )
1391
+ . unwrap ( ) ;
1392
+ prev_block = Some ( block. clone ( ) ) ;
1393
+ blocks. push ( block) ;
1394
+ }
1395
+
1396
+ for ( i, block) in blocks. iter ( ) . enumerate ( ) . take ( 50 ) {
1397
+ if i != 25 {
1398
+ chain. add_block_to_chain ( block. clone ( ) ) . unwrap ( ) ;
1399
+ }
1400
+ }
1401
+ assert_eq ! ( chain. current_tip, 24 ) ;
1402
+ chain. add_block_to_chain ( blocks[ 25 ] . clone ( ) ) . unwrap ( ) ;
1403
+
1404
+ assert_eq ! ( chain. current_tip, 49 ) ;
1405
+ assert_eq ! ( chain. get_tip( ) . unwrap( ) . chain_block, prev_block. unwrap( ) . hash) ;
1406
+
1407
+ chain. assert_share_window_verified ( ) ;
1408
+ }
1409
+
1410
+ #[ test]
1411
+ fn reorg_with_missing_uncle ( ) {
1412
+ // this test will verify that we reorg to a completely new chain
1413
+ let mut chain = P2Chain :: new_empty ( 50 , 25 , 20 ) ;
1414
+
1415
+ let mut prev_block = None ;
1416
+ let mut tari_block = Block :: new ( BlockHeader :: new ( 0 ) , AggregateBody :: empty ( ) ) ;
1417
+ for i in 0 ..50 {
1418
+ tari_block. header . nonce = i;
1419
+ let address = new_random_address ( ) ;
1420
+ let block = P2BlockBuilder :: new ( prev_block. as_ref ( ) )
1421
+ . with_timestamp ( EpochTime :: now ( ) )
1422
+ . with_height ( i)
1423
+ . with_tari_block ( tari_block. clone ( ) )
1424
+ . unwrap ( )
1425
+ . with_miner_wallet_address ( address. clone ( ) )
1426
+ . with_target_difficulty ( Difficulty :: from_u64 ( 10 ) . unwrap ( ) )
1427
+ . unwrap ( )
1428
+ . build ( )
1429
+ . unwrap ( ) ;
1430
+ prev_block = Some ( block. clone ( ) ) ;
1431
+ chain. add_block_to_chain ( block) . unwrap ( ) ;
1432
+ }
1433
+
1434
+ assert_eq ! ( chain. current_tip, 49 ) ;
1435
+ assert_eq ! ( chain. get_tip( ) . unwrap( ) . chain_block, prev_block. unwrap( ) . hash) ;
1436
+
1437
+ let mut prev_block = None ;
1438
+ let mut tari_block = Block :: new ( BlockHeader :: new ( 0 ) , AggregateBody :: empty ( ) ) ;
1439
+ let mut uncle_parent = None ;
1440
+ let mut uncle_block = None ;
1441
+ for i in 0 ..50 {
1442
+ tari_block. header . nonce = i + 100 ;
1443
+ let address = new_random_address ( ) ;
1444
+ let uncles = if i == 25 {
1445
+ let uncle = P2BlockBuilder :: new ( uncle_parent. as_ref ( ) )
1446
+ . with_timestamp ( EpochTime :: now ( ) )
1447
+ . with_height ( 24 )
1448
+ . with_tari_block ( tari_block. clone ( ) )
1449
+ . unwrap ( )
1450
+ . with_miner_wallet_address ( address. clone ( ) )
1451
+ . build ( )
1452
+ . unwrap ( ) ;
1453
+ uncle_block = Some ( uncle. clone ( ) ) ;
1454
+ vec ! [ uncle]
1455
+ } else {
1456
+ vec ! [ ]
1457
+ } ;
1458
+ let block = P2BlockBuilder :: new ( prev_block. as_ref ( ) )
1459
+ . with_timestamp ( EpochTime :: now ( ) )
1460
+ . with_height ( i)
1461
+ . with_tari_block ( tari_block. clone ( ) )
1462
+ . unwrap ( )
1463
+ . with_miner_wallet_address ( address. clone ( ) )
1464
+ . with_uncles ( & uncles)
1465
+ . unwrap ( )
1466
+ . with_target_difficulty ( Difficulty :: from_u64 ( 11 ) . unwrap ( ) )
1467
+ . unwrap ( )
1468
+ . build ( )
1469
+ . unwrap ( ) ;
1470
+ if i == 23 {
1471
+ uncle_parent = Some ( block. clone ( ) ) ;
1472
+ }
1473
+ prev_block = Some ( block. clone ( ) ) ;
1474
+ chain. add_block_to_chain ( block) . unwrap ( ) ;
1475
+ }
1476
+
1477
+ assert_eq ! ( chain. current_tip, 49 ) ;
1478
+ let hash = prev_block. unwrap ( ) . hash ;
1479
+ assert_ne ! ( chain. get_tip( ) . unwrap( ) . chain_block, hash) ;
1480
+ chain. add_block_to_chain ( uncle_block. unwrap ( ) ) . unwrap ( ) ;
1481
+ assert_eq ! ( chain. get_tip( ) . unwrap( ) . chain_block, hash) ;
1482
+ assert_eq ! (
1483
+ chain
1484
+ . get_tip( )
1485
+ . unwrap( )
1486
+ . block_in_main_chain( )
1487
+ . unwrap( )
1488
+ . original_header
1489
+ . nonce,
1490
+ 149
1491
+ ) ;
1492
+
1493
+ chain. assert_share_window_verified ( ) ;
1494
+ }
1495
+
1371
1496
#[ test]
1372
1497
fn add_blocks_to_chain_super_large_reorg_only_window ( ) {
1373
1498
// this test will verify that we reorg to a completely new chain
0 commit comments