@@ -3,7 +3,6 @@ defmodule LambdaEthereumConsensus.ForkChoice do
3
3
The Store is responsible for tracking information required for the fork choice algorithm.
4
4
"""
5
5
6
- use GenServer
7
6
require Logger
8
7
9
8
alias LambdaEthereumConsensus.Beacon.BeaconChain
@@ -18,47 +17,14 @@ defmodule LambdaEthereumConsensus.ForkChoice do
18
17
alias LambdaEthereumConsensus.Store.StoreDb
19
18
alias LambdaEthereumConsensus.Validator.ValidatorManager
20
19
alias Types.Attestation
21
- alias Types.BeaconState
22
- alias Types.SignedBeaconBlock
23
20
alias Types.Store
24
21
25
22
##########################
26
23
### Public API
27
24
##########################
28
25
29
- @ spec start_link ( { BeaconState . t ( ) , SignedBeaconBlock . t ( ) , Types . uint64 ( ) } ) ::
30
- :ignore | { :error , any } | { :ok , pid }
31
- def start_link ( opts ) do
32
- GenServer . start_link ( __MODULE__ , opts , name: __MODULE__ )
33
- end
34
-
35
- @ spec on_tick ( Types . uint64 ( ) ) :: :ok
36
- def on_tick ( time ) do
37
- GenServer . cast ( __MODULE__ , { :on_tick , time } )
38
- end
39
-
40
- @ spec on_block ( BlockInfo . t ( ) ) :: :ok | :error
41
- def on_block ( block_info ) do
42
- GenServer . cast ( __MODULE__ , { :on_block , block_info , self ( ) } )
43
- end
44
-
45
- @ spec on_attestation ( Types.Attestation . t ( ) ) :: :ok
46
- def on_attestation ( % Attestation { } = attestation ) do
47
- GenServer . cast ( __MODULE__ , { :on_attestation , attestation } )
48
- end
49
-
50
- @ spec notify_attester_slashing ( Types.AttesterSlashing . t ( ) ) :: :ok
51
- def notify_attester_slashing ( attester_slashing ) do
52
- GenServer . cast ( __MODULE__ , { :attester_slashing , attester_slashing } )
53
- end
54
-
55
- ##########################
56
- ### GenServer Callbacks
57
- ##########################
58
-
59
- @ impl GenServer
60
- @ spec init ( { Store . t ( ) , Types . slot ( ) , Types . uint64 ( ) } ) :: { :ok , Store . t ( ) } | { :stop , any }
61
- def init ( { % Store { } = store , head_slot , time } ) do
26
+ @ spec init_store ( Store . t ( ) , Types . slot ( ) , Types . uint64 ( ) ) :: :ok | :error
27
+ def init_store ( % Store { } = store , head_slot , time ) do
62
28
Logger . info ( "[Fork choice] Initialized store." , slot: head_slot )
63
29
64
30
store = Handlers . on_tick ( store , time )
@@ -67,11 +33,10 @@ defmodule LambdaEthereumConsensus.ForkChoice do
67
33
:telemetry . execute ( [ :sync , :on_block ] , % { slot: head_slot } )
68
34
69
35
persist_store ( store )
70
- { :ok , store }
71
36
end
72
37
73
- @ impl GenServer
74
- def handle_cast ( { : on_block, % BlockInfo { } = block_info , from } , _store ) do
38
+ @ spec on_block ( BlockInfo . t ( ) ) :: :ok | { :error , String . t ( ) }
39
+ def on_block ( % BlockInfo { } = block_info ) do
75
40
store = fetch_store! ( )
76
41
slot = block_info . signed_block . message . slot
77
42
block_root = block_info . root
@@ -90,25 +55,24 @@ defmodule LambdaEthereumConsensus.ForkChoice do
90
55
:telemetry . execute ( [ :sync , :on_block ] , % { slot: slot } )
91
56
Logger . info ( "[Fork choice] Added new block" , slot: slot , root: block_root )
92
57
93
- Task . async ( __MODULE__ , :recompute_head , [ new_store ] )
58
+ :telemetry . span ( [ :fork_choice , :recompute_head ] , % { } , fn ->
59
+ { recompute_head ( new_store ) , % { } }
60
+ end )
94
61
95
62
% Store { finalized_checkpoint: new_finalized_checkpoint } = new_store
96
63
97
64
prune_old_states ( last_finalized_checkpoint . epoch , new_finalized_checkpoint . epoch )
98
65
99
66
persist_store ( new_store )
100
- GenServer . cast ( from , { :block_processed , block_root , true } )
101
- { :noreply , new_store }
102
67
103
68
{ :error , reason } ->
104
69
Logger . error ( "[Fork choice] Failed to add block: #{ reason } " , slot: slot , root: block_root )
105
- GenServer . cast ( from , { :block_processed , block_root , false } )
106
- { :noreply , store }
70
+ { :error , reason }
107
71
end
108
72
end
109
73
110
- @ impl GenServer
111
- def handle_cast ( { : on_attestation, % Attestation { } = attestation } , % Store { } = _state ) do
74
+ @ spec on_attestation ( Types.Attestation . t ( ) ) :: :ok
75
+ def on_attestation ( % Attestation { } = attestation ) do
112
76
state = fetch_store! ( )
113
77
id = attestation . signature |> Base . encode16 ( ) |> String . slice ( 0 , 8 )
114
78
Logger . debug ( "[Fork choice] Adding attestation #{ id } to the store" )
@@ -120,61 +84,56 @@ defmodule LambdaEthereumConsensus.ForkChoice do
120
84
end
121
85
122
86
persist_store ( state )
123
- { :noreply , state }
124
87
end
125
88
126
- @ impl GenServer
127
- def handle_cast ( { : attester_slashing, attester_slashing } , _state ) do
89
+ @ spec on_attester_slashing ( Types.AttesterSlashing . t ( ) ) :: :ok
90
+ def on_attester_slashing ( attester_slashing ) do
128
91
Logger . info ( "[Fork choice] Adding attester slashing to the store" )
129
92
state = fetch_store! ( )
130
93
131
- state =
132
- case Handlers . on_attester_slashing ( state , attester_slashing ) do
133
- { :ok , new_state } ->
134
- new_state
135
-
136
- _ ->
137
- Logger . error ( "[Fork choice] Failed to add attester slashing to the store" )
138
- state
139
- end
94
+ case Handlers . on_attester_slashing ( state , attester_slashing ) do
95
+ { :ok , new_state } ->
96
+ persist_store ( new_state )
140
97
141
- persist_store ( state )
142
- { :noreply , state }
98
+ _ ->
99
+ Logger . error ( "[Fork choice] Failed to add attester slashing to the store" )
100
+ end
143
101
end
144
102
145
- @ impl GenServer
146
- def handle_cast ( { : on_tick, time } , _store ) do
103
+ @ spec on_tick ( Types . uint64 ( ) ) :: :ok
104
+ def on_tick ( time ) do
147
105
store = fetch_store! ( )
148
106
% Store { finalized_checkpoint: last_finalized_checkpoint } = store
149
107
150
108
new_store = Handlers . on_tick ( store , time )
151
109
% Store { finalized_checkpoint: new_finalized_checkpoint } = new_store
152
110
prune_old_states ( last_finalized_checkpoint . epoch , new_finalized_checkpoint . epoch )
153
111
persist_store ( new_store )
154
- { :noreply , new_store }
155
- end
156
-
157
- @ impl GenServer
158
- def handle_info ( _msg , state ) do
159
- { :noreply , state }
160
112
end
161
113
162
114
##########################
163
115
### Private Functions
164
116
##########################
165
117
166
- def prune_old_states ( last_finalized_epoch , new_finalized_epoch ) do
118
+ defp prune_old_states ( last_finalized_epoch , new_finalized_epoch ) do
167
119
if last_finalized_epoch < new_finalized_epoch do
168
120
new_finalized_slot =
169
121
new_finalized_epoch * ChainSpec . get ( "SLOTS_PER_EPOCH" )
170
122
171
- Task . async ( StateDb , :prune_states_older_than , [ new_finalized_slot ] )
172
- Task . async ( BlockDb , :prune_blocks_older_than , [ new_finalized_slot ] )
123
+ Task.Supervisor . start_child (
124
+ PruneStatesSupervisor ,
125
+ fn -> StateDb . prune_states_older_than ( new_finalized_slot ) end
126
+ )
127
+
128
+ Task.Supervisor . start_child (
129
+ PruneBlocksSupervisor ,
130
+ fn -> BlockDb . prune_blocks_older_than ( new_finalized_slot ) end
131
+ )
173
132
end
174
133
end
175
134
176
135
@ spec apply_handler ( any ( ) , any ( ) , any ( ) ) :: any ( )
177
- def apply_handler ( iter , state , handler ) do
136
+ defp apply_handler ( iter , state , handler ) do
178
137
iter
179
138
|> Enum . reduce_while ( { :ok , state } , fn
180
139
x , { :ok , st } -> { :cont , handler . ( st , x ) }
0 commit comments