diff --git a/Cargo.lock b/Cargo.lock index 6abe1e5a704..2313417d5e3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4311,6 +4311,7 @@ dependencies = [ "slog-async", "slog-scope", "slog-term", + "thiserror 2.0.16", "tokio", ] @@ -5071,7 +5072,6 @@ dependencies = [ [[package]] name = "pallas-codec" version = "1.0.0-alpha.2" -source = "git+https://github.com/txpipe/pallas.git?branch=main#d34b143f838c16e33759d63cd3aec8eaab539111" dependencies = [ "hex", "minicbor 0.26.5", @@ -5097,7 +5097,6 @@ dependencies = [ [[package]] name = "pallas-crypto" version = "1.0.0-alpha.2" -source = "git+https://github.com/txpipe/pallas.git?branch=main#d34b143f838c16e33759d63cd3aec8eaab539111" dependencies = [ "cryptoxide", "hex", @@ -5128,7 +5127,6 @@ dependencies = [ [[package]] name = "pallas-network" version = "1.0.0-alpha.2" -source = "git+https://github.com/txpipe/pallas.git?branch=main#d34b143f838c16e33759d63cd3aec8eaab539111" dependencies = [ "byteorder", "hex", diff --git a/internal/mithril-dmq/Cargo.toml b/internal/mithril-dmq/Cargo.toml index 7a5b53cc1c0..fa2175c1d76 100644 --- a/internal/mithril-dmq/Cargo.toml +++ b/internal/mithril-dmq/Cargo.toml @@ -24,12 +24,15 @@ bincode = { version = "2.0.1" } blake2 = "0.10.6" mithril-cardano-node-chain = { path = "../cardano-node/mithril-cardano-node-chain" } mithril-common = { path = "../../mithril-common" } -pallas-codec = { git = "https://github.com/txpipe/pallas.git", branch = "main" } -pallas-network = { git = "https://github.com/txpipe/pallas.git", branch = "main" } +#pallas-codec = { git = "https://github.com/txpipe/pallas.git", branch = "main" } +#pallas-network = { git = "https://github.com/txpipe/pallas.git", branch = "main" } +pallas-codec = { path = "../../../pallas-fork-scaling/pallas-codec" } +pallas-network = { path = "../../../pallas-fork-scaling/pallas-network" } serde = { workspace = true } serde_bytes = "0.11.17" slog = { workspace = true } slog-scope = "4.4.0" +thiserror = { workspace = true } tokio = { workspace = true, features = ["sync","rt-multi-thread"] } [dev-dependencies] diff --git a/internal/mithril-dmq/src/consumer/client/pallas.rs b/internal/mithril-dmq/src/consumer/client/pallas.rs index fa9ee422951..a550c807a36 100644 --- a/internal/mithril-dmq/src/consumer/client/pallas.rs +++ b/internal/mithril-dmq/src/consumer/client/pallas.rs @@ -6,7 +6,7 @@ use slog::{Logger, debug, error}; use tokio::sync::{Mutex, MutexGuard}; use mithril_common::{ - CardanoNetwork, StdResult, + StdResult, crypto_helper::{ OpCert, OpCertWithoutColdVerificationKey, TryFromBytes, ed25519::Ed25519VerificationKey, }, @@ -14,14 +14,14 @@ use mithril_common::{ logging::LoggerExtensions, }; -use crate::DmqConsumerClient; +use crate::{DmqConsumerClient, model::DmqNetwork}; /// A DMQ client consumer implementation. /// /// This implementation is built upon the n2c mini-protocols DMQ implementation in Pallas. pub struct DmqConsumerClientPallas { socket: PathBuf, - network: CardanoNetwork, + network: DmqNetwork, client: Mutex>, logger: Logger, phantom: PhantomData, @@ -29,7 +29,7 @@ pub struct DmqConsumerClientPallas { impl DmqConsumerClientPallas { /// Creates a new `DmqConsumerClientPallas` instance. - pub fn new(socket: PathBuf, network: CardanoNetwork, logger: Logger) -> Self { + pub fn new(socket: PathBuf, network: DmqNetwork, logger: Logger) -> Self { Self { socket, network, @@ -115,11 +115,13 @@ impl DmqConsumerClientPallas { .0 .into_iter() .map(|dmq_message| { - let opcert_without_verification_key = - OpCertWithoutColdVerificationKey::try_from_bytes( - &dmq_message.operational_certificate, - ) - .with_context(|| "Failed to parse operational certificate")?; + let opcert_without_verification_key = OpCertWithoutColdVerificationKey::try_new( + &dmq_message.operational_certificate.kes_vk, + dmq_message.operational_certificate.issue_number, + dmq_message.operational_certificate.start_kes_period, + &dmq_message.operational_certificate.cert_sig, + ) + .with_context(|| "Failed to parse operational certificate")?; let cold_verification_key = Ed25519VerificationKey::from_bytes(&dmq_message.cold_verification_key) .with_context(|| "Failed to parse cold verification key")? @@ -171,7 +173,7 @@ mod tests { facades::DmqServer, miniprotocols::{ localmsgnotification, - localmsgsubmission::{DmqMsg, DmqMsgPayload}, + localmsgsubmission::{DmqMsg, DmqMsgOperationalCertificate, DmqMsgPayload}, }, }; use tokio::{net::UnixListener, task::JoinHandle, time::sleep}; @@ -194,14 +196,20 @@ mod tests { expires_at: 100, }, kes_signature: vec![0, 1, 2, 3], - operational_certificate: vec![ - 132, 88, 32, 230, 80, 215, 83, 21, 9, 187, 108, 255, 215, 153, 140, 40, 198, - 142, 78, 200, 250, 98, 26, 9, 82, 32, 110, 161, 30, 176, 63, 205, 125, 203, 41, - 0, 0, 88, 64, 212, 171, 206, 39, 218, 5, 255, 3, 193, 52, 44, 198, 171, 83, 19, - 80, 114, 225, 186, 191, 156, 192, 84, 146, 245, 159, 31, 240, 9, 247, 4, 87, - 170, 168, 98, 199, 21, 139, 19, 190, 12, 251, 65, 215, 169, 26, 86, 37, 137, - 188, 17, 14, 178, 205, 175, 93, 39, 86, 4, 138, 187, 234, 95, 5, - ], + operational_certificate: DmqMsgOperationalCertificate { + kes_vk: vec![ + 50, 45, 160, 42, 80, 78, 184, 20, 210, 77, 140, 152, 63, 49, 165, 168, 5, + 131, 101, 152, 110, 242, 144, 157, 176, 210, 5, 10, 166, 91, 196, 168, + ], + issue_number: 0, + start_kes_period: 0, + cert_sig: vec![ + 207, 135, 144, 168, 238, 41, 179, 216, 245, 74, 164, 231, 4, 158, 234, 141, + 5, 19, 166, 11, 78, 34, 210, 211, 183, 72, 127, 83, 185, 156, 107, 55, 160, + 190, 73, 251, 204, 47, 197, 86, 174, 231, 13, 49, 7, 83, 173, 177, 27, 53, + 209, 66, 24, 203, 226, 152, 3, 91, 66, 56, 244, 206, 79, 0, + ], + }, cold_verification_key: vec![ 32, 253, 186, 201, 177, 11, 117, 135, 187, 167, 181, 188, 22, 59, 206, 105, 231, 150, 215, 30, 78, 212, 76, 16, 252, 180, 72, 134, 137, 247, 161, 68, @@ -215,14 +223,20 @@ mod tests { expires_at: 101, }, kes_signature: vec![1, 2, 3, 4], - operational_certificate: vec![ - 132, 88, 32, 230, 80, 215, 83, 21, 9, 187, 108, 255, 215, 153, 140, 40, 198, - 142, 78, 200, 250, 98, 26, 9, 82, 32, 110, 161, 30, 176, 63, 205, 125, 203, 41, - 0, 0, 88, 64, 212, 171, 206, 39, 218, 5, 255, 3, 193, 52, 44, 198, 171, 83, 19, - 80, 114, 225, 186, 191, 156, 192, 84, 146, 245, 159, 31, 240, 9, 247, 4, 87, - 170, 168, 98, 199, 21, 139, 19, 190, 12, 251, 65, 215, 169, 26, 86, 37, 137, - 188, 17, 14, 178, 205, 175, 93, 39, 86, 4, 138, 187, 234, 95, 5, - ], + operational_certificate: DmqMsgOperationalCertificate { + kes_vk: vec![ + 50, 45, 160, 42, 80, 78, 184, 20, 210, 77, 140, 152, 63, 49, 165, 168, 5, + 131, 101, 152, 110, 242, 144, 157, 176, 210, 5, 10, 166, 91, 196, 168, + ], + issue_number: 0, + start_kes_period: 0, + cert_sig: vec![ + 207, 135, 144, 168, 238, 41, 179, 216, 245, 74, 164, 231, 4, 158, 234, 141, + 5, 19, 166, 11, 78, 34, 210, 211, 183, 72, 127, 83, 185, 156, 107, 55, 160, + 190, 73, 251, 204, 47, 197, 86, 174, 231, 13, 49, 7, 83, 173, 177, 27, 53, + 209, 66, 24, 203, 226, 152, 3, 91, 66, 56, 244, 206, 79, 0, + ], + }, cold_verification_key: vec![ 77, 75, 24, 6, 47, 133, 2, 89, 141, 224, 69, 202, 123, 105, 240, 103, 245, 159, 147, 177, 110, 58, 248, 115, 58, 152, 138, 220, 35, 65, 245, 200, @@ -278,7 +292,7 @@ mod tests { let consumer = DmqConsumerClientPallas::new( socket_path, - CardanoNetwork::TestNet(0), + DmqNetwork::TestNet(0), TestLogger::stdout(), ); @@ -314,7 +328,7 @@ mod tests { let consumer = DmqConsumerClientPallas::::new( socket_path, - CardanoNetwork::TestNet(0), + DmqNetwork::TestNet(0), TestLogger::stdout(), ); @@ -341,7 +355,7 @@ mod tests { let consumer = DmqConsumerClientPallas::::new( socket_path, - CardanoNetwork::TestNet(0), + DmqNetwork::TestNet(0), TestLogger::stdout(), ); diff --git a/internal/mithril-dmq/src/consumer/server/pallas.rs b/internal/mithril-dmq/src/consumer/server/pallas.rs index 4888e2f083a..5417a8842e1 100644 --- a/internal/mithril-dmq/src/consumer/server/pallas.rs +++ b/internal/mithril-dmq/src/consumer/server/pallas.rs @@ -11,16 +11,16 @@ use tokio::{ use slog::{Logger, debug, error, info, warn}; -use mithril_common::{CardanoNetwork, StdResult, logging::LoggerExtensions}; +use mithril_common::{StdResult, logging::LoggerExtensions}; -use crate::{DmqConsumerServer, DmqMessage}; +use crate::{DmqConsumerServer, DmqMessage, DmqNetwork}; use super::queue::MessageQueue; /// A DMQ server implementation for messages notification from a DMQ node. pub struct DmqConsumerServerPallas { socket: PathBuf, - network: CardanoNetwork, + network: DmqNetwork, server: Mutex>, messages_receiver: Mutex>>, messages_buffer: MessageQueue, @@ -32,7 +32,7 @@ impl DmqConsumerServerPallas { /// Creates a new instance of [DmqConsumerServerPallas]. pub fn new( socket: PathBuf, - network: CardanoNetwork, + network: DmqNetwork, stop_rx: Receiver<()>, logger: Logger, ) -> Self { @@ -303,10 +303,10 @@ mod tests { let (stop_tx, stop_rx) = watch::channel(()); let (signature_dmq_tx, signature_dmq_rx) = unbounded_channel::(); let socket_path = create_temp_dir(current_function_name).join("node.socket"); - let cardano_network = CardanoNetwork::TestNet(0); + let dmq_network = DmqNetwork::TestNet(0); let dmq_consumer_server = Arc::new(DmqConsumerServerPallas::new( socket_path.to_path_buf(), - cardano_network.to_owned(), + dmq_network.to_owned(), stop_rx, TestLogger::stdout(), )); @@ -363,10 +363,10 @@ mod tests { let (stop_tx, stop_rx) = watch::channel(()); let (signature_dmq_tx, signature_dmq_rx) = unbounded_channel::(); let socket_path = create_temp_dir(current_function_name).join("node.socket"); - let cardano_network = CardanoNetwork::TestNet(0); + let dmq_network = DmqNetwork::TestNet(0); let dmq_consumer_server = Arc::new(DmqConsumerServerPallas::new( socket_path.to_path_buf(), - cardano_network.to_owned(), + dmq_network.to_owned(), stop_rx, TestLogger::stdout(), )); @@ -422,10 +422,10 @@ mod tests { let (_stop_tx, stop_rx) = watch::channel(()); let (_signature_dmq_tx, signature_dmq_rx) = unbounded_channel::(); let socket_path = create_temp_dir(current_function!()).join("node.socket"); - let cardano_network = CardanoNetwork::TestNet(0); + let dmq_network = DmqNetwork::TestNet(0); let dmq_consumer_server = Arc::new(DmqConsumerServerPallas::new( socket_path.to_path_buf(), - cardano_network.to_owned(), + dmq_network.to_owned(), stop_rx, TestLogger::stdout(), )); diff --git a/internal/mithril-dmq/src/consumer/server/queue.rs b/internal/mithril-dmq/src/consumer/server/queue.rs index 614cde640ce..d4cc46727a2 100644 --- a/internal/mithril-dmq/src/consumer/server/queue.rs +++ b/internal/mithril-dmq/src/consumer/server/queue.rs @@ -122,7 +122,9 @@ mod tests { use std::{ops::RangeInclusive, time::Duration}; use anyhow::anyhow; - use pallas_network::miniprotocols::localmsgsubmission::{DmqMsg, DmqMsgPayload}; + use pallas_network::miniprotocols::localmsgsubmission::{ + DmqMsg, DmqMsgOperationalCertificate, DmqMsgPayload, + }; use tokio::time::sleep; use crate::model::MockUnixTimestampProvider; @@ -138,7 +140,12 @@ mod tests { expires_at: 100, }, kes_signature: vec![0, 1, 2, 3], - operational_certificate: vec![0, 1, 2, 3, 4], + operational_certificate: DmqMsgOperationalCertificate { + kes_vk: vec![12, 13, 14], + issue_number: 15, + start_kes_period: 16, + cert_sig: vec![17], + }, cold_verification_key: vec![0, 1, 2, 3, 4, 5], } } diff --git a/internal/mithril-dmq/src/lib.rs b/internal/mithril-dmq/src/lib.rs index 21abe080378..fe7a78c4799 100644 --- a/internal/mithril-dmq/src/lib.rs +++ b/internal/mithril-dmq/src/lib.rs @@ -9,7 +9,7 @@ pub mod test; #[cfg(unix)] pub use consumer::DmqConsumerServerPallas; pub use consumer::{DmqConsumerClient, DmqConsumerClientPallas, DmqConsumerServer}; -pub use model::{DmqMessage, DmqMessageBuilder}; +pub use model::{DmqMessage, DmqMessageBuilder, DmqNetwork}; #[cfg(unix)] pub use publisher::DmqPublisherServerPallas; pub use publisher::{DmqPublisherClient, DmqPublisherClientPallas, DmqPublisherServer}; diff --git a/internal/mithril-dmq/src/model/builder.rs b/internal/mithril-dmq/src/model/builder.rs index 2a14c301312..f3f6af13594 100644 --- a/internal/mithril-dmq/src/model/builder.rs +++ b/internal/mithril-dmq/src/model/builder.rs @@ -2,12 +2,14 @@ use std::sync::Arc; use anyhow::Context; use blake2::{Blake2b, Digest, digest::consts::U64}; -use pallas_network::miniprotocols::localmsgsubmission::{DmqMsg, DmqMsgPayload}; +use pallas_network::miniprotocols::localmsgsubmission::{ + DmqMsg, DmqMsgOperationalCertificate, DmqMsgPayload, +}; use mithril_cardano_node_chain::chain_observer::ChainObserver; use mithril_common::{ StdResult, - crypto_helper::{KesSigner, SerDeShelleyFileFormat, TryToBytes}, + crypto_helper::{KesSigner, TryToBytes}, }; use crate::model::{DmqMessage, SystemUnixTimestampProvider, UnixTimestampProvider}; @@ -99,8 +101,19 @@ impl DmqMessageBuilder { let dmq_message = DmqMsg { msg_payload: dmq_message_payload, kes_signature: kes_signature.to_bytes_vec()?, - operational_certificate: operational_certificate_without_cold_verification_key - .to_cbor_bytes()?, + operational_certificate: DmqMsgOperationalCertificate { + kes_vk: operational_certificate_without_cold_verification_key + .kes_vk() + .as_bytes() + .to_vec(), + issue_number: operational_certificate_without_cold_verification_key.issue_number(), + start_kes_period: operational_certificate_without_cold_verification_key + .start_kes_period(), + cert_sig: operational_certificate_without_cold_verification_key + .cert_sig() + .to_bytes() + .to_vec(), + }, cold_verification_key: cold_verification_key.to_bytes().to_vec(), }; @@ -177,10 +190,24 @@ mod tests { DmqMsg { msg_payload: expected_msg_payload.clone(), kes_signature: kes_signature.to_bytes_vec().unwrap(), - operational_certificate: operational_certificate - .get_opcert_without_cold_verification_key() - .to_cbor_bytes() - .unwrap(), + operational_certificate: DmqMsgOperationalCertificate { + kes_vk: operational_certificate + .get_opcert_without_cold_verification_key() + .kes_vk() + .as_bytes() + .to_vec(), + issue_number: operational_certificate + .get_opcert_without_cold_verification_key() + .issue_number(), + start_kes_period: operational_certificate + .get_opcert_without_cold_verification_key() + .start_kes_period(), + cert_sig: operational_certificate + .get_opcert_without_cold_verification_key() + .cert_sig() + .to_bytes() + .to_vec(), + }, cold_verification_key: operational_certificate .get_cold_verification_key() .to_bytes() diff --git a/internal/mithril-dmq/src/model/message.rs b/internal/mithril-dmq/src/model/message.rs index 516eb28bb8b..94ac63348af 100644 --- a/internal/mithril-dmq/src/model/message.rs +++ b/internal/mithril-dmq/src/model/message.rs @@ -72,7 +72,9 @@ impl<'de> Deserialize<'de> for DmqMessage { #[cfg(test)] mod tests { - use pallas_network::miniprotocols::localmsgsubmission::DmqMsgPayload; + use pallas_network::miniprotocols::localmsgsubmission::{ + DmqMsgOperationalCertificate, DmqMsgPayload, + }; use super::*; @@ -86,7 +88,12 @@ mod tests { expires_at: 100, }, kes_signature: vec![0, 1, 2, 3], - operational_certificate: vec![0, 1, 2, 3, 4], + operational_certificate: DmqMsgOperationalCertificate { + kes_vk: vec![12, 13, 14], + issue_number: 15, + start_kes_period: 16, + cert_sig: vec![17], + }, cold_verification_key: vec![0, 1, 2, 3, 4, 5], }; diff --git a/internal/mithril-dmq/src/model/mod.rs b/internal/mithril-dmq/src/model/mod.rs index d5e78173523..0c6700e87f3 100644 --- a/internal/mithril-dmq/src/model/mod.rs +++ b/internal/mithril-dmq/src/model/mod.rs @@ -1,7 +1,9 @@ mod builder; mod message; +mod network; mod timestamp; pub use builder::*; pub use message::*; +pub use network::*; pub use timestamp::*; diff --git a/internal/mithril-dmq/src/model/network.rs b/internal/mithril-dmq/src/model/network.rs new file mode 100644 index 00000000000..5924037a1cc --- /dev/null +++ b/internal/mithril-dmq/src/model/network.rs @@ -0,0 +1,186 @@ +use serde::{Deserialize, Serialize}; +use std::fmt::Display; +use thiserror::Error; + +use mithril_common::MagicId; + +#[derive(Error, Debug)] +pub enum DmqNetworkError { + #[error("parse from code error: '{0}'")] + ParseFromCode(String), +} + +/// The Dmq Network that is being targeted +#[allow(clippy::enum_variant_names)] +#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize, Hash, Eq, PartialOrd)] +pub enum DmqNetwork { + /// The Dmq mainnet network + MainNet, + + /// A Dmq test network (preview, preprod or private testnet) + TestNet(MagicId), +} + +impl DmqNetwork { + /// Mainnet magic ID + pub const MAINNET_MAGIC_ID: MagicId = 123; // TODO: Update magic ids for networks + /// Preprod magic ID + pub const PREPROD_MAGIC_ID: MagicId = 1; // TODO: Update magic ids for networks + /// Preview magic ID + pub const PREVIEW_MAGIC_ID: MagicId = 2; // TODO: Update magic ids for networks + /// Devnet magic ID + pub(crate) const DEVNET_MAGIC_ID: MagicId = 3141592; // TODO: Update magic ids for networks + + /// Instantiates a DmqNetwork from its code and magic id + pub fn from_code( + network_code: String, + network_magic: Option, + ) -> Result { + match network_code.to_lowercase().as_str() { + "mainnet" => Ok(DmqNetwork::MainNet), + "preview" => Ok(DmqNetwork::TestNet(Self::PREVIEW_MAGIC_ID)), + "preprod" => Ok(DmqNetwork::TestNet(Self::PREPROD_MAGIC_ID)), + "devnet" => Ok(DmqNetwork::TestNet(Self::DEVNET_MAGIC_ID)), + "private" => { + if let Some(magic) = network_magic { + Ok(DmqNetwork::TestNet(magic)) + } else { + Err(DmqNetworkError::ParseFromCode( + "no NETWORK MAGIC number given for test network".to_string(), + )) + } + } + what => Err(DmqNetworkError::ParseFromCode(format!( + "could not parse network '{what}', the only recognized networks are: mainnet, devnet, testnet, preview, preprod and private" + ))), + } + } + + /// Returns the magic ID of the network + pub fn magic_id(&self) -> MagicId { + match *self { + DmqNetwork::MainNet => Self::MAINNET_MAGIC_ID, + DmqNetwork::TestNet(magic_id) => magic_id, + } + } +} + +impl Display for DmqNetwork { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match *self { + DmqNetwork::MainNet => write!(f, "mainnet"), + DmqNetwork::TestNet(magic_id) => match magic_id { + Self::PREVIEW_MAGIC_ID => write!(f, "preview"), + Self::PREPROD_MAGIC_ID => write!(f, "preprod"), + Self::DEVNET_MAGIC_ID => write!(f, "devnet"), + _ => write!(f, "private"), + }, + } + } +} + +impl From for String { + fn from(network: DmqNetwork) -> Self { + network.to_string() + } +} + +impl From<&DmqNetwork> for String { + fn from(network: &DmqNetwork) -> Self { + network.to_string() + } +} + +impl From for DmqNetwork { + fn from(magic_id: MagicId) -> Self { + match magic_id { + Self::MAINNET_MAGIC_ID => Self::MainNet, + _ => Self::TestNet(magic_id), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_dmq_network_from_code() { + assert_eq!( + DmqNetwork::from_code("mainnet".to_string(), None).unwrap(), + DmqNetwork::MainNet + ); + assert_eq!( + DmqNetwork::from_code("mainnet".to_string(), Some(123)).unwrap(), + DmqNetwork::MainNet + ); + assert_eq!( + DmqNetwork::from_code("preview".to_string(), None).unwrap(), + DmqNetwork::TestNet(DmqNetwork::PREVIEW_MAGIC_ID) + ); + assert_eq!( + DmqNetwork::from_code("preview".to_string(), Some(123)).unwrap(), + DmqNetwork::TestNet(DmqNetwork::PREVIEW_MAGIC_ID) + ); + assert_eq!( + DmqNetwork::from_code("preprod".to_string(), None).unwrap(), + DmqNetwork::TestNet(DmqNetwork::PREPROD_MAGIC_ID) + ); + assert_eq!( + DmqNetwork::from_code("preprod".to_string(), Some(123)).unwrap(), + DmqNetwork::TestNet(DmqNetwork::PREPROD_MAGIC_ID) + ); + assert_eq!( + DmqNetwork::from_code("devnet".to_string(), None).unwrap(), + DmqNetwork::TestNet(DmqNetwork::DEVNET_MAGIC_ID) + ); + assert_eq!( + DmqNetwork::from_code("devnet".to_string(), Some(123)).unwrap(), + DmqNetwork::TestNet(DmqNetwork::DEVNET_MAGIC_ID) + ); + assert_eq!( + DmqNetwork::from_code("private".to_string(), Some(123)).unwrap(), + DmqNetwork::TestNet(123) + ); + assert!(DmqNetwork::from_code("private".to_string(), None).is_err()); + } + + #[test] + fn network_to_string() { + fn assert_all_conversions_eq(network: DmqNetwork, expected: &str) { + assert_eq!(network.to_string(), expected); + assert_eq!(String::from(network), expected); + assert_eq!(String::from(&network), expected); + } + + assert_all_conversions_eq(DmqNetwork::MainNet, "mainnet"); + assert_all_conversions_eq(DmqNetwork::TestNet(DmqNetwork::DEVNET_MAGIC_ID), "devnet"); + assert_all_conversions_eq(DmqNetwork::TestNet(DmqNetwork::PREVIEW_MAGIC_ID), "preview"); + assert_all_conversions_eq(DmqNetwork::TestNet(DmqNetwork::PREPROD_MAGIC_ID), "preprod"); + assert_all_conversions_eq(DmqNetwork::TestNet(123456), "private"); + } + + #[test] + fn dmq_network_from_magic_id_roundtrip() { + fn assert_magic_id_conversion_roundtrip(magic_id: MagicId, expected: DmqNetwork) { + let network = DmqNetwork::from(magic_id); + assert_eq!(network, expected); + assert_eq!(network.magic_id(), magic_id); + } + + assert_magic_id_conversion_roundtrip(DmqNetwork::MAINNET_MAGIC_ID, DmqNetwork::MainNet); + assert_magic_id_conversion_roundtrip( + DmqNetwork::PREVIEW_MAGIC_ID, + DmqNetwork::TestNet(DmqNetwork::PREVIEW_MAGIC_ID), + ); + assert_magic_id_conversion_roundtrip( + DmqNetwork::PREPROD_MAGIC_ID, + DmqNetwork::TestNet(DmqNetwork::PREPROD_MAGIC_ID), + ); + assert_magic_id_conversion_roundtrip( + DmqNetwork::DEVNET_MAGIC_ID, + DmqNetwork::TestNet(DmqNetwork::DEVNET_MAGIC_ID), + ); + assert_magic_id_conversion_roundtrip(123456, DmqNetwork::TestNet(123456)); + } +} diff --git a/internal/mithril-dmq/src/publisher/client/pallas.rs b/internal/mithril-dmq/src/publisher/client/pallas.rs index d2b268585d3..6421f344dcc 100644 --- a/internal/mithril-dmq/src/publisher/client/pallas.rs +++ b/internal/mithril-dmq/src/publisher/client/pallas.rs @@ -4,18 +4,16 @@ use anyhow::Context; use pallas_network::{facades::DmqClient, miniprotocols::localtxsubmission::Response}; use slog::{Logger, debug, error}; -use mithril_common::{ - CardanoNetwork, StdResult, crypto_helper::TryToBytes, logging::LoggerExtensions, -}; +use mithril_common::{StdResult, crypto_helper::TryToBytes, logging::LoggerExtensions}; -use crate::{DmqMessageBuilder, DmqPublisherClient}; +use crate::{DmqMessageBuilder, DmqPublisherClient, model::DmqNetwork}; /// A DMQ client publisher implementation. /// /// This implementation is built upon the n2c mini-protocols DMQ implementation in Pallas. pub struct DmqPublisherClientPallas { socket: PathBuf, - network: CardanoNetwork, + network: DmqNetwork, dmq_message_builder: DmqMessageBuilder, logger: Logger, phantom: PhantomData, @@ -25,7 +23,7 @@ impl DmqPublisherClientPallas { /// Creates a new instance of [DmqPublisherClientPallas]. pub fn new( socket: PathBuf, - network: CardanoNetwork, + network: DmqNetwork, dmq_message_builder: DmqMessageBuilder, logger: Logger, ) -> Self { @@ -153,7 +151,7 @@ mod tests { let publisher = DmqPublisherClientPallas::new( socket_path, - CardanoNetwork::TestNet(0), + DmqNetwork::TestNet(0), DmqMessageBuilder::new( { let (kes_signature, operational_certificate) = @@ -191,7 +189,7 @@ mod tests { let publisher = DmqPublisherClientPallas::new( socket_path, - CardanoNetwork::TestNet(0), + DmqNetwork::TestNet(0), DmqMessageBuilder::new( { let (kes_signature, operational_certificate) = diff --git a/internal/mithril-dmq/src/publisher/server/pallas.rs b/internal/mithril-dmq/src/publisher/server/pallas.rs index 383cff1695f..558f4edea8c 100644 --- a/internal/mithril-dmq/src/publisher/server/pallas.rs +++ b/internal/mithril-dmq/src/publisher/server/pallas.rs @@ -16,14 +16,14 @@ use tokio::{ use slog::{Logger, debug, error, info, warn}; -use mithril_common::{CardanoNetwork, StdResult, logging::LoggerExtensions}; +use mithril_common::{StdResult, logging::LoggerExtensions}; -use crate::{DmqMessage, DmqPublisherServer}; +use crate::{DmqMessage, DmqNetwork, DmqPublisherServer}; /// A DMQ server implementation for messages publication to a DMQ node. pub struct DmqPublisherServerPallas { socket: PathBuf, - network: CardanoNetwork, + network: DmqNetwork, server: Mutex>, transmitters: Mutex>>, stop_rx: Receiver<()>, @@ -34,7 +34,7 @@ impl DmqPublisherServerPallas { /// Creates a new instance of [DmqPublisherServerPallas]. pub fn new( socket: PathBuf, - network: CardanoNetwork, + network: DmqNetwork, stop_rx: Receiver<()>, logger: Logger, ) -> Self { @@ -243,7 +243,7 @@ mod tests { use pallas_network::{ facades::DmqClient, miniprotocols::{ - localmsgsubmission::{DmqMsg, DmqMsgPayload}, + localmsgsubmission::{DmqMsg, DmqMsgOperationalCertificate, DmqMsgPayload}, localtxsubmission, }, }; @@ -268,7 +268,12 @@ mod tests { expires_at: 100, }, kes_signature: vec![0, 1, 2, 3], - operational_certificate: vec![0, 1, 2, 3, 4], + operational_certificate: DmqMsgOperationalCertificate { + kes_vk: vec![12, 13, 14], + issue_number: 15, + start_kes_period: 16, + cert_sig: vec![17], + }, cold_verification_key: vec![0, 1, 2, 3, 4, 5], } } @@ -278,7 +283,7 @@ mod tests { let (stop_tx, stop_rx) = watch::channel(()); let (signature_dmq_tx, signature_dmq_rx) = unbounded_channel::(); let socket_path = create_temp_dir(current_function!()).join("node.socket"); - let cardano_network = CardanoNetwork::TestNet(0); + let cardano_network = DmqNetwork::TestNet(0); let dmq_publisher_server = Arc::new(DmqPublisherServerPallas::new( socket_path.to_path_buf(), cardano_network.to_owned(), diff --git a/internal/mithril-dmq/tests/consumer_client_server.rs b/internal/mithril-dmq/tests/consumer_client_server.rs index 1cd453cf210..a925f87218e 100644 --- a/internal/mithril-dmq/tests/consumer_client_server.rs +++ b/internal/mithril-dmq/tests/consumer_client_server.rs @@ -3,16 +3,17 @@ use std::sync::Arc; use tokio::sync::{mpsc::unbounded_channel, watch}; -use mithril_common::{CardanoNetwork, current_function, test::TempDir}; +use mithril_common::{current_function, test::TempDir}; use mithril_dmq::{ DmqConsumerClient, DmqConsumerClientPallas, DmqConsumerServer, DmqConsumerServerPallas, - DmqMessage, test::fake_message::compute_fake_msg, test::payload::DmqMessageTestPayload, + DmqMessage, DmqNetwork, + test::{fake_message::compute_fake_msg, payload::DmqMessageTestPayload}, }; #[tokio::test(flavor = "multi_thread")] async fn dmq_consumer_client_server() { let current_function_name = current_function!(); - let cardano_network = CardanoNetwork::TestNet(0); + let dmq_network = DmqNetwork::TestNet(0); let socket_path = TempDir::create_with_short_path("dmq_consumer_client_server", current_function_name) .join("node.socket"); @@ -25,7 +26,7 @@ async fn dmq_consumer_client_server() { async move { let dmq_consumer_server = Arc::new(DmqConsumerServerPallas::new( socket_path.to_path_buf(), - cardano_network, + dmq_network, stop_rx, slog_scope::logger(), )); @@ -41,7 +42,7 @@ async fn dmq_consumer_client_server() { async move { let consumer_client = DmqConsumerClientPallas::::new( socket_path, - cardano_network, + dmq_network, slog_scope::logger(), ); let mut messages = vec![]; @@ -81,7 +82,7 @@ async fn dmq_consumer_client_server() { async move { let consumer_client = DmqConsumerClientPallas::::new( socket_path, - cardano_network, + dmq_network, slog_scope::logger(), ); let mut messages = vec![]; diff --git a/internal/mithril-dmq/tests/publisher_client_server.rs b/internal/mithril-dmq/tests/publisher_client_server.rs index b90728780be..9a14bf73ec5 100644 --- a/internal/mithril-dmq/tests/publisher_client_server.rs +++ b/internal/mithril-dmq/tests/publisher_client_server.rs @@ -5,11 +5,11 @@ use tokio::sync::{mpsc::unbounded_channel, watch}; use mithril_cardano_node_chain::test::double::FakeChainObserver; use mithril_common::{ - CardanoNetwork, current_function, + current_function, test::{TempDir, crypto_helper::KesSignerFake}, }; use mithril_dmq::{ - DmqMessage, DmqMessageBuilder, DmqPublisherClient, DmqPublisherClientPallas, + DmqMessage, DmqMessageBuilder, DmqNetwork, DmqPublisherClient, DmqPublisherClientPallas, DmqPublisherServer, DmqPublisherServerPallas, test::{fake_message::compute_fake_msg, payload::DmqMessageTestPayload}, }; @@ -17,7 +17,7 @@ use mithril_dmq::{ #[tokio::test] async fn dmq_publisher_client_server() { let current_function_name = current_function!(); - let cardano_network = CardanoNetwork::TestNet(0); + let dmq_network = DmqNetwork::TestNet(0); let socket_path = TempDir::create_with_short_path("dmq_publisher_client_server", current_function_name) .join("node.socket"); @@ -30,7 +30,7 @@ async fn dmq_publisher_client_server() { async move { let dmq_publisher_server = Arc::new(DmqPublisherServerPallas::new( socket_path.to_path_buf(), - cardano_network, + dmq_network, stop_rx, slog_scope::logger(), )); @@ -62,7 +62,7 @@ async fn dmq_publisher_client_server() { .set_ttl(100); let publisher_client = DmqPublisherClientPallas::::new( socket_path, - cardano_network, + dmq_network, dmq_builder, slog_scope::logger(), ); @@ -104,7 +104,7 @@ async fn dmq_publisher_client_server() { .set_ttl(100); let publisher_client = DmqPublisherClientPallas::::new( socket_path, - cardano_network, + dmq_network, dmq_builder, slog_scope::logger(), ); diff --git a/mithril-aggregator/Cargo.toml b/mithril-aggregator/Cargo.toml index 13eb7606775..7875b3e265a 100644 --- a/mithril-aggregator/Cargo.toml +++ b/mithril-aggregator/Cargo.toml @@ -10,7 +10,7 @@ license = { workspace = true } repository = { workspace = true } [features] -default = ["jemallocator"] +default = ["jemallocator", "future_dmq"] bundle_tls = ["reqwest/native-tls-vendored"] jemallocator = ["dep:tikv-jemallocator"] diff --git a/mithril-aggregator/src/configuration.rs b/mithril-aggregator/src/configuration.rs index 3ccd3aaf6e5..c8aa9d950ce 100644 --- a/mithril-aggregator/src/configuration.rs +++ b/mithril-aggregator/src/configuration.rs @@ -1,10 +1,11 @@ -use anyhow::Context; -use config::{ConfigError, Map, Source, Value, ValueKind}; -use serde::{Deserialize, Serialize}; use std::collections::{BTreeSet, HashMap, HashSet}; use std::path::PathBuf; use std::str::FromStr; +use anyhow::Context; +use config::{ConfigError, Map, Source, Value, ValueKind}; +use serde::{Deserialize, Serialize}; + use mithril_cardano_node_chain::chain_observer::ChainObserverType; use mithril_cli_helper::{register_config_value, serde_deserialization}; use mithril_common::crypto_helper::{ManifestSigner, ProtocolGenesisSigner}; @@ -14,6 +15,7 @@ use mithril_common::entities::{ SignedEntityTypeDiscriminants, }; use mithril_common::{CardanoNetwork, StdResult}; +use mithril_dmq::DmqNetwork; use mithril_doc::{Documenter, DocumenterDefault, StructDoc}; use mithril_era::adapters::EraReaderAdapterType; @@ -80,6 +82,11 @@ pub trait ConfigurationSource { panic!("cardano_node_version is not implemented."); } + /// Cardano network + fn network(&self) -> String { + panic!("network is not implemented."); + } + /// Cardano Network Magic number /// /// useful for TestNet & DevNet @@ -87,9 +94,12 @@ pub trait ConfigurationSource { panic!("network_magic is not implemented."); } - /// Cardano network - fn network(&self) -> String { - panic!("network is not implemented."); + /// DMQ Network Magic number + /// + /// useful for TestNet & DevNet + #[cfg(feature = "future_dmq")] + fn dmq_network_magic(&self) -> Option { + panic!("dmq_network_magic is not implemented."); } /// Cardano chain observer type @@ -302,6 +312,13 @@ pub trait ConfigurationSource { .with_context(|| "Invalid network configuration") } + /// Get a representation of the DMQ network. + #[cfg(feature = "future_dmq")] + fn get_dmq_network(&self) -> StdResult { + DmqNetwork::from_code(self.network(), self.dmq_network_magic()) + .with_context(|| "Invalid DMQ network configuration") + } + /// Get the directory of the SQLite stores. fn get_sqlite_dir(&self) -> PathBuf { let store_dir = &self.data_stores_directory(); @@ -409,15 +426,21 @@ pub struct ServeCommandConfiguration { /// is why it has to be manually given to the Aggregator pub cardano_node_version: String, - /// Cardano Network Magic number + /// Cardano network + #[example = "`mainnet` or `preprod` or `devnet`"] + pub network: String, + + /// Cardano network magic number /// /// useful for TestNet & DevNet #[example = "`1097911063` or `42`"] pub network_magic: Option, - /// Cardano network - #[example = "`mainnet` or `preprod` or `devnet`"] - pub network: String, + /// Dmq network magic number + /// + /// useful for TestNet & DevNet + #[example = "`1097911063` or `42`"] + pub dmq_network_magic: Option, /// Cardano chain observer type pub chain_observer_type: ChainObserverType, @@ -636,8 +659,9 @@ impl ServeCommandConfiguration { cardano_node_socket_path: PathBuf::new(), dmq_node_socket_path: None, cardano_node_version: "0.0.1".to_string(), - network_magic: Some(42), network: "devnet".to_string(), + network_magic: Some(42), + dmq_network_magic: Some(3141592), chain_observer_type: ChainObserverType::Fake, protocol_parameters: ProtocolParameters { k: 5, @@ -722,12 +746,16 @@ impl ConfigurationSource for ServeCommandConfiguration { self.cardano_node_version.clone() } + fn network(&self) -> String { + self.network.clone() + } + fn network_magic(&self) -> Option { self.network_magic } - fn network(&self) -> String { - self.network.clone() + fn dmq_network_magic(&self) -> Option { + self.dmq_network_magic } fn chain_observer_type(&self) -> ChainObserverType { diff --git a/mithril-aggregator/src/dependency_injection/builder/enablers/misc.rs b/mithril-aggregator/src/dependency_injection/builder/enablers/misc.rs index 62f4e17526a..a30783e8754 100644 --- a/mithril-aggregator/src/dependency_injection/builder/enablers/misc.rs +++ b/mithril-aggregator/src/dependency_injection/builder/enablers/misc.rs @@ -92,7 +92,7 @@ impl DependenciesBuilder { let dmq_consumer = Arc::new(DmqConsumerClientPallas::::new( dmq_node_socket_path, - self.configuration.get_network()?, + self.configuration.get_dmq_network()?, self.root_logger(), )); Arc::new(SignatureConsumerDmq::new(dmq_consumer)) as Arc diff --git a/mithril-common/src/crypto_helper/cardano/opcert.rs b/mithril-common/src/crypto_helper/cardano/opcert.rs index 4d21e9f06aa..ae6ffb64e41 100644 --- a/mithril-common/src/crypto_helper/cardano/opcert.rs +++ b/mithril-common/src/crypto_helper/cardano/opcert.rs @@ -1,9 +1,6 @@ //! Module to (de)serialise, OpCert using the same structure as used in Cardano. -use super::SerDeShelleyFileFormat; -use crate::crypto_helper::cardano::ProtocolRegistrationErrorWrapper; -use crate::crypto_helper::{ProtocolPartyId, encode_bech32}; - +use anyhow::anyhow; use blake2::{Blake2b, Digest, digest::consts::U28}; use ed25519_dalek::{ Signature as EdSignature, Signer, SigningKey as EdSecretKey, Verifier, @@ -16,6 +13,12 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer}; use sha2::Sha256; use thiserror::Error; +use crate::StdResult; +use crate::crypto_helper::cardano::ProtocolRegistrationErrorWrapper; +use crate::crypto_helper::{ProtocolPartyId, encode_bech32}; + +use super::SerDeShelleyFileFormat; + /// Operational certificate error #[derive(Error, Debug, PartialEq, Eq)] pub enum OpCertError { @@ -47,6 +50,45 @@ pub struct OpCertWithoutColdVerificationKey { pub(crate) cert_sig: EdSignature, } +impl OpCertWithoutColdVerificationKey { + /// OpCertWithoutColdVerificationKey factory + pub fn try_new( + kes_vk: &[u8], + issue_number: u64, + start_kes_period: u64, + cert_sig: &[u8], + ) -> StdResult { + Ok(Self { + kes_vk: KesPublicKey::from_bytes(kes_vk) + .map_err(|_| anyhow!("KES vk serialisation error"))?, + issue_number, + start_kes_period, + cert_sig: EdSignature::from_slice(cert_sig) + .map_err(|_| anyhow!("ed25519 signature serialisation error"))?, + }) + } + + /// Get the KES verification key + pub fn kes_vk(&self) -> KesPublicKey { + self.kes_vk + } + + /// Get the issue number + pub fn issue_number(&self) -> u64 { + self.issue_number + } + + /// Get the start KES period + pub fn start_kes_period(&self) -> u64 { + self.start_kes_period + } + + /// Get the certificate signature + pub fn cert_sig(&self) -> EdSignature { + self.cert_sig + } +} + impl SerDeShelleyFileFormat for OpCertWithoutColdVerificationKey { const TYPE: &'static str = "NodeOperationalCertificateWithoutColdVerificationKey"; const DESCRIPTION: &'static str = ""; diff --git a/mithril-relay/Cargo.toml b/mithril-relay/Cargo.toml index 6473cdedb02..e1873f17500 100644 --- a/mithril-relay/Cargo.toml +++ b/mithril-relay/Cargo.toml @@ -10,6 +10,8 @@ license = { workspace = true } repository = { workspace = true } [features] +default = ["future_dmq"] + bundle_tls = ["reqwest/native-tls-vendored"] future_dmq = ["dep:mithril-dmq"] diff --git a/mithril-relay/src/commands/aggregator.rs b/mithril-relay/src/commands/aggregator.rs index ba75b5fdf39..827ba12f860 100644 --- a/mithril-relay/src/commands/aggregator.rs +++ b/mithril-relay/src/commands/aggregator.rs @@ -5,9 +5,9 @@ use clap::Parser; use libp2p::Multiaddr; use slog::error; -#[cfg(feature = "future_dmq")] -use mithril_common::CardanoNetwork; use mithril_common::StdResult; +#[cfg(feature = "future_dmq")] +use mithril_dmq::DmqNetwork; use crate::AggregatorRelay; @@ -33,16 +33,16 @@ pub struct AggregatorCommand { )] dmq_node_socket_path: PathBuf, - /// Cardano network + /// DMQ network #[cfg(feature = "future_dmq")] #[clap(long, env = "NETWORK")] pub network: String, - /// Cardano Network Magic number + /// DMQ Network Magic number /// useful for TestNet & DevNet #[cfg(feature = "future_dmq")] - #[clap(long, env = "NETWORK_MAGIC")] - pub network_magic: Option, + #[clap(long, env = "DMQ_NETWORK_MAGIC")] + pub dmq_network_magic: Option, /// Aggregator endpoint URL. #[clap(long, env = "AGGREGATOR_ENDPOINT")] @@ -57,15 +57,14 @@ impl AggregatorCommand { let addr: Multiaddr = format!("/ip4/0.0.0.0/tcp/{}", self.listen_port).parse()?; let aggregator_endpoint = self.aggregator_endpoint.to_owned(); #[cfg(feature = "future_dmq")] - let cardano_network = - CardanoNetwork::from_code(self.network.to_owned(), self.network_magic)?; + let dmq_network = DmqNetwork::from_code(self.network.to_owned(), self.dmq_network_magic)?; let mut relay = AggregatorRelay::start( &addr, #[cfg(feature = "future_dmq")] &self.dmq_node_socket_path, #[cfg(feature = "future_dmq")] - &cardano_network, + &dmq_network, &aggregator_endpoint, logger, ) diff --git a/mithril-relay/src/commands/signer.rs b/mithril-relay/src/commands/signer.rs index cafb6857684..7afd31f294e 100644 --- a/mithril-relay/src/commands/signer.rs +++ b/mithril-relay/src/commands/signer.rs @@ -4,11 +4,12 @@ use std::time::Duration; use clap::Parser; use libp2p::Multiaddr; + use slog::error; -#[cfg(feature = "future_dmq")] -use mithril_common::CardanoNetwork; use mithril_common::StdResult; +#[cfg(feature = "future_dmq")] +use mithril_dmq::DmqNetwork; use crate::{SignerRelay, SignerRelayConfiguration, SignerRelayMode}; @@ -46,8 +47,8 @@ pub struct SignerCommand { /// Cardano Network Magic number /// useful for TestNet & DevNet #[cfg(feature = "future_dmq")] - #[clap(long, env = "NETWORK_MAGIC")] - pub network_magic: Option, + #[clap(long, env = "DMQ_NETWORK_MAGIC")] + pub dmq_network_magic: Option, /// Aggregator endpoint URL. #[clap(long, env = "AGGREGATOR_ENDPOINT")] @@ -78,8 +79,7 @@ impl SignerCommand { let aggregator_endpoint = self.aggregator_endpoint.to_owned(); let signer_repeater_delay = Duration::from_millis(self.signer_repeater_delay); #[cfg(feature = "future_dmq")] - let cardano_network = - CardanoNetwork::from_code(self.network.to_owned(), self.network_magic)?; + let dmq_network = DmqNetwork::from_code(self.network.to_owned(), self.dmq_network_magic)?; let mut relay = SignerRelay::start(SignerRelayConfiguration { address: &addr, @@ -87,7 +87,7 @@ impl SignerCommand { #[cfg(feature = "future_dmq")] dmq_node_socket_path: &self.dmq_node_socket_path, #[cfg(feature = "future_dmq")] - cardano_network: &cardano_network, + dmq_network: &dmq_network, signer_registration_mode, signature_registration_mode, aggregator_endpoint: &aggregator_endpoint, diff --git a/mithril-relay/src/relay/aggregator.rs b/mithril-relay/src/relay/aggregator.rs index ccc5c0edcae..da4e4381eab 100644 --- a/mithril-relay/src/relay/aggregator.rs +++ b/mithril-relay/src/relay/aggregator.rs @@ -3,8 +3,6 @@ use std::{path::Path, sync::Arc}; use anyhow::anyhow; use libp2p::Multiaddr; -#[cfg(feature = "future_dmq")] -use mithril_dmq::{DmqConsumerServer, DmqConsumerServerPallas, DmqMessage}; use reqwest::StatusCode; use slog::{Logger, error, info}; #[cfg(feature = "future_dmq")] @@ -13,13 +11,13 @@ use tokio::sync::{ watch::{self, Receiver, Sender}, }; -#[cfg(feature = "future_dmq")] -use mithril_common::CardanoNetwork; use mithril_common::{ StdResult, logging::LoggerExtensions, messages::{RegisterSignatureMessageHttp, RegisterSignerMessage}, }; +#[cfg(feature = "future_dmq")] +use mithril_dmq::{DmqConsumerServer, DmqConsumerServerPallas, DmqMessage, DmqNetwork}; use crate::p2p::{BroadcastMessage, Peer, PeerEvent}; @@ -39,7 +37,7 @@ impl AggregatorRelay { pub async fn start( addr: &Multiaddr, #[cfg(feature = "future_dmq")] dmq_node_socket_path: &Path, - #[cfg(feature = "future_dmq")] cardano_network: &CardanoNetwork, + #[cfg(feature = "future_dmq")] dmq_network: &DmqNetwork, aggregator_endpoint: &str, logger: &Logger, ) -> StdResult { @@ -52,7 +50,7 @@ impl AggregatorRelay { #[cfg(unix)] let _dmq_consumer_server = Self::start_dmq_consumer_server( dmq_node_socket_path, - cardano_network, + dmq_network, signature_dmq_rx, stop_rx, logger.clone(), @@ -88,14 +86,14 @@ impl AggregatorRelay { #[cfg(feature = "future_dmq")] async fn start_dmq_consumer_server( socket: &Path, - cardano_network: &CardanoNetwork, + dmq_network: &DmqNetwork, signature_dmq_rx: UnboundedReceiver, stop_rx: Receiver<()>, logger: Logger, ) -> StdResult> { let dmq_consumer_server = Arc::new(DmqConsumerServerPallas::new( socket.to_path_buf(), - cardano_network.to_owned(), + dmq_network.to_owned(), stop_rx, logger.clone(), )); @@ -271,7 +269,7 @@ mod tests { #[cfg(feature = "future_dmq")] Path::new("test"), #[cfg(feature = "future_dmq")] - &CardanoNetwork::TestNet(123), + &DmqNetwork::TestNet(123), &server.url(""), &TestLogger::stdout(), ) diff --git a/mithril-relay/src/relay/signer.rs b/mithril-relay/src/relay/signer.rs index 46abc93e4f0..235f596b74d 100644 --- a/mithril-relay/src/relay/signer.rs +++ b/mithril-relay/src/relay/signer.rs @@ -15,15 +15,13 @@ use tokio::sync::mpsc::{UnboundedReceiver, UnboundedSender, unbounded_channel}; use tokio::sync::watch::{self, Receiver, Sender}; use warp::Filter; -#[cfg(feature = "future_dmq")] -use mithril_common::CardanoNetwork; use mithril_common::{ StdResult, logging::LoggerExtensions, messages::{RegisterSignatureMessageHttp, RegisterSignerMessage}, }; #[cfg(feature = "future_dmq")] -use mithril_dmq::{DmqMessage, DmqPublisherServer, DmqPublisherServerPallas}; +use mithril_dmq::{DmqMessage, DmqNetwork, DmqPublisherServer, DmqPublisherServerPallas}; use mithril_test_http_server::{TestHttpServer, test_http_server_with_socket_address}; use crate::{ @@ -67,9 +65,9 @@ pub struct SignerRelayConfiguration<'a> { /// Path to the DMQ node socket file #[cfg(feature = "future_dmq")] pub dmq_node_socket_path: &'a Path, - /// Cardano network + /// DMQ network #[cfg(feature = "future_dmq")] - pub cardano_network: &'a CardanoNetwork, + pub dmq_network: &'a DmqNetwork, /// Signer registration mode pub signer_registration_mode: &'a SignerRelayMode, /// Signature registration mode @@ -129,7 +127,7 @@ impl SignerRelay { #[cfg(unix)] let _dmq_publisher_server = Self::start_dmq_publisher_server( config.dmq_node_socket_path, - config.cardano_network, + config.dmq_network, signature_dmq_tx, stop_rx, relay_logger.clone(), @@ -171,14 +169,14 @@ impl SignerRelay { #[cfg(feature = "future_dmq")] async fn start_dmq_publisher_server( socket: &Path, - cardano_network: &CardanoNetwork, + dmq_network: &DmqNetwork, signature_dmq_tx: UnboundedSender, stop_rx: Receiver<()>, logger: Logger, ) -> StdResult> { let dmq_publisher_server = Arc::new(DmqPublisherServerPallas::new( socket.to_path_buf(), - cardano_network.to_owned(), + dmq_network.to_owned(), stop_rx, logger.clone(), )); diff --git a/mithril-relay/tests/register_signer_signature.rs b/mithril-relay/tests/register_signer_signature.rs index 3ed905491cf..a5280eefe42 100644 --- a/mithril-relay/tests/register_signer_signature.rs +++ b/mithril-relay/tests/register_signer_signature.rs @@ -7,10 +7,10 @@ use reqwest::StatusCode; use slog::{Drain, Level, Logger}; use slog_scope::{error, info}; -#[cfg(feature = "future_dmq")] -use mithril_common::CardanoNetwork; use mithril_common::messages::{RegisterSignatureMessageHttp, RegisterSignerMessage}; use mithril_common::test::double::Dummy; +#[cfg(feature = "future_dmq")] +use mithril_dmq::DmqNetwork; use mithril_relay::{ PassiveRelay, SignerRelay, SignerRelayConfiguration, SignerRelayMode, p2p::{BroadcastMessage, PeerBehaviourEvent, PeerEvent}, @@ -44,7 +44,7 @@ async fn should_receive_registrations_from_signers_when_subscribed_to_pubsub() { #[cfg(feature = "future_dmq")] let dmq_node_socket_path = PathBuf::new(); #[cfg(feature = "future_dmq")] - let cardano_network = CardanoNetwork::TestNet(123); + let dmq_network = DmqNetwork::TestNet(123); let signer_registration_mode = SignerRelayMode::P2P; let signature_registration_mode = SignerRelayMode::P2P; let aggregator_endpoint = "http://0.0.0.0:1234".to_string(); @@ -55,7 +55,7 @@ async fn should_receive_registrations_from_signers_when_subscribed_to_pubsub() { #[cfg(feature = "future_dmq")] dmq_node_socket_path: &dmq_node_socket_path, #[cfg(feature = "future_dmq")] - cardano_network: &cardano_network, + dmq_network: &dmq_network, signer_registration_mode: &signer_registration_mode, signature_registration_mode: &signature_registration_mode, aggregator_endpoint: &aggregator_endpoint, diff --git a/mithril-signer/Cargo.toml b/mithril-signer/Cargo.toml index 6beed3eb73c..d5956d8ca3b 100644 --- a/mithril-signer/Cargo.toml +++ b/mithril-signer/Cargo.toml @@ -10,7 +10,7 @@ license = { workspace = true } repository = { workspace = true } [features] -default = ["jemallocator"] +default = ["jemallocator", "future_dmq"] bundle_tls = ["reqwest/native-tls-vendored"] jemallocator = ["dep:tikv-jemallocator"] diff --git a/mithril-signer/src/configuration.rs b/mithril-signer/src/configuration.rs index 069d0bc2a00..188b773e225 100644 --- a/mithril-signer/src/configuration.rs +++ b/mithril-signer/src/configuration.rs @@ -1,5 +1,7 @@ use anyhow::Context; use config::{ConfigError, Map, Source, Value}; +#[cfg(feature = "future_dmq")] +use mithril_dmq::DmqNetwork; use mithril_doc::{Documenter, DocumenterDefault, StructDoc}; use serde::{Deserialize, Serialize}; use std::{path::PathBuf, sync::Arc}; @@ -53,11 +55,16 @@ pub struct Configuration { #[example = "`mainnet` or `preprod` or `devnet`"] pub network: String, - /// Cardano Network Magic number + /// Cardano network magic number /// useful for TestNet & DevNet #[example = "`1097911063` or `42`"] pub network_magic: Option, + /// DMQ network magic number + /// useful for TestNet & DevNet + #[example = "`1097911063` or `42`"] + pub dmq_network_magic: Option, + /// Also known as `k`, it defines the number of blocks that are required for the blockchain to /// be considered final, preventing any further rollback `[default: 2160]`. pub network_security_parameter: BlockNumber, @@ -164,6 +171,7 @@ impl Configuration { db_directory: PathBuf::new(), network: "devnet".to_string(), network_magic: Some(42), + dmq_network_magic: Some(3141592), network_security_parameter: BlockNumber(2160), preload_security_parameter: BlockNumber(30), party_id: Some(party_id), @@ -195,7 +203,7 @@ impl Configuration { } } - /// Return the CardanoNetwork value from the configuration. + /// Return the Cardano network value from the configuration. pub fn get_network(&self) -> StdResult { CardanoNetwork::from_code(self.network.clone(), self.network_magic).with_context(|| { format!( @@ -205,6 +213,17 @@ impl Configuration { }) } + /// Return the DMQ network value from the configuration. + #[cfg(feature = "future_dmq")] + pub fn get_dmq_network(&self) -> StdResult { + DmqNetwork::from_code(self.network.clone(), self.dmq_network_magic).with_context(|| { + format!( + "Could not read DMQ Network '{}' from configuration.", + &self.network + ) + }) + } + /// Create the SQL store directory if not exist and return the path of the /// SQLite3 file. pub fn get_sqlite_file(&self, sqlite_file_name: &str) -> StdResult { diff --git a/mithril-signer/src/dependency_injection/builder.rs b/mithril-signer/src/dependency_injection/builder.rs index 2a737d04244..72e01ac2954 100644 --- a/mithril-signer/src/dependency_injection/builder.rs +++ b/mithril-signer/src/dependency_injection/builder.rs @@ -422,7 +422,7 @@ impl<'a> DependenciesBuilder<'a> { let first_publisher = SignaturePublisherRetrier::new( match &self.config.dmq_node_socket_path { Some(dmq_node_socket_path) => { - let cardano_network = &self.config.get_network()?; + let dmq_network = &self.config.get_dmq_network()?; let dmq_message_builder = DmqMessageBuilder::new( kes_signer .clone() @@ -432,7 +432,7 @@ impl<'a> DependenciesBuilder<'a> { Arc::new(SignaturePublisherDmq::new(Arc::new( DmqPublisherClientPallas::::new( dmq_node_socket_path.to_owned(), - *cardano_network, + *dmq_network, dmq_message_builder, self.root_logger(), ), diff --git a/mithril-test-lab/mithril-devnet/devnet-log.sh b/mithril-test-lab/mithril-devnet/devnet-log.sh index 64b4efe4d5e..0f5beb5135b 100755 --- a/mithril-test-lab/mithril-devnet/devnet-log.sh +++ b/mithril-test-lab/mithril-devnet/devnet-log.sh @@ -39,4 +39,15 @@ if [ "${NODES}" = "cardano" ] || [ "${NODES}" = "*" ]; then LINES=${LINES} ./log-cardano.sh echo +fi +if [ "${NODES}" = "*" ]; then + echo "=====================================================================" + echo "=== DMQ Network" + echo "=====================================================================" + echo +fi +if [ "${NODES}" = "dmq" ] || [ "${NODES}" = "*" ]; then + + LINES=${LINES} ./log-dmq.sh + echo fi \ No newline at end of file diff --git a/mithril-test-lab/mithril-devnet/devnet-mkfiles.sh b/mithril-test-lab/mithril-devnet/devnet-mkfiles.sh index 2f6b003d163..a73cf35e9f8 100755 --- a/mithril-test-lab/mithril-devnet/devnet-mkfiles.sh +++ b/mithril-test-lab/mithril-devnet/devnet-mkfiles.sh @@ -13,12 +13,18 @@ SCRIPT_DIRECTORY=$(dirname $0) # Init script . $SCRIPT_DIRECTORY/mkfiles/mkfiles-init.sh -# Generate the topology -. ${SCRIPT_DIRECTORY}/mkfiles/mkfiles-topology.sh +# Generate the Cardano nodes topology +. ${SCRIPT_DIRECTORY}/mkfiles/mkfiles-topology-cardano.sh # Generate Cardano devnet artifacts . $SCRIPT_DIRECTORY/mkfiles/mkfiles-cardano.sh +# Generate the DMQ nodes topology +. ${SCRIPT_DIRECTORY}/mkfiles/mkfiles-topology-dmq.sh + +# Generate Cardano DMQ artifacts +. $SCRIPT_DIRECTORY/mkfiles/mkfiles-dmq.sh + # Generate the start scripts . $SCRIPT_DIRECTORY/mkfiles/mkfiles-start.sh diff --git a/mithril-test-lab/mithril-devnet/devnet-run.sh b/mithril-test-lab/mithril-devnet/devnet-run.sh index b191a3af129..b69642cdcb4 100755 --- a/mithril-test-lab/mithril-devnet/devnet-run.sh +++ b/mithril-test-lab/mithril-devnet/devnet-run.sh @@ -31,6 +31,16 @@ echo # Change directory pushd ${ARTIFACTS_DIR} > /dev/null +# Start devnet DMQ nodes +if [ "${NODES}" = "dmq" ] || [ "${NODES}" = "*" ]; then + echo "=====================================================================" + echo " Start DMQ nodes" + echo "=====================================================================" + echo + ./start-dmq.sh + echo +fi + # Start devnet Cardano nodes if [ "${NODES}" = "cardano" ] || [ "${NODES}" = "*" ]; then echo "=====================================================================" diff --git a/mithril-test-lab/mithril-devnet/mkfiles/mkfiles-cardano.sh b/mithril-test-lab/mithril-devnet/mkfiles/mkfiles-cardano.sh index 1f4ea58e307..a111d0d7107 100644 --- a/mithril-test-lab/mithril-devnet/mkfiles/mkfiles-cardano.sh +++ b/mithril-test-lab/mithril-devnet/mkfiles/mkfiles-cardano.sh @@ -33,6 +33,7 @@ esac CARDANO_BIN_PATH=./bin CARDANO_CLI=${CARDANO_BIN_PATH}/cardano-cli CARDANO_NODE=${CARDANO_BIN_PATH}/cardano-node +DMQ_NODE=${CARDANO_BIN_PATH}/dmq-node NUM_SPO_NODES=$NUM_POOL_NODES INIT_SUPPLY=12000000 TOTAL_SUPPLY=2000000000000 diff --git a/mithril-test-lab/mithril-devnet/mkfiles/mkfiles-dmq.sh b/mithril-test-lab/mithril-devnet/mkfiles/mkfiles-dmq.sh new file mode 100644 index 00000000000..7bd30490da1 --- /dev/null +++ b/mithril-test-lab/mithril-devnet/mkfiles/mkfiles-dmq.sh @@ -0,0 +1,18 @@ +# Temporary script to copy DMQ node binary +cp $DMQ_NODE_BINARY/dmq-node ./bin/ + +for NODE in ${ALL_NODES}; do + cat >> ${NODE}/config.dmq.json <> log-dmq.sh <> start-dmq.sh <> Start DMQ network" +killall dmq-node > /dev/null 2>&1 + +# Stop when there's an error, activate it after the killall since it will report an error if it doesn't kill anything +set -e + +$DMQ_NODE --version + +EOF + +for NODE in ${ALL_NODES}; do + cat >> ${NODE}/start-dmq.sh < ${NODE}/dmq.node.log +EOF + chmod u+x ${NODE}/start-dmq.sh + cat >> start-dmq.sh <> Starting DMQ node '${NODE}'" +./${NODE}/start-dmq.sh & + +EOF +done + +chmod u+x start-dmq.sh + cat >> start-mithril.sh <> stop.sh <> Stop Cardano network" killall cardano-node +echo ">> Stop DMQ network" +killall dmq-node + echo ">> Stop Mithril network" if [ -z "\${MITHRIL_IMAGE_ID}" ]; then export MITHRIL_AGGREGATOR_IMAGE="mithril/mithril-aggregator" diff --git a/mithril-test-lab/mithril-devnet/mkfiles/mkfiles-topology.sh b/mithril-test-lab/mithril-devnet/mkfiles/mkfiles-topology-cardano.sh similarity index 100% rename from mithril-test-lab/mithril-devnet/mkfiles/mkfiles-topology.sh rename to mithril-test-lab/mithril-devnet/mkfiles/mkfiles-topology-cardano.sh diff --git a/mithril-test-lab/mithril-devnet/mkfiles/mkfiles-topology-dmq.sh b/mithril-test-lab/mithril-devnet/mkfiles/mkfiles-topology-dmq.sh new file mode 100644 index 00000000000..302e5780b62 --- /dev/null +++ b/mithril-test-lab/mithril-devnet/mkfiles/mkfiles-topology-dmq.sh @@ -0,0 +1,60 @@ + +NODE_PORT_START=4000 + +# Create network topology +FULL_NODES=() +FULL_NODES_N=() +for (( i=1; i<=${NUM_FULL_NODES}; i++ )) + do + FULL_NODES=("${FULL_NODES[@]}" "node-full${i}") + FULL_NODES_N=("${FULL_NODES_N[@]}" "${i}") +done +FULL_NODES=${FULL_NODES[@]} +FULL_NODES_N=${FULL_NODES_N[@]} + +POOL_NODES=() +POOL_NODES_N=() +for (( i=1; i<=${NUM_POOL_NODES}; i++ )) + do + POOL_NODES=("${POOL_NODES[@]}" "node-pool${i}") + POOL_NODES_N=("${POOL_NODES_N[@]}" "${i}") +done +POOL_NODES=${POOL_NODES[@]} +POOL_NODES_N=${POOL_NODES_N[@]} + +ALL_NODES="${FULL_NODES} ${POOL_NODES}" + +# create the topology files +NODE_ADDR=$LISTENING_ADDR +NODE_PORT=NODE_PORT_START +TOPOLOGY=' +{ + "bootstrapPeers": [], + "localRoots": [ + { + "accessPoints": [], + "advertise": false, + "trustable": false, + "valency": 1 + } + ], + "peerSnapshotFile": null, + "publicRoots": [ + { + "accessPoints": [], + "advertise": false + } + ] +}' +for NODE in ${ALL_NODES}; do + NODE_PORT=$(( ${NODE_PORT} + 1)) + echo ${NODE_PORT} > ${NODE}/port.dmq + TOPOLOGY=$(echo ${TOPOLOGY} | jq '.localRoots[0].accessPoints[.localRoots[0].accessPoints | length] |= . + {"address": "'${NODE_ADDR}'","port": '${NODE_PORT}', "valency": 1}') +done +echo $TOPOLOGY | jq . > topology.dmq.json + +NODE_IX=0 +for NODE in ${ALL_NODES}; do + cat topology.dmq.json | jq '.localRoots[0].accessPoints |= del(.['${NODE_IX}'])' > ${NODE}/topology.dmq.json + NODE_IX=$(( ${NODE_IX} + 1)) +done \ No newline at end of file diff --git a/mithril-test-lab/mithril-end-to-end/src/devnet/runner.rs b/mithril-test-lab/mithril-end-to-end/src/devnet/runner.rs index 3541e2d4662..202de5c6f2e 100644 --- a/mithril-test-lab/mithril-end-to-end/src/devnet/runner.rs +++ b/mithril-test-lab/mithril-end-to-end/src/devnet/runner.rs @@ -24,6 +24,7 @@ pub struct Devnet { pub struct PoolNode { pub db_path: PathBuf, pub socket_path: PathBuf, + pub dmq_socket_path: PathBuf, pub pool_env_path: PathBuf, pub kes_secret_key_path: PathBuf, pub operational_certificate_path: PathBuf, @@ -50,6 +51,7 @@ impl PoolNode { pub struct FullNode { pub db_path: PathBuf, pub socket_path: PathBuf, + pub dmq_socket_path: PathBuf, } #[derive(Debug, Clone, PartialEq, Eq)] @@ -122,9 +124,14 @@ impl Devnet { bootstrap_args.cardano_hard_fork_latest_era_at_epoch.to_string(), ); + // TODO: temporary implementation + let dmq_node_binary = + PathBuf::from(r"/home/jp/Works/Cardano/Mithril/ouroboros-network/result/bin"); + bootstrap_command.env("DMQ_NODE_BINARY", &dmq_node_binary); + bootstrap_command .current_dir(&bootstrap_args.devnet_scripts_dir) - .stdout(Stdio::null()) + //.stdout(Stdio::null()) .kill_on_drop(true); info!("Bootstrapping the Devnet"; "script" => &bootstrap_script_path.display()); @@ -198,6 +205,7 @@ impl Devnet { .map(|n| PoolNode { db_path: self.artifacts_dir.join(format!("node-pool{n}/db")), socket_path: self.artifacts_dir.join(format!("node-pool{n}/ipc/node.sock")), + dmq_socket_path: self.artifacts_dir.join(format!("node-pool{n}/ipc/dmq.node.sock")), pool_env_path: self.artifacts_dir.join(format!("node-pool{n}/pool.env")), kes_secret_key_path: self .artifacts_dir @@ -211,6 +219,7 @@ impl Devnet { .map(|n| FullNode { db_path: self.artifacts_dir.join(format!("node-full{n}/db")), socket_path: self.artifacts_dir.join(format!("node-full{n}/ipc/node.sock")), + dmq_socket_path: self.artifacts_dir.join(format!("node-full{n}/ipc/dmq.node.sock")), }) .collect::>(); @@ -226,20 +235,43 @@ impl Devnet { let mut run_command = Command::new(&run_script_path); run_command.current_dir(&self.artifacts_dir).kill_on_drop(true); - info!("Starting the Devnet"; "script" => &run_script_path.display()); + info!("Starting the Cardano devnet"; "script" => &run_script_path.display()); + + let status = run_command + .spawn() + .with_context(|| "Failed to start the Cardano devnet")? + .wait() + .await + .with_context(|| "Error while starting the Cardano devnet")?; + match status.code() { + Some(0) => Ok(()), + Some(code) => Err(anyhow!(RetryableDevnetError(format!( + "Run Cardano devnet exited with status code: {code}" + )))), + None => Err(anyhow!("Run Cardano devnet terminated by signal")), + } + } + + pub async fn run_dmq(&self) -> StdResult<()> { + let run_script = "start-dmq.sh"; + let run_script_path = self.artifacts_dir.join(run_script); + let mut run_command = Command::new(&run_script_path); + run_command.current_dir(&self.artifacts_dir).kill_on_drop(true); + + info!("Starting the DMQ devnet"; "script" => &run_script_path.display()); let status = run_command .spawn() - .with_context(|| "Failed to start the devnet")? + .with_context(|| "Failed to start the DMQ devnet")? .wait() .await - .with_context(|| "Error while starting the devnet")?; + .with_context(|| "Error while starting the DMQ devnet")?; match status.code() { Some(0) => Ok(()), Some(code) => Err(anyhow!(RetryableDevnetError(format!( - "Run devnet exited with status code: {code}" + "Run DMQ devnet exited with status code: {code}" )))), - None => Err(anyhow!("Run devnet terminated by signal")), + None => Err(anyhow!("Run DMQ devnet terminated by signal")), } } @@ -377,6 +409,7 @@ mod tests { pool_nodes: vec![PoolNode { db_path: PathBuf::from(r"test/path/node-pool1/db"), socket_path: PathBuf::from(r"test/path/node-pool1/ipc/node.sock"), + dmq_socket_path: PathBuf::from(r"test/path/node-pool1/ipc/dmq.node.sock"), pool_env_path: PathBuf::from(r"test/path/node-pool1/pool.env"), kes_secret_key_path: PathBuf::from(r"test/path/node-pool1/shelley/kes.skey"), operational_certificate_path: PathBuf::from( @@ -385,7 +418,8 @@ mod tests { },], full_nodes: vec![FullNode { db_path: PathBuf::from(r"test/path/node-full1/db"), - socket_path: PathBuf::from(r"test/path/node-full1/ipc/node.sock") + socket_path: PathBuf::from(r"test/path/node-full1/ipc/node.sock"), + dmq_socket_path: PathBuf::from(r"test/path/node-full1/ipc/dmq.node.sock") }] }, devnet.topology() diff --git a/mithril-test-lab/mithril-end-to-end/src/main.rs b/mithril-test-lab/mithril-end-to-end/src/main.rs index d041d4211d7..97b37543547 100644 --- a/mithril-test-lab/mithril-end-to-end/src/main.rs +++ b/mithril-test-lab/mithril-end-to-end/src/main.rs @@ -133,6 +133,13 @@ pub struct Args { #[clap(long)] use_dmq: bool, + /// DMQ node flavor (used only when 'use_dmq' is set, can be 'haskell' or 'fake') + /// + /// 'haskell': will use the DMQ network created within the 'mithril-devnet' + /// 'fake': will use a fake DMQ network within created with the Mithril relay + #[clap(long, default_value = "haskell")] + dmq_node_flavor: Option, + /// Skip cardano binaries download #[clap(long)] skip_cardano_bin_download: bool, @@ -372,6 +379,7 @@ impl App { signed_entity_types: args.signed_entity_types.clone(), run_only_mode, use_dmq, + dmq_node_flavor: args.dmq_node_flavor, use_relays, relay_signer_registration_mode, relay_signature_registration_mode, diff --git a/mithril-test-lab/mithril-end-to-end/src/mithril/aggregator.rs b/mithril-test-lab/mithril-end-to-end/src/mithril/aggregator.rs index cca71603ff3..b46bba28ac0 100644 --- a/mithril-test-lab/mithril-end-to-end/src/mithril/aggregator.rs +++ b/mithril-test-lab/mithril-end-to-end/src/mithril/aggregator.rs @@ -15,7 +15,7 @@ use mithril_common::{CardanoNetwork, StdResult, entities}; use crate::utils::MithrilCommand; use crate::{ - ANCILLARY_MANIFEST_SECRET_KEY, DEVNET_MAGIC_ID, ERA_MARKERS_SECRET_KEY, + ANCILLARY_MANIFEST_SECRET_KEY, DEVNET_DMQ_MAGIC_ID, DEVNET_MAGIC_ID, ERA_MARKERS_SECRET_KEY, ERA_MARKERS_VERIFICATION_KEY, FullNode, GENESIS_SECRET_KEY, GENESIS_VERIFICATION_KEY, RetryableDevnetError, }; @@ -40,6 +40,7 @@ pub struct AggregatorConfig<'a> { pub chain_observer_type: &'a str, pub leader_aggregator_endpoint: &'a Option, pub use_dmq: bool, + pub dmq_node_flavor: &'a Option, } pub struct Aggregator { @@ -56,6 +57,7 @@ pub struct Aggregator { impl Aggregator { pub fn new(aggregator_config: &AggregatorConfig) -> StdResult { let magic_id = DEVNET_MAGIC_ID.to_string(); + let dmq_magic_id = DEVNET_DMQ_MAGIC_ID.to_string(); let server_port_parameter = aggregator_config.server_port.to_string(); let era_reader_adapter_params = if aggregator_config.mithril_era_reader_adapter == "cardano-chain" { @@ -77,6 +79,7 @@ impl Aggregator { let mut env = HashMap::from([ ("NETWORK", "devnet"), ("NETWORK_MAGIC", &magic_id), + ("DMQ_NETWORK_MAGIC", &dmq_magic_id), ("RUN_INTERVAL", &mithril_run_interval), ("SERVER_IP", "0.0.0.0"), ("SERVER_PORT", &server_port_parameter), @@ -130,14 +133,32 @@ impl Aggregator { if let Some(leader_aggregator_endpoint) = aggregator_config.leader_aggregator_endpoint { env.insert("LEADER_AGGREGATOR_ENDPOINT", leader_aggregator_endpoint); } - let dmq_node_socket_path = aggregator_config - .work_dir - .join(format!("dmq-aggregator-{}.socket", aggregator_config.index)); + let dmq_node_socket_path = if aggregator_config.use_dmq { + match aggregator_config.dmq_node_flavor { + Some(flavor) if flavor == "haskell" => aggregator_config + .full_node + .dmq_socket_path + .to_str() + .unwrap() + .to_string(), + Some(flavor) if flavor == "fake" => aggregator_config + .work_dir + .join(format!("dmq-aggregator-{}.socket", aggregator_config.index)) + .to_str() + .unwrap() + .to_string(), + _ => { + return Err(anyhow!(format!( + "Unsupported DMQ node flavor: {:?}", + aggregator_config.dmq_node_flavor + ))); + } + } + } else { + "".to_string() + }; if aggregator_config.use_dmq { - env.insert( - "DMQ_NODE_SOCKET_PATH", - dmq_node_socket_path.to_str().unwrap(), - ); + env.insert("DMQ_NODE_SOCKET_PATH", dmq_node_socket_path.as_str()); } let args = vec![ "--db-directory", diff --git a/mithril-test-lab/mithril-end-to-end/src/mithril/infrastructure.rs b/mithril-test-lab/mithril-end-to-end/src/mithril/infrastructure.rs index 8212015db5c..90310fb88aa 100644 --- a/mithril-test-lab/mithril-end-to-end/src/mithril/infrastructure.rs +++ b/mithril-test-lab/mithril-end-to-end/src/mithril/infrastructure.rs @@ -37,6 +37,7 @@ pub struct MithrilInfrastructureConfig { pub use_p2p_passive_relays: bool, pub skip_signature_delayer: bool, pub use_dmq: bool, + pub dmq_node_flavor: Option, pub use_era_specific_work_dir: bool, } @@ -72,6 +73,7 @@ impl MithrilInfrastructureConfig { use_p2p_passive_relays: false, skip_signature_delayer: false, use_dmq: false, + dmq_node_flavor: Some("fake".to_string()), use_era_specific_work_dir: false, } } @@ -97,6 +99,9 @@ impl MithrilInfrastructure { pub async fn start(config: &MithrilInfrastructureConfig) -> StdResult { let chain_observer_type = "pallas"; config.devnet.run().await?; + if config.use_dmq && config.dmq_node_flavor == Some("haskell".to_string()) { + config.devnet.run_dmq().await?; + } let devnet_topology = config.devnet.topology(); let aggregator_cardano_nodes = &devnet_topology.full_nodes; let signer_cardano_nodes = &devnet_topology.pool_nodes; @@ -260,6 +265,7 @@ impl MithrilInfrastructure { chain_observer_type, leader_aggregator_endpoint: &leader_aggregator_endpoint, use_dmq: config.use_dmq, + dmq_node_flavor: &config.dmq_node_flavor, })?; aggregator @@ -399,6 +405,7 @@ impl MithrilInfrastructure { enable_certification, skip_signature_delayer: config.skip_signature_delayer, use_dmq: config.use_dmq, + dmq_node_flavor: &config.dmq_node_flavor, })?; signer.start().await?; diff --git a/mithril-test-lab/mithril-end-to-end/src/mithril/mod.rs b/mithril-test-lab/mithril-end-to-end/src/mithril/mod.rs index c1bd066bff9..493d352138b 100644 --- a/mithril-test-lab/mithril-end-to-end/src/mithril/mod.rs +++ b/mithril-test-lab/mithril-end-to-end/src/mithril/mod.rs @@ -18,6 +18,7 @@ pub use relay_signer::RelaySigner; pub use signer::Signer; pub const DEVNET_MAGIC_ID: mithril_common::MagicId = 42; +pub const DEVNET_DMQ_MAGIC_ID: mithril_common::MagicId = 3141592; pub const GENESIS_VERIFICATION_KEY: &str = "5b33322c3235332c3138362c3230312c3137372c31312c3131372c3133352c3138372c3136372c3138312c3138382c32322c35392c3230362c3130352c3233312c3135302c3231352c33302c37382c3231322c37362c31362c3235322c3138302c37322c3133342c3133372c3234372c3136312c36385d"; pub const GENESIS_SECRET_KEY: &str = "5b3131382c3138342c3232342c3137332c3136302c3234312c36312c3134342c36342c39332c3130362c3232392c38332c3133342c3138392c34302c3138392c3231302c32352c3138342c3136302c3134312c3233372c32362c3136382c35342c3233392c3230342c3133392c3131392c31332c3139395d"; diff --git a/mithril-test-lab/mithril-end-to-end/src/mithril/relay_aggregator.rs b/mithril-test-lab/mithril-end-to-end/src/mithril/relay_aggregator.rs index f5a39e3e342..d50cbd86fd0 100644 --- a/mithril-test-lab/mithril-end-to-end/src/mithril/relay_aggregator.rs +++ b/mithril-test-lab/mithril-end-to-end/src/mithril/relay_aggregator.rs @@ -1,5 +1,5 @@ use crate::utils::MithrilCommand; -use crate::{Aggregator, DEVNET_MAGIC_ID}; +use crate::{Aggregator, DEVNET_DMQ_MAGIC_ID}; use mithril_common::StdResult; use std::collections::HashMap; use std::path::Path; @@ -25,11 +25,11 @@ impl RelayAggregator { ) -> StdResult { let name = Aggregator::name_suffix(index); let listen_port_str = format!("{listen_port}"); - let magic_id = DEVNET_MAGIC_ID.to_string(); + let dmq_magic_id = DEVNET_DMQ_MAGIC_ID.to_string(); let mut env = HashMap::from([ ("LISTEN_PORT", listen_port_str.as_str()), ("NETWORK", "devnet"), - ("NETWORK_MAGIC", &magic_id), + ("DMQ_NETWORK_MAGIC", &dmq_magic_id), ("AGGREGATOR_ENDPOINT", aggregator_endpoint), ]); if let Some(dial_to) = &dial_to { diff --git a/mithril-test-lab/mithril-end-to-end/src/mithril/relay_signer.rs b/mithril-test-lab/mithril-end-to-end/src/mithril/relay_signer.rs index 26e4c9bca32..a034500e483 100644 --- a/mithril-test-lab/mithril-end-to-end/src/mithril/relay_signer.rs +++ b/mithril-test-lab/mithril-end-to-end/src/mithril/relay_signer.rs @@ -1,4 +1,4 @@ -use crate::DEVNET_MAGIC_ID; +use crate::DEVNET_DMQ_MAGIC_ID; use crate::utils::MithrilCommand; use mithril_common::StdResult; use mithril_common::entities::PartyId; @@ -35,7 +35,7 @@ impl RelaySigner { let listen_port_str = format!("{}", configuration.listen_port); let server_port_str = format!("{}", configuration.server_port); - let magic_id = DEVNET_MAGIC_ID.to_string(); + let dmq_magic_id = DEVNET_DMQ_MAGIC_ID.to_string(); let relay_signer_registration_mode = configuration.relay_signer_registration_mode.to_string(); let relay_signature_registration_mode = @@ -44,7 +44,7 @@ impl RelaySigner { ("LISTEN_PORT", listen_port_str.as_str()), ("SERVER_PORT", server_port_str.as_str()), ("NETWORK", "devnet"), - ("NETWORK_MAGIC", &magic_id), + ("DMQ_NETWORK_MAGIC", &dmq_magic_id), ("AGGREGATOR_ENDPOINT", configuration.aggregator_endpoint), ("SIGNER_REPEATER_DELAY", "100"), ( diff --git a/mithril-test-lab/mithril-end-to-end/src/mithril/signer.rs b/mithril-test-lab/mithril-end-to-end/src/mithril/signer.rs index 2d6fbe958a8..3aa9315f033 100644 --- a/mithril-test-lab/mithril-end-to-end/src/mithril/signer.rs +++ b/mithril-test-lab/mithril-end-to-end/src/mithril/signer.rs @@ -1,16 +1,18 @@ -use crate::devnet::PoolNode; -use crate::utils::MithrilCommand; -use crate::{DEVNET_MAGIC_ID, ERA_MARKERS_VERIFICATION_KEY}; -use anyhow::Context; -use mithril_common::StdResult; -use mithril_common::entities::PartyId; -use slog_scope::info; use std::collections::HashMap; use std::path::Path; use std::sync::Arc; + +use anyhow::{Context, anyhow}; +use mithril_common::StdResult; +use mithril_common::entities::PartyId; +use slog_scope::info; use tokio::process::Child; use tokio::sync::RwLock; +use crate::devnet::PoolNode; +use crate::utils::MithrilCommand; +use crate::{DEVNET_DMQ_MAGIC_ID, DEVNET_MAGIC_ID, ERA_MARKERS_VERIFICATION_KEY}; + #[derive(Debug)] pub struct SignerConfig<'a> { pub signer_number: usize, @@ -27,6 +29,7 @@ pub struct SignerConfig<'a> { pub enable_certification: bool, pub skip_signature_delayer: bool, pub use_dmq: bool, + pub dmq_node_flavor: &'a Option, } #[derive(Debug)] @@ -41,6 +44,7 @@ impl Signer { pub fn new(signer_config: &SignerConfig) -> StdResult { let party_id = signer_config.pool_node.party_id()?; let magic_id = DEVNET_MAGIC_ID.to_string(); + let dmq_magic_id = DEVNET_DMQ_MAGIC_ID.to_string(); let era_reader_adapter_params = if signer_config.mithril_era_reader_adapter == "cardano-chain" { format!( @@ -62,6 +66,7 @@ impl Signer { let mut env = HashMap::from([ ("NETWORK", "devnet"), ("NETWORK_MAGIC", &magic_id), + ("DMQ_NETWORK_MAGIC", &dmq_magic_id), ("RUN_INTERVAL", &mithril_run_interval), ("AGGREGATOR_ENDPOINT", &signer_config.aggregator_endpoint), ( @@ -105,14 +110,29 @@ impl Signer { } else { env.insert("PARTY_ID", &party_id); } - let dmq_node_socket_path = signer_config - .work_dir - .join(format!("dmq-signer-{}.socket", signer_config.signer_number)); + let dmq_node_socket_path = if signer_config.use_dmq { + match signer_config.dmq_node_flavor { + Some(flavor) if flavor == "haskell" => { + signer_config.pool_node.dmq_socket_path.to_str().unwrap().to_string() + } + Some(flavor) if flavor == "fake" => signer_config + .work_dir + .join(format!("dmq-signer-{}.socket", signer_config.signer_number)) + .to_str() + .unwrap() + .to_string(), + _ => { + return Err(anyhow!(format!( + "Unsupported DMQ node flavor: {:?}", + signer_config.dmq_node_flavor + ))); + } + } + } else { + "".to_string() + }; if signer_config.use_dmq { - env.insert( - "DMQ_NODE_SOCKET_PATH", - dmq_node_socket_path.to_str().unwrap(), - ); + env.insert("DMQ_NODE_SOCKET_PATH", dmq_node_socket_path.as_str()); } let args = vec!["-vvv"]; diff --git a/mithril-test-lab/mithril-end-to-end/src/stress_test/aggregator_helpers.rs b/mithril-test-lab/mithril-end-to-end/src/stress_test/aggregator_helpers.rs index fb8227f6ec3..7c19cc9d7db 100644 --- a/mithril-test-lab/mithril-end-to-end/src/stress_test/aggregator_helpers.rs +++ b/mithril-test-lab/mithril-end-to-end/src/stress_test/aggregator_helpers.rs @@ -37,6 +37,7 @@ pub async fn bootstrap_aggregator( chain_observer_type, leader_aggregator_endpoint: &None, use_dmq: false, + dmq_node_flavor: &None, }) .unwrap(); diff --git a/mithril-test-lab/mithril-end-to-end/src/stress_test/entities.rs b/mithril-test-lab/mithril-end-to-end/src/stress_test/entities.rs index 5e2592c54b9..15015715403 100644 --- a/mithril-test-lab/mithril-end-to-end/src/stress_test/entities.rs +++ b/mithril-test-lab/mithril-end-to-end/src/stress_test/entities.rs @@ -74,6 +74,7 @@ impl AggregatorParameters { let full_node = FullNode { db_path: db_path.to_path_buf(), socket_path: PathBuf::new(), + dmq_socket_path: PathBuf::new(), }; let tmp_dir = opts .temporary_path