Skip to content

Commit

Permalink
Merge pull request #857 from input-output-hk/greg/848/beacon_message_…
Browse files Browse the repository at this point in the history
…type

embed beacon in open_message type
  • Loading branch information
ghubertpalo authored Apr 11, 2023
2 parents ca18af4 + bd2de93 commit d1c6af7
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 62 deletions.
4 changes: 2 additions & 2 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.2.47"
version = "0.2.48"
description = "A Mithril Aggregator server"
authors = { workspace = true }
edition = { workspace = true }
Expand Down
61 changes: 25 additions & 36 deletions mithril-aggregator/src/database/provider/open_message.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use mithril_common::StdError;

use mithril_common::{
entities::{Beacon, Epoch, SignedEntityType},
entities::{Epoch, SignedEntityType},
sqlite::{HydrationError, Projection, SqLiteEntity, WhereCondition},
sqlite::{Provider, SourceAlias},
};
Expand Down Expand Up @@ -30,10 +30,6 @@ pub struct OpenMessage {
/// Epoch
epoch: Epoch,

/// Beacon, this is the discriminant of this message type in the current
/// Epoch
beacon: Beacon,

/// Type of message
signed_entity_type: SignedEntityType,

Expand All @@ -60,21 +56,13 @@ impl SqLiteEntity for OpenMessage {
let epoch_val = u64::try_from(epoch_setting_id)
.map_err(|e| panic!("Integer field open_message.epoch_setting_id (value={epoch_setting_id}) is incompatible with u64 Epoch representation. Error = {e}"))?;

let beacon_str = row.get::<String, _>(2);
let signed_entity_type_id = usize::try_from(row.get::<i64, _>(3)).map_err(|e| {
panic!(
"Integer field open_message.signed_entity_type_id cannot be turned into usize: {e}"
)
})?;
let signed_entity_type = SignedEntityType::from_repr(signed_entity_type_id)
.ok_or_else(|| HydrationError::InvalidData(format!(
"Field open_message.signed_type_id can be either 0, 1 or 2, ({signed_entity_type_id} given)."
)))?;
let beacon_str = row.get::<String, _>(2);
let beacon: Beacon = serde_json::from_str(&beacon_str).map_err(|e| {
HydrationError::InvalidData(format!(
"Invalid Beacon JSON in open_message.beacon: '{beacon_str}'. Error: {e}"
))
})?;
let signed_entity_type = SignedEntityType::hydrate(signed_entity_type_id, &beacon_str)?;
let datetime = &row.get::<String, _>(5);
let created_at =
NaiveDateTime::parse_from_str(datetime, "%Y-%m-%d %H:%M:%S").map_err(|e| {
Expand All @@ -86,7 +74,6 @@ impl SqLiteEntity for OpenMessage {
let open_message = Self {
open_message_id,
epoch: Epoch(epoch_val),
beacon,
signed_entity_type,
message,
created_at,
Expand Down Expand Up @@ -141,7 +128,7 @@ impl<'client> OpenMessageProvider<'client> {
) -> WhereCondition {
WhereCondition::new(
"signed_entity_type_id = ?*",
vec![Value::Integer(*signed_entity_type as i64)],
vec![Value::Integer(signed_entity_type.index() as i64)],
)
}

Expand Down Expand Up @@ -181,16 +168,16 @@ impl<'client> InsertOpenMessageProvider<'client> {
fn get_insert_condition(
&self,
epoch: Epoch,
beacon: &Beacon,
signed_entity_type: &SignedEntityType,
message: &str,
) -> StdResult<WhereCondition> {
let expression = "(open_message_id, epoch_setting_id, beacon, signed_entity_type_id, message) values (?*, ?*, ?*, ?*, ?*)";
let beacon_str = signed_entity_type.get_json_beacon()?;
let parameters = vec![
Value::String(Uuid::new_v4().to_string()),
Value::Integer(epoch.0 as i64),
Value::String(serde_json::to_string(beacon)?),
Value::Integer(*signed_entity_type as i64),
Value::String(beacon_str),
Value::Integer(signed_entity_type.index() as i64),
Value::String(message.to_string()),
];

Expand Down Expand Up @@ -279,13 +266,12 @@ impl OpenMessageRepository {
pub async fn create_open_message(
&self,
epoch: Epoch,
beacon: &Beacon,
signed_entity_type: &SignedEntityType,
message: &str,
) -> StdResult<OpenMessage> {
let lock = self.connection.lock().await;
let provider = InsertOpenMessageProvider::new(&lock);
let filters = provider.get_insert_condition(epoch, beacon, signed_entity_type, message)?;
let filters = provider.get_insert_condition(epoch, signed_entity_type, message)?;
let mut cursor = provider.find(filters)?;

cursor
Expand All @@ -307,7 +293,7 @@ impl OpenMessageRepository {

#[cfg(test)]
mod tests {
use mithril_common::sqlite::SourceAlias;
use mithril_common::{entities::Beacon, sqlite::SourceAlias};

use crate::{dependency_injection::DependenciesBuilder, Configuration};

Expand Down Expand Up @@ -338,8 +324,13 @@ mod tests {
fn provider_message_type_condition() {
let connection = Connection::open(":memory:").unwrap();
let provider = OpenMessageProvider::new(&connection);
let beacon = Beacon {
network: "whatever".to_string(),
epoch: Epoch(4),
immutable_file_number: 400,
};
let (expr, params) = provider
.get_signed_entity_type_condition(&SignedEntityType::CardanoImmutableFilesFull)
.get_signed_entity_type_condition(&SignedEntityType::CardanoImmutableFilesFull(beacon))
.expand();

assert_eq!("signed_entity_type_id = ?1".to_string(), expr);
Expand Down Expand Up @@ -367,11 +358,11 @@ mod tests {
fn insert_provider_condition() {
let connection = Connection::open(":memory:").unwrap();
let provider = InsertOpenMessageProvider::new(&connection);
let epoch = Epoch(12);
let (expr, params) = provider
.get_insert_condition(
Epoch(12),
&Beacon::default(),
&SignedEntityType::CardanoStakeDistribution,
epoch,
&SignedEntityType::CardanoImmutableFilesFull(Beacon::default()),
"This is a message",
)
.unwrap()
Expand All @@ -383,7 +374,7 @@ mod tests {
Value::String(r#"{"network":"","epoch":0,"immutable_file_number":0}"#.to_string()),
params[2]
);
assert_eq!(Value::Integer(1), params[3]);
assert_eq!(Value::Integer(2), params[3]);
assert_eq!(Value::String("This is a message".to_string()), params[4]);
}

Expand Down Expand Up @@ -413,11 +404,11 @@ mod tests {
async fn repository_create_open_message() {
let connection = get_connection().await;
let repository = OpenMessageRepository::new(connection.clone());
let epoch = Epoch(1);
let open_message = repository
.create_open_message(
Epoch(1),
&Beacon::default(),
&SignedEntityType::CardanoImmutableFilesFull,
epoch,
&SignedEntityType::CardanoImmutableFilesFull(Beacon::default()),
"this is a message",
)
.await
Expand All @@ -426,7 +417,7 @@ mod tests {
assert_eq!(Epoch(1), open_message.epoch);
assert_eq!("this is a message".to_string(), open_message.message);
assert_eq!(
SignedEntityType::CardanoImmutableFilesFull,
SignedEntityType::CardanoImmutableFilesFull(Beacon::default()),
open_message.signed_entity_type
);

Expand Down Expand Up @@ -459,17 +450,15 @@ mod tests {
let _ = repository
.create_open_message(
Epoch(1),
&Beacon::default(),
&SignedEntityType::CardanoImmutableFilesFull,
&SignedEntityType::CardanoImmutableFilesFull(Beacon::default()),
"this is a message",
)
.await
.unwrap();
let _ = repository
.create_open_message(
Epoch(1),
&Beacon::default(),
&SignedEntityType::MithrilStakeDistribution,
&SignedEntityType::CardanoImmutableFilesFull(Beacon::default()),
"this is a stake distribution",
)
.await
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.2.37"
version = "0.2.38"
authors = { workspace = true }
edition = { workspace = true }
documentation = { workspace = true }
Expand Down
2 changes: 1 addition & 1 deletion mithril-common/src/entities/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub use epoch_settings::EpochSettings;
pub use http_server_error::{ClientError, InternalServerError};
pub use protocol_message::{ProtocolMessage, ProtocolMessagePartKey, ProtocolMessagePartValue};
pub use protocol_parameters::ProtocolParameters;
pub use signed_entity_type::SignedEntityType;
pub use signed_entity_type::*;
pub use signer::{Signer, SignerWithStake};
pub use single_signatures::SingleSignatures;
pub use snapshot::Snapshot;
Expand Down
93 changes: 72 additions & 21 deletions mithril-common/src/entities/signed_entity_type.rs
Original file line number Diff line number Diff line change
@@ -1,46 +1,97 @@
use strum::IntoEnumIterator;
use strum_macros::{Display, EnumIter, EnumString, FromRepr};
use strum_macros::Display;

use crate::{sqlite::HydrationError, StdError};

use super::{Beacon, Epoch};

/// Database representation of the SignedEntityType::MithrilStakeDistribution value
const ENTITY_TYPE_MITHRIL_STAKE_DISTRIBUTION: usize = 0;

/// Database representation of the SignedEntityType::CardanoStakeDistribution value
const ENTITY_TYPE_CARDANO_STAKE_DISTRIBUTION: usize = 1;

/// Database representation of the SignedEntityType::CardanoImmutableFilesFull value
const ENTITY_TYPE_CARDANO_IMMUTABLE_FILES_FULL: usize = 2;

/// The signed entity type that represents a type of data signed by the Mithril
/// protocol Note: Each variant of this enum must be associated to an entry in
/// the `signed_entity_type` table of the signer/aggregator nodes. The variant
/// are identified by their discriminant (i.e. index in the enum), thus the
/// modification of this type should only ever consist of appending new
/// variants.
#[derive(Display, FromRepr, EnumString, EnumIter, Debug, Clone, Copy, PartialEq, Eq)]
#[derive(Display, Debug, Clone, PartialEq, Eq)]
#[strum(serialize_all = "PascalCase")]
pub enum SignedEntityType {
/// Mithril stake distribution
MithrilStakeDistribution,
MithrilStakeDistribution(Epoch),

/// Cardano Stake Distribution
CardanoStakeDistribution,
CardanoStakeDistribution(Epoch),

/// Full Cardano Immutable Files
CardanoImmutableFilesFull,
CardanoImmutableFilesFull(Beacon),
}

impl SignedEntityType {
/// Retrieve the list of entity types
pub fn entity_types() -> Vec<Self> {
Self::iter().collect()
}

/// Retrieve a dummy enty (for test only)
pub fn dummy() -> Self {
Self::entity_types().first().unwrap().to_owned()
Self::MithrilStakeDistribution(Epoch(5))
}
}

#[cfg(test)]
mod tests {
use super::*;
/// Create an instance from data coming from the database
pub fn hydrate(signed_entity_type_id: usize, beacon_str: &str) -> Result<Self, HydrationError> {
let myself = match signed_entity_type_id {
ENTITY_TYPE_MITHRIL_STAKE_DISTRIBUTION => {
let epoch: Epoch = serde_json::from_str(beacon_str).map_err(|e| {
HydrationError::InvalidData(format!(
"Invalid Epoch JSON representation '{beacon_str}. Error: {e}'."
))
})?;
Self::MithrilStakeDistribution(epoch)
}
ENTITY_TYPE_CARDANO_STAKE_DISTRIBUTION => {
let epoch: Epoch = serde_json::from_str(beacon_str).map_err(|e| {
HydrationError::InvalidData(format!(
"Invalid Epoch JSON representation '{beacon_str}. Error: {e}'."
))
})?;
Self::CardanoStakeDistribution(epoch)
}
ENTITY_TYPE_CARDANO_IMMUTABLE_FILES_FULL => {
let beacon: Beacon = serde_json::from_str(beacon_str).map_err(|e| {
HydrationError::InvalidData(format!(
"Invalid Beacon JSON in open_message.beacon: '{beacon_str}'. Error: {e}"
))
})?;
Self::CardanoImmutableFilesFull(beacon)
}
index => panic!("Invalid entity_type_id {index}."),
};

#[test]
fn from_repr() {
let supported_entity_type = SignedEntityType::from_repr(SignedEntityType::dummy() as usize)
.expect("This signed entity type should support conversion from representation.");
Ok(myself)
}

assert_eq!(SignedEntityType::dummy(), supported_entity_type);
/// Get the database value from enum's instance
pub fn index(&self) -> usize {
match self {
Self::MithrilStakeDistribution(_) => ENTITY_TYPE_MITHRIL_STAKE_DISTRIBUTION,
Self::CardanoStakeDistribution(_) => ENTITY_TYPE_CARDANO_STAKE_DISTRIBUTION,
Self::CardanoImmutableFilesFull(_) => ENTITY_TYPE_CARDANO_IMMUTABLE_FILES_FULL,
}
}

/// Return a JSON serialized value of the internal beacon
pub fn get_json_beacon(&self) -> Result<String, StdError> {
let value = match self {
Self::CardanoImmutableFilesFull(value) => serde_json::to_string(value)?,
Self::CardanoStakeDistribution(value) | Self::MithrilStakeDistribution(value) => {
serde_json::to_string(value)?
}
};

Ok(value)
}
}

#[cfg(test)]
mod tests {}

0 comments on commit d1c6af7

Please sign in to comment.