Skip to content

Commit b826a8f

Browse files
committed
Prune old verification keys at signer registration round opening
1 parent 59b5f31 commit b826a8f

File tree

3 files changed

+70
-6
lines changed

3 files changed

+70
-6
lines changed

mithril-aggregator/src/dependency_injection/builder.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -643,6 +643,7 @@ impl DependenciesBuilder {
643643
self.get_chain_observer().await?,
644644
self.get_verification_key_store().await?,
645645
self.get_signer_recorder().await?,
646+
self.configuration.store_retention_limit.map(|l| l as u64),
646647
);
647648

648649
Ok(Arc::new(registerer))

mithril-aggregator/src/runtime/runner.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,7 @@ pub mod tests {
733733
deps.chain_observer.clone(),
734734
deps.verification_key_store.clone(),
735735
deps.signer_recorder.clone(),
736+
None,
736737
));
737738
deps.signer_registration_round_opener = signer_registration_round_opener.clone();
738739
let stake_store = deps.stake_store.clone();
@@ -772,6 +773,7 @@ pub mod tests {
772773
deps.chain_observer.clone(),
773774
deps.verification_key_store.clone(),
774775
deps.signer_recorder.clone(),
776+
None,
775777
));
776778
deps.signer_registration_round_opener = signer_registration_round_opener.clone();
777779
let deps = Arc::new(deps);

mithril-aggregator/src/signer_registerer.rs

Lines changed: 67 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,10 @@ pub struct MithrilSignerRegisterer {
136136

137137
/// Signer recorder
138138
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>,
139143
}
140144

141145
impl MithrilSignerRegisterer {
@@ -144,12 +148,14 @@ impl MithrilSignerRegisterer {
144148
chain_observer: Arc<dyn ChainObserver>,
145149
verification_key_store: Arc<dyn VerificationKeyStorer>,
146150
signer_recorder: Arc<dyn SignerRecorder>,
151+
verification_key_epoch_retention_limit: Option<u64>,
147152
) -> Self {
148153
Self {
149154
current_round: RwLock::new(None),
150155
chain_observer,
151156
verification_key_store,
152157
signer_recorder,
158+
verification_key_epoch_retention_limit,
153159
}
154160
}
155161

@@ -172,6 +178,12 @@ impl SignerRegistrationRoundOpener for MithrilSignerRegisterer {
172178
stake_distribution,
173179
});
174180

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+
175187
Ok(())
176188
}
177189

@@ -278,6 +290,7 @@ impl SignerRegisterer for MithrilSignerRegisterer {
278290
mod tests {
279291
use std::{collections::HashMap, sync::Arc};
280292

293+
use mithril_common::test_utils::fake_data;
281294
use mithril_common::{
282295
chain_observer::FakeObserver,
283296
entities::{Epoch, PartyId, Signer, SignerWithStake},
@@ -294,7 +307,6 @@ mod tests {
294307

295308
#[tokio::test]
296309
async fn can_register_signer_if_registration_round_is_opened_with_operational_certificate() {
297-
let chain_observer = FakeObserver::default();
298310
let verification_key_store = Arc::new(VerificationKeyStore::new(Box::new(
299311
MemoryAdapter::<Epoch, HashMap<PartyId, SignerWithStake>>::new(None).unwrap(),
300312
)));
@@ -304,9 +316,10 @@ mod tests {
304316
.returning(|_| Ok(()))
305317
.once();
306318
let signer_registerer = MithrilSignerRegisterer::new(
307-
Arc::new(chain_observer),
319+
Arc::new(FakeObserver::default()),
308320
verification_key_store.clone(),
309321
Arc::new(signer_recorder),
322+
None,
310323
);
311324
let registration_epoch = Epoch(1);
312325
let fixture = MithrilFixtureBuilder::default().with_signers(5).build();
@@ -339,7 +352,6 @@ mod tests {
339352

340353
#[tokio::test]
341354
async fn can_register_signer_if_registration_round_is_opened_without_operational_certificate() {
342-
let chain_observer = FakeObserver::default();
343355
let verification_key_store = Arc::new(VerificationKeyStore::new(Box::new(
344356
MemoryAdapter::<Epoch, HashMap<PartyId, SignerWithStake>>::new(None).unwrap(),
345357
)));
@@ -349,9 +361,10 @@ mod tests {
349361
.returning(|_| Ok(()))
350362
.once();
351363
let signer_registerer = MithrilSignerRegisterer::new(
352-
Arc::new(chain_observer),
364+
Arc::new(FakeObserver::default()),
353365
verification_key_store.clone(),
354366
Arc::new(signer_recorder),
367+
None,
355368
);
356369
let registration_epoch = Epoch(1);
357370
let fixture = MithrilFixtureBuilder::default()
@@ -387,15 +400,15 @@ mod tests {
387400

388401
#[tokio::test]
389402
async fn cant_register_signer_if_registration_round_is_not_opened() {
390-
let chain_observer = FakeObserver::default();
391403
let verification_key_store = Arc::new(VerificationKeyStore::new(Box::new(
392404
MemoryAdapter::<Epoch, HashMap<PartyId, SignerWithStake>>::new(None).unwrap(),
393405
)));
394406
let signer_recorder = MockSignerRecorder::new();
395407
let signer_registerer = MithrilSignerRegisterer::new(
396-
Arc::new(chain_observer),
408+
Arc::new(FakeObserver::default()),
397409
verification_key_store.clone(),
398410
Arc::new(signer_recorder),
411+
None,
399412
);
400413
let registration_epoch = Epoch(1);
401414
let fixture = MithrilFixtureBuilder::default().with_signers(5).build();
@@ -406,4 +419,52 @@ mod tests {
406419
.await
407420
.expect_err("signer registration should fail if no round opened");
408421
}
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+
}
409470
}

0 commit comments

Comments
 (0)