Skip to content

Commit dad3dbc

Browse files
authored
Merge pull request #2062 from input-output-hk/djo/1689/latest_for_registered_signers
Access registered signers for latest epoch in explorer
2 parents 814ab15 + 82ce6ca commit dad3dbc

File tree

7 files changed

+138
-75
lines changed

7 files changed

+138
-75
lines changed

Cargo.lock

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

mithril-aggregator/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mithril-aggregator"
3-
version = "0.5.95"
3+
version = "0.5.96"
44
description = "A Mithril Aggregator server"
55
authors = { workspace = true }
66
edition = { workspace = true }

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

+77-17
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,29 +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-
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+
};
192212

193213
// The given epoch is the epoch at which the signer registered, the store works on
194214
// the recording epoch so we need to offset.
195215
match verification_key_store
196-
.get_signers(registered_at.offset_to_recording_epoch())
216+
.get_signers(registered_at_epoch.offset_to_recording_epoch())
197217
.await
198218
{
199219
Ok(Some(signers)) => {
200-
let message = SignerRegistrationsMessage::new(registered_at, signers);
220+
let message = SignerRegistrationsMessage::new(registered_at_epoch, signers);
201221
Ok(reply::json(&message, StatusCode::OK))
202222
}
203223
Ok(None) => {
@@ -216,7 +236,6 @@ mod handlers {
216236
configuration: Configuration,
217237
signer_getter: Arc<dyn SignerGetter>,
218238
) -> Result<impl warp::Reply, Infallible> {
219-
debug!(logger, "GET /signers/tickers");
220239
let network = configuration.network;
221240

222241
match signer_getter.get_all().await {
@@ -713,4 +732,45 @@ mod tests {
713732

714733
assert_eq!(epoch_str, "".to_string());
715734
}
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+
}
716776
}

mithril-explorer/package-lock.json

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

mithril-explorer/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "mithril-explorer",
3-
"version": "0.7.13",
3+
"version": "0.7.14",
44
"private": true,
55
"scripts": {
66
"dev": "next dev",

mithril-explorer/src/app/registrations/page.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -49,21 +49,21 @@ export default function Registrations() {
4949

5050
useEffect(() => {
5151
const aggregator = searchParams.get(aggregatorSearchParam);
52-
const epoch = Number(searchParams.get("epoch"));
52+
const epoch = searchParams.get("epoch");
5353
let error = undefined;
5454
setAggregator(aggregator);
55-
setRegistrationEpoch(epoch);
5655

5756
if (!checkUrl(aggregator)) {
5857
error = "invalidAggregatorUrl";
59-
} else if (!Number.isInteger(epoch)) {
58+
} else if (epoch !== "latest" && !Number.isInteger(Number(epoch))) {
6059
error = "invalidEpoch";
6160
}
6261

6362
if (error === undefined) {
6463
fetchRegistrations(aggregator, epoch)
6564
.then((data) => {
6665
setSigningEpoch(data.signing_at);
66+
setRegistrationEpoch(data.registered_at);
6767
setRegistrations(data.registrations);
6868
setCharts({
6969
stakesBreakdown: computeStakeShapesDataset(data.registrations),

0 commit comments

Comments
 (0)