@@ -638,6 +638,7 @@ where
638
638
}
639
639
640
640
let parent_weight = if block_number. is_one ( ) {
641
+ // The genesis block is given a zero weight.
641
642
0
642
643
} else {
643
644
// Parent block weight might be missing in special sync modes where block is imported in
@@ -646,6 +647,10 @@ where
646
647
. unwrap_or_default ( )
647
648
} ;
648
649
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).
649
654
let added_weight = calculate_block_weight ( subspace_digest_items. solution_range ) ;
650
655
let total_weight = parent_weight. saturating_add ( added_weight) ;
651
656
@@ -672,8 +677,27 @@ where
672
677
}
673
678
}
674
679
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.)
677
701
let fork_choice = {
678
702
let info = self . client . info ( ) ;
679
703
0 commit comments