15
15
//! 4. Store the fetched certificates in the database, from genesis to latest, for each certificate:
16
16
//! - if it exists in the database, it is replaced
17
17
//! - if it doesn't exist, it is inserted
18
- //! 5. End
18
+ //! 5. Create a certified open message in the database, based on the latest certificate and with a
19
+ //! MithrilStakeDistribution signed entity type
20
+ //! 6. End
19
21
//!
20
22
use anyhow:: { Context , anyhow} ;
21
23
use async_trait:: async_trait;
24
+ use chrono:: Utc ;
22
25
use slog:: { Logger , debug, info} ;
23
26
use std:: collections:: VecDeque ;
24
27
use std:: sync:: Arc ;
25
28
26
29
use mithril_common:: StdResult ;
27
30
use mithril_common:: certificate_chain:: CertificateVerifier ;
28
31
use mithril_common:: crypto_helper:: ProtocolGenesisVerifier ;
29
- use mithril_common:: entities:: Certificate ;
32
+ use mithril_common:: entities:: { Certificate , SignedEntityType } ;
30
33
use mithril_common:: logging:: LoggerExtensions ;
31
34
35
+ use crate :: entities:: OpenMessage ;
36
+
32
37
use super :: {
33
- CertificateChainSynchronizer , RemoteCertificateRetriever , SynchronizedCertificateStorer ,
38
+ CertificateChainSynchronizer , OpenMessageStorer , RemoteCertificateRetriever ,
39
+ SynchronizedCertificateStorer ,
34
40
} ;
35
41
36
42
/// Service that synchronizes the certificate chain with a remote aggregator
@@ -39,6 +45,7 @@ pub struct MithrilCertificateChainSynchronizer {
39
45
certificate_storer : Arc < dyn SynchronizedCertificateStorer > ,
40
46
certificate_verifier : Arc < dyn CertificateVerifier > ,
41
47
genesis_verifier : Arc < ProtocolGenesisVerifier > ,
48
+ open_message_storer : Arc < dyn OpenMessageStorer > ,
42
49
logger : Logger ,
43
50
}
44
51
@@ -68,13 +75,15 @@ impl MithrilCertificateChainSynchronizer {
68
75
certificate_storer : Arc < dyn SynchronizedCertificateStorer > ,
69
76
certificate_verifier : Arc < dyn CertificateVerifier > ,
70
77
genesis_verifier : Arc < ProtocolGenesisVerifier > ,
78
+ open_message_storer : Arc < dyn OpenMessageStorer > ,
71
79
logger : Logger ,
72
80
) -> Self {
73
81
Self {
74
82
remote_certificate_retriever,
75
83
certificate_storer,
76
84
certificate_verifier,
77
85
genesis_verifier,
86
+ open_message_storer,
78
87
logger : logger. new_with_component_name :: < Self > ( ) ,
79
88
}
80
89
}
@@ -164,13 +173,18 @@ impl CertificateChainSynchronizer for MithrilCertificateChainSynchronizer {
164
173
anyhow ! ( "Remote aggregator doesn't have a chain yet" )
165
174
. context ( "Failed to retrieve latest remote certificate details" ) ,
166
175
) ?;
176
+ let open_message = prepare_open_message_to_store ( & starting_point) ;
167
177
let remote_certificate_chain = self
168
178
. retrieve_and_validate_remote_certificate_chain ( starting_point)
169
179
. await
170
180
. with_context ( || "Failed to retrieve and validate remote certificate chain" ) ?;
171
181
self . store_certificate_chain ( remote_certificate_chain)
172
182
. await
173
183
. with_context ( || "Failed to store remote retrieved certificate chain" ) ?;
184
+ self . open_message_storer
185
+ . insert_or_replace_open_message ( open_message)
186
+ . await
187
+ . with_context ( || "Failed to store open message when synchronizing certificate chain" ) ?;
174
188
175
189
info ! (
176
190
self . logger,
@@ -180,6 +194,19 @@ impl CertificateChainSynchronizer for MithrilCertificateChainSynchronizer {
180
194
}
181
195
}
182
196
197
+ fn prepare_open_message_to_store ( latest_certificate : & Certificate ) -> OpenMessage {
198
+ OpenMessage {
199
+ epoch : latest_certificate. epoch ,
200
+ signed_entity_type : SignedEntityType :: MithrilStakeDistribution ( latest_certificate. epoch ) ,
201
+ protocol_message : latest_certificate. protocol_message . clone ( ) ,
202
+ is_certified : true ,
203
+ is_expired : false ,
204
+ single_signatures : Vec :: new ( ) ,
205
+ created_at : Utc :: now ( ) ,
206
+ expires_at : None ,
207
+ }
208
+ }
209
+
183
210
#[ cfg( test) ]
184
211
mod tests {
185
212
use anyhow:: anyhow;
@@ -194,7 +221,9 @@ mod tests {
194
221
mock_extensions:: MockBuilder ,
195
222
} ;
196
223
197
- use crate :: services:: { MockRemoteCertificateRetriever , MockSynchronizedCertificateStorer } ;
224
+ use crate :: services:: {
225
+ MockOpenMessageStorer , MockRemoteCertificateRetriever , MockSynchronizedCertificateStorer ,
226
+ } ;
198
227
use crate :: test_tools:: TestLogger ;
199
228
200
229
use super :: * ;
@@ -240,6 +269,7 @@ mod tests {
240
269
Arc :: new ( ProtocolGenesisVerifier :: from_verification_key (
241
270
genesis_verification_key,
242
271
) ) ,
272
+ Arc :: new ( MockOpenMessageStorer :: new ( ) ) ,
243
273
TestLogger :: stdout ( ) ,
244
274
)
245
275
}
@@ -599,6 +629,8 @@ mod tests {
599
629
}
600
630
601
631
mod synchronize_certificate_chain {
632
+ use mockall:: predicate:: function;
633
+
602
634
use super :: * ;
603
635
604
636
fn build_synchroniser (
@@ -617,6 +649,17 @@ mod tests {
617
649
. return_once ( move || Ok ( Some ( latest) ) ) ;
618
650
} ) ,
619
651
certificate_verifier : fake_verifier ( remote_chain) ,
652
+ open_message_storer : MockBuilder :: < MockOpenMessageStorer > :: configure ( |mock| {
653
+ // Ensure that `store_open_message` is called
654
+ let expected_msd_epoch = remote_chain. latest_certificate ( ) . epoch ;
655
+ mock. expect_insert_or_replace_open_message ( )
656
+ . with ( function ( move |open_message : & OpenMessage | {
657
+ open_message. signed_entity_type
658
+ == SignedEntityType :: MithrilStakeDistribution ( expected_msd_epoch)
659
+ } ) )
660
+ . times ( 1 ..)
661
+ . returning ( |_| Ok ( ( ) ) ) ;
662
+ } ) ,
620
663
..MithrilCertificateChainSynchronizer :: default_for_test ( )
621
664
}
622
665
}
0 commit comments