32 #include <boost/format.hpp> 33 #include <boost/algorithm/string.hpp> 45 #undef ELECTRONEUM_DEFAULT_LOG_CATEGORY 46 #define ELECTRONEUM_DEFAULT_LOG_CATEGORY "wallet.mms" 55 m_next_message_id = 1;
56 m_num_authorized_signers = 0;
57 m_num_required_signers = 0;
84 m_num_authorized_signers = num_authorized_signers;
85 m_num_required_signers = num_required_signers;
88 m_next_message_id = 1;
94 for (
uint32_t i = 0; i < m_num_authorized_signers; ++i)
97 m_signers.push_back(signer);
103 m_nettype =
state.nettype;
105 m_filename =
state.mms_file;
111 const options opts{};
119 m_transporter.
set_options(bitmessage_address, bitmessage_login);
124 const boost::optional<std::string> &label,
125 const boost::optional<std::string> &transport_address,
126 const boost::optional<cryptonote::account_public_address> etn_address)
132 m.
label = label.get();
134 if (transport_address)
150 return m_signers[index];
155 for (
uint32_t i = 0; i < m_num_authorized_signers; ++i)
170 for (
uint32_t i = 0; i < m_num_authorized_signers; ++i)
183 std::stringstream oss;
190 std::vector<authorized_signer> &signers)
194 std::stringstream iss;
219 std::vector<authorized_signer> signers;
223 for (
uint32_t i = 0; i < m_num_authorized_signers; ++i)
238 take_index = new_index;
239 if ((new_index + 1) < m_num_authorized_signers)
261 for (
uint32_t i = 0; i < m_num_authorized_signers; ++i)
266 setup_signer_for_auto_config(i, create_auto_config_token(),
true);
281 uint32_t full_length = num_hex_digits + prefix.length();
282 uint32_t raw_length = raw_token.length();
285 if (raw_length == full_length)
289 boost::algorithm::to_lower(raw_prefix);
290 if (raw_prefix != prefix)
294 hex_digits = raw_token.substr(3);
296 else if (raw_length == num_hex_digits)
299 hex_digits = raw_token;
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');
323 adjusted_token = prefix + hex_digits;
328 std::string message_store::create_auto_config_token()
338 token_bytes +=
hash.data[0];
350 setup_signer_for_auto_config(0, auto_config_token,
false);
358 std::stringstream oss;
372 const message &m = get_message_ref_by_id(
id);
377 std::stringstream iss;
397 for (
uint32_t i = 0; i < m_num_authorized_signers; ++i)
414 void message_store::setup_signer_for_auto_config(
uint32_t index,
const std::string token,
bool receiving)
444 for (
uint32_t i = 0; i < m_num_authorized_signers; ++i)
453 MWARNING(
"No authorized signer with Electroneum address " << account_address_to_string(etn_address));
459 for (
uint32_t i = 0; i < m_num_authorized_signers; ++i)
462 if (m.
label == label)
468 MWARNING(
"No authorized signer with label " << label);
485 for (
uint32_t i = 1; i < m_num_authorized_signers; ++i)
495 if (m_num_required_signers == 1)
519 m.
id = m_next_message_id++;
545 m.
hash = crypto::null_hash;
546 m_messages.push_back(m);
551 MINFO(boost::format(
"Added %s message %s for signer %s of type %s")
553 return m_messages.size() - 1;
557 bool message_store::get_message_index_by_id(
uint32_t id,
size_t &index)
const 559 for (
size_t i = 0; i < m_messages.size(); ++i)
561 if (m_messages[i].
id ==
id)
567 MWARNING(
"No message found with an id of " <<
id);
572 size_t message_store::get_message_index_by_id(
uint32_t id)
const 575 bool found = get_message_index_by_id(
id, index);
583 return m_messages[get_message_index_by_id(
id)];
591 bool found = get_message_index_by_id(
id, index);
594 m = m_messages[index];
610 for (
size_t i = 0; i < m_messages.size(); ++i)
612 if ((m_messages[i].type == type) && (m_messages[i].direction == direction))
622 for (
size_t i = 0; i < m_messages.size(); ++i)
637 size_t message_store::get_other_signers_id_count(
const std::vector<uint32_t> &ids)
const 640 for (
size_t i = 1 ; i < ids.size(); ++i)
651 bool message_store::message_ids_complete(
const std::vector<uint32_t> &ids)
const 653 return get_other_signers_id_count(ids) == (ids.size() - 1);
658 delete_transport_message(
id);
659 size_t index = get_message_index_by_id(
id);
660 m_messages.erase(m_messages.begin() + index);
665 for (
size_t i = 0; i < m_messages.size(); ++i)
667 delete_transport_message(m_messages[i].
id);
676 sanitized_text.clear();
679 size_t length = std::min(m.
content.length(), (size_t)1000);
681 for (
size_t i = 0; i < length; ++i)
690 else if ((c ==
'<') || (c ==
'>'))
702 std::stringstream oss;
707 crypto::chacha_key
key;
710 file_data write_file_data = boost::value_initialized<file_data>();
713 write_file_data.
iv = crypto::rand<crypto::chacha_iv>();
715 encrypted_data.resize(
buf.size());
719 std::stringstream file_oss;
721 file_ar << write_file_data;
729 boost::system::error_code ignored_ec;
730 bool file_exists = boost::filesystem::exists(filename, ignored_ec);
735 MERROR(
"No message store file found: " << filename);
746 std::stringstream iss;
749 ar >> read_file_data;
751 catch (
const std::exception &e)
753 MERROR(
"MMS file " << filename <<
" has bad structure <iv,encrypted_data>: " << e.what());
757 crypto::chacha_key
key;
765 std::stringstream iss;
766 iss << decrypted_data;
770 catch (
const std::exception &e)
772 MERROR(
"MMS file " << filename <<
" has bad structure: " << e.what());
776 m_filename = filename;
784 if (!m_filename.empty())
791 bool force_sync, std::vector<processing_data> &data_list,
std::string &wait_reason)
801 std::vector<uint32_t> auto_config_messages(m_num_authorized_signers, 0);
802 bool any_auto_config =
false;
804 for (
size_t i = 0; i < m_messages.size(); ++i)
812 any_auto_config =
true;
820 bool auto_config_complete = message_ids_complete(auto_config_messages);
821 if (auto_config_complete)
827 data_list.push_back(data);
832 wait_reason =
tr(
"Auto-config cannot proceed because auto config data from other signers is not complete");
841 for (
size_t i = 0; i < m_messages.size(); ++i)
849 data_list.push_back(data);
857 wait_reason =
tr(
"The signer config is not complete.");
871 data_list.push_back(data);
880 std::vector<uint32_t> key_set_messages(m_num_authorized_signers, 0);
882 for (
size_t i = 0; i < m_messages.size(); ++i)
896 bool key_sets_complete = message_ids_complete(key_set_messages);
897 if (key_sets_complete)
904 data_list.push_back(data);
909 wait_reason =
tr(
"Wallet can't go multisig because key sets from other signers are missing or not complete.");
914 if (
state.multisig && !
state.multisig_is_ready)
923 std::vector<uint32_t> additional_key_set_messages(m_num_authorized_signers, 0);
925 for (
size_t i = 0; i < m_messages.size(); ++i)
939 bool key_sets_complete = message_ids_complete(additional_key_set_messages);
940 if (key_sets_complete)
946 data_list.push_back(data);
951 wait_reason =
tr(
"Wallet can't start another key exchange round because key sets from other signers are missing or not complete.");
968 if (
state.has_multisig_partial_key_images || force_sync)
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)
985 own_sync_data_created =
true;
998 if (!own_sync_data_created)
1004 data_list.push_back(data);
1009 bool all_sync_data = id_count == (m_num_authorized_signers - 1);
1013 bool enough_sync_data = id_count >= (m_num_required_signers - 1);
1015 wait_reason =
tr(
"Syncing not done because multisig sync data from other signers are missing or not complete.");
1020 else if (enough_sync_data)
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();
1037 for (
size_t i = 0; i < sync_messages.size(); ++i)
1045 data_list.push_back(data);
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)
1063 waiting_found =
true;
1072 data_list.push_back(data);
1075 for (
uint32_t j = 1; j < m_num_authorized_signers; ++j)
1078 data_list.push_back(data);
1095 for (
uint32_t j = 1; j < m_num_authorized_signers; ++j)
1098 data_list.push_back(data);
1109 data_list.push_back(data);
1119 sync_data_found =
true;
1129 wait_reason =
tr(
"There are waiting messages, but nothing is ready to process under normal circumstances");
1130 if (sync_data_found)
1132 wait_reason +=
tr(
"\nUse \"mms next sync\" if you want to force processing of the waiting sync data");
1136 wait_reason +=
tr(
"\nUse \"mms note\" to display the waiting notes");
1141 wait_reason =
tr(
"There are no messages waiting to be processed.");
1149 for (
size_t i = 0; i < data.
message_ids.size(); ++i)
1157 message &m = get_message_ref_by_id(
id);
1163 delete_transport_message(
id);
1183 crypto::chacha_key chacha_key;
1184 crypto::generate_chacha_key(&derivation,
sizeof(derivation), chacha_key, 1);
1185 iv = crypto::rand<crypto::chacha_iv>();
1186 ciphertext.resize(plaintext.size());
1187 crypto::chacha20(plaintext.data(), plaintext.size(), chacha_key, iv, &ciphertext[0]);
1196 crypto::chacha_key chacha_key;
1197 crypto::generate_chacha_key(&derivation,
sizeof(derivation), chacha_key, 1);
1198 plaintext.resize(ciphertext.size());
1199 crypto::chacha20(ciphertext.data(), ciphertext.size(), chacha_key, iv, &plaintext[0]);
1204 message &m = get_message_ref_by_id(
id);
1228 dm.destination_etn_address = receiver.
etn_address;
1246 m_run.store(
true, std::memory_order_relaxed);
1248 std::vector<std::string> destinations;
1250 for (
uint32_t i = 1; i < m_num_authorized_signers; ++i)
1258 std::vector<transport_message> transport_messages;
1260 if (!m_run.load(std::memory_order_relaxed))
1267 bool new_messages =
false;
1268 for (
size_t i = 0; i < transport_messages.size(); ++i)
1271 if (any_message_with_hash(rm.hash))
1285 for (
uint32_t i = 1; i < m_num_authorized_signers; ++i)
1313 take = rm.destination_etn_address == me.
etn_address;
1320 bool signature_valid =
crypto::check_signature(actual_hash, rm.source_etn_address.m_view_public_key, rm.signature);
1324 decrypt(rm.content, rm.encryption_public_key, rm.iv,
decrypt_key, plaintext);
1326 message &m = m_messages[index];
1329 m.
sent = rm.timestamp;
1332 messages.push_back(m);
1333 new_messages =
true;
1337 return new_messages;
1340 void message_store::delete_transport_message(
uint32_t id)
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");
1371 return tr(
"signer config");
1373 return tr(
"auto-config data");
1375 return tr(
"unknown message type");
1388 return tr(
"unknown message direction");
1397 return tr(
"ready to send");
1401 return tr(
"waiting");
1403 return tr(
"processed");
1405 return tr(
"cancelled");
1407 return tr(
"unknown message state");
1416 s.reserve(max_width);
1419 if (label_len > avail)
1421 s.append(signer.
label.substr(0, avail - 2));
1425 s.append(signer.
label);
1428 if ((transport_addr_len > 0) && (avail > 10))
1432 if (transport_addr_len <= avail)
static void init_options(boost::program_options::options_description &desc_params)
void write_to_file(const multisig_wallet_state &state, const std::string &filename)
crypto::secret_key auto_config_secret_key
static const char * tr(const char *str)
std::string auto_config_transport_address
std::string get_account_address_as_str(network_type nettype, bool subaddress, account_public_address const &adr)
void set_messages_processed(const processing_data &data)
static const char * message_direction_to_string(message_direction direction)
bool delete_transport_address(const std::string &transport_address)
bool check_for_messages(const multisig_wallet_state &state, std::vector< message > &messages)
uint32_t receiving_signer_index
void unpack_signer_config(const multisig_wallet_state &state, const std::string &signer_config, std::vector< authorized_signer > &signers)
void chacha20(const void *data, size_t length, const uint8_t *key, const uint8_t *iv, char *cipher)
void generate_signature(const hash &prefix_hash, const public_key &pub, const secret_key &sec, signature &sig)
void delete_all_messages()
bool load_file_to_string(const std::string &path_to_file, std::string &target_str, size_t max_size=1000000000)
bool check_auto_config_token(const std::string &raw_token, std::string &adjusted_token) const
bool delete_message(const std::string &transport_id)
bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation)
std::string encrypted_data
void send_message(const multisig_wallet_state &state, uint32_t id)
const crypto::secret_key null_skey
void process_auto_config_data_message(uint32_t id)
std::string transport_address
mdb_size_t count(MDB_cursor *cur)
cryptonote::account_public_address etn_address
void rand(size_t N, uint8_t *bytes)
std::string derive_transport_address(const std::string &seed)
crypto::public_key m_view_public_key
const crypto::public_key null_pkey
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
secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key &recovery_key=secret_key(), bool recover=false)
bool save_string_to_file(const std::string &path_to_file, const std::string &str)
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)
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)
void cn_fast_hash(const void *data, size_t length, char *hash)
void add_arg(boost::program_options::options_description &description, const arg_descriptor< T, required, dependent, NUM_DEPS > &arg, bool unique=true)
std::string message("Message requiring signing")
std::string derive_and_receive_transport_address(const std::string &seed)
void set_options(const std::string &bitmessage_address, const epee::wipeable_string &bitmessage_login)
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)
expect< void > success() noexcept
void set_options(const boost::program_options::variables_map &vm)
#define AUTO_CONFIG_TOKEN_PREFIX
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)
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
void process_signer_config(const multisig_wallet_state &state, const std::string &signer_config)
bool send_message(const transport_message &message)
std::string signer_to_string(const authorized_signer &signer, uint32_t max_width)
T get_arg(const boost::program_options::variables_map &vm, const arg_descriptor< T, false, true > &arg)
bool signer_config_complete() const
#define AUTO_CONFIG_TOKEN_BYTES
void hash_to_scalar(const void *data, size_t length, ec_scalar &res)
bool get_message_by_id(uint32_t id, message &m) const
std::vector< uint32_t > message_ids
void set_message_processed_or_sent(uint32_t id)
crypto::secret_key decrypt_key(crypto::secret_key key, const epee::wipeable_string &passphrase)
#define THROW_WALLET_EXCEPTION(err_type,...)
bool secret_key_to_public_key(const secret_key &sec, public_key &pub)
std::string to_string(t_connection_type type)
uint64_t random(const uint64_t max_value)
std::string transport_address
void set_active(bool active)
message_direction direction
bool receive_messages(const std::vector< std::string > &destination_transport_addresses, std::vector< transport_message > &messages)
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)
crypto::public_key auto_config_public_key
bool check_signature(const hash &prefix_hash, const public_key &pub, const signature &sig)
void process_wallet_created_data(const multisig_wallet_state &state, message_type type, const std::string &content)