Skip to content

Commit d1c6af7

Browse files
authored
Merge pull request #857 from input-output-hk/greg/848/beacon_message_type
embed beacon in open_message type
2 parents ca18af4 + bd2de93 commit d1c6af7

File tree

6 files changed

+102
-62
lines changed

6 files changed

+102
-62
lines changed

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

mithril-aggregator/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mithril-aggregator"
3-
version = "0.2.47"
3+
version = "0.2.48"
44
description = "A Mithril Aggregator server"
55
authors = { workspace = true }
66
edition = { workspace = true }

mithril-aggregator/src/database/provider/open_message.rs

Lines changed: 25 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use mithril_common::StdError;
22

33
use mithril_common::{
4-
entities::{Beacon, Epoch, SignedEntityType},
4+
entities::{Epoch, SignedEntityType},
55
sqlite::{HydrationError, Projection, SqLiteEntity, WhereCondition},
66
sqlite::{Provider, SourceAlias},
77
};
@@ -30,10 +30,6 @@ pub struct OpenMessage {
3030
/// Epoch
3131
epoch: Epoch,
3232

33-
/// Beacon, this is the discriminant of this message type in the current
34-
/// Epoch
35-
beacon: Beacon,
36-
3733
/// Type of message
3834
signed_entity_type: SignedEntityType,
3935

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

59+
let beacon_str = row.get::<String, _>(2);
6360
let signed_entity_type_id = usize::try_from(row.get::<i64, _>(3)).map_err(|e| {
6461
panic!(
6562
"Integer field open_message.signed_entity_type_id cannot be turned into usize: {e}"
6663
)
6764
})?;
68-
let signed_entity_type = SignedEntityType::from_repr(signed_entity_type_id)
69-
.ok_or_else(|| HydrationError::InvalidData(format!(
70-
"Field open_message.signed_type_id can be either 0, 1 or 2, ({signed_entity_type_id} given)."
71-
)))?;
72-
let beacon_str = row.get::<String, _>(2);
73-
let beacon: Beacon = serde_json::from_str(&beacon_str).map_err(|e| {
74-
HydrationError::InvalidData(format!(
75-
"Invalid Beacon JSON in open_message.beacon: '{beacon_str}'. Error: {e}"
76-
))
77-
})?;
65+
let signed_entity_type = SignedEntityType::hydrate(signed_entity_type_id, &beacon_str)?;
7866
let datetime = &row.get::<String, _>(5);
7967
let created_at =
8068
NaiveDateTime::parse_from_str(datetime, "%Y-%m-%d %H:%M:%S").map_err(|e| {
@@ -86,7 +74,6 @@ impl SqLiteEntity for OpenMessage {
8674
let open_message = Self {
8775
open_message_id,
8876
epoch: Epoch(epoch_val),
89-
beacon,
9077
signed_entity_type,
9178
message,
9279
created_at,
@@ -141,7 +128,7 @@ impl<'client> OpenMessageProvider<'client> {
141128
) -> WhereCondition {
142129
WhereCondition::new(
143130
"signed_entity_type_id = ?*",
144-
vec![Value::Integer(*signed_entity_type as i64)],
131+
vec![Value::Integer(signed_entity_type.index() as i64)],
145132
)
146133
}
147134

@@ -181,16 +168,16 @@ impl<'client> InsertOpenMessageProvider<'client> {
181168
fn get_insert_condition(
182169
&self,
183170
epoch: Epoch,
184-
beacon: &Beacon,
185171
signed_entity_type: &SignedEntityType,
186172
message: &str,
187173
) -> StdResult<WhereCondition> {
188174
let expression = "(open_message_id, epoch_setting_id, beacon, signed_entity_type_id, message) values (?*, ?*, ?*, ?*, ?*)";
175+
let beacon_str = signed_entity_type.get_json_beacon()?;
189176
let parameters = vec![
190177
Value::String(Uuid::new_v4().to_string()),
191178
Value::Integer(epoch.0 as i64),
192-
Value::String(serde_json::to_string(beacon)?),
193-
Value::Integer(*signed_entity_type as i64),
179+
Value::String(beacon_str),
180+
Value::Integer(signed_entity_type.index() as i64),
194181
Value::String(message.to_string()),
195182
];
196183

@@ -279,13 +266,12 @@ impl OpenMessageRepository {
279266
pub async fn create_open_message(
280267
&self,
281268
epoch: Epoch,
282-
beacon: &Beacon,
283269
signed_entity_type: &SignedEntityType,
284270
message: &str,
285271
) -> StdResult<OpenMessage> {
286272
let lock = self.connection.lock().await;
287273
let provider = InsertOpenMessageProvider::new(&lock);
288-
let filters = provider.get_insert_condition(epoch, beacon, signed_entity_type, message)?;
274+
let filters = provider.get_insert_condition(epoch, signed_entity_type, message)?;
289275
let mut cursor = provider.find(filters)?;
290276

291277
cursor
@@ -307,7 +293,7 @@ impl OpenMessageRepository {
307293

308294
#[cfg(test)]
309295
mod tests {
310-
use mithril_common::sqlite::SourceAlias;
296+
use mithril_common::{entities::Beacon, sqlite::SourceAlias};
311297

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

@@ -338,8 +324,13 @@ mod tests {
338324
fn provider_message_type_condition() {
339325
let connection = Connection::open(":memory:").unwrap();
340326
let provider = OpenMessageProvider::new(&connection);
327+
let beacon = Beacon {
328+
network: "whatever".to_string(),
329+
epoch: Epoch(4),
330+
immutable_file_number: 400,
331+
};
341332
let (expr, params) = provider
342-
.get_signed_entity_type_condition(&SignedEntityType::CardanoImmutableFilesFull)
333+
.get_signed_entity_type_condition(&SignedEntityType::CardanoImmutableFilesFull(beacon))
343334
.expand();
344335

345336
assert_eq!("signed_entity_type_id = ?1".to_string(), expr);
@@ -367,11 +358,11 @@ mod tests {
367358
fn insert_provider_condition() {
368359
let connection = Connection::open(":memory:").unwrap();
369360
let provider = InsertOpenMessageProvider::new(&connection);
361+
let epoch = Epoch(12);
370362
let (expr, params) = provider
371363
.get_insert_condition(
372-
Epoch(12),
373-
&Beacon::default(),
374-
&SignedEntityType::CardanoStakeDistribution,
364+
epoch,
365+
&SignedEntityType::CardanoImmutableFilesFull(Beacon::default()),
375366
"This is a message",
376367
)
377368
.unwrap()
@@ -383,7 +374,7 @@ mod tests {
383374
Value::String(r#"{"network":"","epoch":0,"immutable_file_number":0}"#.to_string()),
384375
params[2]
385376
);
386-
assert_eq!(Value::Integer(1), params[3]);
377+
assert_eq!(Value::Integer(2), params[3]);
387378
assert_eq!(Value::String("This is a message".to_string()), params[4]);
388379
}
389380

@@ -413,11 +404,11 @@ mod tests {
413404
async fn repository_create_open_message() {
414405
let connection = get_connection().await;
415406
let repository = OpenMessageRepository::new(connection.clone());
407+
let epoch = Epoch(1);
416408
let open_message = repository
417409
.create_open_message(
418-
Epoch(1),
419-
&Beacon::default(),
420-
&SignedEntityType::CardanoImmutableFilesFull,
410+
epoch,
411+
&SignedEntityType::CardanoImmutableFilesFull(Beacon::default()),
421412
"this is a message",
422413
)
423414
.await
@@ -426,7 +417,7 @@ mod tests {
426417
assert_eq!(Epoch(1), open_message.epoch);
427418
assert_eq!("this is a message".to_string(), open_message.message);
428419
assert_eq!(
429-
SignedEntityType::CardanoImmutableFilesFull,
420+
SignedEntityType::CardanoImmutableFilesFull(Beacon::default()),
430421
open_message.signed_entity_type
431422
);
432423

@@ -459,17 +450,15 @@ mod tests {
459450
let _ = repository
460451
.create_open_message(
461452
Epoch(1),
462-
&Beacon::default(),
463-
&SignedEntityType::CardanoImmutableFilesFull,
453+
&SignedEntityType::CardanoImmutableFilesFull(Beacon::default()),
464454
"this is a message",
465455
)
466456
.await
467457
.unwrap();
468458
let _ = repository
469459
.create_open_message(
470460
Epoch(1),
471-
&Beacon::default(),
472-
&SignedEntityType::MithrilStakeDistribution,
461+
&SignedEntityType::CardanoImmutableFilesFull(Beacon::default()),
473462
"this is a stake distribution",
474463
)
475464
.await

mithril-common/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mithril-common"
3-
version = "0.2.37"
3+
version = "0.2.38"
44
authors = { workspace = true }
55
edition = { workspace = true }
66
documentation = { workspace = true }

mithril-common/src/entities/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ pub use epoch_settings::EpochSettings;
2626
pub use http_server_error::{ClientError, InternalServerError};
2727
pub use protocol_message::{ProtocolMessage, ProtocolMessagePartKey, ProtocolMessagePartValue};
2828
pub use protocol_parameters::ProtocolParameters;
29-
pub use signed_entity_type::SignedEntityType;
29+
pub use signed_entity_type::*;
3030
pub use signer::{Signer, SignerWithStake};
3131
pub use single_signatures::SingleSignatures;
3232
pub use snapshot::Snapshot;
Lines changed: 72 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,97 @@
1-
use strum::IntoEnumIterator;
2-
use strum_macros::{Display, EnumIter, EnumString, FromRepr};
1+
use strum_macros::Display;
2+
3+
use crate::{sqlite::HydrationError, StdError};
4+
5+
use super::{Beacon, Epoch};
6+
7+
/// Database representation of the SignedEntityType::MithrilStakeDistribution value
8+
const ENTITY_TYPE_MITHRIL_STAKE_DISTRIBUTION: usize = 0;
9+
10+
/// Database representation of the SignedEntityType::CardanoStakeDistribution value
11+
const ENTITY_TYPE_CARDANO_STAKE_DISTRIBUTION: usize = 1;
12+
13+
/// Database representation of the SignedEntityType::CardanoImmutableFilesFull value
14+
const ENTITY_TYPE_CARDANO_IMMUTABLE_FILES_FULL: usize = 2;
315

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

1628
/// Cardano Stake Distribution
17-
CardanoStakeDistribution,
29+
CardanoStakeDistribution(Epoch),
1830

1931
/// Full Cardano Immutable Files
20-
CardanoImmutableFilesFull,
32+
CardanoImmutableFilesFull(Beacon),
2133
}
2234

2335
impl SignedEntityType {
24-
/// Retrieve the list of entity types
25-
pub fn entity_types() -> Vec<Self> {
26-
Self::iter().collect()
27-
}
28-
2936
/// Retrieve a dummy enty (for test only)
3037
pub fn dummy() -> Self {
31-
Self::entity_types().first().unwrap().to_owned()
38+
Self::MithrilStakeDistribution(Epoch(5))
3239
}
33-
}
3440

35-
#[cfg(test)]
36-
mod tests {
37-
use super::*;
41+
/// Create an instance from data coming from the database
42+
pub fn hydrate(signed_entity_type_id: usize, beacon_str: &str) -> Result<Self, HydrationError> {
43+
let myself = match signed_entity_type_id {
44+
ENTITY_TYPE_MITHRIL_STAKE_DISTRIBUTION => {
45+
let epoch: Epoch = serde_json::from_str(beacon_str).map_err(|e| {
46+
HydrationError::InvalidData(format!(
47+
"Invalid Epoch JSON representation '{beacon_str}. Error: {e}'."
48+
))
49+
})?;
50+
Self::MithrilStakeDistribution(epoch)
51+
}
52+
ENTITY_TYPE_CARDANO_STAKE_DISTRIBUTION => {
53+
let epoch: Epoch = serde_json::from_str(beacon_str).map_err(|e| {
54+
HydrationError::InvalidData(format!(
55+
"Invalid Epoch JSON representation '{beacon_str}. Error: {e}'."
56+
))
57+
})?;
58+
Self::CardanoStakeDistribution(epoch)
59+
}
60+
ENTITY_TYPE_CARDANO_IMMUTABLE_FILES_FULL => {
61+
let beacon: Beacon = serde_json::from_str(beacon_str).map_err(|e| {
62+
HydrationError::InvalidData(format!(
63+
"Invalid Beacon JSON in open_message.beacon: '{beacon_str}'. Error: {e}"
64+
))
65+
})?;
66+
Self::CardanoImmutableFilesFull(beacon)
67+
}
68+
index => panic!("Invalid entity_type_id {index}."),
69+
};
3870

39-
#[test]
40-
fn from_repr() {
41-
let supported_entity_type = SignedEntityType::from_repr(SignedEntityType::dummy() as usize)
42-
.expect("This signed entity type should support conversion from representation.");
71+
Ok(myself)
72+
}
4373

44-
assert_eq!(SignedEntityType::dummy(), supported_entity_type);
74+
/// Get the database value from enum's instance
75+
pub fn index(&self) -> usize {
76+
match self {
77+
Self::MithrilStakeDistribution(_) => ENTITY_TYPE_MITHRIL_STAKE_DISTRIBUTION,
78+
Self::CardanoStakeDistribution(_) => ENTITY_TYPE_CARDANO_STAKE_DISTRIBUTION,
79+
Self::CardanoImmutableFilesFull(_) => ENTITY_TYPE_CARDANO_IMMUTABLE_FILES_FULL,
80+
}
81+
}
82+
83+
/// Return a JSON serialized value of the internal beacon
84+
pub fn get_json_beacon(&self) -> Result<String, StdError> {
85+
let value = match self {
86+
Self::CardanoImmutableFilesFull(value) => serde_json::to_string(value)?,
87+
Self::CardanoStakeDistribution(value) | Self::MithrilStakeDistribution(value) => {
88+
serde_json::to_string(value)?
89+
}
90+
};
91+
92+
Ok(value)
4593
}
4694
}
95+
96+
#[cfg(test)]
97+
mod tests {}

0 commit comments

Comments
 (0)