diff --git a/src/lib.rs b/src/lib.rs index 06fd4d6..3e508e2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -48,7 +48,7 @@ pub enum MessageType { }, #[cfg(not(feature = "client-only"))] NodeCmdMessage { - msg: node::NodeCmd, + msg: node::NodeCmdMessage, dest_info: DestInfo, src_section_pk: Option, }, diff --git a/src/node/mod.rs b/src/node/mod.rs index 6c8995c..56c4e96 100644 --- a/src/node/mod.rs +++ b/src/node/mod.rs @@ -9,13 +9,14 @@ mod node_cmd; -pub use self::node_cmd::{ - NodeCmd, NodeCmdError, NodeDataError, NodeDataQueryResponse, NodeEvent, NodeQuery, - NodeQueryResponse, NodeRewardQuery, NodeSystemCmd, NodeSystemQuery, NodeSystemQueryResponse, - NodeTransferCmd, NodeTransferError, NodeTransferQuery, NodeTransferQueryResponse, -}; -use crate::{Error, MessageType, Result, WireMsg}; +use crate::{MessageType, WireMsg}; use bytes::Bytes; +pub use node_cmd::{ + NodeCmd, NodeCmdError, NodeCmdMessage, NodeDataError, NodeDataQueryResponse, NodeEvent, + NodeQuery, NodeQueryResponse, NodeRewardQuery, NodeSystemCmd, NodeSystemQuery, + NodeSystemQueryResponse, NodeTransferCmd, NodeTransferError, NodeTransferQuery, + NodeTransferQueryResponse, +}; use serde::{Deserialize, Serialize}; use std::fmt::{self, Debug, Formatter}; use threshold_crypto::PublicKey as BlsPublicKey; @@ -35,17 +36,19 @@ impl NodeMessage { /// Convenience function to deserialize a 'NodeMessage' from bytes received over the wire. /// It returns an error if the bytes don't correspond to a node message. - pub fn from(bytes: Bytes) -> Result { + pub fn from(bytes: Bytes) -> crate::Result { let deserialized = WireMsg::deserialize(bytes)?; if let MessageType::NodeMessage { msg, .. } = deserialized { Ok(msg) } else { - Err(Error::FailedToParse("bytes as a node message".to_string())) + Err(crate::Error::FailedToParse( + "bytes as a node message".to_string(), + )) } } /// serialize this NodeMessage into bytes ready to be sent over the wire. - pub fn serialize(&self, dest: XorName, dest_section_pk: BlsPublicKey) -> Result { + pub fn serialize(&self, dest: XorName, dest_section_pk: BlsPublicKey) -> crate::Result { WireMsg::serialize_node_msg(self, dest, dest_section_pk) } } diff --git a/src/node/node_cmd.rs b/src/node/node_cmd.rs index 7dedf0b..addd580 100644 --- a/src/node/node_cmd.rs +++ b/src/node/node_cmd.rs @@ -7,21 +7,110 @@ // specific language governing permissions and limitations relating to use of the SAFE Network // Software. +// FIXME: change NodeCmd defnintions to return Result and +// Error defined for the crate::node instead of client Result/Error +use crate::client::{Error, Result}; use crate::{ - client::{ - BlobRead, BlobWrite, DataCmd as NodeDataCmd, DataQuery as NodeDataQuery, Error, Result, - }, - EndUser, + client::{BlobRead, BlobWrite, DataCmd as NodeDataCmd, DataQuery as NodeDataQuery}, + EndUser, MessageId, MessageType, WireMsg, }; +use bytes::Bytes; use serde::{Deserialize, Serialize}; use sn_data_types::{ ActorHistory, Blob, BlobAddress, CreditAgreementProof, NodeAge, PublicKey, ReplicaEvent, SectionElders, Signature, }; use std::collections::BTreeMap; +use threshold_crypto::PublicKey as BlsPublicKey; use xor_name::XorName; -// -------------- Node Cmds -------------- +// -------------- Node Cmd Messages -------------- +// TODO: this messages hierarchy needs to be merged into +// the NodeMessage hierarchy. It's temporarily here till +// all messages defined within sn_routing are migrated to +// this crate and within NodeMessage struct. + +/// +#[allow(clippy::large_enum_variant)] +#[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)] +pub enum NodeCmdMessage { + /// Cmds only sent internally in the network. + NodeCmd { + /// NodeCmd. + cmd: NodeCmd, + /// Message ID. + id: MessageId, + /// Target section's current PublicKey + target_section_pk: Option, + }, + /// An error of a NodeCmd. + NodeCmdError { + /// The error. + error: NodeCmdError, + /// Message ID. + id: MessageId, + /// ID of causing cmd. + correlation_id: MessageId, + /// Target section's current PublicKey + target_section_pk: Option, + }, + /// Events only sent internally in the network. + NodeEvent { + /// Request. + event: NodeEvent, + /// Message ID. + id: MessageId, + /// ID of causing cmd. + correlation_id: MessageId, + /// Target section's current PublicKey + target_section_pk: Option, + }, + /// Queries is a read-only operation. + NodeQuery { + /// Query. + query: NodeQuery, + /// Message ID. + id: MessageId, + /// Target section's current PublicKey + target_section_pk: Option, + }, + /// The response to a query, containing the query result. + NodeQueryResponse { + /// QueryResponse. + response: NodeQueryResponse, + /// Message ID. + id: MessageId, + /// ID of causing query. + correlation_id: MessageId, + /// Target section's current PublicKey + target_section_pk: Option, + }, +} + +impl NodeCmdMessage { + /// Convenience function to deserialize a 'NodeCmdMessage' from bytes received over the wire. + /// It returns an error if the bytes don't correspond to a node command message. + pub fn from(bytes: Bytes) -> crate::Result { + let deserialized = WireMsg::deserialize(bytes)?; + if let MessageType::NodeCmdMessage { msg, .. } = deserialized { + Ok(msg) + } else { + Err(crate::Error::FailedToParse( + "bytes as a node command message".to_string(), + )) + } + } + + /// serialize this NodeCmd message into bytes ready to be sent over the wire. + pub fn serialize( + &self, + dest: XorName, + dest_section_pk: BlsPublicKey, + src_section_pk: Option, + ) -> crate::Result { + WireMsg::serialize_node_cmd_msg(self, dest, dest_section_pk, src_section_pk) + } +} /// #[allow(clippy::large_enum_variant)] diff --git a/src/serialisation/mod.rs b/src/serialisation/mod.rs index 6f24de6..5d8199a 100644 --- a/src/serialisation/mod.rs +++ b/src/serialisation/mod.rs @@ -100,7 +100,7 @@ impl WireMsg { /// Creates a new instance keeping a (serialized) copy of the node 'Message' message provided. #[cfg(not(feature = "client-only"))] pub fn new_node_cmd_msg( - msg: &node::NodeCmd, + msg: &node::NodeCmdMessage, dest: XorName, dest_section_pk: PublicKey, src_section_pk: Option, @@ -201,7 +201,7 @@ impl WireMsg { } #[cfg(not(feature = "client-only"))] MessageKind::NodeCmdMessage => { - let node_cmd: node::NodeCmd = + let node_cmd: node::NodeCmdMessage = rmp_serde::from_slice(&self.payload).map_err(|err| { Error::FailedToParse(format!("NodeCmd message payload as Msgpack: {}", err)) })?; @@ -276,7 +276,7 @@ impl WireMsg { /// node::NodeCmdMessage, returning the serialized WireMsg. #[cfg(not(feature = "client-only"))] pub fn serialize_node_cmd_msg( - msg: &node::NodeCmd, + msg: &node::NodeCmdMessage, dest: XorName, dest_section_pk: PublicKey, src_section_pk: Option, @@ -295,12 +295,13 @@ impl WireMsg { mod tests { use super::*; use anyhow::Result; + use threshold_crypto::SecretKey; use xor_name::XorName; #[test] fn serialisation_ping() -> Result<()> { let dest = XorName::random(); - let dest_section_pk = threshold_crypto::SecretKey::random().public_key(); + let dest_section_pk = SecretKey::random().public_key(); let wire_msg = WireMsg::new_ping_msg(dest, dest_section_pk); let serialized = wire_msg.serialize()?; @@ -326,7 +327,7 @@ mod tests { #[test] fn serialisation_sectioninfo_msg() -> Result<()> { let dest = XorName::random(); - let dest_section_pk = threshold_crypto::SecretKey::random().public_key(); + let dest_section_pk = SecretKey::random().public_key(); let query = section_info::Message::GetSectionQuery(dest_section_pk.into()); let wire_msg = WireMsg::new_sectioninfo_msg(&query, dest, dest_section_pk)?; @@ -357,12 +358,18 @@ mod tests { #[test] #[cfg(not(feature = "client-only"))] fn serialisation_node_cmd_msg() -> Result<()> { + use crate::MessageId; + use node::{NodeCmd, NodeCmdMessage, NodeSystemCmd}; + let dest = XorName::random(); - let src_section_pk = threshold_crypto::SecretKey::random().public_key(); - let dest_section_pk = threshold_crypto::SecretKey::random().public_key(); + let src_section_pk = SecretKey::random().public_key(); + let dest_section_pk = SecretKey::random().public_key(); - let node_cmd = - node::NodeCmd::System(node::NodeSystemCmd::RegisterWallet(dest_section_pk.into())); + let node_cmd = NodeCmdMessage::NodeCmd { + cmd: NodeCmd::System(NodeSystemCmd::RegisterWallet(dest_section_pk.into())), + id: MessageId::new(), + target_section_pk: None, + }; // first test without including a source section public key in the header let wire_msg = WireMsg::new_node_cmd_msg(&node_cmd, dest, dest_section_pk, None)?;