Electroneum
Loading...
Searching...
No Matches
mms::message_store Class Reference

#include <message_store.h>

Public Member Functions

 message_store ()
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)
void set_active (bool active)
void set_auto_send (bool auto_send)
void set_options (const boost::program_options::variables_map &vm)
void set_options (const std::string &bitmessage_address, const epee::wipeable_string &bitmessage_login)
bool get_active () const
bool get_auto_send () const
uint32_t get_num_required_signers () const
uint32_t get_num_authorized_signers () const
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)
const authorized_signerget_signer (uint32_t index) const
bool get_signer_index_by_etn_address (const cryptonote::account_public_address &etn_address, uint32_t &index) const
bool get_signer_index_by_label (const std::string label, uint32_t &index) const
const std::vector< authorized_signer > & get_all_signers () const
bool signer_config_complete () const
bool signer_labels_complete () const
void get_signer_config (std::string &signer_config)
void unpack_signer_config (const multisig_wallet_state &state, const std::string &signer_config, std::vector< authorized_signer > &signers)
void process_signer_config (const multisig_wallet_state &state, const std::string &signer_config)
void start_auto_config (const multisig_wallet_state &state)
bool check_auto_config_token (const std::string &raw_token, std::string &adjusted_token) const
size_t add_auto_config_data_message (const multisig_wallet_state &state, const std::string &auto_config_token)
void process_auto_config_data_message (uint32_t id)
void stop_auto_config ()
void process_wallet_created_data (const multisig_wallet_state &state, message_type type, const std::string &content)
bool get_processable_messages (const multisig_wallet_state &state, bool force_sync, std::vector< processing_data > &data_list, std::string &wait_reason)
void set_messages_processed (const processing_data &data)
size_t add_message (const multisig_wallet_state &state, uint32_t signer_index, message_type type, message_direction direction, const std::string &content)
const std::vector< message > & get_all_messages () const
bool get_message_by_id (uint32_t id, message &m) const
message get_message_by_id (uint32_t id) const
void set_message_processed_or_sent (uint32_t id)
void delete_message (uint32_t id)
void delete_all_messages ()
void get_sanitized_message_text (const message &m, std::string &sanitized_text) const
void send_message (const multisig_wallet_state &state, uint32_t id)
bool check_for_messages (const multisig_wallet_state &state, std::vector< message > &messages)
void stop ()
void write_to_file (const multisig_wallet_state &state, const std::string &filename)
void read_from_file (const multisig_wallet_state &state, const std::string &filename)
template<class t_archive>
void serialize (t_archive &a, const unsigned int ver)
std::string signer_to_string (const authorized_signer &signer, uint32_t max_width)

Static Public Member Functions

static const char * message_type_to_string (message_type type)
static const char * message_direction_to_string (message_direction direction)
static const char * message_state_to_string (message_state state)
static const char * tr (const char *str)
static void init_options (boost::program_options::options_description &desc_params)

Detailed Description

Definition at line 202 of file message_store.h.

Constructor & Destructor Documentation

◆ message_store()

mms::message_store::message_store ( )

Definition at line 51 of file message_store.cpp.

52{
53 m_active = false;
54 m_auto_send = false;
55 m_next_message_id = 1;
56 m_num_authorized_signers = 0;
57 m_num_required_signers = 0;
59 m_run = true;
60}

Member Function Documentation

◆ add_auto_config_data_message()

size_t mms::message_store::add_auto_config_data_message ( const multisig_wallet_state & state,
const std::string & auto_config_token )

Definition at line 345 of file message_store.cpp.

347{
348 authorized_signer &me = m_signers[0];
349 me.auto_config_token = auto_config_token;
350 setup_signer_for_auto_config(0, auto_config_token, false);
351 me.auto_config_running = true;
352
353 auto_config_data data;
354 data.label = me.label;
355 data.transport_address = me.transport_address;
356 data.etn_address = me.etn_address;
357
358 std::stringstream oss;
359 boost::archive::portable_binary_oarchive ar(oss);
360 ar << data;
361
363}
size_t add_message(const multisig_wallet_state &state, uint32_t signer_index, message_type type, message_direction direction, const std::string &content)
Here is the call graph for this function:

◆ add_message()

size_t mms::message_store::add_message ( const multisig_wallet_state & state,
uint32_t signer_index,
message_type type,
message_direction direction,
const std::string & content )

Definition at line 514 of file message_store.cpp.

517{
518 message m;
519 m.id = m_next_message_id++;
520 m.type = type;
521 m.direction = direction;
522 m.content = content;
523 m.created = (uint64_t)time(NULL);
524 m.modified = m.created;
525 m.sent = 0;
526 m.signer_index = signer_index;
527 if (direction == message_direction::out)
528 {
530 }
531 else
532 {
533 m.state = message_state::waiting;
534 };
535 m.wallet_height = (uint32_t)state.num_transfer_details;
537 {
538 m.round = state.multisig_rounds_passed;
539 }
540 else
541 {
542 m.round = 0;
543 }
544 m.signature_count = 0; // Future expansion for signature counting when signing txs
545 m.hash = crypto::null_hash;
546 m_messages.push_back(m);
547
548 // Save for every new message right away (at least while in beta)
549 save(state);
550
551 MINFO(boost::format("Added %s message %s for signer %s of type %s")
552 % message_direction_to_string(direction) % m.id % signer_index % message_type_to_string(type));
553 return m_messages.size() - 1;
554}
time_t time
static const char * message_direction_to_string(message_direction direction)
static const char * message_type_to_string(message_type type)
std::string message("Message requiring signing")
#define MINFO(x)
Definition misc_log_ex.h:75
unsigned int uint32_t
Definition stdint.h:126
unsigned __int64 uint64_t
Definition stdint.h:136
Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_auto_config_token()

bool mms::message_store::check_auto_config_token ( const std::string & raw_token,
std::string & adjusted_token ) const

Definition at line 276 of file message_store.cpp.

