Electroneum
message_store.h
Go to the documentation of this file.
1 // Copyright (c) 2018, The Monero Project
2 //
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without modification, are
6 // permitted provided that the following conditions are met:
7 //
8 // 1. Redistributions of source code must retain the above copyright notice, this list of
9 // conditions and the following disclaimer.
10 //
11 // 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 // of conditions and the following disclaimer in the documentation and/or other
13 // materials provided with the distribution.
14 //
15 // 3. Neither the name of the copyright holder nor the names of its contributors may be
16 // used to endorse or promote products derived from this software without specific
17 // prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
20 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
22 // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
27 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 
29 #pragma once
30 
31 #include <cstdlib>
32 #include <string>
33 #include <vector>
34 #include "crypto/hash.h"
35 #include <boost/serialization/vector.hpp>
36 #include <boost/program_options/variables_map.hpp>
37 #include <boost/program_options/options_description.hpp>
38 #include <boost/optional/optional.hpp>
43 #include "common/i18n.h"
44 #include "common/command_line.h"
45 #include "wipeable_string.h"
46 #include "message_transporter.h"
47 
48 #undef ELECTRONEUM_DEFAULT_LOG_CATEGORY
49 #define ELECTRONEUM_DEFAULT_LOG_CATEGORY "wallet.mms"
50 #define AUTO_CONFIG_TOKEN_BYTES 4
51 #define AUTO_CONFIG_TOKEN_PREFIX "mms"
52 
53 namespace mms
54 {
55  enum class message_type
56  {
57  key_set,
62  note,
65  };
66 
67  enum class message_direction
68  {
69  in,
70  out
71  };
72 
73  enum class message_state
74  {
76  sent,
77 
78  waiting,
79  processed,
80 
81  cancelled
82  };
83 
84  enum class message_processing
85  {
91  sign_tx,
92  send_tx,
93  submit_tx,
96  };
97 
98  struct message
99  {
114  };
115  // "wallet_height" (for lack of a short name that would describe what it is about)
116  // is the number of transfers present in the wallet at the time of message
117  // construction; used to coordinate generation of sync info (which depends
118  // on the content of the wallet at time of generation)
119 
121  {
126  bool me;
133 
135  {
136  etn_address_known = false;
137  memset(&etn_address, 0, sizeof(cryptonote::account_public_address));
138  me = false;
139  index = 0;
142  auto_config_running = false;
143  };
144  };
145 
147  {
149  std::vector<uint32_t> message_ids;
151  };
152 
154  {
156  crypto::chacha_iv iv;
159  };
160 
162  {
166  };
167 
168  // Overal .mms file structure, with the "message_store" object serialized to and
169  // encrypted in "encrypted_data"
170  struct file_data
171  {
174  crypto::chacha_iv iv;
176  };
177 
178  // The following struct provides info about the current state of a "wallet2" object
179  // at the time of a "message_store" method call that those methods need. See on the
180  // one hand a first parameter of this type for several of those methods, and on the
181  // other hand the method "wallet2::get_multisig_wallet_state" which clients like the
182  // CLI wallet can use to get that info.
183  //
184  // Note that in the case of a wallet that is already multisig "address" is NOT the
185  // multisig address, but the "original" wallet address at creation time. Likewise
186  // "view_secret_key" is the original view secret key then.
187  //
188  // This struct definition is here and not in "wallet2.h" to avoid circular imports.
190  {
194  bool multisig;
200  };
201 
203  {
204  public:
205  message_store();
206  // Initialize and start to use the MMS, set the first signer, this wallet itself
207  // Filename, if not null and not empty, is used to create the ".mms" file
208  // reset it if already used, with deletion of all signers and messages
209  void init(const multisig_wallet_state &state, const std::string &own_label,
210  const std::string &own_transport_address, uint32_t num_authorized_signers, uint32_t num_required_signers);
211  void set_active(bool active) { m_active = active; };
212  void set_auto_send(bool auto_send) { m_auto_send = auto_send; };
213  void set_options(const boost::program_options::variables_map& vm);
214  void set_options(const std::string &bitmessage_address, const epee::wipeable_string &bitmessage_login);
215  bool get_active() const { return m_active; };
216  bool get_auto_send() const { return m_auto_send; };
217  uint32_t get_num_required_signers() const { return m_num_required_signers; };
218  uint32_t get_num_authorized_signers() const { return m_num_authorized_signers; };
219 
221  uint32_t index,
222  const boost::optional<std::string> &label,
223  const boost::optional<std::string> &transport_address,
224  const boost::optional<cryptonote::account_public_address> etn_address);
225 
226  const authorized_signer &get_signer(uint32_t index) const;
227  bool get_signer_index_by_etn_address(const cryptonote::account_public_address &etn_address, uint32_t &index) const;
228  bool get_signer_index_by_label(const std::string label, uint32_t &index) const;
229  const std::vector<authorized_signer> &get_all_signers() const { return m_signers; };
230  bool signer_config_complete() const;
231  bool signer_labels_complete() const;
234  std::vector<authorized_signer> &signers);
236 
238  bool check_auto_config_token(const std::string &raw_token,
239  std::string &adjusted_token) const;
241  const std::string &auto_config_token);
243  void stop_auto_config();
244 
245  // Process data just created by "me" i.e. the own local wallet, e.g. as the result of a "prepare_multisig" command
246  // Creates the resulting messages to the right signers
248 
249  // Go through all the messages, look at the "ready to process" ones, and check whether any single one
250  // or any group of them can be processed, because they are processable as single messages (like a tx
251  // that is fully signed and thus ready for submit to the net) or because they form a complete group
252  // (e.g. key sets from all authorized signers to make the wallet multisig). If there are multiple
253  // candidates, e.g. in 2/3 multisig sending to one OR the other signer to sign, there will be more
254  // than 1 element in 'data' for the user to choose. If nothing is ready "false" is returned.
255  // The method mostly ignores the order in which the messages were received because messages may be delayed
256  // (e.g. sync data from a signer arrives AFTER a transaction to submit) or because message time stamps
257  // may be wrong so it's not possible to order them reliably.
258  // Messages also may be ready by themselves but the wallet not yet ready for them (e.g. sync data already
259  // arriving when the wallet is not yet multisig because key sets were delayed or were lost altogether.)
260  // If nothing is ready 'wait_reason' may contain further info about the reason why.
262  bool force_sync,
263  std::vector<processing_data> &data_list,
264  std::string &wait_reason);
265  void set_messages_processed(const processing_data &data);
266 
268  uint32_t signer_index, message_type type, message_direction direction,
269  const std::string &content);
270  const std::vector<message> &get_all_messages() const { return m_messages; };
271  bool get_message_by_id(uint32_t id, message &m) const;
274  void delete_message(uint32_t id);
275  void delete_all_messages();
276  void get_sanitized_message_text(const message &m, std::string &sanitized_text) const;
277 
279  bool check_for_messages(const multisig_wallet_state &state, std::vector<message> &messages);
280  void stop() { m_run.store(false, std::memory_order_relaxed); m_transporter.stop(); }
281 
282  void write_to_file(const multisig_wallet_state &state, const std::string &filename);
283  void read_from_file(const multisig_wallet_state &state, const std::string &filename);
284 
285  template <class t_archive>
286  inline void serialize(t_archive &a, const unsigned int ver)
287  {
288  a & m_active;
289  a & m_num_authorized_signers;
290  a & m_nettype;
291  a & m_num_required_signers;
292  a & m_signers;
293  a & m_messages;
294  a & m_next_message_id;
295  a & m_auto_send;
296  }
297 
298  static const char* message_type_to_string(message_type type);
299  static const char* message_direction_to_string(message_direction direction);
300  static const char* message_state_to_string(message_state state);
301  std::string signer_to_string(const authorized_signer &signer, uint32_t max_width);
302 
303  static const char *tr(const char *str) { return i18n_translate(str, "tools::mms"); }
304  static void init_options(boost::program_options::options_description& desc_params);
305 
306  private:
307  bool m_active;
308  uint32_t m_num_authorized_signers;
309  uint32_t m_num_required_signers;
310  bool m_auto_send;
311  cryptonote::network_type m_nettype;
312  std::vector<authorized_signer> m_signers;
313  std::vector<message> m_messages;
314  uint32_t m_next_message_id;
315  std::string m_filename;
316  message_transporter m_transporter;
317  std::atomic<bool> m_run;
318 
319  bool get_message_index_by_id(uint32_t id, size_t &index) const;
320  size_t get_message_index_by_id(uint32_t id) const;
321  message& get_message_ref_by_id(uint32_t id);
322  bool any_message_of_type(message_type type, message_direction direction) const;
323  bool any_message_with_hash(const crypto::hash &hash) const;
324  size_t get_other_signers_id_count(const std::vector<uint32_t> &ids) const;
325  bool message_ids_complete(const std::vector<uint32_t> &ids) const;
326  void encrypt(crypto::public_key public_key, const std::string &plaintext,
327  std::string &ciphertext, crypto::public_key &encryption_public_key, crypto::chacha_iv &iv);
328  void decrypt(const std::string &ciphertext, const crypto::public_key &encryption_public_key, const crypto::chacha_iv &iv,
329  const crypto::secret_key &view_secret_key, std::string &plaintext);
330  std::string create_auto_config_token();
331  void setup_signer_for_auto_config(uint32_t index, const std::string token, bool receiving);
332  void delete_transport_message(uint32_t id);
333  std::string account_address_to_string(const cryptonote::account_public_address &account_address) const;
334  void save(const multisig_wallet_state &state);
335  };
336 }
337 
339 BOOST_CLASS_VERSION(mms::message_store, 0)
341 BOOST_CLASS_VERSION(mms::file_transport_message, 0)
342 BOOST_CLASS_VERSION(mms::authorized_signer, 1)
343 BOOST_CLASS_VERSION(mms::auto_config_data, 0)
344 
345 namespace boost
346 {
347  namespace serialization
348  {
349  template <class Archive>
350  inline void serialize(Archive &a, mms::file_data &x, const boost::serialization::version_type ver)
351  {
352  a & x.magic_string;
353  a & x.file_version;
354  a & x.iv;
355  a & x.encrypted_data;
356  }
357 
358  template <class Archive>
359  inline void serialize(Archive &a, mms::message &x, const boost::serialization::version_type ver)
360  {
361  a & x.id;
362  a & x.type;
363  a & x.direction;
364  a & x.content;
365  a & x.created;
366  a & x.modified;
367  a & x.sent;
368  a & x.signer_index;
369  a & x.hash;
370  a & x.state;
371  a & x.wallet_height;
372  a & x.round;
373  a & x.signature_count;
374  a & x.transport_id;
375  }
376 
377  template <class Archive>
378  inline void serialize(Archive &a, mms::authorized_signer &x, const boost::serialization::version_type ver)
379  {
380  a & x.label;
381  a & x.transport_address;
382  a & x.etn_address_known;
383  a & x.etn_address;
384  a & x.me;
385  a & x.index;
386  if (ver < 1)
387  {
388  return;
389  }
390  a & x.auto_config_token;
394  a & x.auto_config_running;
395  }
396 
397  template <class Archive>
398  inline void serialize(Archive &a, mms::auto_config_data &x, const boost::serialization::version_type ver)
399  {
400  a & x.label;
401  a & x.transport_address;
402  a & x.etn_address;
403  }
404 
405  template <class Archive>
406  inline void serialize(Archive &a, mms::file_transport_message &x, const boost::serialization::version_type ver)
407  {
408  a & x.sender_address;
409  a & x.iv;
411  a & x.internal_message;
412  }
413 
414  template <class Archive>
415  inline void serialize(Archive &a, crypto::chacha_iv &x, const boost::serialization::version_type ver)
416  {
417  a & x.data;
418  }
419 
420  }
421 }
static void init_options(boost::program_options::options_description &desc_params)
void write_to_file(const multisig_wallet_state &state, const std::string &filename)
std::string magic_string
uint64_t modified
crypto::secret_key auto_config_secret_key
static const char * tr(const char *str)
const std::vector< message > & get_all_messages() const
void serialize(t_archive &a, const unsigned int ver)
std::string auto_config_transport_address
message_type type
message_state
Definition: message_store.h:73
message_direction
Definition: message_store.h:67
message_type
Definition: message_store.h:55
void set_messages_processed(const processing_data &data)
::std::string string
Definition: gtest-port.h:1097
const std::vector< authorized_signer > & get_all_signers() const
static const char * message_direction_to_string(message_direction direction)
bool check_for_messages(const multisig_wallet_state &state, std::vector< message > &messages)
uint32_t receiving_signer_index
uint32_t signer_index
void unpack_signer_config(const multisig_wallet_state &state, const std::string &signer_config, std::vector< authorized_signer > &signers)
crypto::chacha_iv iv
cryptonote::account_public_address sender_address
cryptonote::network_type nettype
bool check_auto_config_token(const std::string &raw_token, std::string &adjusted_token) const
std::string transport_id
const char * i18n_translate(const char *s, const std::string &context)
Definition: i18n.cpp:323
std::string encrypted_data
crypto::public_key encryption_public_key
uint32_t wallet_height
void send_message(const multisig_wallet_state &state, uint32_t id)
const crypto::secret_key null_skey
Definition: crypto.cpp:73
void process_auto_config_data_message(uint32_t id)
Simple DSL AAPI based on.
std::string transport_address
cryptonote::account_public_address etn_address
bool serialize(Archive &ar, T &v)
unsigned int uint32_t
Definition: stdint.h:126
const crypto::public_key null_pkey
Definition: crypto.cpp:72
size_t add_auto_config_data_message(const multisig_wallet_state &state, const std::string &auto_config_token)
void read_from_file(const multisig_wallet_state &state, const std::string &filename)
message_processing processing
std::string auto_config_token
bool signer_labels_complete() const
void delete_message(uint32_t id)
const authorized_signer & get_signer(uint32_t index) const
unsigned __int64 uint64_t
Definition: stdint.h:136
BOOST_CLASS_VERSION(nodetool::node_server< cryptonote::t_cryptonote_protocol_handler< tests::proxy_core > >, 1)
void get_sanitized_message_text(const message &m, std::string &sanitized_text) const
void get_signer_config(std::string &signer_config)
static const char * message_type_to_string(message_type type)
uint32_t get_num_required_signers() const
POD_CLASS public_key
Definition: crypto.h:76
bool get_signer_index_by_etn_address(const cryptonote::account_public_address &etn_address, uint32_t &index) const
void start_auto_config(const multisig_wallet_state &state)
std::string message("Message requiring signing")
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition: pointer.h:1124
bool get_processable_messages(const multisig_wallet_state &state, bool force_sync, std::vector< processing_data > &data_list, std::string &wait_reason)
bool get_signer_index_by_label(const std::string label, uint32_t &index) const
static const char * message_state_to_string(message_state state)
void set_options(const boost::program_options::variables_map &vm)
cryptonote::account_public_address etn_address
void set_signer(const multisig_wallet_state &state, uint32_t index, const boost::optional< std::string > &label, const boost::optional< std::string > &transport_address, const boost::optional< cryptonote::account_public_address > etn_address)
Definition: blake256.h:37
bool get_auto_send() const
crypto::secret_key view_secret_key
void process_signer_config(const multisig_wallet_state &state, const std::string &signer_config)
std::string content
std::string signer_to_string(const authorized_signer &signer, uint32_t max_width)
bool signer_config_complete() const
uint32_t signature_count
bool get_active() const
bool get_message_by_id(uint32_t id, message &m) const
uint32_t get_num_authorized_signers() const
std::vector< uint32_t > message_ids
void set_message_processed_or_sent(uint32_t id)
POD_CLASS hash
Definition: hash.h:50
uint64_t created
crypto::hash hash
message_processing
Definition: message_store.h:84
std::string transport_address
message_state state
void set_active(bool active)
uint32_t round
void set_auto_send(bool auto_send)
message_direction direction
size_t add_message(const multisig_wallet_state &state, uint32_t signer_index, message_type type, message_direction direction, const std::string &content)
void init(const multisig_wallet_state &state, const std::string &own_label, const std::string &own_transport_address, uint32_t num_authorized_signers, uint32_t num_required_signers)
uint32_t file_version
crypto::public_key auto_config_public_key
uint64_t sent
cryptonote::account_public_address address
void process_wallet_created_data(const multisig_wallet_state &state, message_type type, const std::string &content)