Electroneum
p2p_protocol_defs.h
Go to the documentation of this file.
1 // Copyrights(c) 2017-2021, The Electroneum Project
2 // Copyrights(c) 2014-2019, The Monero Project
3 //
4 // All rights reserved.
5 //
6 // Redistribution and use in source and binary forms, with or without modification, are
7 // permitted provided that the following conditions are met:
8 //
9 // 1. Redistributions of source code must retain the above copyright notice, this list of
10 // conditions and the following disclaimer.
11 //
12 // 2. Redistributions in binary form must reproduce the above copyright notice, this list
13 // of conditions and the following disclaimer in the documentation and/or other
14 // materials provided with the distribution.
15 //
16 // 3. Neither the name of the copyright holder nor the names of its contributors may be
17 // used to endorse or promote products derived from this software without specific
18 // prior written permission.
19 //
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
21 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
23 // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
28 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
31 
32 #pragma once
33 
34 #include <boost/uuid/uuid.hpp>
35 #include <boost/serialization/version.hpp>
37 #include "net/net_utils_base.h"
38 #include "net/tor_address.h" // needed for serialization
39 #include "net/i2p_address.h" // needed for serialization
40 #include "misc_language.h"
41 #include "string_tools.h"
42 #include "time_helper.h"
43 #include "cryptonote_config.h"
44 #ifdef ALLOW_DEBUG_COMMANDS
45 #include "crypto/crypto.h"
46 #endif
47 
48 namespace nodetool
49 {
50  typedef boost::uuids::uuid uuid;
52 
53  static inline std::string peerid_to_string(peerid_type peer_id)
54  {
55  std::ostringstream s;
56  s << std::hex << peer_id;
57  return epee::string_tools::pad_string(s.str(), 16, '0', true);
58  }
59 
60 #pragma pack (push, 1)
61 
63  {
66 
71  };
72 
73  template<typename AddressType>
75  {
76  AddressType adr;
81 
83  KV_SERIALIZE(adr)
84  KV_SERIALIZE(id)
85  if (!is_store || this_ref.last_seen != 0)
86  KV_SERIALIZE_OPT(last_seen, (int64_t)0)
87  KV_SERIALIZE_OPT(pruning_seed, (uint32_t)0)
88  KV_SERIALIZE_OPT(rpc_port, (uint16_t)0)
90  };
91  typedef peerlist_entry_base<epee::net_utils::network_address> peerlist_entry;
92 
93  template<typename AddressType>
95  {
96  AddressType adr;
99 
101  KV_SERIALIZE(adr)
102  KV_SERIALIZE(id)
103  KV_SERIALIZE(first_seen)
105  };
106  typedef anchor_peerlist_entry_base<epee::net_utils::network_address> anchor_peerlist_entry;
107 
108  template<typename AddressType>
110  {
111  AddressType adr;
113  bool is_income;
114 
116  KV_SERIALIZE(adr)
117  KV_SERIALIZE(id)
118  KV_SERIALIZE(is_income)
120  };
121  typedef connection_entry_base<epee::net_utils::network_address> connection_entry;
122 
123 #pragma pack(pop)
124 
125  inline
126  std::string print_peerlist_to_string(const std::vector<peerlist_entry>& pl)
127  {
128  time_t now_time = 0;
129  time(&now_time);
130  std::stringstream ss;
131  ss << std::setfill ('0') << std::setw (8) << std::hex << std::noshowbase;
132  for(const peerlist_entry& pe: pl)
133  {
134  ss << pe.id << "\t" << pe.adr.str()
135  << " \trpc port " << (pe.rpc_port > 0 ? std::to_string(pe.rpc_port) : "-")
136  << " \tpruning seed " << pe.pruning_seed
137  << " \tlast_seen: " << (pe.last_seen == 0 ? std::string("never") : epee::misc_utils::get_time_interval_string(now_time - pe.last_seen))
138  << std::endl;
139  }
140  return ss.str();
141  }
142 
143 
145  {
147  KV_SERIALIZE(max_out_connection_count)
148  KV_SERIALIZE(max_in_connection_count)
149  KV_SERIALIZE(handshake_interval)
150  KV_SERIALIZE(packet_max_size)
151  KV_SERIALIZE(config_id)
153 
154  uint32_t max_out_connection_count;
155  uint32_t max_in_connection_count;
156  uint32_t connection_timeout;
157  uint32_t ping_connection_timeout;
158  uint32_t handshake_interval;
159  uint32_t packet_max_size;
160  uint32_t config_id;
161  uint32_t send_peerlist_sz;
162  };
163 
165  {
171 
173  KV_SERIALIZE_VAL_POD_AS_BLOB(network_id)
174  KV_SERIALIZE(peer_id)
175  KV_SERIALIZE(local_time)
176  KV_SERIALIZE(my_port)
177  KV_SERIALIZE_OPT(rpc_port, (uint16_t)(0))
179  };
180 
181 
182 #define P2P_COMMANDS_POOL_BASE 1000
183 
184  /************************************************************************/
185  /* */
186  /************************************************************************/
187  template<class t_playload_type>
189  {
190  const static int ID = P2P_COMMANDS_POOL_BASE + 1;
191 
192  struct request_t
193  {
195  t_playload_type payload_data;
196 
198  KV_SERIALIZE(node_data)
199  KV_SERIALIZE(payload_data)
201  };
202  typedef epee::misc_utils::struct_init<request_t> request;
203 
204  struct response_t
205  {
207  t_playload_type payload_data;
208  std::vector<peerlist_entry> local_peerlist_new;
209 
211  KV_SERIALIZE(node_data)
212  KV_SERIALIZE(payload_data)
213  if (is_store)
214  {
215  // saving: save both, so old and new peers can understand it
216  KV_SERIALIZE(local_peerlist_new)
217  std::vector<peerlist_entry_base<network_address_old>> local_peerlist;
218  for (const auto &p: this_ref.local_peerlist_new)
219  {
220  if (p.adr.get_type_id() == epee::net_utils::ipv4_network_address::get_type_id())
221  {
222  const epee::net_utils::network_address &na = p.adr;
224  local_peerlist.push_back(peerlist_entry_base<network_address_old>({{ipv4.ip(), ipv4.port()}, p.id, p.last_seen, p.pruning_seed, p.rpc_port}));
225  }
226  else
227  MDEBUG("Not including in legacy peer list: " << p.adr.str());
228  }
229  epee::serialization::selector<is_store>::serialize_stl_container_pod_val_as_blob(local_peerlist, stg, hparent_section, "local_peerlist");
230  }
231  else
232  {
233  // loading: load old list only if there is no new one
234  if (!epee::serialization::selector<is_store>::serialize(this_ref.local_peerlist_new, stg, hparent_section, "local_peerlist_new"))
235  {
236  std::vector<peerlist_entry_base<network_address_old>> local_peerlist;
237  epee::serialization::selector<is_store>::serialize_stl_container_pod_val_as_blob(local_peerlist, stg, hparent_section, "local_peerlist");
238  for (const auto &p: local_peerlist)
239  ((response&)this_ref).local_peerlist_new.push_back(peerlist_entry({epee::net_utils::ipv4_network_address(p.adr.ip, p.adr.port), p.id, p.last_seen, p.pruning_seed, p.rpc_port}));
240  }
241  }
243  };
245  };
246 
247 
248  /************************************************************************/
249  /* */
250  /************************************************************************/
251  template<class t_playload_type>
253  {
254  const static int ID = P2P_COMMANDS_POOL_BASE + 2;
255 
256  struct request_t
257  {
258  t_playload_type payload_data;
260  KV_SERIALIZE(payload_data)
262  };
263  typedef epee::misc_utils::struct_init<request_t> request;
264 
265  struct response_t
266  {
268  t_playload_type payload_data;
269  std::vector<peerlist_entry> local_peerlist_new;
270 
272  KV_SERIALIZE(local_time)
273  KV_SERIALIZE(payload_data)
274  if (is_store)
275  {
276  // saving: save both, so old and new peers can understand it
277  KV_SERIALIZE(local_peerlist_new)
278  std::vector<peerlist_entry_base<network_address_old>> local_peerlist;
279  for (const auto &p: this_ref.local_peerlist_new)
280  {
281  if (p.adr.get_type_id() == epee::net_utils::ipv4_network_address::get_type_id())
282  {
283  const epee::net_utils::network_address &na = p.adr;
285  local_peerlist.push_back(peerlist_entry_base<network_address_old>({{ipv4.ip(), ipv4.port()}, p.id, p.last_seen}));
286  }
287  else
288  MDEBUG("Not including in legacy peer list: " << p.adr.str());
289  }
290  epee::serialization::selector<is_store>::serialize_stl_container_pod_val_as_blob(local_peerlist, stg, hparent_section, "local_peerlist");
291  }
292  else
293  {
294  // loading: load old list only if there is no new one
295  if (!epee::serialization::selector<is_store>::serialize(this_ref.local_peerlist_new, stg, hparent_section, "local_peerlist_new"))
296  {
297  std::vector<peerlist_entry_base<network_address_old>> local_peerlist;
298  epee::serialization::selector<is_store>::serialize_stl_container_pod_val_as_blob(local_peerlist, stg, hparent_section, "local_peerlist");
299  for (const auto &p: local_peerlist)
300  ((response&)this_ref).local_peerlist_new.push_back(peerlist_entry({epee::net_utils::ipv4_network_address(p.adr.ip, p.adr.port), p.id, p.last_seen}));
301  }
302  }
304  };
306  };
307 
308  /************************************************************************/
309  /* */
310  /************************************************************************/
311 
313  {
314  /*
315  Used to make "callback" connection, to be sure that opponent node
316  have accessible connection point. Only other nodes can add peer to peerlist,
317  and ONLY in case when peer has accepted connection and answered to ping.
318  */
319  const static int ID = P2P_COMMANDS_POOL_BASE + 3;
320 
321 #define PING_OK_RESPONSE_STATUS_TEXT "OK"
322 
323  struct request_t
324  {
325  /*actually we don't need to send any real data*/
326 
329  };
331 
332  struct response_t
333  {
336 
338  KV_SERIALIZE(status)
339  KV_SERIALIZE(peer_id)
341  };
342  typedef epee::misc_utils::struct_init<response_t> response;
343  };
344 
345 
346 #ifdef ALLOW_DEBUG_COMMANDS
347  //These commands are considered as insecure, and made in debug purposes for a limited lifetime.
348  //Anyone who feel unsafe with this commands can disable the ALLOW_GET_STAT_COMMAND macro.
349 
350  struct proof_of_trust
351  {
352  peerid_type peer_id;
353  uint64_t time;
354  crypto::signature sign;
355 
357  KV_SERIALIZE(peer_id)
361  };
362 
363 
364  template<class payload_stat_info>
365  struct COMMAND_REQUEST_STAT_INFO_T
366  {
367  const static int ID = P2P_COMMANDS_POOL_BASE + 4;
368 
369  struct request_t
370  {
371  proof_of_trust tr;
375  };
376  typedef epee::misc_utils::struct_init<request_t> request;
377 
378  struct response_t
379  {
381  std::string os_version;
382  uint64_t connections_count;
383  uint64_t incoming_connections_count;
384  payload_stat_info payload_info;
385 
388  KV_SERIALIZE(os_version)
389  KV_SERIALIZE(connections_count)
390  KV_SERIALIZE(incoming_connections_count)
391  KV_SERIALIZE(payload_info)
393  };
394  typedef epee::misc_utils::struct_init<response_t> response;
395  };
396 
397 
398  /************************************************************************/
399  /* */
400  /************************************************************************/
401  struct COMMAND_REQUEST_NETWORK_STATE
402  {
403  const static int ID = P2P_COMMANDS_POOL_BASE + 5;
404 
405  struct request_t
406  {
407  proof_of_trust tr;
411  };
412  typedef epee::misc_utils::struct_init<request_t> request;
413 
414  struct response_t
415  {
416  std::vector<peerlist_entry> local_peerlist_white;
417  std::vector<peerlist_entry> local_peerlist_gray;
418  std::vector<connection_entry> connections_list;
419  peerid_type my_id;
420  uint64_t local_time;
422  KV_SERIALIZE_CONTAINER_POD_AS_BLOB(local_peerlist_white)
423  KV_SERIALIZE_CONTAINER_POD_AS_BLOB(local_peerlist_gray)
424  KV_SERIALIZE_CONTAINER_POD_AS_BLOB(connections_list)
425  KV_SERIALIZE(my_id)
426  KV_SERIALIZE(local_time)
428  };
429  typedef epee::misc_utils::struct_init<response_t> response;
430  };
431 
432  /************************************************************************/
433  /* */
434  /************************************************************************/
435  struct COMMAND_REQUEST_PEER_ID
436  {
437  const static int ID = P2P_COMMANDS_POOL_BASE + 6;
438 
439  struct request_t
440  {
443  };
444  typedef epee::misc_utils::struct_init<request_t> request;
445 
446  struct response_t
447  {
448  peerid_type my_id;
449 
451  KV_SERIALIZE(my_id)
453  };
454  typedef epee::misc_utils::struct_init<response_t> response;
455  };
456 
457  /************************************************************************/
458  /* */
459  /************************************************************************/
460  struct COMMAND_REQUEST_SUPPORT_FLAGS
461  {
462  const static int ID = P2P_COMMANDS_POOL_BASE + 7;
463 
464  struct request_t
465  {
468  };
469  typedef epee::misc_utils::struct_init<request_t> request;
470 
471  struct response_t
472  {
473  uint32_t support_flags;
474 
476  KV_SERIALIZE(support_flags)
478  };
479  typedef epee::misc_utils::struct_init<response_t> response;
480  };
481 
482 #endif
483 
484 
485  inline crypto::hash get_proof_of_trust_hash(const nodetool::proof_of_trust& pot)
486  {
487  std::string s;
488  s.append(reinterpret_cast<const char*>(&pot.peer_id), sizeof(pot.peer_id));
489  s.append(reinterpret_cast<const char*>(&pot.time), sizeof(pot.time));
490  return crypto::cn_fast_hash(s.data(), s.size());
491  }
492 
493 }
#define tr(x)
Definition: common_defines.h:4
int64_t last_seen
crypto::hash get_proof_of_trust_hash(const nodetool::proof_of_trust &pot)
uint16_t rpc_port
boost::uuids::uuid uuid
AddressType adr
AddressType adr
::std::string string
Definition: gtest-port.h:1097
epee::misc_utils::struct_init< response_t > response
#define P2P_COMMANDS_POOL_BASE
peerlist_entry_base< epee::net_utils::network_address > peerlist_entry
peerid_type id
AddressType adr
uint32_t pruning_seed
unsigned short uint16_t
Definition: stdint.h:125
epee::misc_utils::struct_init< response_t > response
epee::misc_utils::struct_init< request_t > request
#define KV_SERIALIZE(varialble)
int64_t first_seen
std::string pad_string(std::string s, size_t n, char c=' ', bool prepend=false)
Definition: string_tools.h:304
#define MDEBUG(x)
Definition: misc_log_ex.h:76
peerid_type id
time_t time
Definition: blockchain.cpp:93
unsigned int uint32_t
Definition: stdint.h:126
peerid_type id
std::vector< peerlist_entry > local_peerlist_new
bool is_income
static constexpr address_type get_type_id() noexcept
unsigned __int64 uint64_t
Definition: stdint.h:136
#define KV_SERIALIZE_CONTAINER_POD_AS_BLOB(varialble)
std::string get_time_interval_string(const time_t &time_)
Definition: time_helper.h:120
epee::misc_utils::struct_init< response_t > response
uint64_t peerid_type
#define KV_SERIALIZE_VAL_POD_AS_BLOB(varialble)
version
Supported socks variants.
Definition: socks.h:57
void cn_fast_hash(const void *data, size_t length, char *hash)
POD_CLASS signature
Definition: crypto.h:108
std::vector< peerlist_entry > local_peerlist_new
signed __int64 int64_t
Definition: stdint.h:135
std::string print_peerlist_to_string(const std::vector< peerlist_entry > &pl)
POD_CLASS hash
Definition: hash.h:50
std::string to_string(t_connection_type type)
else if(0==res)
#define END_KV_SERIALIZE_MAP()
#define KV_SERIALIZE_OPT(variable, default_value)
#define BEGIN_KV_SERIALIZE_MAP()