278{
279 std::string prefix(AUTO_CONFIG_TOKEN_PREFIX);
280 uint32_t num_hex_digits = (AUTO_CONFIG_TOKEN_BYTES + 1) * 2;
281 uint32_t full_length = num_hex_digits + prefix.length();
282 uint32_t raw_length = raw_token.length();
283 std::string hex_digits;
284
285 if (raw_length == full_length)
286 {
287 // Prefix must be there; accept it in any casing
288 std::string raw_prefix(raw_token.substr(0, 3));
289 boost::algorithm::to_lower(raw_prefix);
290 if (raw_prefix != prefix)
291 {
292 return false;
293 }
294 hex_digits = raw_token.substr(3);
295 }
296 else if (raw_length == num_hex_digits)
297 {
298 // Accept the token without the prefix if it's otherwise ok
299 hex_digits = raw_token;
300 }
301 else
302 {
303 return false;
304 }
305
306 // Convert to strict lowercase and correct any common misspellings
307 boost::algorithm::to_lower(hex_digits);
308 std::replace(hex_digits.begin(), hex_digits.end(), 'o', '0');
309 std::replace(hex_digits.begin(), hex_digits.end(), 'i', '1');
310 std::replace(hex_digits.begin(), hex_digits.end(), 'l', '1');
311
312 // Now it must be correct hex with correct checksum, no further tolerance possible
313 std::string token_bytes;
314 if (!epee::string_tools::parse_hexstr_to_binbuff(hex_digits, token_bytes))
315 {
316 return false;
317 }
318 const crypto::hash &hash = crypto::cn_fast_hash(token_bytes.data(), token_bytes.size() - 1);
319 if (token_bytes[AUTO_CONFIG_TOKEN_BYTES] != hash.data[0])
320 {
321 return false;
322 }
323 adjusted_token = prefix + hex_digits;
324 return true;
325}
#define AUTO_CONFIG_TOKEN_BYTES
#define AUTO_CONFIG_TOKEN_PREFIX
void cn_fast_hash(const void *data, size_t length, char *hash)
POD_CLASS hash
Definition hash.h:50
bool parse_hexstr_to_binbuff(const epee::span< const char > s, epee::span< char > &res)
Here is the call graph for this function:

◆ check_for_messages()

bool mms::message_store::check_for_messages ( const multisig_wallet_state & state,
std::vector< message > & messages )

Definition at line 1244 of file message_store.cpp.

1245{
1246 m_run.store(true, std::memory_order_relaxed);
1247 const authorized_signer &me = m_signers[0];
1248 std::vector<std::string> destinations;
1249 destinations.push_back(me.transport_address);
1250 for (uint32_t i = 1; i < m_num_authorized_signers; ++i)
1251 {
1252 const authorized_signer &m = m_signers[i];
1253 if (m.auto_config_running)
1254 {
1255 destinations.push_back(m.auto_config_transport_address);
1256 }
1257 }
1258 std::vector<transport_message> transport_messages;
1259 bool r = m_transporter.receive_messages(destinations, transport_messages);
1260 if (!m_run.load(std::memory_order_relaxed))
1261 {
1262 // Stop was called, don't waste time processing the messages
1263 // (but once started processing them, don't react to stop request anymore, avoid receiving them "partially)"
1264 return false;
1265 }
1266
1267 bool new_messages = false;
1268 for (size_t i = 0; i < transport_messages.size(); ++i)
1269 {
1270 transport_message &rm = transport_messages[i];
1271 if (any_message_with_hash(rm.hash))
1272 {
1273 // Already seen, do not take again
1274 }
1275 else
1276 {
1277 uint32_t sender_index;
1278 bool take = false;
1279 message_type type = static_cast<message_type>(rm.type);
1280 crypto::secret_key decrypt_key = state.view_secret_key;
1282 {
1283 // Find out which signer sent it by checking which auto config transport address
1284 // the message was sent to
1285 for (uint32_t i = 1; i < m_num_authorized_signers; ++i)
1286 {
1287 const authorized_signer &m = m_signers[i];
1288 if (m.auto_config_transport_address == rm.destination_transport_address)
1289 {
1290 take = true;
1291 sender_index = i;
1292 decrypt_key = m.auto_config_secret_key;
1293 break;
1294 }
1295 }
1296 }
1297 else if (type == message_type::signer_config)
1298 {
1299 // Typically we can't check yet whether we know the sender, so take from any
1300 // and pretend it's from "me" because we might have nothing else yet
1301 take = true;
1302 sender_index = 0;
1303 }
1304 else
1305 {
1306 // Only accept from senders that are known as signer here, otherwise just ignore
1307 take = get_signer_index_by_etn_address(rm.source_etn_address, sender_index);
1308 }
1309 if (take && (type != message_type::auto_config_data))
1310 {
1311 // If the destination address is known, check it as well; this additional filter
1312 // allows using the same transport address for multiple signers
1313 take = rm.destination_etn_address == me.etn_address;
1314 }
1315 if (take)
1316 {
1317 crypto::hash actual_hash = crypto::cn_fast_hash(rm.content.data(), rm.content.size());
1318 THROW_WALLET_EXCEPTION_IF(actual_hash != rm.hash, tools::error::wallet_internal_error, "Message hash mismatch");
1319
1320 bool signature_valid = crypto::check_signature(actual_hash, rm.source_etn_address.m_view_public_key, rm.signature);
1321 THROW_WALLET_EXCEPTION_IF(!signature_valid, tools::error::wallet_internal_error, "Message signature not valid");
1322
1323 std::string plaintext;
1324 decrypt(rm.content, rm.encryption_public_key, rm.iv, decrypt_key, plaintext);
1325 size_t index = add_message(state, sender_index, (message_type)rm.type, message_direction::in, plaintext);
1326 message &m = m_messages[index];
1327 m.hash = rm.hash;
1328 m.transport_id = rm.transport_id;
1329 m.sent = rm.timestamp;
1330 m.round = rm.round;
1331 m.signature_count = rm.signature_count;
1332 messages.push_back(m);
1333 new_messages = true;
1334 }
1335 }
1336 }
1337 return new_messages;
1338}
bool get_signer_index_by_etn_address(const cryptonote::account_public_address &etn_address, uint32_t &index) const
epee::mlocked< tools::scrubbed< ec_scalar > > secret_key
Definition crypto.h:82
bool check_signature(const hash &prefix_hash, const public_key &pub, const signature &sig)
Definition crypto.h:295
crypto::secret_key decrypt_key(crypto::secret_key key, const epee::wipeable_string &passphrase)
epee::misc_utils::struct_init< transport_message_t > transport_message
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
Here is the call graph for this function:

◆ delete_all_messages()

void mms::message_store::delete_all_messages ( )

Definition at line 663 of file message_store.cpp.

664{
665 for (size_t i = 0; i < m_messages.size(); ++i)
666 {
667 delete_transport_message(m_messages[i].id);
668 }
669 m_messages.clear();
670}

◆ delete_message()

void mms::message_store::delete_message ( uint32_t id)

Definition at line 656 of file message_store.cpp.

657{
658 delete_transport_message(id);
659 size_t index = get_message_index_by_id(id);
660 m_messages.erase(m_messages.begin() + index);
661}

