Skip to content

Commit 1c6220e

Browse files
committed
feat(aggregator): accept latest in signers/registered route
1 parent 93399c3 commit 1c6220e

File tree

1 file changed

+77
-14
lines changed

1 file changed

+77
-14
lines changed

mithril-aggregator/src/http_server/routes/signer_routes.rs

Lines changed: 77 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1+
use anyhow::Context;
12
use slog::warn;
23
use warp::Filter;
34

5+
use mithril_common::entities::Epoch;
6+
use mithril_common::StdResult;
7+
48
use crate::dependency_injection::EpochServiceWrapper;
59
use crate::http_server::routes::middlewares;
610
use crate::DependencyContainer;
@@ -52,6 +56,7 @@ fn registered_signers(
5256
warp::path!("signers" / "registered" / String)
5357
.and(warp::get())
5458
.and(middlewares::with_logger(dependency_manager))
59+
.and(middlewares::with_epoch_service(dependency_manager))
5560
.and(middlewares::with_verification_key_store(dependency_manager))
5661
.and_then(handlers::registered_signers)
5762
}
@@ -69,19 +74,34 @@ async fn fetch_epoch_header_value(
6974
}
7075
}
7176

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+
7291
mod handlers {
7392
use crate::database::repository::SignerGetter;
7493
use crate::dependency_injection::EpochServiceWrapper;
7594
use crate::entities::{
7695
SignerRegistrationsMessage, SignerTickerListItemMessage, SignersTickersMessage,
7796
};
7897
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+
};
80101
use crate::{
81102
http_server::routes::reply, Configuration, SignerRegisterer, SignerRegistrationError,
82103
};
83104
use crate::{FromRegisterSignerAdapter, MetricsService, VerificationKeyStorer};
84-
use mithril_common::entities::Epoch;
85105
use mithril_common::messages::{RegisterSignerMessage, TryFromMessageAdapter};
86106
use slog::{debug, warn, Logger};
87107
use std::convert::Infallible;
@@ -175,27 +195,29 @@ mod handlers {
175195
pub async fn registered_signers(
176196
registered_at: String,
177197
logger: Logger,
198+
epoch_service: EpochServiceWrapper,
178199
verification_key_store: Arc<dyn VerificationKeyStorer>,
179200
) -> Result<impl warp::Reply, Infallible> {
180-
let registered_at = match registered_at.parse::<u64>() {
181-
Ok(epoch) => Epoch(epoch),
182-
Err(err) => {
183-
warn!(logger,"registered_signers::invalid_epoch"; "error" => ?err);
184-
return Ok(reply::bad_request(
185-
"invalid_epoch".to_string(),
186-
err.to_string(),
187-
));
188-
}
189-
};
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+
};
190212

191213
// The given epoch is the epoch at which the signer registered, the store works on
192214
// the recording epoch so we need to offset.
193215
match verification_key_store
194-
.get_signers(registered_at.offset_to_recording_epoch())
216+
.get_signers(registered_at_epoch.offset_to_recording_epoch())
195217
.await
196218
{
197219
Ok(Some(signers)) => {
198-
let message = SignerRegistrationsMessage::new(registered_at, signers);
220+
let message = SignerRegistrationsMessage::new(registered_at_epoch, signers);
199221
Ok(reply::json(&message, StatusCode::OK))
200222
}
201223
Ok(None) => {
@@ -710,4 +732,45 @@ mod tests {
710732

711733
assert_eq!(epoch_str, "".to_string());
712734
}
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+
}
713776
}

0 commit comments

Comments
 (0)