@@ -7,6 +7,9 @@ use std::{
7
7
} ;
8
8
use tokio:: sync:: Mutex ;
9
9
10
+ use crate :: VerificationKeyStorer ;
11
+ use mithril_common:: entities:: Signer ;
12
+ use mithril_common:: store:: StoreError ;
10
13
use mithril_common:: {
11
14
crypto_helper:: KESPeriod ,
12
15
entities:: {
@@ -64,9 +67,21 @@ impl SignerRegistrationRecord {
64
67
}
65
68
}
66
69
70
+ impl From < SignerRegistrationRecord > for Signer {
71
+ fn from ( other : SignerRegistrationRecord ) -> Self {
72
+ Self {
73
+ party_id : other. signer_id ,
74
+ verification_key : other. verification_key ,
75
+ verification_key_signature : other. verification_key_signature ,
76
+ operational_certificate : other. operational_certificate ,
77
+ kes_period : other. kes_period ,
78
+ }
79
+ }
80
+ }
81
+
67
82
impl From < SignerRegistrationRecord > for SignerWithStake {
68
- fn from ( other : SignerRegistrationRecord ) -> SignerWithStake {
69
- SignerWithStake {
83
+ fn from ( other : SignerRegistrationRecord ) -> Self {
84
+ Self {
70
85
party_id : other. signer_id ,
71
86
verification_key : other. verification_key ,
72
87
verification_key_signature : other. verification_key_signature ,
@@ -380,6 +395,80 @@ impl<'conn> DeleteSignerRegistrationRecordProvider<'conn> {
380
395
}
381
396
}
382
397
398
+ /// Service to deal with signer_registration (read & write).
399
+ pub struct SignerRegistrationStore {
400
+ connection : Arc < Mutex < Connection > > ,
401
+ /// Number of epoch before previous records will be deleted at the next save
402
+ epoch_retention_limit : Option < u64 > ,
403
+ }
404
+
405
+ impl SignerRegistrationStore {
406
+ /// Create a new [SignerRegistrationStore] service
407
+ pub fn new ( connection : Arc < Mutex < Connection > > , epoch_retention_limit : Option < u64 > ) -> Self {
408
+ Self {
409
+ connection,
410
+ epoch_retention_limit,
411
+ }
412
+ }
413
+ }
414
+
415
+ #[ async_trait]
416
+ impl VerificationKeyStorer for SignerRegistrationStore {
417
+ async fn save_verification_key (
418
+ & self ,
419
+ epoch : Epoch ,
420
+ signer : SignerWithStake ,
421
+ ) -> Result < Option < SignerWithStake > , StoreError > {
422
+ let connection = & * self . connection . lock ( ) . await ;
423
+ let provider = InsertOrReplaceSignerRegistrationRecordProvider :: new ( connection) ;
424
+ let existing_record = SignerRegistrationRecordProvider :: new ( connection)
425
+ . get_by_signer_id_and_epoch ( signer. party_id . clone ( ) , & epoch)
426
+ . map_err ( |e| AdapterError :: QueryError ( e) ) ?
427
+ . next ( ) ;
428
+
429
+ let _updated_record = provider
430
+ . persist ( SignerRegistrationRecord :: from_signer_with_stake (
431
+ signer, epoch,
432
+ ) )
433
+ . map_err ( |e| AdapterError :: GeneralError ( format ! ( "{e}" ) ) ) ?;
434
+
435
+ if let Some ( threshold) = self . epoch_retention_limit {
436
+ // Note: this means that if called with an epoch in the future this could remove all
437
+ // current records, the caller should check that the given epoch is the current one
438
+ // or we must get it to do the work ourself here.
439
+ let _deleted_records = DeleteSignerRegistrationRecordProvider :: new ( connection)
440
+ // we want to prune including the given epoch (+1)
441
+ . prune ( epoch - threshold + 1 )
442
+ . map_err ( |e| AdapterError :: QueryError ( e) ) ?
443
+ . collect :: < Vec < _ > > ( ) ;
444
+ }
445
+
446
+ match existing_record {
447
+ None => Ok ( None ) ,
448
+ Some ( previous_record) => Ok ( Some ( previous_record. into ( ) ) ) ,
449
+ }
450
+ }
451
+
452
+ async fn get_verification_keys (
453
+ & self ,
454
+ epoch : Epoch ,
455
+ ) -> Result < Option < HashMap < PartyId , Signer > > , StoreError > {
456
+ let connection = & * self . connection . lock ( ) . await ;
457
+ let provider = SignerRegistrationRecordProvider :: new ( connection) ;
458
+ let cursor = provider
459
+ . get_by_epoch ( & epoch)
460
+ . map_err ( |e| AdapterError :: GeneralError ( format ! ( "{e}" ) ) ) ?;
461
+
462
+ let signer_with_stakes: HashMap < PartyId , Signer > =
463
+ HashMap :: from_iter ( cursor. map ( |record| ( record. signer_id . to_owned ( ) , record. into ( ) ) ) ) ;
464
+
465
+ match signer_with_stakes. is_empty ( ) {
466
+ true => Ok ( None ) ,
467
+ false => Ok ( Some ( signer_with_stakes) ) ,
468
+ }
469
+ }
470
+ }
471
+
383
472
/// Service to deal with signer_registration (read & write).
384
473
pub struct SignerRegistrationStoreAdapter {
385
474
connection : Arc < Mutex < Connection > > ,
@@ -519,6 +608,7 @@ mod tests {
519
608
use mithril_common:: test_utils:: MithrilFixtureBuilder ;
520
609
521
610
use crate :: database:: provider:: { apply_all_migrations_to_db, disable_foreign_key_support} ;
611
+ use crate :: store:: test_verification_key_storer;
522
612
523
613
use super :: * ;
524
614
@@ -908,4 +998,27 @@ mod tests {
908
998
. collect:: <Vec <( Epoch , BTreeMap <PartyId , SignerWithStake >) >>( )
909
999
)
910
1000
}
1001
+
1002
+ pub fn init_signer_registration_store (
1003
+ initial_data : Vec < ( Epoch , HashMap < PartyId , SignerWithStake > ) > ,
1004
+ retention_limit : Option < usize > ,
1005
+ ) -> Arc < dyn VerificationKeyStorer > {
1006
+ let connection = Connection :: open ( ":memory:" ) . unwrap ( ) ;
1007
+ let initial_data: Vec < ( Epoch , Vec < SignerWithStake > ) > = initial_data
1008
+ . into_iter ( )
1009
+ . map ( |( e, signers) | ( e, signers. into_values ( ) . collect :: < Vec < _ > > ( ) ) )
1010
+ . collect ( ) ;
1011
+
1012
+ setup_signer_registration_db ( & connection, initial_data) . unwrap ( ) ;
1013
+
1014
+ Arc :: new ( SignerRegistrationStore :: new (
1015
+ Arc :: new ( Mutex :: new ( connection) ) ,
1016
+ retention_limit. map ( |threshold| threshold as u64 ) ,
1017
+ ) )
1018
+ }
1019
+
1020
+ test_verification_key_storer ! (
1021
+ test_signer_registration_store =>
1022
+ crate :: database:: provider:: signer_registration:: tests:: init_signer_registration_store
1023
+ ) ;
911
1024
}
0 commit comments