Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Retrieve custom signing configuration with epoch settings in Signer #1939

4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ As a minor extension, we have adopted a slightly different versioning convention

- Optimizations of the state machine used by the signer to create individual signatures.

- Support for buffering of incoming single signatures by the aggregator if it can not aggregate them yet
- Support for buffering of incoming single signatures by the aggregator if it can not aggregate them yet.

- Expose the Cardano transactions signing configuration for the current and upcoming epoch via the `/epoch-settings` route.

- Crates versions:

Expand Down
6 changes: 3 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion mithril-aggregator/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "mithril-aggregator"
version = "0.5.64"
version = "0.5.65"
description = "A Mithril Aggregator server"
authors = { workspace = true }
edition = { workspace = true }
Expand Down
170 changes: 125 additions & 45 deletions mithril-aggregator/src/http_server/routes/epoch_routes.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
use crate::http_server::routes::middlewares;
use crate::DependencyContainer;
use std::sync::Arc;
use warp::Filter;

use mithril_common::{
entities::{SignedEntityConfig, SignedEntityTypeDiscriminants},
messages::{EpochSettingsMessage, SignerMessagePart},
StdResult,
};

use crate::dependency_injection::EpochServiceWrapper;
use crate::http_server::routes::middlewares;
use crate::DependencyContainer;

