Skip to content

Commit d011bbb

Browse files
authored
Merge pull request #222 from input-output-hk/greg/221/certificate_store
Greg/221/certificate store
2 parents 1be5c35 + 465bf7b commit d011bbb

File tree

10 files changed

+160
-9
lines changed

10 files changed

+160
-9
lines changed

mithril-aggregator/config/dev.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@
33
"url_snapshot_manifest": "https://storage.googleapis.com/cardano-testnet/snapshots.json",
44
"snapshot_store_type": "local",
55
"snapshot_uploader_type": "local",
6-
"pending_certificate_store_directory": "/tmp/mithril/cert_db"
7-
}
6+
"pending_certificate_store_directory": "/tmp/mithril/pending_cert_db",
7+
"certificate_store_directory": "/tmp/mithril/cert_db"
8+
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
#![allow(dead_code)]
2+
/// ↑ only until we plug this into main code
3+
use mithril_common::entities::Certificate;
4+
5+
use thiserror::Error;
6+
7+
use super::{store_adapter::AdapterError, StoreAdapter};
8+
9+
#[derive(Debug, Error)]
10+
pub enum StoreError {
11+
#[error("physical adapter returned an error: {0}")]
12+
AdapterError(#[from] AdapterError),
13+
}
14+
15+
type Adapter = Box<dyn StoreAdapter<Key = String, Record = Certificate>>;
16+
17+
pub struct CertificateStore {
18+
adapter: Adapter,
19+
}
20+
21+
impl CertificateStore {
22+
pub fn new(adapter: Adapter) -> Self {
23+
Self { adapter }
24+
}
25+
26+
pub async fn get_from_hash(&self, hash: &str) -> Result<Option<Certificate>, StoreError> {
27+
Ok(self.adapter.get_record(&hash.to_string()).await?)
28+
}
29+
30+
pub async fn save(&mut self, certificate: Certificate) -> Result<(), StoreError> {
31+
Ok(self
32+
.adapter
33+
.store_record(&certificate.hash, &certificate)
34+
.await?)
35+
}
36+
37+
pub async fn get_list(&self, last_n: usize) -> Result<Vec<Certificate>, StoreError> {
38+
let vars = self.adapter.get_last_n_records(last_n).await?;
39+
let result = vars.into_iter().map(|(_, y)| y).collect();
40+
41+
Ok(result)
42+
}
43+
}
44+
45+
#[cfg(test)]
46+
mod test {
47+
use super::*;
48+
use crate::certificate_store::dumb_adapter::DumbStoreAdapter;
49+
use mithril_common::fake_data::{self};
50+
51+
async fn get_certificate_store(size: u64) -> CertificateStore {
52+
let mut adapter: DumbStoreAdapter<String, Certificate> = DumbStoreAdapter::new();
53+
54+
for ix in 0..size {
55+
let certificate = fake_data::certificate(format!("cert_{:0>2}", ix));
56+
adapter
57+
.store_record(&certificate.hash, &certificate)
58+
.await
59+
.unwrap();
60+
}
61+
let store = CertificateStore::new(Box::new(adapter));
62+
63+
store
64+
}
65+
66+
#[tokio::test]
67+
async fn list_is_empty() {
68+
let store = get_certificate_store(0).await;
69+
70+
assert_eq!(0, store.get_list(100).await.unwrap().len());
71+
}
72+
73+
#[tokio::test]
74+
async fn list_has_some_members() {
75+
let store = get_certificate_store(1).await;
76+
77+
assert_eq!(1, store.get_list(100).await.unwrap().len());
78+
}
79+
80+
#[tokio::test]
81+
async fn get_certificate_with_good_hash() {
82+
let store = get_certificate_store(1).await;
83+
let result = store.get_from_hash("cert_00").await.unwrap();
84+
assert!(result.is_some());
85+
}
86+
87+
#[tokio::test]
88+
async fn get_certificate_with_wrong_hash() {
89+
let store = get_certificate_store(1).await;
90+
let result = store.get_from_hash("cert_99").await.unwrap();
91+
assert!(result.is_none());
92+
}
93+
94+
#[tokio::test]
95+
async fn save_certificate_once() {
96+
let mut store = get_certificate_store(1).await;
97+
let certificate = fake_data::certificate(format!("{}", "123".to_string()));
98+
99+
assert!(store.save(certificate).await.is_ok());
100+
}
101+
102+
#[tokio::test]
103+
async fn update_certificate() {
104+
let mut store = get_certificate_store(1).await;
105+
let mut certificate = store.get_from_hash("cert_00").await.unwrap().unwrap();
106+
107+
certificate.previous_hash = "whatever".to_string();
108+
assert!(store.save(certificate).await.is_ok());
109+
let certificate = store.get_from_hash("cert_00").await.unwrap().unwrap();
110+
111+
assert_eq!("whatever".to_string(), certificate.previous_hash);
112+
}
113+
}

mithril-aggregator/src/certificate_store/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
mod certificate_store;
12
mod jsonfile_store_adapter;
23
mod pending_certificate_store;
34
mod store_adapter;
45

6+
pub use certificate_store::CertificateStore;
57
pub use jsonfile_store_adapter::JsonFileStoreAdapter;
68
pub use pending_certificate_store::CertificatePendingStore;
79
pub use store_adapter::{AdapterError, StoreAdapter};

mithril-aggregator/src/dependency.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::beacon_store::BeaconStore;
2-
use crate::CertificatePendingStore;
2+
use crate::{CertificatePendingStore, CertificateStore};
33
use std::sync::Arc;
44
use tokio::sync::RwLock;
55

@@ -18,13 +18,16 @@ pub type MultiSignerWrapper = Arc<RwLock<dyn MultiSigner>>;
1818

1919
pub type CertificatePendingStoreWrapper = Arc<RwLock<CertificatePendingStore>>;
2020

21+
pub type CertificateStoreWrapper = Arc<RwLock<CertificateStore>>;
22+
2123
/// DependencyManager handles the dependencies
2224
pub struct DependencyManager {
2325
pub config: Config,
2426
pub snapshot_store: Option<SnapshotStoreWrapper>,
2527
pub multi_signer: Option<MultiSignerWrapper>,
2628
pub beacon_store: Option<BeaconStoreWrapper>,
2729
pub certificate_pending_store: Option<CertificatePendingStoreWrapper>,
30+
pub certificate_store: Option<CertificateStoreWrapper>,
2831
}
2932

3033
impl DependencyManager {
@@ -36,6 +39,7 @@ impl DependencyManager {
3639
multi_signer: None,
3740
beacon_store: None,
3841
certificate_pending_store: None,
42+
certificate_store: None,
3943
}
4044
}
4145

@@ -64,4 +68,12 @@ impl DependencyManager {
6468
self.certificate_pending_store = Some(certificate_pending_store);
6569
self
6670
}
71+
72+
pub fn with_certificate_store(
73+
&mut self,
74+
certificate_store: CertificateStoreWrapper,
75+
) -> &mut Self {
76+
self.certificate_store = Some(certificate_store);
77+
self
78+
}
6779
}