◆ get_active()

bool mms::message_store::get_active ( ) const
inline

Definition at line 215 of file message_store.h.

215{ return m_active; };

◆ get_all_messages()

const std::vector< message > & mms::message_store::get_all_messages ( ) const
inline

Definition at line 270 of file message_store.h.

270{ return m_messages; };

◆ get_all_signers()

const std::vector< authorized_signer > & mms::message_store::get_all_signers ( ) const
inline

Definition at line 229 of file message_store.h.

229{ return m_signers; };

◆ get_auto_send()

bool mms::message_store::get_auto_send ( ) const
inline

Definition at line 216 of file message_store.h.

216{ return m_auto_send; };

◆ get_message_by_id() [1/2]

message mms::message_store::get_message_by_id ( uint32_t id) const

Definition at line 600 of file message_store.cpp.

601{
602 message m;
603 bool found = get_message_by_id(id, m);
604 THROW_WALLET_EXCEPTION_IF(!found, tools::error::wallet_internal_error, "Invalid message id " + std::to_string(id));
605 return m;
606}
bool get_message_by_id(uint32_t id, message &m) const
Here is the call graph for this function:

◆ get_message_by_id() [2/2]

bool mms::message_store::get_message_by_id ( uint32_t id,
message & m ) const

Definition at line 588 of file message_store.cpp.

589{
590 size_t index;
591 bool found = get_message_index_by_id(id, index);
592 if (found)
593 {
594 m = m_messages[index];
595 }
596 return found;
597}
Here is the caller graph for this function:

◆ get_num_authorized_signers()

uint32_t mms::message_store::get_num_authorized_signers ( ) const
inline

Definition at line 218 of file message_store.h.

218{ return m_num_authorized_signers; };

◆ get_num_required_signers()

uint32_t mms::message_store::get_num_required_signers ( ) const
inline

Definition at line 217 of file message_store.h.

217{ return m_num_required_signers; };

◆ get_processable_messages()

bool mms::message_store::get_processable_messages ( const multisig_wallet_state & state,
bool force_sync,
std::vector< processing_data > & data_list,
std::string & wait_reason )

Definition at line 790 of file message_store.cpp.

