@@ -11,27 +11,38 @@ defmodule LambdaEthereumConsensus.ForkChoice.Head do
11
11
@ spec get_head ( Store . t ( ) ) :: { :ok , Types . root ( ) } | { :error , any }
12
12
def get_head ( % Store { } = store ) do
13
13
# Get filtered block tree that only includes viable branches
14
- blocks = get_filtered_block_tree ( store )
14
+ filtered_blocks = get_filtered_block_tree ( store )
15
15
# Execute the LMD-GHOST fork choice
16
16
head = store . justified_checkpoint . root
17
17
18
18
{ _store , % BeaconState { } = justified_state } =
19
19
Store . get_checkpoint_state ( store , store . justified_checkpoint )
20
20
21
- # PERF: return just the parent root and the block root in `get_filtered_block_tree`
22
- Stream . cycle ( [ nil ] )
23
- |> Enum . reduce_while ( head , fn nil , head ->
24
- blocks
25
- |> Stream . filter ( fn { _ , block } -> block . parent_root == head end )
26
- |> Stream . map ( fn { root , _ } -> root end )
27
- # Ties broken by favoring block with lexicographically higher root
28
- |> Enum . sort ( :desc )
29
- |> then ( fn
30
- [ ] -> { :halt , head }
31
- c -> { :cont , Enum . max_by ( c , & get_weight ( store , & 1 , justified_state ) ) }
32
- end )
33
- end )
34
- |> then ( & { :ok , & 1 } )
21
+ head = compute_head ( store , filtered_blocks , head , justified_state )
22
+ { :ok , head }
23
+ end
24
+
25
+ defp compute_head ( store , blocks , current_root , justified_state ) do
26
+ children = for { root , parent_root } <- blocks , parent_root == current_root , do: root
27
+
28
+ case children do
29
+ [ ] ->
30
+ current_root
31
+
32
+ [ only_child ] ->
33
+ # Directly continue without a max_by call
34
+ compute_head ( store , blocks , only_child , justified_state )
35
+
36
+ candidates ->
37
+ # Choose the candidate with the maximal weight according to get_weight/3
38
+ best_child =
39
+ candidates
40
+ # Ties broken by favoring block with lexicographically higher root
41
+ |> Enum . sort ( :desc )
42
+ |> Enum . max_by ( & get_weight ( store , & 1 , justified_state ) )
43
+
44
+ compute_head ( store , blocks , best_child , justified_state )
45
+ end
35
46
end
36
47
37
48
defp get_weight ( % Store { } = store , root , state ) do
@@ -79,11 +90,12 @@ defmodule LambdaEthereumConsensus.ForkChoice.Head do
79
90
80
91
# Retrieve a filtered block tree from ``store``, only returning branches
81
92
# whose leaf state's justified/finalized info agrees with that in ``store``.
93
+ # Only return the roots and their parent roots.
82
94
defp get_filtered_block_tree ( % Store { } = store ) do
83
95
base = store . justified_checkpoint . root
84
96
block = Blocks . get_block! ( base )
85
97
{ _ , blocks } = filter_block_tree ( store , base , block , % { } )
86
- blocks
98
+ Enum . map ( blocks , fn { root , block } -> { root , block . parent_root } end )
87
99
end
88
100
89
101
defp filter_block_tree ( % Store { } = store , block_root , block , blocks ) do
0 commit comments