mithril-aggregator/src/entities.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ pub struct Config {
3434

3535
/// Directory to store pending certificates
3636
pub pending_certificate_store_directory: PathBuf,
37+
38+
/// Directory to store certificates
39+
pub certificate_store_directory: PathBuf,
3740
}
3841

3942
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]

mithril-aggregator/src/http_server.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -536,7 +536,9 @@ mod tests {
536536
server_url: "http://0.0.0.0:8080".to_string(),
537537
db_directory: Default::default(),
538538
snapshot_directory: Default::default(),
539-
pending_certificate_store_directory: std::env::temp_dir().join("mithril_test_cert_db"),
539+
pending_certificate_store_directory: std::env::temp_dir()
540+
.join("mithril_test_pending_cert_db"),
541+
certificate_store_directory: std::env::temp_dir().join("mithril_test_cert_db"),
540542
};
541543
DependencyManager::new(config)
542544
}

mithril-aggregator/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ pub use crate::multi_signer::{MultiSigner, MultiSignerImpl, ProtocolError};
1616
pub use crate::snapshot_stores::{RemoteSnapshotStore, SnapshotStore};
1717
pub use beacon_store::{BeaconStore, BeaconStoreError, MemoryBeaconStore};
1818
pub use certificate_store::{
19-
AdapterError, CertificatePendingStore, JsonFileStoreAdapter, StoreAdapter,
19+
AdapterError, CertificatePendingStore, CertificateStore, JsonFileStoreAdapter, StoreAdapter,
2020
};
2121
pub use dependency::DependencyManager;
2222
pub use runtime::AggregatorRuntime;

mithril-aggregator/src/main.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ use clap::Parser;
44

