@@ -638,6 +638,7 @@ where
638638 }
639639
640640 let parent_weight = if block_number. is_one ( ) {
641+ // The genesis block is given a zero weight.
641642 0
642643 } else {
643644 // Parent block weight might be missing in special sync modes where block is imported in
@@ -646,6 +647,10 @@ where
646647 . unwrap_or_default ( )
647648 } ;
648649
650+ // We prioritise smaller solution ranges numerically, using a solution weight of
651+ // ~`2^64 - range` per block. Solution ranges can be up to ~`2^64`, so it is unlikely
652+ // (but not impossible) that the total extrinsic weight exceeds the total solution weight
653+ // (the maximum block extrinsic weight is ~2^41).
649654 let added_weight = calculate_block_weight ( subspace_digest_items. solution_range ) ;
650655 let total_weight = parent_weight. saturating_add ( added_weight) ;
651656
@@ -672,8 +677,27 @@ where
672677 }
673678 }
674679
675- // The fork choice rule is that we pick the heaviest chain (i.e. smallest solution range),
676- // if there's a tie we go with the longest chain
680+ // The fork choice rule is that we pick the largest total "chain weight".
681+ // This almost always prioritises:
682+ // - the longest chain (the largest number of solutions), and if there is a tie
683+ // - the strictest solutions (the numerically smallest solution ranges),
684+ // and if there is a tie
685+ // - the highest total extrinsic weight.
686+ //
687+ // If the totals are equal:
688+ // - each node keeps the block it already chose (the one that it processed first).
689+ //
690+ // This check is performed using a single integer for the chain weight, so these priorities
691+ // are not perfectly enforced. Unusually large solution ranges, large weights, or long forks
692+ // can temporarily change the priority order above. But this is very unlikely to persist
693+ // beyond a single block, particularly in networks with lots of storage, because the
694+ // solution "weight" per block is much larger than any other factor.
695+ //
696+ // Solution ranges only change at the end of each epoch, but different block times can make
697+ // the range in each fork different. This can lead to an edge case where one fork accepts a
698+ // solution, but another does not. But this would also be resolved with very high
699+ // probability after a few blocks. (And farmers are not incentivised to vote on multiple
700+ // forks, because they have very limited time to vote and audit.)
677701 let fork_choice = {
678702 let info = self . client . info ( ) ;
679703
0 commit comments