@@ -4,6 +4,7 @@ defmodule LambdaEthereumConsensus.Validator.Duties do
4
4
"""
5
5
alias LambdaEthereumConsensus.StateTransition.Accessors
6
6
alias LambdaEthereumConsensus.StateTransition.Misc
7
+ alias LambdaEthereumConsensus.Validator
7
8
alias LambdaEthereumConsensus.Validator.Utils
8
9
alias LambdaEthereumConsensus.ValidatorSet
9
10
alias Types.BeaconState
@@ -44,69 +45,42 @@ defmodule LambdaEthereumConsensus.Validator.Duties do
44
45
}
45
46
46
47
############################
47
- # Accessors
48
-
49
- @ spec current_proposer ( duties ( ) , Types . epoch ( ) , Types . slot ( ) ) :: proposer_duty ( ) | nil
50
- def current_proposer ( duties , epoch , slot ) ,
51
- do: get_in ( duties , [ epoch , :proposers , slot ] )
48
+ # Main Compute functions
52
49
53
- @ spec current_sync_committee ( duties ( ) , Types . epoch ( ) , Types . slot ( ) ) ::
54
- sync_committee_duties ( )
55
- def current_sync_committee ( duties , epoch , slot ) do
56
- for % { last_slot_broadcasted: last_slot } = duty <- sync_committee ( duties , epoch ) ,
57
- last_slot < slot do
58
- duty
59
- end
60
- end
61
-
62
- @ spec current_attesters ( duties ( ) , Types . epoch ( ) , Types . slot ( ) ) :: attester_duties ( )
63
- def current_attesters ( duties , epoch , slot ) do
64
- for % { attested?: false } = duty <- attesters ( duties , epoch , slot ) do
65
- duty
66
- end
67
- end
50
+ @ spec compute_duties_for_epochs (
51
+ % { Types . epoch ( ) => duties ( ) } ,
52
+ [ { Types . epoch ( ) , Types . slot ( ) } ] ,
53
+ Types . root ( ) ,
54
+ ValidatorSet . validators ( )
55
+ ) :: duties ( )
56
+ def compute_duties_for_epochs ( duties_map , epochs_and_start_slots , head_root , validators ) do
57
+ for { epoch , slot } <- epochs_and_start_slots , reduce: duties_map do
58
+ duties_map ->
59
+ beacon = Validator . fetch_target_state_and_go_to_slot ( slot , head_root )
60
+ last_epoch = Map . keys ( duties_map ) |> Enum . max ( fn -> 0 end )
61
+
62
+ new_proposers = compute_proposers_for_epoch ( beacon , epoch , validators )
63
+ new_attesters = compute_attesters_for_epoch ( beacon , epoch , validators )
64
+
65
+ new_sync_committees =
66
+ case sync_committee_compute_check ( epoch , { last_epoch , Map . get ( duties_map , last_epoch ) } ) do
67
+ { :already_computed , sync_committees } -> sync_committees
68
+ :not_computed -> compute_current_sync_committees ( beacon , validators )
69
+ end
70
+
71
+ new_duties = % {
72
+ proposers: new_proposers ,
73
+ attesters: new_attesters ,
74
+ sync_committees: new_sync_committees
75
+ }
68
76
69
- @ spec current_aggregators ( duties ( ) , Types . epoch ( ) , Types . slot ( ) ) :: attester_duties ( )
70
- def current_aggregators ( duties , epoch , slot ) do
71
- for % { should_aggregate?: true } = duty <- attesters ( duties , epoch , slot ) do
72
- duty
77
+ Map . put ( duties_map , epoch , new_duties )
73
78
end
74
79
end
75
80
76
- defp sync_committee ( duties , epoch ) , do: get_in ( duties , [ epoch , :sync_committees ] ) || [ ]
77
- defp attesters ( duties , epoch , slot ) , do: get_in ( duties , [ epoch , :attesters , slot ] ) || [ ]
78
-
79
- ############################
80
- # Update functions
81
-
82
- @ spec update_duties! (
83
- duties ( ) ,
84
- kind ( ) ,
85
- Types . epoch ( ) ,
86
- Types . slot ( ) ,
87
- attester_duties ( ) | proposer_duties ( )
88
- ) :: duties ( )
89
- def update_duties! ( duties , :sync_committees , epoch , _slot , updated ) ,
90
- do: put_in ( duties , [ epoch , :sync_committees ] , updated )
91
-
92
- def update_duties! ( duties , kind , epoch , slot , updated ) ,
93
- do: put_in ( duties , [ epoch , kind , slot ] , updated )
94
-
95
- @ spec attested ( attester_duty ( ) ) :: attester_duty ( )
96
- def attested ( duty ) , do: Map . put ( duty , :attested? , true )
97
-
98
- @ spec aggregated ( attester_duty ( ) ) :: attester_duty ( )
99
- def aggregated ( duty ) , do: Map . put ( duty , :should_aggregate? , false )
100
-
101
- @ spec sync_committee_broadcasted ( sync_committee_duty ( ) , Types . slot ( ) ) :: sync_committee_duty ( )
102
- def sync_committee_broadcasted ( duty , slot ) , do: Map . put ( duty , :last_slot_broadcasted , slot )
103
-
104
- ############################
105
- # Main functions
106
-
107
81
@ spec compute_proposers_for_epoch ( BeaconState . t ( ) , Types . epoch ( ) , ValidatorSet . validators ( ) ) ::
108
82
proposer_duties_per_slot ( )
109
- def compute_proposers_for_epoch ( % BeaconState { } = state , epoch , validators ) do
83
+ defp compute_proposers_for_epoch ( % BeaconState { } = state , epoch , validators ) do
110
84
with { :ok , epoch } <- check_valid_epoch ( state , epoch ) ,
111
85
{ start_slot , end_slot } <- boundary_slots ( epoch ) do
112
86
for slot <- start_slot .. end_slot ,
@@ -120,7 +94,7 @@ defmodule LambdaEthereumConsensus.Validator.Duties do
120
94
121
95
@ spec compute_current_sync_committees ( BeaconState . t ( ) , ValidatorSet . validators ( ) ) ::
122
96
sync_committee_duties ( )
123
- def compute_current_sync_committees ( % BeaconState { } = state , validators ) do
97
+ defp compute_current_sync_committees ( % BeaconState { } = state , validators ) do
124
98
for validator_index <- Map . keys ( validators ) ,
125
99
subnet_ids = Utils . compute_subnets_for_sync_committee ( state , validator_index ) do
126
100
% {
@@ -131,9 +105,20 @@ defmodule LambdaEthereumConsensus.Validator.Duties do
131
105
end
132
106
end
133
107
108
+ defp sync_committee_compute_check ( _epoch , { _last_epoch , nil } ) , do: :not_computed
109
+
110
+ defp sync_committee_compute_check ( epoch , { last_epoch , last_duties } ) do
111
+ last_period = Misc . compute_sync_committee_period ( last_epoch )
112
+ current_period = Misc . compute_sync_committee_period ( epoch )
113
+
114
+ if last_period == current_period ,
115
+ do: { :already_computed , last_duties . sync_committees } ,
116
+ else: :not_computed
117
+ end
118
+
134
119
@ spec compute_attesters_for_epoch ( BeaconState . t ( ) , Types . epoch ( ) , ValidatorSet . validators ( ) ) ::
135
120
attester_duties_per_slot ( )
136
- def compute_attesters_for_epoch ( % BeaconState { } = state , epoch , validators ) do
121
+ defp compute_attesters_for_epoch ( % BeaconState { } = state , epoch , validators ) do
137
122
with { :ok , epoch } <- check_valid_epoch ( state , epoch ) ,
138
123
{ start_slot , end_slot } <- boundary_slots ( epoch ) do
139
124
committee_count_per_slot = Accessors . get_committee_count_per_slot ( state , epoch )
@@ -193,6 +178,64 @@ defmodule LambdaEthereumConsensus.Validator.Duties do
193
178
Map . put ( duty , :subnet_id , subnet_id )
194
179
end
195
180
181
+ ############################
182
+ # Accessors
183
+
184
+ @ spec current_proposer ( duties ( ) , Types . epoch ( ) , Types . slot ( ) ) :: proposer_duty ( ) | nil
185
+ def current_proposer ( duties , epoch , slot ) ,
186
+ do: get_in ( duties , [ epoch , :proposers , slot ] )
187
+
188
+ @ spec current_sync_committee ( duties ( ) , Types . epoch ( ) , Types . slot ( ) ) ::
189
+ sync_committee_duties ( )
190
+ def current_sync_committee ( duties , epoch , slot ) do
191
+ for % { last_slot_broadcasted: last_slot } = duty <- sync_committee ( duties , epoch ) ,
192
+ last_slot < slot do
193
+ duty
194
+ end
195
+ end
196
+
197
+ @ spec current_attesters ( duties ( ) , Types . epoch ( ) , Types . slot ( ) ) :: attester_duties ( )
198
+ def current_attesters ( duties , epoch , slot ) do
199
+ for % { attested?: false } = duty <- attesters ( duties , epoch , slot ) do
200
+ duty
201
+ end
202
+ end
203
+
204
+ @ spec current_aggregators ( duties ( ) , Types . epoch ( ) , Types . slot ( ) ) :: attester_duties ( )
205
+ def current_aggregators ( duties , epoch , slot ) do
206
+ for % { should_aggregate?: true } = duty <- attesters ( duties , epoch , slot ) do
207
+ duty
208
+ end
209
+ end
210
+
211
+ defp sync_committee ( duties , epoch ) , do: get_in ( duties , [ epoch , :sync_committees ] ) || [ ]
212
+ defp attesters ( duties , epoch , slot ) , do: get_in ( duties , [ epoch , :attesters , slot ] ) || [ ]
213
+
214
+ ############################
215
+ # Update functions
216
+
217
+ @ spec update_duties! (
218
+ duties ( ) ,
219
+ kind ( ) ,
220
+ Types . epoch ( ) ,
221
+ Types . slot ( ) ,
222
+ attester_duties ( ) | proposer_duties ( )
223
+ ) :: duties ( )
224
+ def update_duties! ( duties , :sync_committees , epoch , _slot , updated ) ,
225
+ do: put_in ( duties , [ epoch , :sync_committees ] , updated )
226
+
227
+ def update_duties! ( duties , kind , epoch , slot , updated ) ,
228
+ do: put_in ( duties , [ epoch , kind , slot ] , updated )
229
+
230
+ @ spec attested ( attester_duty ( ) ) :: attester_duty ( )
231
+ def attested ( duty ) , do: Map . put ( duty , :attested? , true )
232
+
233
+ @ spec aggregated ( attester_duty ( ) ) :: attester_duty ( )
234
+ def aggregated ( duty ) , do: Map . put ( duty , :should_aggregate? , false )
235
+
236
+ @ spec sync_committee_broadcasted ( sync_committee_duty ( ) , Types . slot ( ) ) :: sync_committee_duty ( )
237
+ def sync_committee_broadcasted ( duty , slot ) , do: Map . put ( duty , :last_slot_broadcasted , slot )
238
+
196
239
############################
197
240
# Helpers
198
241
0 commit comments