Skip to content

Commit e274a5d

Browse files
authored
Merge pull request #2108 from input-output-hk/sfa/2075/refactor_signer_pruning_with_upkeep_service
Refactor signer pruning with upkeep service
2 parents 0a7fb9f + d9ca627 commit e274a5d

File tree

14 files changed

+263
-225
lines changed

14 files changed

+263
-225
lines changed

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/mithril-persistence/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mithril-persistence"
3-
version = "0.2.32"
3+
version = "0.2.33"
44
description = "Common types, interfaces, and utilities to persist data for Mithril nodes."
55
authors = { workspace = true }
66
edition = { workspace = true }

internal/mithril-persistence/src/store/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ pub mod adapter;
55
mod stake_store;
66
mod store_pruner;
77

8-
pub use stake_store::{StakeStore, StakeStorer};
8+
pub use stake_store::StakeStorer;
99
pub use store_pruner::StorePruner;
Lines changed: 4 additions & 189 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11
use async_trait::async_trait;
2-
use mithril_common::entities::{Epoch, StakeDistribution};
3-
use mithril_common::signable_builder::StakeDistributionRetriever;
4-
use mithril_common::StdResult;
5-
use tokio::sync::RwLock;
6-
7-
use super::{adapter::StoreAdapter, StorePruner};
8-
9-
type Adapter = Box<dyn StoreAdapter<Key = Epoch, Record = StakeDistribution>>;
2+
use mithril_common::{
3+
entities::{Epoch, StakeDistribution},
4+
StdResult,
5+
};
106

117
/// Represent a way to store the stake of mithril party members.
128
#[async_trait]
@@ -21,184 +17,3 @@ pub trait StakeStorer: Sync + Send {
2117
/// Get the stakes of all party at a given `epoch`.
2218
async fn get_stakes(&self, epoch: Epoch) -> StdResult<Option<StakeDistribution>>;
2319
}
24-
25-
/// A [StakeStorer] that use a [StoreAdapter] to store data.
26-
pub struct StakeStore {
27-
adapter: RwLock<Adapter>,
28-
retention_limit: Option<usize>,
29-
}
30-
31-
impl StakeStore {
32-
/// StakeStore factory
33-
pub fn new(adapter: Adapter, retention_limit: Option<usize>) -> Self {
34-
Self {
35-
adapter: RwLock::new(adapter),
36-
retention_limit,
37-
}
38-
}
39-
}
40-
41-
#[async_trait]
42-
impl StorePruner for StakeStore {
43-
type Key = Epoch;
44-
type Record = StakeDistribution;
45-
46-
fn get_adapter(
47-
&self,
48-
) -> &RwLock<Box<dyn StoreAdapter<Key = Self::Key, Record = Self::Record>>> {
49-
&self.adapter
50-
}
51-
52-
fn get_max_records(&self) -> Option<usize> {
53-
self.retention_limit
54-
}
55-
}
56-
57-
#[async_trait]
58-
impl StakeStorer for StakeStore {
59-
async fn save_stakes(
60-
&self,
61-
epoch: Epoch,
62-
stakes: StakeDistribution,
63-
) -> StdResult<Option<StakeDistribution>> {
64-
let signers = {
65-
let mut adapter = self.adapter.write().await;
66-
let signers = adapter.get_record(&epoch).await?;
67-
adapter.store_record(&epoch, &stakes).await?;
68-
69-
signers
70-
};
71-
// it is important the adapter gets out of the scope to free the write lock it holds.
72-
// Otherwise the method below will hang forever waiting for the lock.
73-
self.prune().await?;
74-
75-
Ok(signers)
76-
}
77-
78-
async fn get_stakes(&self, epoch: Epoch) -> StdResult<Option<StakeDistribution>> {
79-
Ok(self.adapter.read().await.get_record(&epoch).await?)
80-
}
81-
}
82-
83-
#[async_trait]
84-
impl StakeDistributionRetriever for StakeStore {
85-
async fn retrieve(&self, epoch: Epoch) -> StdResult<Option<StakeDistribution>> {
86-
let stake_distribution = self.get_stakes(epoch).await?;
87-
88-
Ok(stake_distribution)
89-
}
90-
}
91-
92-
#[cfg(test)]
93-
mod tests {
94-
use super::super::adapter::MemoryAdapter;
95-
use super::*;
96-
97-
fn init_store(
98-
nb_epoch: u64,
99-
signers_per_epoch: u64,
100-
retention_limit: Option<usize>,
101-
) -> StakeStore {
102-
let mut values: Vec<(Epoch, StakeDistribution)> = Vec::new();
103-
104-
for epoch in 1..=nb_epoch {
105-
let mut signers: StakeDistribution = StakeDistribution::new();
106-
107-
for party_idx in 1..=signers_per_epoch {
108-
let party_id = format!("{party_idx}");
109-
signers.insert(party_id.clone(), 100 * party_idx + 1);
110-
}
111-
values.push((Epoch(epoch), signers));
112-
}
113-
114-
let values = if !values.is_empty() {
115-
Some(values)
116-
} else {
117-
None
118-
};
119-
let adapter: MemoryAdapter<Epoch, StakeDistribution> = MemoryAdapter::new(values).unwrap();
120-
StakeStore::new(Box::new(adapter), retention_limit)
121-
}
122-
123-
#[tokio::test]
124-
async fn save_key_in_empty_store() {
125-
let store = init_store(0, 0, None);
126-
let res = store
127-
.save_stakes(Epoch(1), StakeDistribution::from([("1".to_string(), 123)]))
128-
.await
129-
.expect("Test adapter should not fail.");
130-
131-
assert!(res.is_none());
132-
}
133-
134-
#[tokio::test]
135-
async fn update_signer_in_store() {
136-
let store = init_store(1, 1, None);
137-
let res = store
138-
.save_stakes(Epoch(1), StakeDistribution::from([("1".to_string(), 123)]))
139-
.await
140-
.expect("Test adapter should not fail.");
141-
142-
assert_eq!(
143-
StakeDistribution::from([("1".to_string(), 101)]),
144-
res.expect("the result should not be empty"),
145-
);
146-
}
147-
148-
#[tokio::test]
149-
async fn get_stakes_for_empty_epoch() {
150-
let store = init_store(2, 1, None);
151-
let res = store
152-
.get_stakes(Epoch(0))
153-
.await
154-
.expect("Test adapter should not fail.");
155-
156-
assert!(res.is_none());
157-
}
158-
159-
#[tokio::test]
160-
async fn get_stakes_for_existing_epoch() {
161-
let store = init_store(2, 2, None);
162-
let res = store
163-
.get_stakes(Epoch(1))
164-
.await
165-
.expect("Test adapter should not fail.");
166-
167-
assert!(res.is_some());
168-
assert_eq!(2, res.expect("Query result should not be empty.").len());
169-
}
170-
171-
#[tokio::test]
172-
async fn check_retention_limit() {
173-
let store = init_store(2, 2, Some(2));
174-
let _res = store
175-
.save_stakes(Epoch(3), StakeDistribution::from([("1".to_string(), 123)]))
176-
.await
177-
.unwrap();
178-
assert!(store.get_stakes(Epoch(1)).await.unwrap().is_none());
179-
}
180-
181-
#[tokio::test]
182-
async fn retrieve_with_no_stakes_returns_none() {
183-
let store = init_store(0, 0, None);
184-
185-
let result = store.retrieve(Epoch(1)).await.unwrap();
186-
187-
assert!(result.is_none());
188-
}
189-
190-
#[tokio::test]
191-
async fn retrieve_returns_stake_distribution() {
192-
let stake_distribution_to_retrieve =
193-
StakeDistribution::from([("pool-123".to_string(), 123)]);
194-
let store = init_store(0, 0, None);
195-
store
196-
.save_stakes(Epoch(1), stake_distribution_to_retrieve.clone())
197-
.await
198-
.unwrap();
199-
200-
let stake_distribution = store.retrieve(Epoch(1)).await.unwrap();
201-
202-
assert_eq!(stake_distribution, Some(stake_distribution_to_retrieve));
203-
}
204-
}