pub fn routes(
dependency_manager: Arc<DependencyContainer>,
) -> impl Filter<Extract = (impl warp::Reply,), Error = warp::Rejection> + Clone {
Expand All @@ -15,70 +23,86 @@ fn epoch_settings(
) -> impl Filter<Extract = (impl warp::Reply,), Error = warp::Rejection> + Clone {
warp::path!("epoch-settings")
.and(warp::get())
.and(middlewares::with_epoch_service(dependency_manager))
.and(middlewares::with_epoch_service(dependency_manager.clone()))
.and(middlewares::with_signed_entity_config(dependency_manager))
.and_then(handlers::epoch_settings)
}

async fn get_epoch_settings_message(
epoch_service: EpochServiceWrapper,
signed_entity_config: SignedEntityConfig,
) -> StdResult<EpochSettingsMessage> {
let epoch_service = epoch_service.read().await;

let epoch = epoch_service.epoch_of_current_data()?;
let protocol_parameters = epoch_service.next_protocol_parameters()?.clone();
let next_protocol_parameters = epoch_service.upcoming_protocol_parameters()?.clone();
let current_signers = epoch_service.current_signers()?;
let next_signers = epoch_service.next_signers()?;

let cardano_transactions_signing_config = signed_entity_config
.list_allowed_signed_entity_types_discriminants()
.contains(&SignedEntityTypeDiscriminants::CardanoTransactions)
.then_some(signed_entity_config.cardano_transactions_signing_config);
let next_cardano_transactions_signing_config = cardano_transactions_signing_config.clone();

let epoch_settings_message = EpochSettingsMessage {
epoch,
protocol_parameters,
next_protocol_parameters,
current_signers: SignerMessagePart::from_signers(current_signers.to_vec()),
next_signers: SignerMessagePart::from_signers(next_signers.to_vec()),
cardano_transactions_signing_config,
next_cardano_transactions_signing_config,
};

Ok(epoch_settings_message)
}

mod handlers {
use crate::dependency_injection::EpochServiceWrapper;
use crate::http_server::routes::reply;
use mithril_common::messages::{EpochSettingsMessage, SignerMessagePart};
use slog_scope::{debug, warn};
use slog_scope::debug;
use std::convert::Infallible;
use warp::http::StatusCode;

use mithril_common::entities::SignedEntityConfig;

use crate::dependency_injection::EpochServiceWrapper;
use crate::http_server::routes::epoch_routes::get_epoch_settings_message;
use crate::http_server::routes::reply;

/// Epoch Settings
pub async fn epoch_settings(
epoch_service: EpochServiceWrapper,
signed_entity_config: SignedEntityConfig,
) -> Result<impl warp::Reply, Infallible> {
debug!("⇄ HTTP SERVER: epoch_settings");
let epoch_service = epoch_service.read().await;

match (
epoch_service.epoch_of_current_data(),
epoch_service.next_protocol_parameters(),
epoch_service.upcoming_protocol_parameters(),
epoch_service.current_signers(),
epoch_service.next_signers(),
) {
(
Ok(epoch),
Ok(protocol_parameters),
Ok(next_protocol_parameters),
Ok(current_signers),
Ok(next_signers),
) => {
let epoch_settings_message = EpochSettingsMessage {
epoch,
protocol_parameters: protocol_parameters.clone(),
next_protocol_parameters: next_protocol_parameters.clone(),
current_signers: SignerMessagePart::from_signers(current_signers.to_vec()),
next_signers: SignerMessagePart::from_signers(next_signers.to_vec()),
};
Ok(reply::json(&epoch_settings_message, StatusCode::OK))
}
(Err(err), _, _, _, _)
| (_, Err(err), _, _, _)
| (_, _, Err(err), _, _)
| (_, _, _, Err(err), _)
| (_, _, _, _, Err(err)) => {
warn!("epoch_settings::error"; "error" => ?err);
Ok(reply::server_error(err))
}
let epoch_settings_message =
get_epoch_settings_message(epoch_service, signed_entity_config).await;

match epoch_settings_message {
Ok(message) => Ok(reply::json(&message, StatusCode::OK)),
Err(err) => Ok(reply::server_error(err)),
}
}
}

#[cfg(test)]
mod tests {
use serde_json::Value::Null;
use std::collections::BTreeSet;
use tokio::sync::RwLock;
use warp::{
http::{Method, StatusCode},
test::request,
};

use mithril_common::{
entities::Epoch,
entities::{
BlockNumber, CardanoTransactionsSigningConfig, Epoch, SignedEntityConfig,
SignedEntityTypeDiscriminants,
},
test_utils::{apispec::APISpec, MithrilFixtureBuilder},
};
use serde_json::Value::Null;
use tokio::sync::RwLock;
use warp::http::{Method, StatusCode};
use warp::test::request;

use crate::http_server::SERVER_BASE_PATH;
use crate::initialize_dependencies;
Expand All @@ -99,6 +123,62 @@ mod tests {
.and(routes(dependency_manager).with(cors))
}

#[tokio::test]
async fn get_epoch_settings_message_with_cardano_transactions_enabled() {
let fixture = MithrilFixtureBuilder::default().with_signers(3).build();
let epoch_service = FakeEpochService::from_fixture(Epoch(4), &fixture);
let epoch_service = Arc::new(RwLock::new(epoch_service));

let cardano_transactions_signing_config = CardanoTransactionsSigningConfig {
security_parameter: BlockNumber(70),
step: BlockNumber(15),
};
let signed_entity_config = SignedEntityConfig {
cardano_transactions_signing_config: cardano_transactions_signing_config.clone(),
allowed_discriminants: BTreeSet::from([
SignedEntityTypeDiscriminants::CardanoTransactions,
]),
..SignedEntityConfig::dummy()
};

let message = get_epoch_settings_message(epoch_service, signed_entity_config)
.await
.unwrap();

assert_eq!(
message.cardano_transactions_signing_config,
Some(cardano_transactions_signing_config.clone())
);
assert_eq!(
message.next_cardano_transactions_signing_config,
Some(cardano_transactions_signing_config)
);
}

#[tokio::test]
async fn get_epoch_settings_message_with_cardano_transactions_not_enabled() {
let fixture = MithrilFixtureBuilder::default().with_signers(3).build();
let epoch_service = FakeEpochService::from_fixture(Epoch(4), &fixture);
let epoch_service = Arc::new(RwLock::new(epoch_service));

let cardano_transactions_signing_config = CardanoTransactionsSigningConfig {
security_parameter: BlockNumber(70),
step: BlockNumber(15),
};
let signed_entity_config = SignedEntityConfig {
cardano_transactions_signing_config,
allowed_discriminants: BTreeSet::new(),
..SignedEntityConfig::dummy()
};

let message = get_epoch_settings_message(epoch_service, signed_entity_config)
.await
.unwrap();

assert_eq!(message.cardano_transactions_signing_config, None);
assert_eq!(message.next_cardano_transactions_signing_config, None);
}

#[tokio::test]
async fn test_epoch_settings_get_ok() {
let method = Method::GET.as_str();
Expand Down
2 changes: 1 addition & 1 deletion mithril-common/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "mithril-common"
version = "0.4.52"
version = "0.4.53"
description = "Common types, interfaces, and utilities for Mithril nodes."
authors = { workspace = true }
edition = { workspace = true }
Expand Down
8 changes: 7 additions & 1 deletion mithril-common/src/entities/epoch_settings.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::entities::{Epoch, ProtocolParameters};
use crate::entities::{CardanoTransactionsSigningConfig, Epoch, ProtocolParameters};

use super::Signer;

Expand All @@ -19,4 +19,10 @@ pub struct EpochSettings {

/// Signers that will be able to sign on the next epoch
pub next_signers: Vec<Signer>,

/// Cardano transactions signing configuration for the current epoch
pub cardano_transactions_signing_config: Option<CardanoTransactionsSigningConfig>,

/// Cardano transactions signing configuration for the next epoch
pub next_cardano_transactions_signing_config: Option<CardanoTransactionsSigningConfig>,
}
Loading
Loading