1
+ use anyhow:: Context ;
1
2
use slog:: warn;
2
3
use warp:: Filter ;
3
4
5
+ use mithril_common:: entities:: Epoch ;
6
+ use mithril_common:: StdResult ;
7
+
4
8
use crate :: dependency_injection:: EpochServiceWrapper ;
5
9
use crate :: http_server:: routes:: middlewares;
6
10
use crate :: DependencyContainer ;
@@ -52,6 +56,7 @@ fn registered_signers(
52
56
warp:: path!( "signers" / "registered" / String )
53
57
. and ( warp:: get ( ) )
54
58
. and ( middlewares:: with_logger ( dependency_manager) )
59
+ . and ( middlewares:: with_epoch_service ( dependency_manager) )
55
60
. and ( middlewares:: with_verification_key_store ( dependency_manager) )
56
61
. and_then ( handlers:: registered_signers)
57
62
}
@@ -69,19 +74,34 @@ async fn fetch_epoch_header_value(
69
74
}
70
75
}
71
76
77
+ async fn compute_registration_epoch (
78
+ registered_at : & str ,
79
+ epoch_service : EpochServiceWrapper ,
80
+ ) -> StdResult < Epoch > {
81
+ if registered_at. to_lowercase ( ) == "latest" {
82
+ epoch_service. read ( ) . await . epoch_of_current_data ( )
83
+ } else {
84
+ registered_at
85
+ . parse :: < u64 > ( )
86
+ . map ( Epoch )
87
+ . with_context ( || "Invalid epoch: must be a number or 'latest'" )
88
+ }
89
+ }
90
+
72
91
mod handlers {
73
92
use crate :: database:: repository:: SignerGetter ;
74
93
use crate :: dependency_injection:: EpochServiceWrapper ;
75
94
use crate :: entities:: {
76
95
SignerRegistrationsMessage , SignerTickerListItemMessage , SignersTickersMessage ,
77
96
} ;
78
97
use crate :: event_store:: { EventMessage , TransmitterService } ;
79
- use crate :: http_server:: routes:: signer_routes:: fetch_epoch_header_value;
98
+ use crate :: http_server:: routes:: signer_routes:: {
99
+ compute_registration_epoch, fetch_epoch_header_value,
100
+ } ;
80
101
use crate :: {
81
102
http_server:: routes:: reply, Configuration , SignerRegisterer , SignerRegistrationError ,
82
103
} ;
83
104
use crate :: { FromRegisterSignerAdapter , MetricsService , VerificationKeyStorer } ;
84
- use mithril_common:: entities:: Epoch ;
85
105
use mithril_common:: messages:: { RegisterSignerMessage , TryFromMessageAdapter } ;
86
106
use slog:: { debug, warn, Logger } ;
87
107
use std:: convert:: Infallible ;
@@ -175,29 +195,29 @@ mod handlers {
175
195
pub async fn registered_signers (
176
196
registered_at : String ,
177
197
logger : Logger ,
198
+ epoch_service : EpochServiceWrapper ,
178
199
verification_key_store : Arc < dyn VerificationKeyStorer > ,
179
200
) -> Result < impl warp:: Reply , Infallible > {
180
- debug ! ( logger, "GET /signers/registered/{registered_at:?}" ) ;
181
-
182
- let registered_at = match registered_at. parse :: < u64 > ( ) {
183
- Ok ( epoch) => Epoch ( epoch) ,
184
- Err ( err) => {
185
- warn ! ( logger, "registered_signers::invalid_epoch" ; "error" => ?err) ;
186
- return Ok ( reply:: bad_request (
187
- "invalid_epoch" . to_string ( ) ,
188
- err. to_string ( ) ,
189
- ) ) ;
190
- }
191
- } ;
201
+ let registered_at_epoch =
202
+ match compute_registration_epoch ( & registered_at, epoch_service) . await {
203
+ Ok ( epoch) => epoch,
204
+ Err ( err) => {
205
+ warn ! ( logger, "registered_signers::invalid_epoch" ; "error" => ?err) ;
206
+ return Ok ( reply:: bad_request (
207
+ "invalid_epoch" . to_string ( ) ,
208
+ err. to_string ( ) ,
209
+ ) ) ;
210
+ }
211
+ } ;
192
212
193
213
// The given epoch is the epoch at which the signer registered, the store works on
194
214
// the recording epoch so we need to offset.
195
215
match verification_key_store
196
- . get_signers ( registered_at . offset_to_recording_epoch ( ) )
216
+ . get_signers ( registered_at_epoch . offset_to_recording_epoch ( ) )
197
217
. await
198
218
{
199
219
Ok ( Some ( signers) ) => {
200
- let message = SignerRegistrationsMessage :: new ( registered_at , signers) ;
220
+ let message = SignerRegistrationsMessage :: new ( registered_at_epoch , signers) ;
201
221
Ok ( reply:: json ( & message, StatusCode :: OK ) )
202
222
}
203
223
Ok ( None ) => {
@@ -216,7 +236,6 @@ mod handlers {
216
236
configuration : Configuration ,
217
237
signer_getter : Arc < dyn SignerGetter > ,
218
238
) -> Result < impl warp:: Reply , Infallible > {
219
- debug ! ( logger, "GET /signers/tickers" ) ;
220
239
let network = configuration. network ;
221
240
222
241
match signer_getter. get_all ( ) . await {
@@ -713,4 +732,45 @@ mod tests {
713
732
714
733
assert_eq ! ( epoch_str, "" . to_string( ) ) ;
715
734
}
735
+
736
+ mod registered_signers_registration_epoch {
737
+ use crate :: services:: FakeEpochServiceBuilder ;
738
+
739
+ use super :: * ;
740
+
741
+ #[ tokio:: test]
742
+ async fn use_given_epoch_if_valid_number ( ) {
743
+ let epoch_service = Arc :: new ( RwLock :: new (
744
+ FakeEpochServiceBuilder :: dummy ( Epoch ( 89 ) ) . build ( ) ,
745
+ ) ) ;
746
+ let epoch = compute_registration_epoch ( "456" , epoch_service)
747
+ . await
748
+ . unwrap ( ) ;
749
+
750
+ assert_eq ! ( epoch, Epoch ( 456 ) ) ;
751
+ }
752
+
753
+ #[ tokio:: test]
754
+ async fn use_epoch_service_current_epoch_if_latest ( ) {
755
+ let epoch_service = Arc :: new ( RwLock :: new (
756
+ FakeEpochServiceBuilder :: dummy ( Epoch ( 89 ) ) . build ( ) ,
757
+ ) ) ;
758
+ let epoch = compute_registration_epoch ( "latest" , epoch_service)
759
+ . await
760
+ . unwrap ( ) ;
761
+
762
+ assert_eq ! ( epoch, Epoch ( 89 ) ) ;
763
+ }
764
+
765
+ #[ tokio:: test]
766
+ async fn error_if_given_epoch_is_not_a_number_nor_latest ( ) {
767
+ let epoch_service = Arc :: new ( RwLock :: new (
768
+ FakeEpochServiceBuilder :: dummy ( Epoch ( 89 ) ) . build ( ) ,
769
+ ) ) ;
770
+
771
+ compute_registration_epoch ( "invalid" , epoch_service)
772
+ . await
773
+ . expect_err ( "Should fail if epoch is not a number nor 'latest'" ) ;
774
+ }
775
+ }
716
776
}
0 commit comments