792{
793 uint32_t wallet_height = (uint32_t)state.num_transfer_details;
794 data_list.clear();
795 wait_reason.clear();
796 // In all scans over all messages looking for complete sets (1 message for each signer),
797 // if there are duplicates, the OLDEST of them is taken. This may not play a role with
798 // any of the current message types, but may with future ones, and it's probably a good
799 // idea to have a clear and somewhat defensive strategy.
800
801 std::vector<uint32_t> auto_config_messages(m_num_authorized_signers, 0);
802 bool any_auto_config = false;
803
804 for (size_t i = 0; i < m_messages.size(); ++i)
805 {
806 message &m = m_messages[i];
807 if ((m.type == message_type::auto_config_data) && (m.state == message_state::waiting))
808 {
809 if (auto_config_messages[m.signer_index] == 0)
810 {
811 auto_config_messages[m.signer_index] = m.id;
812 any_auto_config = true;
813 }
814 // else duplicate auto config data, ignore
815 }
816 }
817
818 if (any_auto_config)
819 {
820 bool auto_config_complete = message_ids_complete(auto_config_messages);
821 if (auto_config_complete)
822 {
823 processing_data data;
825 data.message_ids = auto_config_messages;
826 data.message_ids.erase(data.message_ids.begin());
827 data_list.push_back(data);
828 return true;
829 }
830 else
831 {
832 wait_reason = tr("Auto-config cannot proceed because auto config data from other signers is not complete");
833 return false;
834 // With ANY auto config data present but not complete refuse to check for any
835 // other processing. Manually delete those messages to abort such an auto config
836 // phase if needed.
837 }
838 }
839
840 // Any signer config that arrived will be processed right away, regardless of other things that may wait
841 for (size_t i = 0; i < m_messages.size(); ++i)
842 {
843 message &m = m_messages[i];
844 if ((m.type == message_type::signer_config) && (m.state == message_state::waiting))
845 {
846 processing_data data;
848 data.message_ids.push_back(m.id);
849 data_list.push_back(data);
850 return true;
851 }
852 }
853
854 // ALL of the following processings depend on the signer info being complete
856 {
857 wait_reason = tr("The signer config is not complete.");
858 return false;
859 }
860
861 if (!state.multisig)
862 {
863
864 if (!any_message_of_type(message_type::key_set, message_direction::out))
865 {
866 // With the own key set not yet ready we must do "prepare_multisig" first;
867 // Key sets from other signers may be here already, but if we process them now
868 // the wallet will go multisig too early: we can't produce our own key set any more!
869 processing_data data;
870 data.processing = message_processing::prepare_multisig;
871 data_list.push_back(data);
872 return true;
873 }
874
875 // Ids of key set messages per signer index, to check completeness
876 // Naturally, does not care about the order of the messages and is trivial to secure against
877 // key sets that were received more than once
878 // With full M/N multisig now possible consider only key sets of the right round, i.e.
879 // with not yet multisig the only possible round 0
880 std::vector<uint32_t> key_set_messages(m_num_authorized_signers, 0);
881
882 for (size_t i = 0; i < m_messages.size(); ++i)
883 {
884 message &m = m_messages[i];
885 if ((m.type == message_type::key_set) && (m.state == message_state::waiting)
886 && (m.round == 0))
887 {
888 if (key_set_messages[m.signer_index] == 0)
889 {
890 key_set_messages[m.signer_index] = m.id;
891 }
892 // else duplicate key set, ignore
893 }
894 }
895
896 bool key_sets_complete = message_ids_complete(key_set_messages);
897 if (key_sets_complete)
898 {
899 // Nothing else can be ready to process earlier than this, ignore everything else and give back
900 processing_data data;
901 data.processing = message_processing::make_multisig;
902 data.message_ids = key_set_messages;
903 data.message_ids.erase(data.message_ids.begin());
904 data_list.push_back(data);
905 return true;
906 }
907 else
908 {
909 wait_reason = tr("Wallet can't go multisig because key sets from other signers are missing or not complete.");
910 return false;
911 }
912 }
913
914 if (state.multisig && !state.multisig_is_ready)
915 {
916 // In the case of M/N multisig the call 'wallet2::multisig' returns already true
917 // after "make_multisig" but with calls to "exchange_multisig_keys" still needed, and
918 // sets the parameter 'ready' to false to document this particular "in-between" state.
919 // So what may be possible here, with all necessary messages present, is a call to
920 // "exchange_multisig_keys".
921 // Consider only messages belonging to the next round to do, which has the number
922 // "state.multisig_rounds_passed".
923 std::vector<uint32_t> additional_key_set_messages(m_num_authorized_signers, 0);
924
925 for (size_t i = 0; i < m_messages.size(); ++i)
926 {
927 message &m = m_messages[i];
928 if ((m.type == message_type::additional_key_set) && (m.state == message_state::waiting)
929 && (m.round == state.multisig_rounds_passed))
930 {
931 if (additional_key_set_messages[m.signer_index] == 0)
932 {
933 additional_key_set_messages[m.signer_index] = m.id;
934 }
935 // else duplicate key set, ignore
936 }
937 }
938
939 bool key_sets_complete = message_ids_complete(additional_key_set_messages);
940 if (key_sets_complete)
941 {
942 processing_data data;
944 data.message_ids = additional_key_set_messages;
945 data.message_ids.erase(data.message_ids.begin());
946 data_list.push_back(data);
947 return true;
948 }
949 else
950 {
951 wait_reason = tr("Wallet can't start another key exchange round because key sets from other signers are missing or not complete.");
952 return false;
953 }
954 }
955
956 // Properly exchanging multisig sync data is easiest and most transparent
957 // for the user if a wallet sends its own data first and processes any received
958 // sync data afterwards so that's the order that the MMS enforces here.
959 // (Technically, it seems to work also the other way round.)
960 //
961 // To check whether a NEW round of syncing is necessary the MMS works with a
962 // "wallet state": new state means new syncing needed.
963 //
964 // The MMS monitors the "wallet state" by recording "wallet heights" as
965 // numbers of transfers present in a wallet at the time of message creation. While
966 // not watertight, this quite simple scheme should already suffice to trigger
967 // and orchestrate a sensible exchange of sync data.
968 if (state.has_multisig_partial_key_images || force_sync)
969 {
970 // Sync is necessary and not yet completed: Processing of transactions
971 // will only be possible again once properly synced
972 // Check first whether we generated already OUR sync info; take note of
973 // any processable sync info from other signers on the way in case we need it
974 bool own_sync_data_created = false;
975 std::vector<uint32_t> sync_messages(m_num_authorized_signers, 0);
976 for (size_t i = 0; i < m_messages.size(); ++i)
977 {
978 message &m = m_messages[i];
979 if ((m.type == message_type::multisig_sync_data) && (force_sync || (m.wallet_height == wallet_height)))
980 // It's data for the same "round" of syncing, on the same "wallet height", therefore relevant
981 // With "force_sync" take ANY waiting sync data, maybe it will work out
982 {
983 if (m.direction == message_direction::out)
984 {
985 own_sync_data_created = true;
986 // Ignore whether sent already or not, and assume as complete if several other signers there
987 }
988 else if ((m.direction == message_direction::in) && (m.state == message_state::waiting))
989 {
990 if (sync_messages[m.signer_index] == 0)
991 {
992 sync_messages[m.signer_index] = m.id;
993 }
994 // else duplicate sync message, ignore
995 }
996 }
997 }
998 if (!own_sync_data_created)
999 {
1000 // As explained above, creating sync data BEFORE processing such data from
1001 // other signers reliably works, so insist on that here
1002 processing_data data;
1003 data.processing = message_processing::create_sync_data;
1004 data_list.push_back(data);
1005 return true;
1006 }
1007 uint32_t id_count = (uint32_t)get_other_signers_id_count(sync_messages);
1008 // Do we have sync data from ALL other signers?
1009 bool all_sync_data = id_count == (m_num_authorized_signers - 1);
1010 // Do we have just ENOUGH sync data to have a minimal viable sync set?
1011 // In cases like 2/3 multisig we don't need messages from ALL other signers, only
1012 // from enough of them i.e. num_required_signers minus 1 messages
1013 bool enough_sync_data = id_count >= (m_num_required_signers - 1);
1014 bool sync = false;
1015 wait_reason = tr("Syncing not done because multisig sync data from other signers are missing or not complete.");
1016 if (all_sync_data)
1017 {
1018 sync = true;
1019 }
1020 else if (enough_sync_data)
1021 {
1022 if (force_sync)
1023 {
1024 sync = true;
1025 }
1026 else
1027 {
1028 // Don't sync, but give a hint how this minimal set COULD be synced if really wanted
1029 wait_reason += (boost::format("\nUse \"mms next sync\" if you want to sync with just %s out of %s authorized signers and transact just with them")
1030 % (m_num_required_signers - 1) % (m_num_authorized_signers - 1)).str();
1031 }
1032 }
1033 if (sync)
1034 {
1035 processing_data data;
1036 data.processing = message_processing::process_sync_data;
1037 for (size_t i = 0; i < sync_messages.size(); ++i)
1038 {
1039 uint32_t id = sync_messages[i];
1040 if (id != 0)
1041 {
1042 data.message_ids.push_back(id);
1043 }
1044 }
1045 data_list.push_back(data);
1046 return true;
1047 }
1048 else
1049 {
1050 // We can't proceed to any transactions until we have synced; "wait_reason" already set above
1051 return false;
1052 }
1053 }
1054
1055 bool waiting_found = false;
1056 bool note_found = false;
1057 bool sync_data_found = false;
1058 for (size_t i = 0; i < m_messages.size(); ++i)
1059 {
1060 message &m = m_messages[i];
1061 if (m.state == message_state::waiting)
1062 {
1063 waiting_found = true;
1064 switch (m.type)
1065 {
1067 {
1068 // We can either submit it ourselves, or send it to any other signer for submission
1069 processing_data data;
1070 data.processing = message_processing::submit_tx;
1071 data.message_ids.push_back(m.id);
1072 data_list.push_back(data);
1073
1074 data.processing = message_processing::send_tx;
1075 for (uint32_t j = 1; j < m_num_authorized_signers; ++j)
1076 {
1077 data.receiving_signer_index = j;
1078 data_list.push_back(data);
1079 }
1080 return true;
1081 }
1082
1084 {
1085 if (m.signer_index == 0)
1086 {
1087 // We started this ourselves, or signed it but with still signatures missing:
1088 // We can send it to any other signer for signing / further signing
1089 // In principle it does not make sense to send it back to somebody who
1090 // already signed, but the MMS does not / not yet keep track of that,
1091 // because that would be somewhat complicated.
1092 processing_data data;
1093 data.processing = message_processing::send_tx;
1094 data.message_ids.push_back(m.id);
1095 for (uint32_t j = 1; j < m_num_authorized_signers; ++j)
1096 {
1097 data.receiving_signer_index = j;
1098 data_list.push_back(data);
1099 }
1100 return true;
1101 }
1102 else
1103 {
1104 // Somebody else sent this to us: We can sign it
1105 // It would be possible to just pass it on, but that's not directly supported here
1106 processing_data data;
1107 data.processing = message_processing::sign_tx;
1108 data.message_ids.push_back(m.id);
1109 data_list.push_back(data);
1110 return true;
1111 }
1112 }
1113
1114 case message_type::note:
1115 note_found = true;
1116 break;
1117
1119 sync_data_found = true;
1120 break;
1121
1122 default:
1123 break;
1124 }
1125 }
1126 }
1127 if (waiting_found)
1128 {
1129 wait_reason = tr("There are waiting messages, but nothing is ready to process under normal circumstances");
1130 if (sync_data_found)
1131 {
1132 wait_reason += tr("\nUse \"mms next sync\" if you want to force processing of the waiting sync data");
1133 }
1134 if (note_found)
1135 {
1136 wait_reason += tr("\nUse \"mms note\" to display the waiting notes");
1137 }
1138 }
1139 else
1140 {
1141 wait_reason = tr("There are no messages waiting to be processed.");
1142 }
1143
1144 return false;
1145}
bool signer_config_complete() const
#define tr(x)
Here is the call graph for this function:

