Skip to content

Commit 3e17cbe

Browse files
committed
[wip] message list
1 parent 48ff787 commit 3e17cbe

File tree

5 files changed

+273
-7
lines changed

5 files changed

+273
-7
lines changed
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
use std::sync::Arc;
2+
3+
use mithril_common::{
4+
messages::{
5+
CertificateListItemMessage, CertificateListItemMessageMetadata, CertificateMessage,
6+
CertificateMetadataMessagePart,
7+
},
8+
StdResult,
9+
};
10+
use sqlite::ConnectionWithFullMutex;
11+
12+
use super::{CertificateRecord, CertificateRecordProvider};
13+
14+
pub struct CertificateMessageRepository {
15+
connection: Arc<ConnectionWithFullMutex>,
16+
}
17+
18+
impl CertificateMessageRepository {
19+
pub fn new(connection: Arc<ConnectionWithFullMutex>) -> Self {
20+
Self { connection }
21+
}
22+
}
23+
24+
impl From<CertificateRecord> for CertificateMessage {
25+
fn from(value: CertificateRecord) -> Self {
26+
let metadata = CertificateMetadataMessagePart {
27+
protocol_version: value.protocol_version,
28+
protocol_parameters: value.protocol_parameters,
29+
initiated_at: value.initiated_at,
30+
sealed_at: value.sealed_at,
31+
signers: value.signers,
32+
};
33+
let (multi_signature, genesis_signature) = if value.parent_certificate_id.is_none() {
34+
(String::new(), value.signature)
35+
} else {
36+
(value.signature, String::new())
37+
};
38+
39+
CertificateMessage {
40+
hash: value.certificate_id,
41+
previous_hash: value.parent_certificate_id.unwrap_or_else(|| String::new()),
42+
beacon: value.beacon,
43+
metadata,
44+
protocol_message: value.protocol_message,
45+
signed_message: value.message,
46+
aggregate_verification_key: value.aggregate_verification_key,
47+
multi_signature,
48+
genesis_signature,
49+
}
50+
}
51+
}
52+
53+
impl From<CertificateRecord> for CertificateListItemMessage {
54+
fn from(value: CertificateRecord) -> Self {
55+
let metadata = CertificateListItemMessageMetadata {
56+
protocol_version: value.protocol_version,
57+
protocol_parameters: value.protocol_parameters,
58+
initiated_at: value.initiated_at,
59+
sealed_at: value.sealed_at,
60+
total_signers: value.signers.len(),
61+
};
62+
let (multi_signature, genesis_signature) = if value.parent_certificate_id.is_none() {
63+
(String::new(), value.signature)
64+
} else {
65+
(value.signature, String::new())
66+
};
67+
68+
CertificateListItemMessage {
69+
hash: value.certificate_id,
70+
previous_hash: value.parent_certificate_id.unwrap_or_else(|| String::new()),
71+
beacon: value.beacon,
72+
metadata,
73+
protocol_message: value.protocol_message,
74+
signed_message: value.message,
75+
aggregate_verification_key: value.aggregate_verification_key,
76+
}
77+
}
78+
}
79+
80+
impl CertificateMessageRepository {
81+
pub async fn get_certificate(&self, hash: &str) -> StdResult<Option<CertificateMessage>> {
82+
let provider = CertificateRecordProvider::new(&self.connection);
83+
let mut cursor = provider.get_by_certificate_id(hash)?;
84+
85+
Ok(cursor.next().map(|v| v.into()))
86+
}
87+
88+
pub async fn get_last(&self, limit: usize) -> StdResult<Vec<CertificateListItemMessage>> {
89+
let provider = CertificateRecordProvider::new(&self.connection);
90+
let cursor = provider.get_all()?;
91+
92+
Ok(cursor.into_iter().take(limit).map(|v| v.into()).collect())
93+
}
94+
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! Aggregator related database providers
22
mod certificate;
33
mod epoch_setting;
4+
mod message;
45
mod open_message;
56
mod signed_entity;
67
mod signer;
@@ -12,6 +13,7 @@ mod test_helper;
1213

1314
pub use certificate::*;
1415
pub use epoch_setting::*;
16+
pub use message::*;
1517
pub use open_message::*;
1618
pub use signed_entity::*;
1719
pub use signer::*;

mithril-aggregator/src/dependency_injection/builder.rs

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,16 +45,16 @@ use crate::{
4545
},
4646
configuration::ExecutionEnvironment,
4747
database::provider::{
48-
CertificateRepository, EpochSettingStore, OpenMessageRepository, SignedEntityStoreAdapter,
49-
SignedEntityStorer, SignerRegistrationStore, SignerStore, SingleSignatureRepository,
50-
StakePoolStore,
48+
CertificateMessageRepository, CertificateRepository, EpochSettingStore,
49+
OpenMessageRepository, SignedEntityStoreAdapter, SignedEntityStorer,
50+
SignerRegistrationStore, SignerStore, SingleSignatureRepository, StakePoolStore,
5151
},
5252
event_store::{EventMessage, EventStore, TransmitterService},
5353
http_server::routes::router,
5454
services::{
55-
CertifierService, MithrilCertifierService, MithrilEpochService, MithrilSignedEntityService,
56-
MithrilStakeDistributionService, MithrilTickerService, SignedEntityService,
57-
StakeDistributionService, TickerService,
55+
CertifierService, HttpMessageService, MithrilCertifierService, MithrilEpochService,
56+
MithrilHttpMessageService, MithrilSignedEntityService, MithrilStakeDistributionService,
57+
MithrilTickerService, SignedEntityService, StakeDistributionService, TickerService,
5858
},
5959
tools::{CExplorerSignerRetriever, GcpFileUploader, GenesisToolsDependency, SignersImporter},
6060
AggregatorConfig, AggregatorRunner, AggregatorRuntime, CertificatePendingStore,
@@ -185,6 +185,9 @@ pub struct DependenciesBuilder {
185185

186186
/// Signed Entity storer
187187
pub signed_entity_storer: Option<Arc<dyn SignedEntityStorer>>,
188+
189+
/// HTTP Message service
190+
pub http_message_service: Option<Arc<dyn HttpMessageService>>,
188191
}
189192

190193
impl DependenciesBuilder {
@@ -225,6 +228,7 @@ impl DependenciesBuilder {
225228
certifier_service: None,
226229
epoch_service: None,
227230
signed_entity_storer: None,
231+
http_message_service: None,
228232
}
229233
}
230234

@@ -1208,7 +1212,26 @@ impl DependenciesBuilder {
12081212
Ok(self.certifier_service.as_ref().cloned().unwrap())
12091213
}
12101214

1211-
/// Remove the dependencies builder from memory to release Arc.
1215+
/// build HTTP message service
1216+
pub async fn build_http_message_service(&mut self) -> Result<Arc<dyn HttpMessageService>> {
1217+
let certificate_message_repository = Arc::new(CertificateMessageRepository::new(
1218+
self.get_sqlite_connection().await?,
1219+
));
1220+
let service = MithrilHttpMessageService::new(certificate_message_repository);
1221+
1222+
Ok(Arc::new(service))
1223+
}
1224+
1225+
/// [HttpMessageService] service
1226+
pub async fn get_http_message_service(&mut self) -> Result<Arc<dyn HttpMessageService>> {
1227+
if self.http_message_service.is_none() {
1228+
self.http_message_service = Some(self.build_http_message_service().await?);
1229+
}
1230+
1231+
Ok(self.http_message_service.as_ref().cloned().unwrap())
1232+
}
1233+
1234+
/// Remove the dependencies builder from memory to release Arc instances.
12121235
pub async fn vanish(self) {
12131236
self.drop_sqlite_connection().await;
12141237
}
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
//! This service is responsible of provinding HTTP server with messages as fast as possible.
2+
3+
use std::sync::Arc;
4+
5+
use async_trait::async_trait;
6+
use thiserror::Error;
7+
8+
use mithril_common::{
9+
messages::{CertificateListMessage, CertificateMessage, CertificatePendingMessage},
10+
StdResult,
11+
};
12+
13+
use crate::database::provider::CertificateMessageRepository;
14+
15+
/// Error related to the [HttpMessageService]
16+
#[derive(Debug, Error)]
17+
pub enum HttpMessageServiceError {
18+
/// There is no current PendingCertificate
19+
#[error("There is no current pending certificate.")]
20+
PendingCertificateDoesNotExist,
21+
}
22+
/// HTTP Message service trait.
23+
#[async_trait]
24+
pub trait HttpMessageService {
25+
/// Return the message representation of a certificate if it exists.
26+
async fn get_certificate(
27+
&self,
28+
certificate_hash: &str,
29+
) -> StdResult<Option<CertificateMessage>>;
30+
31+
/// Return the message representation of the last N certificates
32+
async fn get_last_certificates(&self, limit: usize) -> StdResult<CertificateListMessage>;
33+
34+
/// Return the message representation of the current pending certificate
35+
async fn get_pending_certificate(&self) -> StdResult<CertificatePendingMessage>;
36+
}
37+
38+
pub struct MithrilHttpMessageService {
39+
certificate_message_repository: Arc<CertificateMessageRepository>,
40+
}
41+
42+
impl MithrilHttpMessageService {
43+
pub fn new(certificate_message_repository: Arc<CertificateMessageRepository>) -> Self {
44+
Self {
45+
certificate_message_repository,
46+
}
47+
}
48+
}
49+
50+
#[async_trait]
51+
impl HttpMessageService for MithrilHttpMessageService {
52+
async fn get_certificate(
53+
&self,
54+
certificate_hash: &str,
55+
) -> StdResult<Option<CertificateMessage>> {
56+
self.certificate_message_repository
57+
.get_certificate(certificate_hash)
58+
.await
59+
}
60+
61+
async fn get_last_certificates(&self, limit: usize) -> StdResult<CertificateListMessage> {
62+
self.certificate_message_repository.get_last(limit).await
63+
}
64+
65+
async fn get_pending_certificate(&self) -> StdResult<CertificatePendingMessage> {
66+
todo!()
67+
}
68+
}
69+
70+
#[cfg(test)]
71+
mod tests {
72+
use mithril_common::{entities::Beacon, test_utils::MithrilFixtureBuilder};
73+
74+
use crate::{dependency_injection::DependenciesBuilder, Configuration};
75+
76+
use super::*;
77+
78+
#[tokio::test]
79+
async fn get_no_certificate() {
80+
// setup
81+
let configuration = Configuration::new_sample();
82+
let mut dep_builder = DependenciesBuilder::new(configuration);
83+
let service = dep_builder.get_http_message_service().await.unwrap();
84+
85+
// test
86+
let certificate_hash = "whatever";
87+
let certficate_message = service.get_certificate(certificate_hash).await.unwrap();
88+
assert!(certficate_message.is_none());
89+
}
90+
91+
#[tokio::test]
92+
async fn get_certificate() {
93+
// setup
94+
let configuration = Configuration::new_sample();
95+
let mut dep_builder = DependenciesBuilder::new(configuration);
96+
let service = dep_builder.get_http_message_service().await.unwrap();
97+
let beacon = Beacon::new("devnet".to_string(), 3, 1);
98+
let fixture = MithrilFixtureBuilder::default().with_signers(3).build();
99+
let genesis_beacon = Beacon {
100+
epoch: beacon.epoch - 1,
101+
..beacon.clone()
102+
};
103+
let genesis_certificate = fixture.create_genesis_certificate(&genesis_beacon);
104+
dep_builder
105+
.get_certificate_repository()
106+
.await
107+
.unwrap()
108+
.create_certificate(genesis_certificate.clone())
109+
.await
110+
.unwrap();
111+
112+
// test
113+
let certficate_message = service
114+
.get_certificate(&genesis_certificate.hash)
115+
.await
116+
.unwrap()
117+
.expect("There should be a certificate.");
118+
assert_eq!(genesis_certificate.hash, certficate_message.hash);
119+
}
120+
121+
#[tokio::test]
122+
async fn get_last_certificates() {
123+
let configuration = Configuration::new_sample();
124+
let mut dep_builder = DependenciesBuilder::new(configuration);
125+
let service = dep_builder.get_http_message_service().await.unwrap();
126+
let beacon = Beacon::new("devnet".to_string(), 3, 1);
127+
let fixture = MithrilFixtureBuilder::default().with_signers(3).build();
128+
let genesis_beacon = Beacon {
129+
epoch: beacon.epoch - 1,
130+
..beacon.clone()
131+
};
132+
let genesis_certificate = fixture.create_genesis_certificate(&genesis_beacon);
133+
dep_builder
134+
.get_certificate_repository()
135+
.await
136+
.unwrap()
137+
.create_certificate(genesis_certificate.clone())
138+
.await
139+
.unwrap();
140+
141+
// test
142+
let certficate_messages = service.get_last_certificates(5).await.unwrap();
143+
assert_eq!(genesis_certificate.hash, certficate_messages[0].hash);
144+
}
145+
}

mithril-aggregator/src/services/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,14 @@
1111
1212
mod certifier;
1313
mod epoch_service;
14+
mod http_message;
1415
mod signed_entity;
1516
mod stake_distribution;
1617
mod ticker;
1718

1819
pub use certifier::*;
1920
pub use epoch_service::*;
21+
pub use http_message::*;
2022
pub use signed_entity::*;
2123
pub use stake_distribution::*;
2224
pub use ticker::*;

0 commit comments

Comments
 (0)