55
use config::{Map, Source, Value, ValueKind};
66
use mithril_aggregator::{
7-
AggregatorRuntime, CertificatePendingStore, Config, DependencyManager, JsonFileStoreAdapter,
8-
MemoryBeaconStore, MultiSigner, MultiSignerImpl, Server,
7+
AggregatorRuntime, CertificatePendingStore, CertificateStore, Config, DependencyManager,
8+
JsonFileStoreAdapter, MemoryBeaconStore, MultiSigner, MultiSignerImpl, Server,
99
};
1010
use mithril_common::crypto_helper::ProtocolStakeDistribution;
1111
use mithril_common::fake_data;
@@ -132,14 +132,18 @@ async fn main() -> Result<(), Box<dyn Error>> {
132132
let certificate_pending_store = Arc::new(RwLock::new(CertificatePendingStore::new(Box::new(
133133
JsonFileStoreAdapter::new(config.pending_certificate_store_directory.clone())?,
134134
))));
135+
let certificate_store = Arc::new(RwLock::new(CertificateStore::new(Box::new(
136+
JsonFileStoreAdapter::new(config.certificate_store_directory.clone())?,
137+
))));
135138

136139
// Init dependency manager
137140
let mut dependency_manager = DependencyManager::new(config.clone());
138141
dependency_manager
139142
.with_snapshot_store(snapshot_store.clone())
140143
.with_multi_signer(multi_signer.clone())
141144
.with_beacon_store(beacon_store.clone())
142-
.with_certificate_pending_store(certificate_pending_store.clone());
145+
.with_certificate_pending_store(certificate_pending_store.clone())
146+
.with_certificate_store(certificate_store.clone());
143147
let dependency_manager = Arc::new(dependency_manager);
144148

145149
// Start snapshot uploader
@@ -154,6 +158,8 @@ async fn main() -> Result<(), Box<dyn Error>> {
154158
multi_signer.clone(),
155159
snapshot_store.clone(),
156160
snapshot_uploader,
161+
certificate_pending_store.clone(),
162+
certificate_store.clone(),
157163
);
158164
runtime.run().await
159165
});

mithril-aggregator/src/runtime.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use mithril_common::digesters::{Digester, DigesterError, ImmutableDigester};
66
use mithril_common::entities::Beacon;
77
use mithril_common::fake_data;
88

9+
use crate::dependency::{CertificatePendingStoreWrapper, CertificateStoreWrapper};
910
use crate::snapshot_stores::SnapshotStoreError;
1011
use crate::snapshot_uploaders::{SnapshotLocation, SnapshotUploader};
1112
use chrono::{DateTime, Utc};
@@ -68,6 +69,12 @@ pub struct AggregatorRuntime {
6869

6970
/// Snapshot uploader
7071
snapshot_uploader: Box<dyn SnapshotUploader>,
72+
73+
/// Pending certificate store
74+
certificate_pending_store: CertificatePendingStoreWrapper,
75+
76+
/// Certificate store
77+
certificate_store: CertificateStoreWrapper,
7178
}
7279

7380
impl AggregatorRuntime {
@@ -83,6 +90,8 @@ impl AggregatorRuntime {
8390
multi_signer: MultiSignerWrapper,
8491
snapshot_store: SnapshotStoreWrapper,
8592
snapshot_uploader: Box<dyn SnapshotUploader>,
93+
certificate_pending_store: CertificatePendingStoreWrapper,
94+
certificate_store: CertificateStoreWrapper,
8695
) -> Self {
8796
Self {
8897
interval,
@@ -93,6 +102,8 @@ impl AggregatorRuntime {
93102
multi_signer,
94103
snapshot_store,
95104
snapshot_uploader,
105+
certificate_pending_store,
106+
certificate_store,
96107
}
97108
}
98109

mithril-test-lab/mithril-end-to-end/src/Mithril/Aggregator.hs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,8 @@ aggregatorProcess cwd port = do
100100
("URL_SNAPSHOT_MANIFEST", "https://storage.googleapis.com/cardano-testnet/snapshots.json"),
101101
("SNAPSHOT_STORE_TYPE", "local"),
102102
("SNAPSHOT_UPLOADER_TYPE", "local"),
103-
("PENDING_CERTIFICATE_STORE_DIRECTORY", "./pending-certs")
103+
("PENDING_CERTIFICATE_STORE_DIRECTORY", "./store/pending-certs"),
104+
("CERTIFICATE_STORE_DIRECTORY", "./store/certs")
104105
]
105106
<> baseEnv
106107
unlessM (doesFileExist aggregator) $ failure $ "cannot find mithril-aggregator executable in expected location (" <> binDir <> ")"

0 commit comments

Comments
 (0)