26
26
27
27
from chia .consensus .block_body_validation import ForkInfo , validate_block_body
28
28
from chia .consensus .block_header_validation import validate_unfinished_header_block
29
- from chia .consensus .consensus_store_protocol import ConsensusStoreProtocol
29
+ from chia .consensus .consensus_store_protocol import ConsensusStoreProtocol , ConsensusStoreWriteProtocol
30
30
from chia .consensus .cost_calculator import NPCResult
31
31
from chia .consensus .difficulty_adjustment import get_next_sub_slot_iters_and_difficulty
32
32
from chia .consensus .find_fork_point import lookup_fork_chain
@@ -510,117 +510,135 @@ async def _reconsider_peak(
510
510
and the new chain, or returns None if there was no update to the heaviest chain.
511
511
"""
512
512
513
+ if genesis and self .get_peak () is not None :
514
+ return [], None
515
+
516
+ async with self .consensus_store .writer () as writer :
517
+ records_to_add , state_summary = await self ._perform_db_operations_for_peak (
518
+ writer , block_record , genesis , fork_info
519
+ )
520
+
521
+ # Changes the peak to be the new peak
522
+ await writer .set_peak (block_record .header_hash )
523
+
524
+ return records_to_add , state_summary
525
+
526
+ async def _perform_db_operations_for_peak (
527
+ self ,
528
+ writer : ConsensusStoreWriteProtocol ,
529
+ block_record : BlockRecord ,
530
+ genesis : bool ,
531
+ fork_info : ForkInfo ,
532
+ ) -> tuple [list [BlockRecord ], Optional [StateChangeSummary ]]:
533
+ """
534
+ Perform database operations to consider a new peak.
535
+ Creates and returns the records to add and the complete StateChangeSummary.
536
+ """
513
537
peak = self .get_peak ()
514
538
rolled_back_state : dict [bytes32 , CoinRecord ] = {}
515
539
516
- if genesis and peak is not None :
517
- return [], None
540
+ if peak is not None :
541
+ if block_record .weight < peak .weight :
542
+ # This is not a heavier block than the heaviest we have seen, so we don't change the coin set
543
+ return [], None
544
+ if block_record .weight == peak .weight and peak .total_iters <= block_record .total_iters :
545
+ # this is an equal weight block but our peak has lower iterations, so we dont change the coin set
546
+ return [], None
547
+ if block_record .weight == peak .weight :
548
+ log .info (
549
+ f"block has equal weight as our peak ({ peak .weight } ), but fewer "
550
+ f"total iterations { block_record .total_iters } "
551
+ f"peak: { peak .total_iters } "
552
+ f"peak-hash: { peak .header_hash } "
553
+ )
518
554
519
- async with self .consensus_store .writer () as writer :
520
- if peak is not None :
521
- if block_record .weight < peak .weight :
522
- # This is not a heavier block than the heaviest we have seen, so we don't change the coin set
523
- return [], None
524
- if block_record .weight == peak .weight and peak .total_iters <= block_record .total_iters :
525
- # this is an equal weight block but our peak has lower iterations, so we dont change the coin set
526
- return [], None
527
- if block_record .weight == peak .weight :
555
+ if block_record .prev_hash != peak .header_hash :
556
+ rolled_back_state = await writer .rollback_to_block (fork_info .fork_height )
557
+ if self ._log_coins and len (rolled_back_state ) > 0 :
558
+ log .info (f"rolled back { len (rolled_back_state )} coins, to fork height { fork_info .fork_height } " )
528
559
log .info (
529
- f"block has equal weight as our peak ({ peak .weight } ), but fewer "
530
- f"total iterations { block_record .total_iters } "
531
- f"peak: { peak .total_iters } "
532
- f"peak-hash: { peak .header_hash } "
560
+ "removed: %s" ,
561
+ "," .join (
562
+ [
563
+ name .hex ()[0 :6 ]
564
+ for name , state in rolled_back_state .items ()
565
+ if state .confirmed_block_index == 0
566
+ ]
567
+ ),
533
568
)
534
-
535
- if block_record .prev_hash != peak .header_hash :
536
- rolled_back_state = await writer .rollback_to_block (fork_info .fork_height )
537
- if self ._log_coins and len (rolled_back_state ) > 0 :
538
- log .info (f"rolled back { len (rolled_back_state )} coins, to fork height { fork_info .fork_height } " )
539
- log .info (
540
- "removed: %s" ,
541
- "," .join (
542
- [
543
- name .hex ()[0 :6 ]
544
- for name , state in rolled_back_state .items ()
545
- if state .confirmed_block_index == 0
546
- ]
547
- ),
548
- )
549
- log .info (
550
- "unspent: %s" ,
551
- "," .join (
552
- [
553
- name .hex ()[0 :6 ]
554
- for name , state in rolled_back_state .items ()
555
- if state .confirmed_block_index != 0
556
- ]
557
- ),
558
- )
559
-
560
- # Collects all blocks from fork point to new peak
561
- records_to_add : list [BlockRecord ] = []
562
-
563
- if genesis :
564
- records_to_add = [block_record ]
565
- elif fork_info .block_hashes == [block_record .header_hash ]:
566
- # in the common case, we just add a block on top of the chain. Check
567
- # for that here to avoid an unnecessary database lookup.
568
- records_to_add = [block_record ]
569
- else :
570
- records_to_add = await self .consensus_store .get_block_records_by_hash (fork_info .block_hashes )
571
-
572
- for fetched_block_record in records_to_add :
573
- if not fetched_block_record .is_transaction_block :
574
- # Coins are only created in TX blocks so there are no state updates for this block
575
- continue
576
-
577
- height = fetched_block_record .height
578
- # We need to recompute the additions and removals, since they are
579
- # not stored on DB. We have all the additions and removals in the
580
- # fork_info object, we just need to pick the ones belonging to each
581
- # individual block height
582
-
583
- # Apply the coin store changes for each block that is now in the blockchain
584
- included_reward_coins = [
585
- fork_add .coin
586
- for fork_add in fork_info .additions_since_fork .values ()
587
- if fork_add .confirmed_height == height and fork_add .is_coinbase
588
- ]
589
- tx_additions = [
590
- (coin_id , fork_add .coin , fork_add .same_as_parent )
591
- for coin_id , fork_add in fork_info .additions_since_fork .items ()
592
- if fork_add .confirmed_height == height and not fork_add .is_coinbase
593
- ]
594
- tx_removals = [
595
- coin_id for coin_id , fork_rem in fork_info .removals_since_fork .items () if fork_rem .height == height
596
- ]
597
- assert fetched_block_record .timestamp is not None
598
- await writer .new_block (
599
- height ,
600
- fetched_block_record .timestamp ,
601
- included_reward_coins ,
602
- tx_additions ,
603
- tx_removals ,
604
- )
605
- if self ._log_coins and (len (tx_removals ) > 0 or len (tx_additions ) > 0 ):
606
569
log .info (
607
- f"adding new block to coin_store "
608
- f"(hh: { fetched_block_record .header_hash } "
609
- f"height: { fetched_block_record .height } ), { len (tx_removals )} spends"
570
+ "unspent: %s" ,
571
+ "," .join (
572
+ [
573
+ name .hex ()[0 :6 ]
574
+ for name , state in rolled_back_state .items ()
575
+ if state .confirmed_block_index != 0
576
+ ]
577
+ ),
610
578
)
611
- log .info ("rewards: %s" , "," .join ([add .name ().hex ()[0 :6 ] for add in included_reward_coins ]))
612
- log .info ("additions: %s" , "," .join ([add [0 ].hex ()[0 :6 ] for add in tx_additions ]))
613
- log .info ("removals: %s" , "," .join ([f"{ rem } " [0 :6 ] for rem in tx_removals ]))
614
579
615
- # we made it to the end successfully
616
- # Rollback sub_epoch_summaries
617
- await writer .rollback (fork_info .fork_height )
618
- await writer .set_in_chain ([(br .header_hash ,) for br in records_to_add ])
580
+ # Collects all blocks from fork point to new peak
581
+ records_to_add : list [BlockRecord ] = []
619
582
620
- # Changes the peak to be the new peak
621
- await writer .set_peak (block_record .header_hash )
583
+ if genesis :
584
+ records_to_add = [block_record ]
585
+ elif fork_info .block_hashes == [block_record .header_hash ]:
586
+ # in the common case, we just add a block on top of the chain. Check
587
+ # for that here to avoid an unnecessary database lookup.
588
+ records_to_add = [block_record ]
589
+ else :
590
+ records_to_add = await self .consensus_store .get_block_records_by_hash (fork_info .block_hashes )
591
+
592
+ for fetched_block_record in records_to_add :
593
+ if not fetched_block_record .is_transaction_block :
594
+ # Coins are only created in TX blocks so there are no state updates for this block
595
+ continue
596
+
597
+ height = fetched_block_record .height
598
+ # We need to recompute the additions and removals, since they are
599
+ # not stored on DB. We have all the additions and removals in the
600
+ # fork_info object, we just need to pick the ones belonging to each
601
+ # individual block height
602
+
603
+ # Apply the coin store changes for each block that is now in the blockchain
604
+ included_reward_coins = [
605
+ fork_add .coin
606
+ for fork_add in fork_info .additions_since_fork .values ()
607
+ if fork_add .confirmed_height == height and fork_add .is_coinbase
608
+ ]
609
+ tx_additions = [
610
+ (coin_id , fork_add .coin , fork_add .same_as_parent )
611
+ for coin_id , fork_add in fork_info .additions_since_fork .items ()
612
+ if fork_add .confirmed_height == height and not fork_add .is_coinbase
613
+ ]
614
+ tx_removals = [
615
+ coin_id for coin_id , fork_rem in fork_info .removals_since_fork .items () if fork_rem .height == height
616
+ ]
617
+ assert fetched_block_record .timestamp is not None
618
+ await writer .new_block (
619
+ height ,
620
+ fetched_block_record .timestamp ,
621
+ included_reward_coins ,
622
+ tx_additions ,
623
+ tx_removals ,
624
+ )
625
+ if self ._log_coins and (len (tx_removals ) > 0 or len (tx_additions ) > 0 ):
626
+ log .info (
627
+ f"adding new block to coin_store "
628
+ f"(hh: { fetched_block_record .header_hash } "
629
+ f"height: { fetched_block_record .height } ), { len (tx_removals )} spends"
630
+ )
631
+ log .info ("rewards: %s" , "," .join ([add .name ().hex ()[0 :6 ] for add in included_reward_coins ]))
632
+ log .info ("additions: %s" , "," .join ([add [0 ].hex ()[0 :6 ] for add in tx_additions ]))
633
+ log .info ("removals: %s" , "," .join ([f"{ rem } " [0 :6 ] for rem in tx_removals ]))
634
+
635
+ # we made it to the end successfully
636
+ # Rollback sub_epoch_summaries
637
+ await writer .rollback (fork_info .fork_height )
638
+ await writer .set_in_chain ([(br .header_hash ,) for br in records_to_add ])
622
639
623
- return records_to_add , StateChangeSummary (
640
+ # Create and return the complete StateChangeSummary
641
+ state_summary = StateChangeSummary (
624
642
block_record ,
625
643
uint32 (max (fork_info .fork_height , 0 )),
626
644
list (rolled_back_state .values ()),
@@ -633,6 +651,8 @@ async def _reconsider_peak(
633
651
[fork_add .coin for fork_add in fork_info .additions_since_fork .values () if fork_add .is_coinbase ],
634
652
)
635
653
654
+ return records_to_add , state_summary
655
+
636
656
def get_next_sub_slot_iters_and_difficulty (self , header_hash : bytes32 , new_slot : bool ) -> tuple [uint64 , uint64 ]:
637
657
curr = self .try_block_record (header_hash )
638
658
assert curr is not None
0 commit comments