Skip to content

Commit 58ae447

Browse files
committed
Migrate pruning of signer registrations in the upkeep service
1 parent b4ec1a6 commit 58ae447

File tree

3 files changed

+106
-56
lines changed

3 files changed

+106
-56
lines changed

mithril-aggregator/src/database/repository/signer_registration_store.rs

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -98,12 +98,10 @@ impl VerificationKeyStorer for SignerRegistrationStore {
9898
}
9999

100100
async fn prune_verification_keys(&self, max_epoch_to_prune: Epoch) -> StdResult<()> {
101-
let _deleted_records = self
102-
.connection
103-
.fetch_first(
104-
// we want to prune including the given epoch (+1)
105-
DeleteSignerRegistrationRecordQuery::below_epoch_threshold(max_epoch_to_prune + 1),
106-
)
101+
self.connection
102+
.apply(DeleteSignerRegistrationRecordQuery::below_epoch_threshold(
103+
max_epoch_to_prune,
104+
))
107105
.map_err(AdapterError::QueryError)?;
108106

109107
Ok(())
@@ -190,7 +188,7 @@ mod tests {
190188

191189
pub fn init_signer_registration_store(
192190
initial_data: Vec<(Epoch, HashMap<PartyId, SignerWithStake>)>,
193-
) -> Arc<dyn VerificationKeyStorer> {
191+
) -> Arc<SignerRegistrationStore> {
194192
let connection = main_db_connection().unwrap();
195193
let initial_data: Vec<(Epoch, Vec<SignerWithStake>)> = initial_data
196194
.into_iter()
@@ -328,12 +326,50 @@ mod tests {
328326
"Keys should exist before pruning"
329327
);
330328
store
331-
.prune_verification_keys(Epoch(epoch))
329+
.prune_verification_keys(Epoch(epoch) + 1)
332330
.await
333331
.expect("Pruning should not fail");
334332

335333
let pruned_epoch_keys = store.get_verification_keys(Epoch(epoch)).await.unwrap();
336334
assert_eq!(None, pruned_epoch_keys);
337335
}
338336
}
337+
338+
async fn get_epochs_in_database_until(
339+
store: &SignerRegistrationStore,
340+
until_epoch: Epoch,
341+
) -> Vec<Epoch> {
342+
let mut epochs_in_database = vec![];
343+
let mut current_epoch = Epoch(1);
344+
while current_epoch <= until_epoch {
345+
if store
346+
.get_verification_keys(current_epoch)
347+
.await
348+
.unwrap()
349+
.is_some()
350+
{
351+
epochs_in_database.push(current_epoch);
352+
}
353+
current_epoch += 1;
354+
}
355+
epochs_in_database
356+
}
357+
358+
#[tokio::test]
359+
async fn prune_epoch_older_than_threshold() {
360+
let signers = build_signers(5, 2);
361+
let store = init_signer_registration_store(signers);
362+
363+
assert_eq!(
364+
vec!(Epoch(1), Epoch(2), Epoch(3), Epoch(4), Epoch(5)),
365+
get_epochs_in_database_until(&store, Epoch(8)).await
366+
);
367+
368+
store.prune_verification_keys(Epoch(4)).await.unwrap();
369+
370+
assert_eq!(
371+
vec!(Epoch(4), Epoch(5)),
372+
get_epochs_in_database_until(&store, Epoch(8)).await
373+
);
374+
}
339375
}

mithril-aggregator/src/dependency_injection/builder.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1315,14 +1315,19 @@ impl DependenciesBuilder {
13151315
async fn build_upkeep_service(&mut self) -> Result<Arc<dyn UpkeepService>> {
13161316
let stake_pool_pruning_task = self.get_stake_store().await?;
13171317
let epoch_settings_pruning_task = self.get_epoch_settings_store().await?;
1318+
let mithril_registerer_pruning_task = self.get_mithril_registerer().await?;
13181319

13191320
let upkeep_service = Arc::new(AggregatorUpkeepService::new(
13201321
self.get_sqlite_connection().await?,
13211322
self.get_sqlite_connection_cardano_transaction_pool()
13221323
.await?,
13231324
self.get_event_store_sqlite_connection().await?,
13241325
self.get_signed_entity_lock().await?,
1325-
vec![stake_pool_pruning_task, epoch_settings_pruning_task],
1326+
vec![
1327+
stake_pool_pruning_task,
1328+
epoch_settings_pruning_task,
1329+
mithril_registerer_pruning_task,
1330+
],
13261331
self.root_logger(),
13271332
));
13281333

mithril-aggregator/src/signer_registerer.rs

Lines changed: 56 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use mithril_common::{
1111
StdError, StdResult,
1212
};
1313

14-
use crate::VerificationKeyStorer;
14+
use crate::{services::EpochPruningTask, VerificationKeyStorer};
1515

1616
use mithril_common::chain_observer::ChainObserverError;
1717

@@ -164,28 +164,38 @@ impl SignerRegistrationRoundOpener for MithrilSignerRegisterer {
164164
stake_distribution,
165165
});
166166

167+
Ok(())
168+
}
169+
170+
async fn close_registration_round(&self) -> StdResult<()> {
171+
let mut current_round = self.current_round.write().await;
172+
*current_round = None;
173+
174+
Ok(())
175+
}
176+
}
177+
178+
#[async_trait]
179+
impl EpochPruningTask for MithrilSignerRegisterer {
180+
fn pruned_data(&self) -> &'static str {
181+
"Signer registration"
182+
}
183+
184+
async fn prune(&self, epoch: Epoch) -> StdResult<()> {
167185
if let Some(retention_limit) = self.verification_key_epoch_retention_limit {
168186
self.verification_key_store
169-
.prune_verification_keys(registration_epoch - retention_limit)
187+
.prune_verification_keys(epoch - retention_limit)
170188
.await
171189
.with_context(|| {
172190
format!(
173191
"VerificationKeyStorer can not prune verification keys below epoch: '{}'",
174-
registration_epoch - retention_limit
192+
epoch - retention_limit
175193
)
176-
})
177-
.map_err(|e| SignerRegistrationError::StoreError(anyhow!(e)))?;
194+
})?;
178195
}
179196

