1mod account;
11mod auth;
12mod blob;
13mod cmd;
14mod data;
15mod duty;
16mod map;
17mod network;
18mod query;
19mod sequence;
20mod transfer;
21
22pub use self::{
23 account::{Account, AccountRead, AccountWrite, MAX_LOGIN_PACKET_BYTES},
24 auth::{AuthCmd, AuthQuery},
25 blob::{BlobRead, BlobWrite},
26 cmd::Cmd,
27 data::{DataCmd, DataQuery},
28 duty::{AdultDuties, Duty, ElderDuties, NodeDuties},
29 map::{MapRead, MapWrite},
30 network::{
31 NodeCmd, NodeCmdError, NodeDataCmd, NodeDataError, NodeDataQuery, NodeDataQueryResponse,
32 NodeEvent, NodeQuery, NodeQueryResponse, NodeRewardError, NodeRewardQuery,
33 NodeRewardQueryResponse, NodeSystemCmd, NodeTransferCmd, NodeTransferError,
34 NodeTransferQuery, NodeTransferQueryResponse,
35 },
36 query::Query,
37 sequence::{SequenceRead, SequenceWrite},
38 transfer::{TransferCmd, TransferQuery},
39};
40use crate::{
41 errors::ErrorDebug, utils, AppPermissions, Blob, BlsProof, DebitAgreementProof, Error, Map,
42 MapEntries, MapPermissionSet, MapValue, MapValues, Money, Proof, PublicKey, ReplicaEvent,
43 ReplicaPublicKeySet, Result, Sequence, SequenceEntries, SequenceEntry, SequencePermissions,
44 Signature, TransferValidated,
45};
46use serde::{Deserialize, Serialize};
47use std::{
48 collections::{BTreeMap, BTreeSet},
49 convert::TryFrom,
50 fmt,
51};
52use xor_name::XorName;
53#[allow(clippy::large_enum_variant)]
55#[derive(Debug, Hash, Eq, PartialEq, Clone, Serialize, Deserialize)]
56pub struct MsgEnvelope {
57 pub message: Message,
59 pub origin: MsgSender,
61 pub proxies: Vec<MsgSender>, }
65
66impl MsgEnvelope {
67 pub fn id(&self) -> MessageId {
69 self.message.id()
70 }
71
72 pub fn verify(&self) -> bool {
77 let data = if self.proxies.is_empty() {
78 utils::serialise(&self.message)
79 } else {
80 let mut msg = self.clone();
81 let _ = msg.proxies.pop();
82 utils::serialise(&msg)
83 };
84 let signer = self.most_recent_sender();
85 signer.id().verify(&signer.signature(), data).is_ok()
86 }
87
88 pub fn add_proxy(&mut self, proxy: MsgSender) {
92 self.proxies.push(proxy);
93 }
94
95 pub fn most_recent_sender(&self) -> &MsgSender {
97 match self.proxies.last() {
98 None => &self.origin,
99 Some(proxy) => proxy,
100 }
101 }
102
103 pub fn destination(&self) -> Address {
105 use Address::*;
106 use Message::*;
107 match &self.message {
108 Cmd { cmd, .. } => self.cmd_dst(cmd),
109 Query { query, .. } => Section(query.dst_address()),
110 Event { event, .. } => Client(event.dst_address()), QueryResponse { query_origin, .. } => query_origin.clone(),
112 CmdError { cmd_origin, .. } => cmd_origin.clone(),
113 NodeCmd { cmd, .. } => cmd.dst_address(),
114 NodeEvent { event, .. } => event.dst_address(),
115 NodeQuery { query, .. } => query.dst_address(),
116 NodeCmdError { cmd_origin, .. } => cmd_origin.clone(),
117 NodeQueryResponse { query_origin, .. } => query_origin.clone(),
118 }
119 }
120
121 fn cmd_dst(&self, cmd: &Cmd) -> Address {
122 use Address::*;
123 use Cmd::*;
124 match cmd {
125 Auth(_) => Section(self.origin.id().into()),
127 Transfer(c) => Section(c.dst_address()),
129 Data { cmd, payment } => {
132 match self.most_recent_sender() {
133 MsgSender::Client { .. } => Section(self.origin.id().into()),
135 MsgSender::Node {
137 duty: Duty::Elder(ElderDuties::Gateway),
138 ..
139 } => Section(payment.from().into()),
140 MsgSender::Node {
142 duty: Duty::Elder(ElderDuties::Payment),
143 ..
144 } => Section(cmd.dst_address()),
145 MsgSender::Section {
149 duty: Duty::Elder(ElderDuties::Payment),
150 ..
151 } => Section(cmd.dst_address()),
152 _ => {
153 Section(self.origin.id().into())
157 }
158 }
159 }
160 }
161 }
162}
163
164#[derive(Debug, Hash, Eq, PartialEq, Clone, Serialize, Deserialize)]
166pub enum MsgSender {
167 Client(Proof),
169 Node {
171 duty: Duty,
173 proof: Proof,
175 },
176 Section {
178 duty: Duty,
180 proof: BlsProof,
182 },
183}
184
185impl MsgSender {
186 pub fn id(&self) -> PublicKey {
188 use MsgSender::*;
189 match self {
190 Client(proof) | Node { proof, .. } => proof.id(),
191 Section { proof, .. } => proof.id(),
192 }
193 }
194
195 pub fn address(&self) -> Address {
197 use MsgSender::*;
198 match self {
199 Client(_) => Address::Client(self.id().into()),
200 Node { .. } => Address::Node(self.id().into()),
201 Section { .. } => Address::Section(self.id().into()),
202 }
203 }
204
205 pub fn signature(&self) -> Signature {
207 use MsgSender::*;
208 match self {
209 Client(proof) => proof.signature(),
210 Node { proof, .. } => proof.signature(),
211 Section { proof, .. } => proof.signature(),
212 }
213 }
214}
215
216#[derive(Debug, Hash, Eq, PartialEq, Clone, Serialize, Deserialize)]
218pub enum Address {
219 Client(XorName),
221 Node(XorName),
223 Section(XorName),
225}
226
227impl Address {
228 pub fn xorname(&self) -> XorName {
230 use Address::*;
231 match self {
232 Client(xorname) | Node(xorname) | Section(xorname) => *xorname,
233 }
234 }
235}
236
237#[allow(clippy::large_enum_variant)]
239#[derive(Debug, Hash, Eq, PartialEq, Clone, Serialize, Deserialize)]
240pub enum Message {
241 Cmd {
245 cmd: Cmd,
247 id: MessageId,
249 },
250 Query {
252 query: Query,
254 id: MessageId,
256 },
257 Event {
259 event: Event,
261 id: MessageId,
263 correlation_id: MessageId,
265 },
266 QueryResponse {
268 response: QueryResponse,
270 id: MessageId,
272 correlation_id: MessageId,
274 query_origin: Address,
276 },
277 CmdError {
279 error: CmdError,
281 id: MessageId,
283 correlation_id: MessageId,
285 cmd_origin: Address,
287 },
288 NodeCmd {
290 cmd: NodeCmd,
292 id: MessageId,
294 },
295 NodeCmdError {
297 error: NodeCmdError,
299 id: MessageId,
301 correlation_id: MessageId,
303 cmd_origin: Address,
305 },
306 NodeEvent {
308 event: NodeEvent,
310 id: MessageId,
312 correlation_id: MessageId,
314 },
315 NodeQuery {
317 query: NodeQuery,
319 id: MessageId,
321 },
322 NodeQueryResponse {
324 response: NodeQueryResponse,
326 id: MessageId,
328 correlation_id: MessageId,
330 query_origin: Address,
332 },
333}
334
335impl Message {
336 pub fn id(&self) -> MessageId {
338 match self {
339 Self::Cmd { id, .. }
340 | Self::Query { id, .. }
341 | Self::Event { id, .. }
342 | Self::QueryResponse { id, .. }
343 | Self::CmdError { id, .. }
344 | Self::NodeCmd { id, .. }
345 | Self::NodeEvent { id, .. }
346 | Self::NodeQuery { id, .. }
347 | Self::NodeCmdError { id, .. }
348 | Self::NodeQueryResponse { id, .. } => *id,
349 }
350 }
351}
352
353#[derive(Ord, PartialOrd, Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Hash)]
359pub struct MessageId(pub XorName);
360
361impl MessageId {
362 pub fn new() -> Self {
364 Self(XorName::random())
365 }
366}
367
368impl Default for MessageId {
369 fn default() -> Self {
370 Self::new()
371 }
372}
373
374#[derive(Debug, Hash, Eq, PartialEq, Clone, Serialize, Deserialize)]
376pub enum CmdError {
377 Auth(Error), Data(Error), Transfer(TransferError),
383}
384
385#[derive(Debug, Hash, Eq, PartialEq, Clone, Serialize, Deserialize)]
387pub enum TransferError {
388 TransferValidation(Error),
390 TransferRegistration(Error),
392}
393
394#[allow(clippy::large_enum_variant, clippy::type_complexity)]
397#[derive(Debug, Hash, Eq, PartialEq, Clone, Serialize, Deserialize)]
398pub enum Event {
399 TransferValidated {
401 client: XorName,
404 event: TransferValidated,
407 },
408 TransferDebitAgreementReached {
414 client: XorName,
417 proof: DebitAgreementProof,
419 },
420}
421
422impl Event {
423 pub fn dst_address(&self) -> XorName {
425 use Event::*;
426 match self {
427 TransferValidated { client, .. } => *client,
428 TransferDebitAgreementReached { client, .. } => *client,
429 }
430 }
431}
432
433#[allow(clippy::large_enum_variant, clippy::type_complexity)]
435#[derive(Hash, Eq, PartialEq, Clone, Serialize, Deserialize)]
436pub enum QueryResponse {
437 GetBlob(Result<Blob>),
442 GetMap(Result<Map>),
447 GetMapShell(Result<Map>),
449 GetMapVersion(Result<u64>),
451 ListMapEntries(Result<MapEntries>),
453 ListMapKeys(Result<BTreeSet<Vec<u8>>>),
455 ListMapValues(Result<MapValues>),
457 ListMapUserPermissions(Result<MapPermissionSet>),
459 ListMapPermissions(Result<BTreeMap<PublicKey, MapPermissionSet>>),
461 GetMapValue(Result<MapValue>),
463 GetSequence(Result<Sequence>),
468 GetSequenceOwner(Result<PublicKey>),
470 GetSequenceRange(Result<SequenceEntries>),
472 GetSequenceLastEntry(Result<(u64, SequenceEntry)>),
474 GetSequencePermissions(Result<SequencePermissions>),
476 GetReplicaKeys(Result<ReplicaPublicKeySet>),
481 GetBalance(Result<Money>),
483 GetHistory(Result<Vec<ReplicaEvent>>),
485 GetAccount(Result<(Vec<u8>, Signature)>),
490 ListAuthKeysAndVersion(Result<(BTreeMap<PublicKey, AppPermissions>, u64)>),
495}
496
497pub enum AuthorisationKind {
499 Data(DataAuthKind),
501 Money(MoneyAuthKind),
503 Misc(MiscAuthKind),
506 None,
508}
509
510pub enum DataAuthKind {
512 PublicRead,
514 PrivateRead,
516 Write,
518}
519
520pub enum MoneyAuthKind {
522 ReadBalance,
524 ReadHistory,
526 Transfer,
528}
529
530pub enum MiscAuthKind {
533 ManageAppKeys,
535 WriteAndTransfer,
537}
538
539#[derive(Debug, PartialEq)]
542pub enum TryFromError {
543 WrongType,
545 Response(Error),
547}
548
549macro_rules! try_from {
550 ($ok_type:ty, $($variant:ident),*) => {
551 impl TryFrom<QueryResponse> for $ok_type {
552 type Error = TryFromError;
553 fn try_from(response: QueryResponse) -> std::result::Result<Self, Self::Error> {
554 match response {
555 $(
556 QueryResponse::$variant(Ok(data)) => Ok(data),
557 QueryResponse::$variant(Err(error)) => Err(TryFromError::Response(error)),
558 )*
559 _ => Err(TryFromError::WrongType),
560 }
561 }
562 }
563 };
564}
565
566try_from!(Blob, GetBlob);
567try_from!(Map, GetMap, GetMapShell);
568try_from!(u64, GetMapVersion);
569try_from!(MapEntries, ListMapEntries);
570try_from!(BTreeSet<Vec<u8>>, ListMapKeys);
571try_from!(MapValues, ListMapValues);
572try_from!(MapPermissionSet, ListMapUserPermissions);
573try_from!(BTreeMap<PublicKey, MapPermissionSet>, ListMapPermissions);
574try_from!(MapValue, GetMapValue);
575try_from!(Sequence, GetSequence);
576try_from!(PublicKey, GetSequenceOwner);
577try_from!(SequenceEntries, GetSequenceRange);
578try_from!((u64, SequenceEntry), GetSequenceLastEntry);
579try_from!(SequencePermissions, GetSequencePermissions);
580try_from!(Money, GetBalance);
581try_from!(ReplicaPublicKeySet, GetReplicaKeys);
582try_from!(Vec<ReplicaEvent>, GetHistory);
583try_from!(
584 (BTreeMap<PublicKey, AppPermissions>, u64),
585 ListAuthKeysAndVersion
586);
587try_from!((Vec<u8>, Signature), GetAccount);
588
589impl fmt::Debug for QueryResponse {
590 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
591 use QueryResponse::*;
592
593 match self {
594 GetBlob(res) => write!(f, "QueryResponse::GetBlob({:?})", ErrorDebug(res)),
596 GetMap(res) => write!(f, "QueryResponse::GetMap({:?})", ErrorDebug(res)),
598 GetMapShell(res) => write!(f, "QueryResponse::GetMapShell({:?})", ErrorDebug(res)),
599 GetMapVersion(res) => write!(f, "QueryResponse::GetMapVersion({:?})", ErrorDebug(res)),
600 ListMapEntries(res) => {
601 write!(f, "QueryResponse::ListMapEntries({:?})", ErrorDebug(res))
602 }
603 ListMapKeys(res) => write!(f, "QueryResponse::ListMapKeys({:?})", ErrorDebug(res)),
604 ListMapValues(res) => write!(f, "QueryResponse::ListMapValues({:?})", ErrorDebug(res)),
605 ListMapPermissions(res) => write!(
606 f,
607 "QueryResponse::ListMapPermissions({:?})",
608 ErrorDebug(res)
609 ),
610 ListMapUserPermissions(res) => write!(
611 f,
612 "QueryResponse::ListMapUserPermissions({:?})",
613 ErrorDebug(res)
614 ),
615 GetMapValue(res) => write!(f, "QueryResponse::GetMapValue({:?})", ErrorDebug(res)),
616 GetSequence(res) => write!(f, "QueryResponse::GetSequence({:?})", ErrorDebug(res)),
618 GetSequenceRange(res) => {
619 write!(f, "QueryResponse::GetSequenceRange({:?})", ErrorDebug(res))
620 }
621 GetSequenceLastEntry(res) => write!(
622 f,
623 "QueryResponse::GetSequenceLastEntry({:?})",
624 ErrorDebug(res)
625 ),
626 GetSequencePermissions(res) => write!(
627 f,
628 "QueryResponse::GetSequencePermissions({:?})",
629 ErrorDebug(res)
630 ),
631 GetSequenceOwner(res) => {
632 write!(f, "QueryResponse::GetSequenceOwner({:?})", ErrorDebug(res))
633 }
634 GetReplicaKeys(res) => {
636 write!(f, "QueryResponse::GetReplicaKeys({:?})", ErrorDebug(res))
637 }
638 GetBalance(res) => write!(f, "QueryResponse::GetBalance({:?})", ErrorDebug(res)),
639 GetHistory(res) => write!(f, "QueryResponse::GetHistory({:?})", ErrorDebug(res)),
640 GetAccount(res) => write!(f, "QueryResponse::GetAccount({:?})", ErrorDebug(res)),
642 ListAuthKeysAndVersion(res) => write!(
644 f,
645 "QueryResponse::ListAuthKeysAndVersion({:?})",
646 ErrorDebug(res)
647 ),
648 }
649 }
650}
651
652#[cfg(test)]
653mod tests {
654 use super::*;
655 use crate::{PublicBlob, UnseqMap};
656 use std::convert::{TryFrom, TryInto};
657 use unwrap::{unwrap, unwrap_err};
658
659 #[test]
660 fn debug_format() {
661 use crate::Error;
662 let errored_response = QueryResponse::GetSequence(Err(Error::AccessDenied));
663 assert_eq!(
664 format!("{:?}", errored_response),
665 "QueryResponse::GetSequence(AccessDenied)"
666 );
667 }
668
669 #[test]
670 fn try_from() {
671 use QueryResponse::*;
672
673 let i_data = Blob::Public(PublicBlob::new(vec![1, 3, 1, 4]));
674 let e = Error::AccessDenied;
675 assert_eq!(i_data, unwrap!(GetBlob(Ok(i_data.clone())).try_into()));
676 assert_eq!(
677 TryFromError::Response(e.clone()),
678 unwrap_err!(Blob::try_from(GetBlob(Err(e.clone()))))
679 );
680
681 let mut data = BTreeMap::new();
682 let _ = data.insert(vec![1], vec![10]);
683 let owners = PublicKey::Bls(threshold_crypto::SecretKey::random().public_key());
684 let m_data = Map::Unseq(UnseqMap::new_with_data(
685 *i_data.name(),
686 1,
687 data,
688 BTreeMap::new(),
689 owners,
690 ));
691 assert_eq!(m_data, unwrap!(GetMap(Ok(m_data.clone())).try_into()));
692 assert_eq!(
693 TryFromError::Response(e.clone()),
694 unwrap_err!(Map::try_from(GetMap(Err(e))))
695 );
696 }
697}