◆ get_sanitized_message_text()

void mms::message_store::get_sanitized_message_text ( const message & m,
std::string & sanitized_text ) const

Definition at line 674 of file message_store.cpp.

675{
676 sanitized_text.clear();
677
678 // Restrict the size to fend of DOS-style attacks with heaps of data
679 size_t length = std::min(m.content.length(), (size_t)1000);
680
681 for (size_t i = 0; i < length; ++i)
682 {
683 char c = m.content[i];
684 if ((int)c < 32)
685 {
686 // Strip out any controls, especially ESC for getting rid of potentially dangerous
687 // ANSI escape sequences that a console window might interpret
688 c = ' ';
689 }
690 else if ((c == '<') || (c == '>'))
691 {
692 // Make XML or HTML impossible that e.g. might contain scripts that Qt might execute
693 // when displayed in the GUI wallet
694 c = ' ';
695 }
696 sanitized_text += c;
697 }
698}

◆ get_signer()

const authorized_signer & mms::message_store::get_signer ( uint32_t index) const

Definition at line 147 of file message_store.cpp.

148{
149 THROW_WALLET_EXCEPTION_IF(index >= m_num_authorized_signers, tools::error::wallet_internal_error, "Invalid signer index " + std::to_string(index));
150 return m_signers[index];
151}

◆ get_signer_config()

void mms::message_store::get_signer_config ( std::string & signer_config)

Definition at line 181 of file message_store.cpp.

182{
183 std::stringstream oss;
184 boost::archive::portable_binary_oarchive ar(oss);
185 ar << m_signers;
186 signer_config = oss.str();
187}

◆ get_signer_index_by_etn_address()

bool mms::message_store::get_signer_index_by_etn_address ( const cryptonote::account_public_address & etn_address,
uint32_t & index ) const

Definition at line 442 of file message_store.cpp.

443{
444 for (uint32_t i = 0; i < m_num_authorized_signers; ++i)
445 {
446 const authorized_signer &m = m_signers[i];
447 if (m.etn_address == etn_address)
448 {
449 index = m.index;
450 return true;
451 }
452 }
453 MWARNING("No authorized signer with Electroneum address " << account_address_to_string(etn_address));
454 return false;
455}
#define MWARNING(x)
Definition misc_log_ex.h:74
Here is the caller graph for this function:

◆ get_signer_index_by_label()

bool mms::message_store::get_signer_index_by_label ( const std::string label,
uint32_t & index ) const

Definition at line 457 of file message_store.cpp.

458{
459 for (uint32_t i = 0; i < m_num_authorized_signers; ++i)
460 {
461 const authorized_signer &m = m_signers[i];
462 if (m.label == label)
463 {
464 index = m.index;
465 return true;
466 }
467 }
468 MWARNING("No authorized signer with label " << label);
469 return false;
470}

◆ init()

void mms::message_store::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 )

Definition at line 81 of file message_store.cpp.

83{
84 m_num_authorized_signers = num_authorized_signers;
85 m_num_required_signers = num_required_signers;
86 m_signers.clear();
87 m_messages.clear();
88 m_next_message_id = 1;
89
90 // The vector "m_signers" gets here once the required number of elements, one for each authorized signer,
91 // and is never changed again. The rest of the code relies on "size(m_signers) == m_num_authorized_signers"
92 // without further checks.
93 authorized_signer signer;
94 for (uint32_t i = 0; i < m_num_authorized_signers; ++i)
95 {
96 signer.me = signer.index == 0; // Strict convention: The very first signer is fixed as / must be "me"
97 m_signers.push_back(signer);
98 signer.index++;
99 }
100
101 set_signer(state, 0, own_label, own_transport_address, state.address);
102
103 m_nettype = state.nettype;
104 set_active(true);
105 m_filename = state.mms_file;
106 save(state);
107}
void set_active(bool active)
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)
Here is the call graph for this function:

◆ init_options()

void mms::message_store::init_options ( boost::program_options::options_description & desc_params)
static

Definition at line 74 of file message_store.cpp.

75{
76 const options opts{};
77 command_line::add_arg(desc_params, opts.bitmessage_address);
78 command_line::add_arg(desc_params, opts.bitmessage_login);
79}
void add_arg(boost::program_options::options_description &description, const arg_descriptor< T, required, dependent, NUM_DEPS > &arg, bool unique=true)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ message_direction_to_string()

const char * mms::message_store::message_direction_to_string ( message_direction direction)
static

Definition at line 1379 of file message_store.cpp.

1380{
1381 switch (direction)
1382 {
1384 return tr("in");
1386 return tr("out");
1387 default:
1388 return tr("unknown message direction");
1389 }
1390}
Here is the caller graph for this function:

◆ message_state_to_string()

const char * mms::message_store::message_state_to_string ( message_state state)
static

Definition at line 1392 of file message_store.cpp.

1393{
1394 switch (state)
1395 {
1397 return tr("ready to send");
1399 return tr("sent");
1401 return tr("waiting");
1403 return tr("processed");
1405 return tr("cancelled");
1406 default:
1407 return tr("unknown message state");
1408 }
1409}

◆ message_type_to_string()