180197
Ok(())
181198
}
182-
183-
async fn close_registration_round(&self) -> StdResult<()> {
184-
let mut current_round = self.current_round.write().await;
185-
*current_round = None;
186-
187-
Ok(())
188-
}
189199
}
190200

191201
#[async_trait]
@@ -288,14 +298,16 @@ mod tests {
288298
use mithril_common::{
289299
chain_observer::FakeObserver,
290300
entities::{Epoch, Signer},
291-
test_utils::{fake_data, MithrilFixtureBuilder},
301+
test_utils::MithrilFixtureBuilder,
292302
};
303+
use mockall::predicate::eq;
293304

294305
use crate::{
295306
database::{repository::SignerRegistrationStore, test_helper::main_db_connection},
296307
MithrilSignerRegisterer, SignerRegisterer, SignerRegistrationRoundOpener,
297308
VerificationKeyStorer,
298309
};
310+
use crate::{services::EpochPruningTask, store::MockVerificationKeyStorer};
299311

300312
use super::MockSignerRecorder;
301313

@@ -418,47 +430,44 @@ mod tests {
418430
}
419431

420432
#[tokio::test]
421-
async fn should_prune_verification_keys_older_than_two_epochs_at_round_opening() {
422-
let verification_key_store = Arc::new(SignerRegistrationStore::new(Arc::new(
423-
main_db_connection().unwrap(),
424-
)));
425-
for initial_key in 1..=5 {
426-
let signer_with_stake = fake_data::signers_with_stakes(1).pop().unwrap();
427-
verification_key_store
428-
.save_verification_key(Epoch(initial_key), signer_with_stake)
429-
.await
430-
.unwrap();
431-
}
433+
async fn mock_prune_epoch_older_than_threshold() {
434+
const PROTOCOL_INITIALIZER_PRUNE_EPOCH_THRESHOLD: u64 = 10;
435+
let retention_limit = Some(PROTOCOL_INITIALIZER_PRUNE_EPOCH_THRESHOLD);
436+
437+
let mut verification_key_store = MockVerificationKeyStorer::new();
438+
verification_key_store
439+
.expect_prune_verification_keys()
440+
.with(eq(Epoch(4)))
441+
.times(1)
442+
.returning(|_| Ok(()));
432443

433-
let signer_recorder = MockSignerRecorder::new();
434444
let signer_registerer = MithrilSignerRegisterer::new(
435445
Arc::new(FakeObserver::default()),
436-
verification_key_store.clone(),
437-
Arc::new(signer_recorder),
438-
Some(2),
446+
Arc::new(verification_key_store),
447+
Arc::new(MockSignerRecorder::new()),
448+
retention_limit,
439449
);
440-
let fixture = MithrilFixtureBuilder::default().with_signers(5).build();
441450

442-
signer_registerer
443-
.open_registration_round(Epoch(5), fixture.stake_distribution())
444-
.await
445-
.expect("Opening a registration round should not fail");
451+
let current_epoch = Epoch(4) + PROTOCOL_INITIALIZER_PRUNE_EPOCH_THRESHOLD;
452+
signer_registerer.prune(current_epoch).await.unwrap();
453+
}
446454

447-
for epoch in 1..=3 {
448-
let verification_keys = verification_key_store
449-
.get_verification_keys(Epoch(epoch))
450-
.await
451-
.unwrap();
452-
assert_eq!(None, verification_keys);
453-
}
455+
#[tokio::test]
456+
async fn mock_without_threshold_nothing_is_pruned() {
457+
let retention_limit = None;
454458

455-
let verification_keys = verification_key_store
456-
.get_verification_keys(Epoch(4))
457-
.await
458-
.unwrap();
459-
assert!(
460-
verification_keys.is_some(),
461-
"Verification keys of the previous epoch should not have been pruned"
459+
let mut verification_key_store = MockVerificationKeyStorer::new();
460+
verification_key_store
461+
.expect_prune_verification_keys()
462+
.never();
463+
464+
let signer_registerer = MithrilSignerRegisterer::new(
465+
Arc::new(FakeObserver::default()),
466+
Arc::new(verification_key_store),
467+
Arc::new(MockSignerRecorder::new()),
468+
retention_limit,
462469
);
470+
471+
signer_registerer.prune(Epoch(100)).await.unwrap();
463472
}
464473
}

0 commit comments

Comments
 (0)