@@ -4,7 +4,7 @@ use beacon_chain::test_utils::{
4
4
use beacon_chain:: validator_monitor:: { ValidatorMonitorConfig , MISSED_BLOCK_LAG_SLOTS } ;
5
5
use logging:: test_logger;
6
6
use std:: sync:: LazyLock ;
7
- use types:: { Epoch , EthSpec , ForkName , Keypair , MainnetEthSpec , PublicKeyBytes , Slot } ;
7
+ use types:: { Epoch , EthSpec , Keypair , MainnetEthSpec , PublicKeyBytes , Slot } ;
8
8
9
9
// Should ideally be divisible by 3.
10
10
pub const VALIDATOR_COUNT : usize = 48 ;
@@ -117,7 +117,7 @@ async fn missed_blocks_across_epochs() {
117
117
}
118
118
119
119
#[ tokio:: test]
120
- async fn produces_missed_blocks ( ) {
120
+ async fn missed_blocks_basic ( ) {
121
121
let validator_count = 16 ;
122
122
123
123
let slots_per_epoch = E :: slots_per_epoch ( ) ;
@@ -127,13 +127,10 @@ async fn produces_missed_blocks() {
127
127
// Generate 63 slots (2 epochs * 32 slots per epoch - 1)
128
128
let initial_blocks = slots_per_epoch * nb_epoch_to_simulate. as_u64 ( ) - 1 ;
129
129
130
- // The validator index of the validator that is 'supposed' to miss a block
131
- let validator_index_to_monitor = 1 ;
132
-
133
130
// 1st scenario //
134
131
//
135
132
// Missed block happens when slot and prev_slot are in the same epoch
136
- let harness1 = get_harness ( validator_count, vec ! [ validator_index_to_monitor ] ) ;
133
+ let harness1 = get_harness ( validator_count, vec ! [ ] ) ;
137
134
harness1
138
135
. extend_chain (
139
136
initial_blocks as usize ,
@@ -153,7 +150,7 @@ async fn produces_missed_blocks() {
153
150
let mut prev_slot = Slot :: new ( idx - 1 ) ;
154
151
let mut duplicate_block_root = * _state. block_roots ( ) . get ( idx as usize ) . unwrap ( ) ;
155
152
let mut validator_indexes = _state. get_beacon_proposer_indices ( & harness1. spec ) . unwrap ( ) ;
156
- let mut validator_index = validator_indexes[ slot_in_epoch. as_usize ( ) ] ;
153
+ let mut missed_block_proposer = validator_indexes[ slot_in_epoch. as_usize ( ) ] ;
157
154
let mut proposer_shuffling_decision_root = _state
158
155
. proposer_shuffling_decision_root ( duplicate_block_root)
159
156
. unwrap ( ) ;
@@ -170,7 +167,7 @@ async fn produces_missed_blocks() {
170
167
beacon_proposer_cache. lock( ) . insert(
171
168
epoch,
172
169
proposer_shuffling_decision_root,
173
- validator_indexes. into_iter ( ) . collect :: < Vec < usize >> ( ) ,
170
+ validator_indexes,
174
171
_state. fork( )
175
172
) ,
176
173
Ok ( ( ) )
@@ -187,12 +184,15 @@ async fn produces_missed_blocks() {
187
184
// Let's validate the state which will call the function responsible for
188
185
// adding the missed blocks to the validator monitor
189
186
let mut validator_monitor = harness1. chain . validator_monitor . write ( ) ;
187
+
188
+ validator_monitor. add_validator_pubkey ( KEYPAIRS [ missed_block_proposer] . pk . compress ( ) ) ;
190
189
validator_monitor. process_valid_state ( nb_epoch_to_simulate, _state, & harness1. chain . spec ) ;
191
190
192
191
// We should have one entry in the missed blocks map
193
192
assert_eq ! (
194
- validator_monitor. get_monitored_validator_missed_block_count( validator_index as u64 ) ,
195
- 1
193
+ validator_monitor
194
+ . get_monitored_validator_missed_block_count( missed_block_proposer as u64 ) ,
195
+ 1 ,
196
196
) ;
197
197
}
198
198
@@ -201,23 +201,7 @@ async fn produces_missed_blocks() {
201
201
// Missed block happens when slot and prev_slot are not in the same epoch
202
202
// making sure that the cache reloads when the epoch changes
203
203
// in that scenario the slot that missed a block is the first slot of the epoch
204
- // We are adding other validators to monitor as these ones will miss a block depending on
205
- // the fork name specified when running the test as the proposer cache differs depending on
206
- // the fork name (cf. seed)
207
- //
208
- // If you are adding a new fork and seeing errors, print
209
- // `validator_indexes[slot_in_epoch.as_usize()]` and add it below.
210
- let validator_index_to_monitor = match harness1. spec . fork_name_at_slot :: < E > ( Slot :: new ( 0 ) ) {
211
- ForkName :: Base => 7 ,
212
- ForkName :: Altair => 2 ,
213
- ForkName :: Bellatrix => 4 ,
214
- ForkName :: Capella => 11 ,
215
- ForkName :: Deneb => 3 ,
216
- ForkName :: Electra => 1 ,
217
- ForkName :: Fulu => 6 ,
218
- } ;
219
-
220
- let harness2 = get_harness ( validator_count, vec ! [ validator_index_to_monitor] ) ;
204
+ let harness2 = get_harness ( validator_count, vec ! [ ] ) ;
221
205
let advance_slot_by = 9 ;
222
206
harness2
223
207
. extend_chain (
@@ -238,11 +222,7 @@ async fn produces_missed_blocks() {
238
222
slot_in_epoch = slot % slots_per_epoch;
239
223
duplicate_block_root = * _state2. block_roots ( ) . get ( idx as usize ) . unwrap ( ) ;
240
224
validator_indexes = _state2. get_beacon_proposer_indices ( & harness2. spec ) . unwrap ( ) ;
241
- validator_index = validator_indexes[ slot_in_epoch. as_usize ( ) ] ;
242
- // If you are adding a new fork and seeing errors, it means the fork seed has changed the
243
- // validator_index. Uncomment this line, run the test again and add the resulting index to the
244
- // list above.
245
- //eprintln!("new index which needs to be added => {:?}", validator_index);
225
+ missed_block_proposer = validator_indexes[ slot_in_epoch. as_usize ( ) ] ;
246
226
247
227
let beacon_proposer_cache = harness2
248
228
. chain
@@ -256,7 +236,7 @@ async fn produces_missed_blocks() {
256
236
beacon_proposer_cache. lock( ) . insert(
257
237
epoch,
258
238
duplicate_block_root,
259
- validator_indexes. into_iter ( ) . collect :: < Vec < usize >> ( ) ,
239
+ validator_indexes. clone ( ) ,
260
240
_state2. fork( )
261
241
) ,
262
242
Ok ( ( ) )
@@ -271,30 +251,33 @@ async fn produces_missed_blocks() {
271
251
// Let's validate the state which will call the function responsible for
272
252
// adding the missed blocks to the validator monitor
273
253
let mut validator_monitor2 = harness2. chain . validator_monitor . write ( ) ;
254
+ validator_monitor2. add_validator_pubkey ( KEYPAIRS [ missed_block_proposer] . pk . compress ( ) ) ;
274
255
validator_monitor2. process_valid_state ( epoch, _state2, & harness2. chain . spec ) ;
275
256
// We should have one entry in the missed blocks map
276
257
assert_eq ! (
277
- validator_monitor2. get_monitored_validator_missed_block_count( validator_index as u64 ) ,
258
+ validator_monitor2
259
+ . get_monitored_validator_missed_block_count( missed_block_proposer as u64 ) ,
278
260
1
279
261
) ;
280
262
281
263
// 3rd scenario //
282
264
//
283
265
// A missed block happens but the validator is not monitored
284
266
// it should not be flagged as a missed block
285
- idx = initial_blocks + ( advance_slot_by) - 7 ;
267
+ while validator_indexes[ ( idx % slots_per_epoch) as usize ] == missed_block_proposer
268
+ && idx / slots_per_epoch == epoch. as_u64 ( )
269
+ {
270
+ idx += 1 ;
271
+ }
286
272
slot = Slot :: new ( idx) ;
287
273
prev_slot = Slot :: new ( idx - 1 ) ;
288
274
slot_in_epoch = slot % slots_per_epoch;
289
275
duplicate_block_root = * _state2. block_roots ( ) . get ( idx as usize ) . unwrap ( ) ;
290
- validator_indexes = _state2. get_beacon_proposer_indices ( & harness2. spec ) . unwrap ( ) ;
291
- let not_monitored_validator_index = validator_indexes[ slot_in_epoch. as_usize ( ) ] ;
292
- // This could do with a refactor: https://github.com/sigp/lighthouse/issues/6293
293
- assert_ne ! (
294
- not_monitored_validator_index,
295
- validator_index_to_monitor,
296
- "this test has a fragile dependency on hardcoded indices. you need to tweak some settings or rewrite this"
297
- ) ;
276
+ let second_missed_block_proposer = validator_indexes[ slot_in_epoch. as_usize ( ) ] ;
277
+
278
+ // This test may fail if we can't find another distinct proposer in the same epoch.
279
+ // However, this should be vanishingly unlikely: P ~= (1/16)^32 = 2e-39.
280
+ assert_ne ! ( missed_block_proposer, second_missed_block_proposer) ;
298
281
299
282
assert_eq ! (
300
283
_state2. set_block_root( prev_slot, duplicate_block_root) ,
@@ -306,10 +289,9 @@ async fn produces_missed_blocks() {
306
289
validator_monitor2. process_valid_state ( epoch, _state2, & harness2. chain . spec ) ;
307
290
308
291
// We shouldn't have any entry in the missed blocks map
309
- assert_ne ! ( validator_index, not_monitored_validator_index) ;
310
292
assert_eq ! (
311
293
validator_monitor2
312
- . get_monitored_validator_missed_block_count( not_monitored_validator_index as u64 ) ,
294
+ . get_monitored_validator_missed_block_count( second_missed_block_proposer as u64 ) ,
313
295
0
314
296
) ;
315
297
}
@@ -318,7 +300,7 @@ async fn produces_missed_blocks() {
318
300
//
319
301
// A missed block happens at state.slot - LOG_SLOTS_PER_EPOCH
320
302
// it shouldn't be flagged as a missed block
321
- let harness3 = get_harness ( validator_count, vec ! [ validator_index_to_monitor ] ) ;
303
+ let harness3 = get_harness ( validator_count, vec ! [ ] ) ;
322
304
harness3
323
305
. extend_chain (
324
306
slots_per_epoch as usize ,
@@ -338,7 +320,7 @@ async fn produces_missed_blocks() {
338
320
prev_slot = Slot :: new ( idx - 1 ) ;
339
321
duplicate_block_root = * _state3. block_roots ( ) . get ( idx as usize ) . unwrap ( ) ;
340
322
validator_indexes = _state3. get_beacon_proposer_indices ( & harness3. spec ) . unwrap ( ) ;
341
- validator_index = validator_indexes[ slot_in_epoch. as_usize ( ) ] ;
323
+ missed_block_proposer = validator_indexes[ slot_in_epoch. as_usize ( ) ] ;
342
324
proposer_shuffling_decision_root = _state3
343
325
. proposer_shuffling_decision_root_at_epoch ( epoch, duplicate_block_root)
344
326
. unwrap ( ) ;
@@ -355,7 +337,7 @@ async fn produces_missed_blocks() {
355
337
beacon_proposer_cache. lock( ) . insert(
356
338
epoch,
357
339
proposer_shuffling_decision_root,
358
- validator_indexes. into_iter ( ) . collect :: < Vec < usize >> ( ) ,
340
+ validator_indexes,
359
341
_state3. fork( )
360
342
) ,
361
343
Ok ( ( ) )
@@ -372,11 +354,13 @@ async fn produces_missed_blocks() {
372
354
// Let's validate the state which will call the function responsible for
373
355
// adding the missed blocks to the validator monitor
374
356
let mut validator_monitor3 = harness3. chain . validator_monitor . write ( ) ;
357
+ validator_monitor3. add_validator_pubkey ( KEYPAIRS [ missed_block_proposer] . pk . compress ( ) ) ;
375
358
validator_monitor3. process_valid_state ( epoch, _state3, & harness3. chain . spec ) ;
376
359
377
360
// We shouldn't have one entry in the missed blocks map
378
361
assert_eq ! (
379
- validator_monitor3. get_monitored_validator_missed_block_count( validator_index as u64 ) ,
362
+ validator_monitor3
363
+ . get_monitored_validator_missed_block_count( missed_block_proposer as u64 ) ,
380
364
0
381
365
) ;
382
366
}
0 commit comments