mithril-signer/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mithril-signer"
3-
version = "0.2.211"
3+
version = "0.2.212"
44
description = "A Mithril Signer"
55
authors = { workspace = true }
66
edition = { workspace = true }

mithril-signer/src/dependency_injection/builder.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ use mithril_persistence::database::repository::CardanoTransactionRepository;
3333
use mithril_persistence::database::{ApplicationNodeType, SqlMigration};
3434
use mithril_persistence::sqlite::{ConnectionBuilder, SqliteConnection, SqliteConnectionPool};
3535
use mithril_persistence::store::adapter::SQLiteAdapter;
36-
use mithril_persistence::store::StakeStore;
3736

3837
use crate::database::repository::SignedBeaconRepository;
3938
use crate::dependency_injection::SignerDependencyContainer;
@@ -44,7 +43,7 @@ use crate::services::{
4443
SignerUpkeepService, TransactionsImporterByChunk, TransactionsImporterWithPruner,
4544
TransactionsImporterWithVacuum,
4645
};
47-
use crate::store::{MKTreeStoreSqlite, ProtocolInitializerStore};
46+
use crate::store::{MKTreeStoreSqlite, ProtocolInitializerStore, StakeStore};
4847
use crate::{
4948
Configuration, MetricsService, HTTP_REQUEST_TIMEOUT_DURATION, SQLITE_FILE,
5049
SQLITE_FILE_CARDANO_TRANSACTION,
@@ -371,7 +370,11 @@ impl<'a> DependenciesBuilder<'a> {
371370
sqlite_connection.clone(),
372371
sqlite_connection_cardano_transaction_pool,
373372
signed_entity_type_lock.clone(),
374-
vec![signed_beacon_repository.clone()],
373+
vec![
374+
signed_beacon_repository.clone(),
375+
stake_store.clone(),
376+
protocol_initializer_store.clone(),
377+
],
375378
self.root_logger(),
376379
));
377380
let certifier = Arc::new(SignerCertifierService::new(

mithril-signer/src/dependency_injection/containers.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,12 @@ use mithril_common::era::{EraChecker, EraReader};
88
use mithril_common::signable_builder::SignableBuilderService;
99
use mithril_common::signed_entity_type_lock::SignedEntityTypeLock;
1010
use mithril_common::TickerService;
11-
use mithril_persistence::store::StakeStore;
1211
use tokio::sync::RwLock;
1312

1413
use crate::services::{
1514
AggregatorClient, CertifierService, EpochService, SingleSigner, UpkeepService,
1615
};
17-
use crate::store::ProtocolInitializerStorer;
16+
use crate::store::{ProtocolInitializerStorer, StakeStore};
1817
use crate::MetricsService;
1918

2019
type StakeStoreService = Arc<StakeStore>;

mithril-signer/src/runtime/runner.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ mod tests {
358358
MithrilTickerService, TickerService,
359359
};
360360
use mithril_persistence::store::adapter::{DumbStoreAdapter, MemoryAdapter};
361-
use mithril_persistence::store::{StakeStore, StakeStorer};
361+
use mithril_persistence::store::StakeStorer;
362362

363363
use crate::database::repository::SignedBeaconRepository;
364364
use crate::database::test_helper::main_db_connection;
@@ -368,7 +368,7 @@ mod tests {
368368
MithrilSingleSigner, MockTransactionStore, MockUpkeepService, SignerCertifierService,
369369
SignerSignableSeedBuilder, SignerSignedEntityConfigProvider,
370370
};
371-
use crate::store::ProtocolInitializerStore;
371+
use crate::store::{ProtocolInitializerStore, StakeStore};
372372
use crate::test_tools::TestLogger;
373373

374374
use super::*;

mithril-signer/src/services/epoch_service.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ use std::collections::BTreeSet;
55
use std::sync::Arc;
66
use thiserror::Error;
77

8+
use crate::dependency_injection::EpochServiceWrapper;
9+
use crate::entities::SignerEpochSettings;
10+
use crate::services::SignedEntityConfigProvider;
11+
use crate::store::ProtocolInitializerStorer;
12+
use crate::RunnerError;
813
use mithril_common::crypto_helper::ProtocolInitializer;
914
use mithril_common::entities::{
1015
CardanoTransactionsSigningConfig, Epoch, PartyId, ProtocolParameters, SignedEntityConfig,
@@ -14,12 +19,6 @@ use mithril_common::logging::LoggerExtensions;
1419
use mithril_common::{CardanoNetwork, StdResult};
1520
use mithril_persistence::store::StakeStorer;
1621

17-
use crate::dependency_injection::EpochServiceWrapper;
18-
use crate::entities::SignerEpochSettings;
19-
use crate::services::SignedEntityConfigProvider;
20-
use crate::store::ProtocolInitializerStorer;
21-
use crate::RunnerError;
22-
2322
/// Errors dedicated to the EpochService.
2423
#[derive(Debug, Error)]
2524
pub enum EpochServiceError {
@@ -327,9 +326,9 @@ impl MithrilEpochService {
327326
/// `TEST ONLY` - Create a new instance of the service using dumb dependencies.
328327
pub fn new_with_dumb_dependencies() -> Self {
329328
use crate::store::ProtocolInitializerStore;
329+
use crate::store::StakeStore;
330330
use crate::test_tools::TestLogger;
331331
use mithril_persistence::store::adapter::DumbStoreAdapter;
332-
use mithril_persistence::store::StakeStore;
333332

334333
let stake_store = Arc::new(StakeStore::new(Box::new(DumbStoreAdapter::new()), None));
335334
let protocol_initializer_store = Arc::new(ProtocolInitializerStore::new(
@@ -437,11 +436,10 @@ mod tests {
437436
use mithril_common::entities::{Epoch, StakeDistribution};
438437
use mithril_common::test_utils::{fake_data, MithrilFixtureBuilder};
439438
use mithril_persistence::store::adapter::{DumbStoreAdapter, MemoryAdapter};
440-
use mithril_persistence::store::{StakeStore, StakeStorer};
441439

442440
use crate::entities::SignerEpochSettings;
443441
use crate::services::MithrilProtocolInitializerBuilder;
444-
use crate::store::ProtocolInitializerStore;
442+
use crate::store::{ProtocolInitializerStore, StakeStore};
445443
use crate::test_tools::TestLogger;
446444

447445
use super::*;

mithril-signer/src/services/single_signer.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,10 +176,9 @@ mod tests {
176176
use mithril_common::entities::{Epoch, ProtocolMessagePartKey};
177177
use mithril_common::test_utils::MithrilFixtureBuilder;
178178
use mithril_persistence::store::adapter::{DumbStoreAdapter, MemoryAdapter};
179-
use mithril_persistence::store::StakeStore;
180179

181180
use crate::services::MithrilEpochService;
182-
use crate::store::ProtocolInitializerStore;
181+
use crate::store::{ProtocolInitializerStore, StakeStore};
183182
use crate::test_tools::TestLogger;
184183

185184
use super::*;

0 commit comments

Comments
 (0)