const char * mms::message_store::message_type_to_string ( message_type type)
static

Definition at line 1354 of file message_store.cpp.

1355{
1356 switch (type)
1357 {
1359 return tr("key set");
1361 return tr("additional key set");
1363 return tr("multisig sync data");
1365 return tr("partially signed tx");
1367 return tr("fully signed tx");
1368 case message_type::note:
1369 return tr("note");
1371 return tr("signer config");
1373 return tr("auto-config data");
1374 default:
1375 return tr("unknown message type");
1376 }
1377}
Here is the caller graph for this function:

◆ process_auto_config_data_message()

void mms::message_store::process_auto_config_data_message ( uint32_t id)

Definition at line 366 of file message_store.cpp.

367{
368 // "auto_config_data" contains the label that the auto-config data sender uses for "me", but that's
369 // more for completeness' sake, and right now it's not used. In general, the auto-config manager
370 // decides/defines the labels, and right after completing auto-config ALL wallets use the SAME labels.
371
372 const message &m = get_message_ref_by_id(id);
373
374 auto_config_data data;
375 try
376 {
377 std::stringstream iss;
378 iss << m.content;
379 boost::archive::portable_binary_iarchive ar(iss);
380 ar >> data;
381 }
382 catch (...)
383 {
384 THROW_WALLET_EXCEPTION_IF(true, tools::error::wallet_internal_error, "Invalid structure of auto config data");
385 }
386
387 authorized_signer &signer = m_signers[m.signer_index];
388 // "signer.label" does NOT change, see comment above
389 signer.transport_address = data.transport_address;
390 signer.etn_address_known = true;
391 signer.etn_address = data.etn_address;
392 signer.auto_config_running = false;
393}

◆ process_signer_config()

void mms::message_store::process_signer_config ( const multisig_wallet_state & state,
const std::string & signer_config )

Definition at line 207 of file message_store.cpp.

208{
209 // The signers in "signer_config" and the resident wallet signers are matched not by label, but
210 // by Electroneum address, and ALL labels will be set from "signer_config", even the "me" label.
211 // In the auto-config process as implemented now the auto-config manager is responsible for defining
212 // the labels, and right at the end of the process ALL wallets use the SAME labels. The idea behind this
213 // is preventing problems like duplicate labels and confusion (Bob choosing a label "IamAliceHonest").
214 // (Of course signers are free to re-define any labels they don't like AFTER auto-config.)
215 //
216 // Usually this method will be called with only the "me" signer defined in the wallet, and may
217 // produce unexpected behaviour if that wallet contains additional signers that have nothing to do with
218 // those arriving in "signer_config".
219 std::vector<authorized_signer> signers;
220 unpack_signer_config(state, signer_config, signers);
221
222 uint32_t new_index = 1;
223 for (uint32_t i = 0; i < m_num_authorized_signers; ++i)
224 {
225 const authorized_signer &m = signers[i];
226 uint32_t index;
227 uint32_t take_index;
228 bool found = get_signer_index_by_etn_address(m.etn_address, index);
229 if (found)
230 {
231 // Redefine existing (probably "me", under usual circumstances)
232 take_index = index;
233 }
234 else
235 {
236 // Add new; neglect that we may erroneously overwrite already defined signers
237 // (but protect "me")
238 take_index = new_index;
239 if ((new_index + 1) < m_num_authorized_signers)
240 {
241 new_index++;
242 }
243 }
244 authorized_signer &modify = m_signers[take_index];
245 modify.label = m.label; // ALWAYS set label, see comments above
246 if (!modify.me)
247 {
248 modify.transport_address = m.transport_address;
249 modify.etn_address_known = m.etn_address_known;
250 if (m.etn_address_known)
251 {
252 modify.etn_address = m.etn_address;
253 }
254 }
255 }
256 save(state);
257}
void unpack_signer_config(const multisig_wallet_state &state, const std::string &signer_config, std::vector< authorized_signer > &signers)
Here is the call graph for this function:

◆ process_wallet_created_data()

void mms::message_store::process_wallet_created_data ( const multisig_wallet_state & state,
message_type type,
const std::string & content )

Definition at line 472 of file message_store.cpp.

473{
474 switch(type)
475 {
477 // Result of a "prepare_multisig" command in the wallet
478 // Send the key set to all other signers
480 // Result of a "make_multisig" command or a "exchange_multisig_keys" in the wallet in case of M/N multisig
481 // Send the additional key set to all other signers
483 // Result of a "export_multisig_info" command in the wallet
484 // Send the sync data to all other signers
485 for (uint32_t i = 1; i < m_num_authorized_signers; ++i)
486 {
487 add_message(state, i, type, message_direction::out, content);
488 }
489 break;
490
492 // Result of a "transfer" command in the wallet, or a "sign_multisig" command
493 // that did not yet result in the minimum number of signatures required
494 // Create a message "from me to me" as a container for the tx data
495 if (m_num_required_signers == 1)
496 {
497 // Probably rare, but possible: The 1 signature is already enough, correct the type
498 // Easier to correct here than asking all callers to detect this rare special case
500 }
501 add_message(state, 0, type, message_direction::in, content);
502 break;
503
505 add_message(state, 0, type, message_direction::in, content);
506 break;
507
508 default:
509 THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, "Illegal message type " + std::to_string((uint32_t)type));
510 break;
511 }
512}
#define THROW_WALLET_EXCEPTION(err_type,...)
Here is the call graph for this function:

◆ read_from_file()

void mms::message_store::read_from_file ( const multisig_wallet_state & state,
const std::string & filename )

Definition at line 727 of file message_store.cpp.

