Skip to content

Commit 58a0815

Browse files
committed
Add the SignerRegistrationStore
A `VerificationKeyStorer` that use directly sqlite providers instead of being a implementation of a `StoreAdapter` like the `SignerRegistrationStoreAdapter`. This means: better performances and simplicity (because we don't have to retrieve all keys from a given epoch to do an insert or udpate).
1 parent e4f25d9 commit 58a0815

File tree

1 file changed

+115
-2
lines changed

1 file changed

+115
-2
lines changed

mithril-aggregator/src/database/provider/signer_registration.rs

Lines changed: 115 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ use std::{
77
};
88
use tokio::sync::Mutex;
99

10+
use crate::VerificationKeyStorer;
11+
use mithril_common::entities::Signer;
12+
use mithril_common::store::StoreError;
1013
use mithril_common::{
1114
crypto_helper::KESPeriod,
1215
entities::{
@@ -64,9 +67,21 @@ impl SignerRegistrationRecord {
6467
}
6568
}
6669

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+
6782
impl From<SignerRegistrationRecord> for SignerWithStake {
68-
fn from(other: SignerRegistrationRecord) -> SignerWithStake {
69-
SignerWithStake {
83+
fn from(other: SignerRegistrationRecord) -> Self {
84+
Self {
7085
party_id: other.signer_id,
7186
verification_key: other.verification_key,
7287
verification_key_signature: other.verification_key_signature,
@@ -380,6 +395,80 @@ impl<'conn> DeleteSignerRegistrationRecordProvider<'conn> {
380395
}
381396
}
382397

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+
383472
/// Service to deal with signer_registration (read & write).
384473
pub struct SignerRegistrationStoreAdapter {
385474
connection: Arc<Mutex<Connection>>,
@@ -519,6 +608,7 @@ mod tests {
519608
use mithril_common::test_utils::MithrilFixtureBuilder;
520609

521610
use crate::database::provider::{apply_all_migrations_to_db, disable_foreign_key_support};
611+
use crate::store::test_verification_key_storer;
522612

523613
use super::*;
524614

@@ -908,4 +998,27 @@ mod tests {
908998
.collect::<Vec<(Epoch, BTreeMap<PartyId, SignerWithStake>)>>()
909999
)
9101000
}
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+
);
9111024
}

0 commit comments

Comments
 (0)