1
1
use async_trait:: async_trait;
2
- use mithril_common:: store:: StorePruner ;
3
2
use std:: collections:: HashMap ;
4
3
use tokio:: sync:: RwLock ;
5
4
@@ -24,40 +23,25 @@ pub trait VerificationKeyStorer: Sync + Send {
24
23
& self ,
25
24
epoch : Epoch ,
26
25
) -> Result < Option < HashMap < PartyId , Signer > > , StoreError > ;
26
+
27
+ /// Prune all verification keys that are at or below the given epoch.
28
+ async fn prune_verification_keys ( & self , max_epoch_to_prune : Epoch ) -> Result < ( ) , StoreError > ;
27
29
}
28
30
29
31
/// Store for the `VerificationKey`.
30
32
pub struct VerificationKeyStore {
31
33
adapter : RwLock < Adapter > ,
32
- retention_limit : Option < usize > ,
33
34
}
34
35
35
36
impl VerificationKeyStore {
36
37
/// Create a new instance.
37
- pub fn new ( adapter : Adapter , retention_limit : Option < usize > ) -> Self {
38
+ pub fn new ( adapter : Adapter ) -> Self {
38
39
Self {
39
40
adapter : RwLock :: new ( adapter) ,
40
- retention_limit,
41
41
}
42
42
}
43
43
}
44
44
45
- #[ async_trait]
46
- impl StorePruner for VerificationKeyStore {
47
- type Key = Epoch ;
48
- type Record = HashMap < PartyId , SignerWithStake > ;
49
-
50
- fn get_adapter (
51
- & self ,
52
- ) -> & RwLock < Box < dyn StoreAdapter < Key = Self :: Key , Record = Self :: Record > > > {
53
- & self . adapter
54
- }
55
-
56
- fn get_max_records ( & self ) -> Option < usize > {
57
- self . retention_limit
58
- }
59
- }
60
-
61
45
#[ async_trait]
62
46
impl VerificationKeyStorer for VerificationKeyStore {
63
47
async fn save_verification_key (
@@ -75,7 +59,6 @@ impl VerificationKeyStorer for VerificationKeyStore {
75
59
. await
76
60
. store_record ( & epoch, & signers)
77
61
. await ?;
78
- self . prune ( ) . await ?;
79
62
80
63
Ok ( prev_signer)
81
64
}
@@ -87,6 +70,21 @@ impl VerificationKeyStorer for VerificationKeyStore {
87
70
let record = self . adapter . read ( ) . await . get_record ( & epoch) . await ?;
88
71
Ok ( record. map ( |h| h. into_iter ( ) . map ( |( k, v) | ( k, v. into ( ) ) ) . collect ( ) ) )
89
72
}
73
+
74
+ async fn prune_verification_keys ( & self , max_epoch_to_prune : Epoch ) -> Result < ( ) , StoreError > {
75
+ let mut adapter = self . adapter . write ( ) . await ;
76
+
77
+ for ( epoch, _record) in adapter
78
+ . get_last_n_records ( usize:: MAX )
79
+ . await ?
80
+ . into_iter ( )
81
+ . filter ( |( e, _) | e <= & max_epoch_to_prune)
82
+ {
83
+ adapter. remove ( & epoch) . await ?;
84
+ }
85
+
86
+ Ok ( ( ) )
87
+ }
90
88
}
91
89
92
90
/// Macro that generate tests that a [VerificationKeyStorer] must pass
@@ -118,8 +116,8 @@ macro_rules! test_verification_key_storer {
118
116
}
119
117
120
118
#[ tokio:: test]
121
- async fn check_retention_limit ( ) {
122
- test_suite:: check_retention_limit ( & $store_builder) . await ;
119
+ async fn can_prune_keys_from_given_epoch_retention_limit ( ) {
120
+ test_suite:: can_prune_keys_from_given_epoch_retention_limit ( & $store_builder) . await ;
123
121
}
124
122
}
125
123
} ;
@@ -139,11 +137,8 @@ pub mod test_suite {
139
137
140
138
/// A builder of [VerificationKeyStorer], the arguments are:
141
139
/// * initial_data
142
- /// * optional retention limit
143
- type StoreBuilder = dyn Fn (
144
- Vec < ( Epoch , HashMap < PartyId , SignerWithStake > ) > ,
145
- Option < usize > ,
146
- ) -> Arc < dyn VerificationKeyStorer > ;
140
+ type StoreBuilder =
141
+ dyn Fn ( Vec < ( Epoch , HashMap < PartyId , SignerWithStake > ) > ) -> Arc < dyn VerificationKeyStorer > ;
147
142
148
143
fn build_signers (
149
144
nb_epoch : u64 ,
@@ -177,7 +172,7 @@ pub mod test_suite {
177
172
178
173
pub async fn save_key_in_empty_store ( store_builder : & StoreBuilder ) {
179
174
let signers = build_signers ( 0 , 0 ) ;
180
- let store = store_builder ( signers, None ) ;
175
+ let store = store_builder ( signers) ;
181
176
let res = store
182
177
. save_verification_key (
183
178
Epoch ( 0 ) ,
@@ -198,7 +193,7 @@ pub mod test_suite {
198
193
199
194
pub async fn update_signer_in_store ( store_builder : & StoreBuilder ) {
200
195
let signers = build_signers ( 1 , 1 ) ;
201
- let store = store_builder ( signers, None ) ;
196
+ let store = store_builder ( signers) ;
202
197
let res = store
203
198
. save_verification_key (
204
199
Epoch ( 1 ) ,
@@ -229,23 +224,23 @@ pub mod test_suite {
229
224
230
225
pub async fn get_verification_keys_for_empty_epoch ( store_builder : & StoreBuilder ) {
231
226
let signers = build_signers ( 2 , 1 ) ;
232
- let store = store_builder ( signers, None ) ;
227
+ let store = store_builder ( signers) ;
233
228
let res = store. get_verification_keys ( Epoch ( 0 ) ) . await . unwrap ( ) ;
234
229
235
230
assert ! ( res. is_none( ) ) ;
236
231
}
237
232
238
233
pub async fn get_verification_keys_for_existing_epoch ( store_builder : & StoreBuilder ) {
239
234
let signers = build_signers ( 2 , 2 ) ;
235
+ let store = store_builder ( signers. clone ( ) ) ;
236
+
240
237
let expected_signers: Option < BTreeMap < PartyId , Signer > > = signers
241
- . iter ( )
238
+ . into_iter ( )
242
239
. filter ( |( e, _) | e == 1 )
243
- . cloned ( )
244
240
. map ( |( _, signers) | {
245
241
BTreeMap :: from_iter ( signers. into_iter ( ) . map ( |( p, s) | ( p, s. into ( ) ) ) )
246
242
} )
247
243
. next ( ) ;
248
- let store = store_builder ( signers, None ) ;
249
244
let res = store
250
245
. get_verification_keys ( Epoch ( 1 ) )
251
246
. await
@@ -255,30 +250,27 @@ pub mod test_suite {
255
250
assert_eq ! ( expected_signers, res) ;
256
251
}
257
252
258
- pub async fn check_retention_limit ( store_builder : & StoreBuilder ) {
259
- let signers = build_signers ( 2 , 2 ) ;
260
- let store = store_builder ( signers, Some ( 2 ) ) ;
261
- assert ! ( store
262
- . get_verification_keys( Epoch ( 1 ) )
263
- . await
264
- . unwrap( )
265
- . is_some( ) ) ;
266
- let _ = store
267
- . save_verification_key (
268
- Epoch ( 3 ) ,
269
- SignerWithStake {
270
- party_id : "party_id" . to_string ( ) ,
271
- verification_key : "whatever" . to_string ( ) ,
272
- verification_key_signature : None ,
273
- operational_certificate : None ,
274
- kes_period : None ,
275
- stake : 10 ,
276
- } ,
277
- )
278
- . await
279
- . unwrap ( ) ;
280
- let first_epoch_keys = store. get_verification_keys ( Epoch ( 1 ) ) . await . unwrap ( ) ;
281
- assert_eq ! ( None , first_epoch_keys) ;
253
+ pub async fn can_prune_keys_from_given_epoch_retention_limit ( store_builder : & StoreBuilder ) {
254
+ let signers = build_signers ( 6 , 2 ) ;
255
+ let store = store_builder ( signers) ;
256
+
257
+ for epoch in 1 ..6 {
258
+ assert ! (
259
+ store
260
+ . get_verification_keys( Epoch ( epoch) )
261
+ . await
262
+ . unwrap( )
263
+ . is_some( ) ,
264
+ "Keys should exist before pruning"
265
+ ) ;
266
+ store
267
+ . prune_verification_keys ( Epoch ( epoch) )
268
+ . await
269
+ . expect ( "Pruning should not fail" ) ;
270
+
271
+ let pruned_epoch_keys = store. get_verification_keys ( Epoch ( epoch) ) . await . unwrap ( ) ;
272
+ assert_eq ! ( None , pruned_epoch_keys) ;
273
+ }
282
274
}
283
275
}
284
276
@@ -294,7 +286,6 @@ mod tests {
294
286
295
287
pub fn init_store (
296
288
initial_data : Vec < ( Epoch , HashMap < PartyId , SignerWithStake > ) > ,
297
- retention_limit : Option < usize > ,
298
289
) -> Arc < dyn VerificationKeyStorer > {
299
290
let values = if initial_data. is_empty ( ) {
300
291
None
@@ -305,10 +296,7 @@ mod tests {
305
296
let adapter: MemoryAdapter < Epoch , HashMap < PartyId , SignerWithStake > > =
306
297
MemoryAdapter :: new ( values) . unwrap ( ) ;
307
298
308
- Arc :: new ( VerificationKeyStore :: new (
309
- Box :: new ( adapter) ,
310
- retention_limit,
311
- ) )
299
+ Arc :: new ( VerificationKeyStore :: new ( Box :: new ( adapter) ) )
312
300
}
313
301
314
302
test_verification_key_storer ! (
0 commit comments