ant_protocol/messages/
query.rs

1// Copyright 2024 MaidSafe.net limited.
2//
3// This SAFE Network Software is licensed to you under The General Public License (GPL), version 3.
4// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
5// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
6// KIND, either express or implied. Please review the Licences for the specific language governing
7// permissions and limitations relating to use of the SAFE Network Software.
8
9use crate::{NetworkAddress, messages::Nonce};
10use libp2p::kad::U256;
11use serde::{Deserialize, Serialize};
12
13/// Data queries - retrieving data and inspecting their structure.
14///
15/// See the [`protocol`] module documentation for more details of the types supported by the Safe
16/// Network, and their semantics.
17///
18/// [`protocol`]: crate
19#[derive(Eq, PartialEq, PartialOrd, Clone, Serialize, Deserialize, custom_debug::Debug)]
20pub enum Query {
21    /// Retrieve the quote to store a record at the given address.
22    /// The storage verification is optional to be undertaken
23    GetStoreQuote {
24        /// The Address of the record to be stored.
25        key: NetworkAddress,
26        /// DataTypes as represented as its `index`
27        data_type: u32,
28        /// Data size of the record
29        data_size: usize,
30        /// The random nonce that nodes use to produce the Proof (i.e., hash(record+nonce))
31        /// Set to None if no need to carry out storage check.
32        nonce: Option<Nonce>,
33        /// Defines the expected number of answers to the challenge.
34        /// Node shall try their best to fulfill the number, based on their capacity.
35        /// Set to 0 to indicate not carry out any verification.
36        difficulty: usize,
37    },
38    /// Retrieve a specific record from a specific peer.
39    ///
40    /// This should eventually lead to a [`GetReplicatedRecord`] response.
41    ///
42    /// [`GetReplicatedRecord`]: super::QueryResponse::GetReplicatedRecord
43    GetReplicatedRecord {
44        /// Sender of the query
45        requester: NetworkAddress,
46        /// Key of the record to be fetched
47        key: NetworkAddress,
48    },
49    /// Get the proof that the chunk with the given NetworkAddress exists with the requested node.
50    GetChunkExistenceProof {
51        /// The Address of the chunk that we are trying to verify.
52        key: NetworkAddress,
53        /// The random nonce that the node uses to produce the Proof (i.e., hash(record+nonce))
54        nonce: Nonce,
55        /// Defines the expected number of answers to the challenge.
56        /// For client publish verification, use 1 for efficiency.
57        /// Node shall try their best to fulfill the number, based on their capacity.
58        difficulty: usize,
59    },
60    /// Queries close_group peers whether the target peer is a bad_node
61    CheckNodeInProblem(NetworkAddress),
62    /// Query the peers in range to the target address, from the receiver's perspective.
63    /// In case none of the parameters provided, returns nothing.
64    /// In case both of the parameters provided, `range` is preferred to be replied.
65    GetClosestPeers {
66        key: NetworkAddress,
67        // Shall be greater than K_VALUE, otherwise can use libp2p function directly
68        num_of_peers: Option<usize>,
69        // Defines the range that replied peers shall be within
70        range: Option<[u8; 32]>,
71        // For future econ usage,
72        sign_result: bool,
73    },
74    /// *** From now on, the order of variants shall be retained to be backward compatible
75    /// Query peer's cargo package version.
76    GetVersion(NetworkAddress),
77    /// Write operation to upload a record.
78    PutRecord {
79        /// Holder of the record.
80        holder: NetworkAddress,
81        /// serialized record.
82        #[debug(skip)]
83        serialized_record: Vec<u8>,
84        /// Address of the record.
85        address: NetworkAddress,
86    },
87}
88
89impl Query {
90    /// Used to send a query to the close group of the address.
91    pub fn dst(&self) -> NetworkAddress {
92        match self {
93            Query::CheckNodeInProblem(address) | Query::GetVersion(address) => address.clone(),
94            // Shall not be called for this, as this is a `one-to-one` message,
95            // and the destination shall be decided by the requester already.
96            Query::GetStoreQuote { key, .. }
97            | Query::GetReplicatedRecord { key, .. }
98            | Query::GetChunkExistenceProof { key, .. }
99            | Query::GetClosestPeers { key, .. } => key.clone(),
100            Query::PutRecord { holder, .. } => holder.clone(),
101        }
102    }
103}
104
105impl std::fmt::Display for Query {
106    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
107        match self {
108            Query::GetStoreQuote {
109                key,
110                data_type,
111                data_size,
112                nonce,
113                difficulty,
114            } => {
115                write!(
116                    f,
117                    "Query::GetStoreQuote({key:?} {data_type} {data_size} {nonce:?} {difficulty})"
118                )
119            }
120            Query::GetReplicatedRecord { key, requester } => {
121                write!(f, "Query::GetReplicatedRecord({requester:?} {key:?})")
122            }
123            Query::GetChunkExistenceProof {
124                key,
125                nonce,
126                difficulty,
127            } => {
128                write!(
129                    f,
130                    "Query::GetChunkExistenceProof({key:?} {nonce:?} {difficulty})"
131                )
132            }
133            Query::CheckNodeInProblem(address) => {
134                write!(f, "Query::CheckNodeInProblem({address:?})")
135            }
136            Query::GetClosestPeers {
137                key,
138                num_of_peers,
139                range,
140                sign_result,
141            } => {
142                let distance = range.as_ref().map(|value| U256::from_big_endian(value));
143                write!(
144                    f,
145                    "Query::GetClosestPeers({key:?} {num_of_peers:?} {distance:?} {sign_result})"
146                )
147            }
148            Query::GetVersion(address) => {
149                write!(f, "Query::GetVersion({address:?})")
150            }
151            Query::PutRecord {
152                holder,
153                address,
154                serialized_record,
155            } => {
156                write!(
157                    f,
158                    "Cmd::PutRecord(To {:?}, with record {address:?} has {} data_size)",
159                    holder.as_peer_id(),
160                    serialized_record.len()
161                )
162            }
163        }
164    }
165}