@@ -136,6 +136,10 @@ pub struct MithrilSignerRegisterer {
136
136
137
137
/// Signer recorder
138
138
signer_recorder : Arc < dyn SignerRecorder > ,
139
+
140
+ /// Number of epochs before previous records will be deleted at the next registration round
141
+ /// opening
142
+ verification_key_epoch_retention_limit : Option < u64 > ,
139
143
}
140
144
141
145
impl MithrilSignerRegisterer {
@@ -144,12 +148,14 @@ impl MithrilSignerRegisterer {
144
148
chain_observer : Arc < dyn ChainObserver > ,
145
149
verification_key_store : Arc < dyn VerificationKeyStorer > ,
146
150
signer_recorder : Arc < dyn SignerRecorder > ,
151
+ verification_key_epoch_retention_limit : Option < u64 > ,
147
152
) -> Self {
148
153
Self {
149
154
current_round : RwLock :: new ( None ) ,
150
155
chain_observer,
151
156
verification_key_store,
152
157
signer_recorder,
158
+ verification_key_epoch_retention_limit,
153
159
}
154
160
}
155
161
@@ -172,6 +178,12 @@ impl SignerRegistrationRoundOpener for MithrilSignerRegisterer {
172
178
stake_distribution,
173
179
} ) ;
174
180
181
+ if let Some ( retention_limit) = self . verification_key_epoch_retention_limit {
182
+ self . verification_key_store
183
+ . prune_verification_keys ( registration_epoch - retention_limit)
184
+ . await ?;
185
+ }
186
+
175
187
Ok ( ( ) )
176
188
}
177
189
@@ -278,6 +290,7 @@ impl SignerRegisterer for MithrilSignerRegisterer {
278
290
mod tests {
279
291
use std:: { collections:: HashMap , sync:: Arc } ;
280
292
293
+ use mithril_common:: test_utils:: fake_data;
281
294
use mithril_common:: {
282
295
chain_observer:: FakeObserver ,
283
296
entities:: { Epoch , PartyId , Signer , SignerWithStake } ,
@@ -294,7 +307,6 @@ mod tests {
294
307
295
308
#[ tokio:: test]
296
309
async fn can_register_signer_if_registration_round_is_opened_with_operational_certificate ( ) {
297
- let chain_observer = FakeObserver :: default ( ) ;
298
310
let verification_key_store = Arc :: new ( VerificationKeyStore :: new ( Box :: new (
299
311
MemoryAdapter :: < Epoch , HashMap < PartyId , SignerWithStake > > :: new ( None ) . unwrap ( ) ,
300
312
) ) ) ;
@@ -304,9 +316,10 @@ mod tests {
304
316
. returning ( |_| Ok ( ( ) ) )
305
317
. once ( ) ;
306
318
let signer_registerer = MithrilSignerRegisterer :: new (
307
- Arc :: new ( chain_observer ) ,
319
+ Arc :: new ( FakeObserver :: default ( ) ) ,
308
320
verification_key_store. clone ( ) ,
309
321
Arc :: new ( signer_recorder) ,
322
+ None ,
310
323
) ;
311
324
let registration_epoch = Epoch ( 1 ) ;
312
325
let fixture = MithrilFixtureBuilder :: default ( ) . with_signers ( 5 ) . build ( ) ;
@@ -339,7 +352,6 @@ mod tests {
339
352
340
353
#[ tokio:: test]
341
354
async fn can_register_signer_if_registration_round_is_opened_without_operational_certificate ( ) {
342
- let chain_observer = FakeObserver :: default ( ) ;
343
355
let verification_key_store = Arc :: new ( VerificationKeyStore :: new ( Box :: new (
344
356
MemoryAdapter :: < Epoch , HashMap < PartyId , SignerWithStake > > :: new ( None ) . unwrap ( ) ,
345
357
) ) ) ;
@@ -349,9 +361,10 @@ mod tests {
349
361
. returning ( |_| Ok ( ( ) ) )
350
362
. once ( ) ;
351
363
let signer_registerer = MithrilSignerRegisterer :: new (
352
- Arc :: new ( chain_observer ) ,
364
+ Arc :: new ( FakeObserver :: default ( ) ) ,
353
365
verification_key_store. clone ( ) ,
354
366
Arc :: new ( signer_recorder) ,
367
+ None ,
355
368
) ;
356
369
let registration_epoch = Epoch ( 1 ) ;
357
370
let fixture = MithrilFixtureBuilder :: default ( )
@@ -387,15 +400,15 @@ mod tests {
387
400
388
401
#[ tokio:: test]
389
402
async fn cant_register_signer_if_registration_round_is_not_opened ( ) {
390
- let chain_observer = FakeObserver :: default ( ) ;
391
403
let verification_key_store = Arc :: new ( VerificationKeyStore :: new ( Box :: new (
392
404
MemoryAdapter :: < Epoch , HashMap < PartyId , SignerWithStake > > :: new ( None ) . unwrap ( ) ,
393
405
) ) ) ;
394
406
let signer_recorder = MockSignerRecorder :: new ( ) ;
395
407
let signer_registerer = MithrilSignerRegisterer :: new (
396
- Arc :: new ( chain_observer ) ,
408
+ Arc :: new ( FakeObserver :: default ( ) ) ,
397
409
verification_key_store. clone ( ) ,
398
410
Arc :: new ( signer_recorder) ,
411
+ None ,
399
412
) ;
400
413
let registration_epoch = Epoch ( 1 ) ;
401
414
let fixture = MithrilFixtureBuilder :: default ( ) . with_signers ( 5 ) . build ( ) ;
@@ -406,4 +419,52 @@ mod tests {
406
419
. await
407
420
. expect_err ( "signer registration should fail if no round opened" ) ;
408
421
}
422
+
423
+ #[ tokio:: test]
424
+ async fn should_prune_verification_keys_older_than_two_epochs_at_round_opening ( ) {
425
+ let initial_keys = ( 1 ..=5 )
426
+ . map ( |epoch| {
427
+ let signers: HashMap < PartyId , SignerWithStake > = HashMap :: from_iter (
428
+ fake_data:: signers_with_stakes ( 1 )
429
+ . into_iter ( )
430
+ . map ( |s| ( s. party_id . to_owned ( ) , s) ) ,
431
+ ) ;
432
+ ( Epoch ( epoch) , signers)
433
+ } )
434
+ . collect ( ) ;
435
+ let verification_key_store = Arc :: new ( VerificationKeyStore :: new ( Box :: new (
436
+ MemoryAdapter :: < Epoch , HashMap < PartyId , SignerWithStake > > :: new ( Some ( initial_keys) )
437
+ . unwrap ( ) ,
438
+ ) ) ) ;
439
+ let signer_recorder = MockSignerRecorder :: new ( ) ;
440
+ let signer_registerer = MithrilSignerRegisterer :: new (
441
+ Arc :: new ( FakeObserver :: default ( ) ) ,
442
+ verification_key_store. clone ( ) ,
443
+ Arc :: new ( signer_recorder) ,
444
+ Some ( 2 ) ,
445
+ ) ;
446
+ let fixture = MithrilFixtureBuilder :: default ( ) . with_signers ( 5 ) . build ( ) ;
447
+
448
+ signer_registerer
449
+ . open_registration_round ( Epoch ( 5 ) , fixture. stake_distribution ( ) )
450
+ . await
451
+ . expect ( "Opening a registration round should not fail" ) ;
452
+
453
+ for epoch in 1 ..=3 {
454
+ let verification_keys = verification_key_store
455
+ . get_verification_keys ( Epoch ( epoch) )
456
+ . await
457
+ . unwrap ( ) ;
458
+ assert_eq ! ( None , verification_keys) ;
459
+ }
460
+
461
+ let verification_keys = verification_key_store
462
+ . get_verification_keys ( Epoch ( 4 ) )
463
+ . await
464
+ . unwrap ( ) ;
465
+ assert ! (
466
+ verification_keys. is_some( ) ,
467
+ "Verification keys of the previous epoch should not have been pruned"
468
+ ) ;
469
+ }
409
470
}
0 commit comments