728{
729 boost::system::error_code ignored_ec;
730 bool file_exists = boost::filesystem::exists(filename, ignored_ec);
731 if (!file_exists)
732 {
733 // Simply do nothing if the file is not there; allows e.g. easy recovery
734 // from problems with the MMS by deleting the file
735 MERROR("No message store file found: " << filename);
736 return;
737 }
738
739 std::string buf;
740 bool success = epee::file_io_utils::load_file_to_string(filename, buf);
742
743 file_data read_file_data;
744 try
745 {
746 std::stringstream iss;
747 iss << buf;
748 boost::archive::portable_binary_iarchive ar(iss);
749 ar >> read_file_data;
750 }
751 catch (const std::exception &e)
752 {
753 MERROR("MMS file " << filename << " has bad structure <iv,encrypted_data>: " << e.what());
755 }
756
757 crypto::chacha_key key;
758 crypto::generate_chacha_key(&state.view_secret_key, sizeof(crypto::secret_key), key, 1);
759 std::string decrypted_data;
760 decrypted_data.resize(read_file_data.encrypted_data.size());
761 crypto::chacha20(read_file_data.encrypted_data.data(), read_file_data.encrypted_data.size(), key, read_file_data.iv, &decrypted_data[0]);
762
763 try
764 {
765 std::stringstream iss;
766 iss << decrypted_data;
767 boost::archive::portable_binary_iarchive ar(iss);
768 ar >> *this;
769 }
770 catch (const std::exception &e)
771 {
772 MERROR("MMS file " << filename << " has bad structure: " << e.what());
774 }
775
776 m_filename = filename;
777}
const char * key
#define MERROR(x)
Definition misc_log_ex.h:73
bool load_file_to_string(const std::string &path_to_file, std::string &target_str, size_t max_size=1000000000)
file_error_base< file_exists_message_index > file_exists
file_error_base< file_read_error_message_index > file_read_error
const char * buf
Here is the call graph for this function:

◆ send_message()

void mms::message_store::send_message ( const multisig_wallet_state & state,
uint32_t id )

Definition at line 1202 of file message_store.cpp.

1203{
1204 message &m = get_message_ref_by_id(id);
1205 const authorized_signer &me = m_signers[0];
1206 const authorized_signer &receiver = m_signers[m.signer_index];
1209
1210 dm.timestamp = (uint64_t)time(NULL);
1211 dm.subject = "MMS V0 " + tools::get_human_readable_timestamp(dm.timestamp);
1212 dm.source_transport_address = me.transport_address;
1213 dm.source_etn_address = me.etn_address;
1214 if (m.type == message_type::auto_config_data)
1215 {
1216 // Encrypt with the public key derived from the auto-config token, and send to the
1217 // transport address likewise derived from that token
1218 public_key = me.auto_config_public_key;
1219 dm.destination_transport_address = me.auto_config_transport_address;
1220 // The destination Electroneum address is not yet known
1221 memset(&dm.destination_etn_address, 0, sizeof(cryptonote::account_public_address));
1222 }
1223 else
1224 {
1225 // Encrypt with the receiver's view public key
1226 public_key = receiver.etn_address.m_view_public_key;
1227 const authorized_signer &receiver = m_signers[m.signer_index];
1228 dm.destination_etn_address = receiver.etn_address;
1229 dm.destination_transport_address = receiver.transport_address;
1230 }
1231 encrypt(public_key, m.content, dm.content, dm.encryption_public_key, dm.iv);
1232 dm.type = (uint32_t)m.type;
1233 dm.hash = crypto::cn_fast_hash(dm.content.data(), dm.content.size());
1234 dm.round = m.round;
1235
1236 crypto::generate_signature(dm.hash, me.etn_address.m_view_public_key, state.view_secret_key, dm.signature);
1237
1238 m_transporter.send_message(dm);
1239
1240 m.state=message_state::sent;
1241 m.sent= (uint64_t)time(NULL);
1242}
void generate_signature(const hash &prefix_hash, const public_key &pub, const secret_key &sec, signature &sig)
Definition crypto.h:292
POD_CLASS public_key
Definition crypto.h:79
std::string get_human_readable_timestamp(uint64_t ts)
Definition util.cpp:1077
Here is the call graph for this function:

◆ serialize()

template<class t_archive>
void mms::message_store::serialize ( t_archive & a,
const unsigned int ver )
inline

Definition at line 286 of file message_store.h.

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 }
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition pointer.h:1124

◆ set_active()

void mms::message_store::set_active ( bool active)
inline

Definition at line 211 of file message_store.h.

211{ m_active = active; };
Here is the caller graph for this function:

◆ set_auto_send()

void mms::message_store::set_auto_send ( bool auto_send)
inline

Definition at line 212 of file message_store.h.

212{ m_auto_send = auto_send; };

◆ set_message_processed_or_sent()

void mms::message_store::set_message_processed_or_sent ( uint32_t id)

Definition at line 1155 of file message_store.cpp.

1156{
1157 message &m = get_message_ref_by_id(id);
1158 if (m.state == message_state::waiting)
1159 {
1160 // So far a fairly cautious and conservative strategy: Only delete from Bitmessage
1161 // when fully processed (and e.g. not already after reception and writing into
1162 // the message store file)
1163 delete_transport_message(id);
1164 m.state = message_state::processed;
1165 }
1166 else if (m.state == message_state::ready_to_send)
1167 {
1168 m.state = message_state::sent;
1169 }
1170 m.modified = (uint64_t)time(NULL);
1171}
Here is the caller graph for this function:

◆ set_messages_processed()

void mms::message_store::set_messages_processed ( const processing_data & data)

Definition at line 1147 of file message_store.cpp.

1148{
1149 for (size_t i = 0; i < data.message_ids.size(); ++i)
1150 {
1151 set_message_processed_or_sent(data.message_ids[i]);
1152 }
1153}
void set_message_processed_or_sent(uint32_t id)
Here is the call graph for this function:

◆ set_options() [1/2]

void mms::message_store::set_options ( const boost::program_options::variables_map & vm)

Definition at line 109 of file message_store.cpp.

110{
111 const options opts{};
112 std::string bitmessage_address = command_line::get_arg(vm, opts.bitmessage_address);
113 epee::wipeable_string bitmessage_login = command_line::get_arg(vm, opts.bitmessage_login);
114 set_options(bitmessage_address, bitmessage_login);
115}
void set_options(const boost::program_options::variables_map &vm)
T get_arg(const boost::program_options::variables_map &vm, const arg_descriptor< T, false, true > &arg)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_options() [2/2]

void mms::message_store::set_options ( const std::string & bitmessage_address,
const epee::wipeable_string & bitmessage_login )

Definition at line 117 of file message_store.cpp.

118{
119 m_transporter.set_options(bitmessage_address, bitmessage_login);
120}

◆ set_signer()

void mms::message_store::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 at line 122 of file message_store.cpp.

127{
128 THROW_WALLET_EXCEPTION_IF(index >= m_num_authorized_signers, tools::error::wallet_internal_error, "Invalid signer index " + std::to_string(index));
129 authorized_signer &m = m_signers[index];
130 if (label)
131 {
132 m.label = label.get();
133 }
134 if (transport_address)
135 {
136 m.transport_address = transport_address.get();
137 }
138 if (etn_address)
139 {
140 m.etn_address_known = true;
141 m.etn_address = etn_address.get();
142 }
143 // Save to minimize the chance to loose that info (at least while in beta)
144 save(state);
145}
Here is the caller graph for this function:

