mod blob;
mod cmd;
mod data;
mod data_exchange;
mod duty;
mod errors;
mod map;
mod network;
mod query;
mod register;
mod sender;
mod sequence;
mod transfer;
pub use self::{
blob::{BlobRead, BlobWrite},
cmd::Cmd,
data::{DataCmd, DataQuery},
data_exchange::{
BlobDataExchange, ChunkMetadata, DataExchange, HolderMetadata, MapDataExchange,
SequenceDataExchange,
},
duty::{AdultDuties, Duty, ElderDuties, NodeDuties},
errors::{Error, ErrorDebug, Result},
map::{MapRead, MapWrite},
network::{
NodeCmd, NodeCmdError, NodeDataError, NodeEvent, NodeQuery, NodeQueryResponse,
NodeRewardQuery, NodeSystemCmd, NodeSystemQuery, NodeSystemQueryResponse, NodeTransferCmd,
NodeTransferError, NodeTransferQuery, NodeTransferQueryResponse,
},
query::Query,
register::{RegisterRead, RegisterWrite},
sender::{Address, MsgSender, TransientElderKey, TransientSectionKey},
sequence::{SequenceRead, SequenceWrite},
transfer::{TransferCmd, TransferQuery},
};
use crate::{MessageId, MessageType, WireMsg};
use bytes::Bytes;
use serde::{Deserialize, Serialize};
use sn_data_types::{
register::{Entry, EntryHash, Permissions, Policy, Register},
ActorHistory, Blob, Map, MapEntries, MapPermissionSet, MapValue, MapValues, PublicKey,
Sequence, SequenceEntries, SequenceEntry, SequencePermissions, SequencePrivatePolicy,
SequencePublicPolicy, Token, TransferAgreementProof, TransferValidated,
};
use std::{
collections::{BTreeMap, BTreeSet},
convert::TryFrom,
fmt,
};
impl Message {
pub fn from(bytes: Bytes) -> crate::Result<Self> {
let deserialized = WireMsg::deserialize(bytes)?;
if let MessageType::ClientMessage(msg) = deserialized {
Ok(msg)
} else {
Err(crate::Error::FailedToParse(
"bytes as a client message".to_string(),
))
}
}
pub fn serialize(&self) -> crate::Result<Bytes> {
WireMsg::serialize_client_msg(self)
}
}
#[allow(clippy::large_enum_variant)]
#[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)]
pub enum Message {
Cmd {
cmd: Cmd,
id: MessageId,
},
Query {
query: Query,
id: MessageId,
},
Event {
event: Event,
id: MessageId,
correlation_id: MessageId,
},
QueryResponse {
response: QueryResponse,
id: MessageId,
correlation_id: MessageId,
},
CmdError {
error: CmdError,
id: MessageId,
correlation_id: MessageId,
},
NodeCmd {
cmd: NodeCmd,
id: MessageId,
},
NodeCmdError {
error: NodeCmdError,
id: MessageId,
correlation_id: MessageId,
},
NodeEvent {
event: NodeEvent,
id: MessageId,
correlation_id: MessageId,
},
NodeQuery {
query: NodeQuery,
id: MessageId,
},
NodeQueryResponse {
response: NodeQueryResponse,
id: MessageId,
correlation_id: MessageId,
},
}
impl Message {
pub fn id(&self) -> MessageId {
match self {
Self::Cmd { id, .. }
| Self::Query { id, .. }
| Self::Event { id, .. }
| Self::QueryResponse { id, .. }
| Self::CmdError { id, .. }
| Self::NodeCmd { id, .. }
| Self::NodeEvent { id, .. }
| Self::NodeQuery { id, .. }
| Self::NodeCmdError { id, .. }
| Self::NodeQueryResponse { id, .. } => *id,
}
}
}
#[derive(Debug, Hash, Eq, PartialEq, Clone, Serialize, Deserialize)]
pub enum CmdError {
Data(Error),
Transfer(TransferError),
}
#[derive(Debug, Hash, Eq, PartialEq, Clone, Serialize, Deserialize)]
pub enum TransferError {
TransferValidation(Error),
TransferRegistration(Error),
}
#[allow(clippy::large_enum_variant, clippy::type_complexity)]
#[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)]
pub enum Event {
TransferValidated {
event: TransferValidated,
},
TransferAgreementReached {
proof: TransferAgreementProof,
},
}
#[allow(clippy::large_enum_variant, clippy::type_complexity)]
#[derive(Eq, PartialEq, Clone, Serialize, Deserialize)]
pub enum QueryResponse {
GetBlob(Result<Blob>),
GetMap(Result<Map>),
GetMapShell(Result<Map>),
GetMapVersion(Result<u64>),
ListMapEntries(Result<MapEntries>),
ListMapKeys(Result<BTreeSet<Vec<u8>>>),
ListMapValues(Result<MapValues>),
ListMapUserPermissions(Result<MapPermissionSet>),
ListMapPermissions(Result<BTreeMap<PublicKey, MapPermissionSet>>),
GetMapValue(Result<MapValue>),
GetSequence(Result<Sequence>),
GetSequenceRange(Result<SequenceEntries>),
GetSequenceLastEntry(Result<(u64, SequenceEntry)>),
GetSequencePublicPolicy(Result<SequencePublicPolicy>),
GetSequencePrivatePolicy(Result<SequencePrivatePolicy>),
GetSequenceUserPermissions(Result<SequencePermissions>),
GetRegister(Result<Register>),
GetRegisterOwner(Result<PublicKey>),
ReadRegister(Result<BTreeSet<(EntryHash, Entry)>>),
GetRegisterPolicy(Result<Policy>),
GetRegisterUserPermissions(Result<Permissions>),
GetBalance(Result<Token>),
GetHistory(Result<ActorHistory>),
GetStoreCost(Result<Token>),
}
#[derive(Debug, PartialEq)]
#[allow(clippy::large_enum_variant)]
pub enum TryFromError {
WrongType,
Response(Error),
}
macro_rules! try_from {
($ok_type:ty, $($variant:ident),*) => {
impl TryFrom<QueryResponse> for $ok_type {
type Error = TryFromError;
fn try_from(response: QueryResponse) -> std::result::Result<Self, Self::Error> {
match response {
$(
QueryResponse::$variant(Ok(data)) => Ok(data),
QueryResponse::$variant(Err(error)) => Err(TryFromError::Response(error)),
)*
_ => Err(TryFromError::WrongType),
}
}
}
};
}
try_from!(Blob, GetBlob);
try_from!(Map, GetMap, GetMapShell);
try_from!(u64, GetMapVersion);
try_from!(MapEntries, ListMapEntries);
try_from!(BTreeSet<Vec<u8>>, ListMapKeys);
try_from!(MapValues, ListMapValues);
try_from!(MapPermissionSet, ListMapUserPermissions);
try_from!(BTreeMap<PublicKey, MapPermissionSet>, ListMapPermissions);
try_from!(MapValue, GetMapValue);
try_from!(Sequence, GetSequence);
try_from!(SequenceEntries, GetSequenceRange);
try_from!((u64, SequenceEntry), GetSequenceLastEntry);
try_from!(SequencePublicPolicy, GetSequencePublicPolicy);
try_from!(SequencePrivatePolicy, GetSequencePrivatePolicy);
try_from!(SequencePermissions, GetSequenceUserPermissions);
try_from!(Register, GetRegister);
try_from!(PublicKey, GetRegisterOwner);
try_from!(BTreeSet<(EntryHash, Entry)>, ReadRegister);
try_from!(Policy, GetRegisterPolicy);
try_from!(Permissions, GetRegisterUserPermissions);
try_from!(Token, GetBalance);
try_from!(ActorHistory, GetHistory);
impl fmt::Debug for QueryResponse {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use QueryResponse::*;
match self {
GetBlob(res) => write!(f, "QueryResponse::GetBlob({:?})", ErrorDebug(res)),
GetMap(res) => write!(f, "QueryResponse::GetMap({:?})", ErrorDebug(res)),
GetMapShell(res) => write!(f, "QueryResponse::GetMapShell({:?})", ErrorDebug(res)),
GetMapVersion(res) => write!(f, "QueryResponse::GetMapVersion({:?})", ErrorDebug(res)),
ListMapEntries(res) => {
write!(f, "QueryResponse::ListMapEntries({:?})", ErrorDebug(res))
}
ListMapKeys(res) => write!(f, "QueryResponse::ListMapKeys({:?})", ErrorDebug(res)),
ListMapValues(res) => write!(f, "QueryResponse::ListMapValues({:?})", ErrorDebug(res)),
ListMapPermissions(res) => write!(
f,
"QueryResponse::ListMapPermissions({:?})",
ErrorDebug(res)
),
ListMapUserPermissions(res) => write!(
f,
"QueryResponse::ListMapUserPermissions({:?})",
ErrorDebug(res)
),
GetMapValue(res) => write!(f, "QueryResponse::GetMapValue({:?})", ErrorDebug(res)),
GetSequence(res) => write!(f, "QueryResponse::GetSequence({:?})", ErrorDebug(res)),
GetSequenceRange(res) => {
write!(f, "QueryResponse::GetSequenceRange({:?})", ErrorDebug(res))
}
GetSequenceLastEntry(res) => write!(
f,
"QueryResponse::GetSequenceLastEntry({:?})",
ErrorDebug(res)
),
GetSequenceUserPermissions(res) => write!(
f,
"QueryResponse::GetSequenceUserPermissions({:?})",
ErrorDebug(res)
),
GetSequencePublicPolicy(res) => write!(
f,
"QueryResponse::GetSequencePublicPolicy({:?})",
ErrorDebug(res)
),
GetSequencePrivatePolicy(res) => write!(
f,
"QueryResponse::GetSequencePrivatePolicy({:?})",
ErrorDebug(res)
),
GetRegister(res) => write!(f, "QueryResponse::GetRegister({:?})", ErrorDebug(res)),
ReadRegister(res) => {
write!(f, "QueryResponse::ReadRegister({:?})", ErrorDebug(res))
}
GetRegisterUserPermissions(res) => write!(
f,
"QueryResponse::GetRegisterUserPermissions({:?})",
ErrorDebug(res)
),
GetRegisterPolicy(res) => {
write!(f, "QueryResponse::GetRegisterPolicy({:?})", ErrorDebug(res))
}
GetRegisterOwner(res) => {
write!(f, "QueryResponse::GetRegisterOwner({:?})", ErrorDebug(res))
}
GetBalance(res) => write!(f, "QueryResponse::GetBalance({:?})", ErrorDebug(res)),
GetHistory(res) => write!(f, "QueryResponse::GetHistory({:?})", ErrorDebug(res)),
GetStoreCost(res) => write!(f, "QueryResponse::GetStoreCost({:?})", ErrorDebug(res)),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use anyhow::{anyhow, Result};
use sn_data_types::{Keypair, PublicBlob, UnseqMap};
use std::convert::{TryFrom, TryInto};
fn gen_keypairs() -> Vec<Keypair> {
let mut rng = rand::thread_rng();
let bls_secret_key = threshold_crypto::SecretKeySet::random(1, &mut rng);
vec![
Keypair::new_ed25519(&mut rng),
Keypair::new_bls_share(
0,
bls_secret_key.secret_key_share(0),
bls_secret_key.public_keys(),
),
]
}
pub fn gen_keys() -> Vec<PublicKey> {
gen_keypairs().iter().map(PublicKey::from).collect()
}
#[test]
fn debug_format() -> Result<()> {
if let Some(key) = gen_keys().first() {
let errored_response = QueryResponse::GetSequence(Err(Error::AccessDenied(*key)));
assert!(format!("{:?}", errored_response)
.contains("QueryResponse::GetSequence(AccessDenied(PublicKey::"));
Ok(())
} else {
Err(anyhow!("Could not generate public key"))
}
}
#[test]
fn try_from() -> Result<()> {
use QueryResponse::*;
let key = match gen_keys().first() {
Some(key) => *key,
None => return Err(anyhow!("Could not generate public key")),
};
let i_data = Blob::Public(PublicBlob::new(vec![1, 3, 1, 4]));
let e = Error::AccessDenied(key);
assert_eq!(
i_data,
GetBlob(Ok(i_data.clone()))
.try_into()
.map_err(|_| anyhow!("Mismatched types".to_string()))?
);
assert_eq!(
Err(TryFromError::Response(e.clone())),
Blob::try_from(GetBlob(Err(e.clone())))
);
let mut data = BTreeMap::new();
let _ = data.insert(vec![1], vec![10]);
let owners = PublicKey::Bls(threshold_crypto::SecretKey::random().public_key());
let m_data = Map::Unseq(UnseqMap::new_with_data(
*i_data.name(),
1,
data,
BTreeMap::new(),
owners,
));
assert_eq!(
m_data,
GetMap(Ok(m_data.clone()))
.try_into()
.map_err(|_| anyhow!("Mismatched types".to_string()))?
);
assert_eq!(
Err(TryFromError::Response(e.clone())),
Map::try_from(GetMap(Err(e)))
);
Ok(())
}
#[test]
fn serialization() -> Result<()> {
let keypair = &gen_keypairs()[0];
let pk = keypair.public_key();
let random_xor = xor_name::XorName::random();
let id = MessageId(random_xor);
let message = Message::Query {
query: Query::Transfer(TransferQuery::GetBalance(pk)),
id,
};
let serialized = message.serialize()?;
let deserialized = Message::from(serialized)?;
assert_eq!(deserialized, message);
Ok(())
}
}