◆ signer_config_complete()

bool mms::message_store::signer_config_complete ( ) const

Definition at line 153 of file message_store.cpp.

154{
155 for (uint32_t i = 0; i < m_num_authorized_signers; ++i)
156 {
157 const authorized_signer &m = m_signers[i];
158 if (m.label.empty() || m.transport_address.empty() || !m.etn_address_known)
159 {
160 return false;
161 }
162 }
163 return true;
164}
Here is the caller graph for this function:

◆ signer_labels_complete()

bool mms::message_store::signer_labels_complete ( ) const

Definition at line 168 of file message_store.cpp.

169{
170 for (uint32_t i = 0; i < m_num_authorized_signers; ++i)
171 {
172 const authorized_signer &m = m_signers[i];
173 if (m.label.empty())
174 {
175 return false;
176 }
177 }
178 return true;
179}

◆ signer_to_string()

std::string mms::message_store::signer_to_string ( const authorized_signer & signer,
uint32_t max_width )

Definition at line 1413 of file message_store.cpp.

1414{
1415 std::string s = "";
1416 s.reserve(max_width);
1417 uint32_t avail = max_width;
1418 uint32_t label_len = signer.label.length();
1419 if (label_len > avail)
1420 {
1421 s.append(signer.label.substr(0, avail - 2));
1422 s.append("..");
1423 return s;
1424 }
1425 s.append(signer.label);
1426 avail -= label_len;
1427 uint32_t transport_addr_len = signer.transport_address.length();
1428 if ((transport_addr_len > 0) && (avail > 10))
1429 {
1430 s.append(": ");
1431 avail -= 2;
1432 if (transport_addr_len <= avail)
1433 {
1434 s.append(signer.transport_address);
1435 }
1436 else
1437 {
1438 s.append(signer.transport_address.substr(0, avail-2));
1439 s.append("..");
1440 }
1441 }
1442 return s;
1443}

◆ start_auto_config()

void mms::message_store::start_auto_config ( const multisig_wallet_state & state)

Definition at line 259 of file message_store.cpp.

260{
261 for (uint32_t i = 0; i < m_num_authorized_signers; ++i)
262 {
263 authorized_signer &m = m_signers[i];
264 if (!m.me)
265 {
266 setup_signer_for_auto_config(i, create_auto_config_token(), true);
267 }
268 m.auto_config_running = true;
269 }
270 save(state);
271}

◆ stop()

void mms::message_store::stop ( )
inline

Definition at line 280 of file message_store.h.

280{ m_run.store(false, std::memory_order_relaxed); m_transporter.stop(); }

◆ stop_auto_config()

void mms::message_store::stop_auto_config ( )

Definition at line 395 of file message_store.cpp.

396{
397 for (uint32_t i = 0; i < m_num_authorized_signers; ++i)
398 {
399 authorized_signer &m = m_signers[i];
400 if (!m.me && !m.auto_config_transport_address.empty())
401 {
402 // Try to delete those "unused API" addresses in PyBitmessage, especially since
403 // it seems it's not possible to delete them interactively, only to "disable" them
404 m_transporter.delete_transport_address(m.auto_config_transport_address);
405 }
406 m.auto_config_token.clear();
407 m.auto_config_public_key = crypto::null_pkey;
408 m.auto_config_secret_key = crypto::null_skey;
409 m.auto_config_transport_address.clear();
410 m.auto_config_running = false;
411 }
412}
const crypto::public_key null_pkey
Definition crypto.cpp:72
const crypto::secret_key null_skey
Definition crypto.cpp:73

◆ tr()

const char * mms::message_store::tr ( const char * str)
inlinestatic

Definition at line 303 of file message_store.h.

303{ return i18n_translate(str, "tools::mms"); }
const char * i18n_translate(const char *s, const std::string &context)
Definition i18n.cpp:323
Here is the call graph for this function:

◆ unpack_signer_config()

void mms::message_store::unpack_signer_config ( const multisig_wallet_state & state,
const std::string & signer_config,
std::vector< authorized_signer > & signers )

Definition at line 189 of file message_store.cpp.

191{
192 try
193 {
194 std::stringstream iss;
195 iss << signer_config;
196 boost::archive::portable_binary_iarchive ar(iss);
197 ar >> signers;
198 }
199 catch (...)
200 {
201 THROW_WALLET_EXCEPTION_IF(true, tools::error::wallet_internal_error, "Invalid structure of signer config");
202 }
203 uint32_t num_signers = (uint32_t)signers.size();
204 THROW_WALLET_EXCEPTION_IF(num_signers != m_num_authorized_signers, tools::error::wallet_internal_error, "Wrong number of signers in config: " + std::to_string(num_signers));
205}
Here is the caller graph for this function:

◆ write_to_file()

void mms::message_store::write_to_file ( const multisig_wallet_state & state,
const std::string & filename )

Definition at line 700 of file message_store.cpp.

701{
702 std::stringstream oss;
703 boost::archive::portable_binary_oarchive ar(oss);
704 ar << *this;
705 std::string buf = oss.str();
706
707 crypto::chacha_key key;
708 crypto::generate_chacha_key(&state.view_secret_key, sizeof(crypto::secret_key), key, 1);
709
710 file_data write_file_data = boost::value_initialized<file_data>();
711 write_file_data.magic_string = "MMS";
712 write_file_data.file_version = 0;
713 write_file_data.iv = crypto::rand<crypto::chacha_iv>();
714 std::string encrypted_data;
715 encrypted_data.resize(buf.size());
716 crypto::chacha20(buf.data(), buf.size(), key, write_file_data.iv, &encrypted_data[0]);
717 write_file_data.encrypted_data = encrypted_data;
718
719 std::stringstream file_oss;
720 boost::archive::portable_binary_oarchive file_ar(file_oss);
721 file_ar << write_file_data;
722
723 bool success = epee::file_io_utils::save_string_to_file(filename, file_oss.str());
725}
std::enable_if< std::is_pod< T >::value, T >::type rand()
Definition crypto.h:216
bool save_string_to_file(const std::string &path_to_file, const std::string &str)
file_error_base< file_save_error_message_index > file_save_error
Here is the call graph for this function:

The documentation for this class was generated from the following files:
  • /home/abuild/rpmbuild/BUILD/electroneum-5.1.3.1-build/electroneum-5.1.3.1/src/wallet/message_store.h
  • /home/abuild/rpmbuild/BUILD/electroneum-5.1.3.1-build/electroneum-5.1.3.1/src/wallet/message_store.cpp