diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/blockchain_db/lmdb/db_lmdb.cpp | 2 | ||||
-rw-r--r-- | src/crypto/CryptonightR_JIT.c | 6 | ||||
-rw-r--r-- | src/crypto/crypto.cpp | 2 | ||||
-rw-r--r-- | src/cryptonote_core/cryptonote_tx_utils.h | 15 | ||||
-rw-r--r-- | src/cryptonote_core/tx_sanity_check.cpp | 4 | ||||
-rw-r--r-- | src/cryptonote_protocol/cryptonote_protocol_handler.inl | 2 | ||||
-rw-r--r-- | src/daemon/rpc_command_executor.cpp | 13 | ||||
-rw-r--r-- | src/device/device_io_hid.cpp | 3 | ||||
-rw-r--r-- | src/p2p/net_node.h | 1 | ||||
-rw-r--r-- | src/p2p/net_node.inl | 9 | ||||
-rw-r--r-- | src/rpc/core_rpc_server.cpp | 16 | ||||
-rw-r--r-- | src/rpc/core_rpc_server_commands_defs.h | 5 | ||||
-rw-r--r-- | src/simplewallet/simplewallet.cpp | 76 | ||||
-rw-r--r-- | src/simplewallet/simplewallet.h | 1 | ||||
-rw-r--r-- | src/wallet/api/transaction_history.cpp | 2 | ||||
-rw-r--r-- | src/wallet/message_store.cpp | 14 | ||||
-rw-r--r-- | src/wallet/message_transporter.cpp | 61 | ||||
-rw-r--r-- | src/wallet/message_transporter.h | 1 | ||||
-rw-r--r-- | src/wallet/wallet2.cpp | 4 | ||||
-rw-r--r-- | src/wallet/wallet2.h | 2 | ||||
-rw-r--r-- | src/wallet/wallet_rpc_server.cpp | 4 |
21 files changed, 159 insertions, 84 deletions
diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index 78db37b5a..1ede7af62 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -1329,7 +1329,7 @@ void BlockchainLMDB::open(const std::string& filename, const int db_flags) // set up lmdb environment if ((result = mdb_env_create(&m_env))) throw0(DB_ERROR(lmdb_error("Failed to create lmdb environment: ", result).c_str())); - if ((result = mdb_env_set_maxdbs(m_env, 20))) + if ((result = mdb_env_set_maxdbs(m_env, 32))) throw0(DB_ERROR(lmdb_error("Failed to set max number of dbs: ", result).c_str())); int threads = tools::get_max_concurrency(); diff --git a/src/crypto/CryptonightR_JIT.c b/src/crypto/CryptonightR_JIT.c index ee8f3f36f..ffe7820a2 100644 --- a/src/crypto/CryptonightR_JIT.c +++ b/src/crypto/CryptonightR_JIT.c @@ -63,7 +63,7 @@ int v4_generate_JIT_code(const struct V4_Instruction* code, v4_random_math_JIT_f #if !(defined(_MSC_VER) || defined(__MINGW32__)) if (mprotect((void*)buf, buf_size, PROT_READ | PROT_WRITE)) - return 1; + return -1; #endif APPEND_CODE(prologue, sizeof(prologue)); @@ -111,13 +111,13 @@ int v4_generate_JIT_code(const struct V4_Instruction* code, v4_random_math_JIT_f #if !(defined(_MSC_VER) || defined(__MINGW32__)) if (mprotect((void*)buf, buf_size, PROT_READ | PROT_EXEC)) - return 1; + return -1; #endif __builtin___clear_cache((char*)buf, (char*)JIT_code); return 0; #else - return 1; + return -1; #endif } diff --git a/src/crypto/crypto.cpp b/src/crypto/crypto.cpp index 3f06c4f3f..d4b2a22bc 100644 --- a/src/crypto/crypto.cpp +++ b/src/crypto/crypto.cpp @@ -275,8 +275,6 @@ namespace crypto { buf.key = pub; try_again: random_scalar(k); - if (((const uint32_t*)(&k))[7] == 0) // we don't want tiny numbers here - goto try_again; ge_scalarmult_base(&tmp3, &k); ge_p3_tobytes(&buf.comm, &tmp3); hash_to_scalar(&buf, sizeof(s_comm), sig.c); diff --git a/src/cryptonote_core/cryptonote_tx_utils.h b/src/cryptonote_core/cryptonote_tx_utils.h index d38aa7474..b03eb6e70 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.h +++ b/src/cryptonote_core/cryptonote_tx_utils.h @@ -83,6 +83,21 @@ namespace cryptonote tx_destination_entry(uint64_t a, const account_public_address &ad, bool is_subaddress) : amount(a), addr(ad), is_subaddress(is_subaddress), is_integrated(false) { } tx_destination_entry(const std::string &o, uint64_t a, const account_public_address &ad, bool is_subaddress) : original(o), amount(a), addr(ad), is_subaddress(is_subaddress), is_integrated(false) { } + std::string address(network_type nettype, const crypto::hash &payment_id) const + { + if (!original.empty()) + { + return original; + } + + if (is_integrated) + { + return get_account_integrated_address_as_str(nettype, addr, reinterpret_cast<const crypto::hash8 &>(payment_id)); + } + + return get_account_address_as_str(nettype, is_subaddress, addr); + } + BEGIN_SERIALIZE_OBJECT() FIELD(original) VARINT_FIELD(amount) diff --git a/src/cryptonote_core/tx_sanity_check.cpp b/src/cryptonote_core/tx_sanity_check.cpp index e95350f76..03cbb5c26 100644 --- a/src/cryptonote_core/tx_sanity_check.cpp +++ b/src/cryptonote_core/tx_sanity_check.cpp @@ -82,7 +82,7 @@ bool tx_sanity_check(Blockchain &blockchain, const cryptonote::blobdata &tx_blob if (rct_indices.size() < n_indices * 8 / 10) { - MERROR("unique indices is only " << rct_indices.size() << "/" << n_indices); + MERROR("amount of unique indices is too low (amount of rct indices is " << rct_indices.size() << ", out of total " << n_indices << "indices."); return false; } @@ -90,7 +90,7 @@ bool tx_sanity_check(Blockchain &blockchain, const cryptonote::blobdata &tx_blob uint64_t median = epee::misc_utils::median(offsets); if (median < n_available * 6 / 10) { - MERROR("median is " << median << "/" << n_available); + MERROR("median offset index is too low (median is " << median << " out of total " << n_available << "offsets). Transactions should contain a higher fraction of recent outputs."); return false; } diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl index a1fa9484c..2ff7b5938 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl @@ -342,7 +342,7 @@ namespace cryptonote if(m_core.have_block(hshd.top_id)) { - if (target > hshd.current_height) + if (target > m_core.get_current_blockchain_height()) { MINFO(context << "peer is not ahead of us and we're syncing, disconnecting"); return false; diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp index dbf0409e5..4d3debed6 100644 --- a/src/daemon/rpc_command_executor.cpp +++ b/src/daemon/rpc_command_executor.cpp @@ -66,15 +66,11 @@ namespace { time(&now); time_t last_seen = static_cast<time_t>(peer.last_seen); - std::string id_str; + std::string elapsed = epee::misc_utils::get_time_interval_string(now - last_seen); + std::string id_str = epee::string_tools::pad_string(epee::string_tools::to_string_hex(peer.id), 16, '0', true); std::string port_str; - std::string elapsed = peer.last_seen == 0 ? "never" : epee::misc_utils::get_time_interval_string(now - last_seen); - std::string ip_str = peer.ip != 0 ? epee::string_tools::get_ip_string_from_int32(peer.ip) : std::string("[") + peer.host + "]"; - std::stringstream peer_id_str; - peer_id_str << std::hex << std::setw(16) << peer.id; - peer_id_str >> id_str; epee::string_tools::xtype_to_string(peer.port, port_str); - std::string addr_str = ip_str + ":" + port_str; + std::string addr_str = peer.host + ":" + port_str; std::string rpc_port = peer.rpc_port ? std::to_string(peer.rpc_port) : "-"; std::string pruning_seed = epee::string_tools::to_string_hex(peer.pruning_seed); tools::msg_writer() << boost::format("%-10s %-25s %-25s %-5s %-4s %s") % prefix % id_str % addr_str % rpc_port % pruning_seed % elapsed; @@ -222,6 +218,9 @@ bool t_rpc_command_executor::print_peer_list_stats() { cryptonote::COMMAND_RPC_GET_PEER_LIST::response res; std::string failure_message = "Couldn't retrieve peer list"; + + req.public_only = false; + if (m_is_rpc) { if (!m_rpc_client->rpc_request(req, res, "/get_peer_list", failure_message.c_str())) diff --git a/src/device/device_io_hid.cpp b/src/device/device_io_hid.cpp index 721bed9ca..72f4c3bdb 100644 --- a/src/device/device_io_hid.cpp +++ b/src/device/device_io_hid.cpp @@ -44,7 +44,8 @@ namespace hw { static std::string safe_hid_error(hid_device *hwdev) { if (hwdev) { - return std::string((char*)hid_error(hwdev)); + const char* error_str = (const char*)hid_error(hwdev); + return std::string(error_str == nullptr ? "Unknown error" : error_str); } return std::string("NULL device"); } diff --git a/src/p2p/net_node.h b/src/p2p/net_node.h index cf6b2c67b..6d2ae878f 100644 --- a/src/p2p/net_node.h +++ b/src/p2p/net_node.h @@ -254,6 +254,7 @@ namespace nodetool size_t get_public_white_peers_count(); size_t get_public_gray_peers_count(); void get_public_peerlist(std::vector<peerlist_entry>& gray, std::vector<peerlist_entry>& white); + void get_peerlist(std::vector<peerlist_entry>& gray, std::vector<peerlist_entry>& white); size_t get_zone_count() const { return m_network_zones.size(); } void change_max_out_public_peers(size_t count); diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index 00467132a..8c0cff7e2 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -1739,6 +1739,15 @@ namespace nodetool } //----------------------------------------------------------------------------------- template<class t_payload_net_handler> + void node_server<t_payload_net_handler>::get_peerlist(std::vector<peerlist_entry>& gray, std::vector<peerlist_entry>& white) + { + for (auto &zone: m_network_zones) + { + zone.second.m_peerlist.get_peerlist(gray, white); // appends + } + } + //----------------------------------------------------------------------------------- + template<class t_payload_net_handler> bool node_server<t_payload_net_handler>::idle_worker() { m_peer_handshake_idle_maker_interval.do_call(boost::bind(&node_server<t_payload_net_handler>::peer_sync_idle_maker, this)); diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 1a854d21c..73138686d 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -1044,31 +1044,35 @@ namespace cryptonote PERF_TIMER(on_get_peer_list); std::vector<nodetool::peerlist_entry> white_list; std::vector<nodetool::peerlist_entry> gray_list; - m_p2p.get_public_peerlist(gray_list, white_list); - res.white_list.reserve(white_list.size()); + if (req.public_only) + { + m_p2p.get_public_peerlist(gray_list, white_list); + } + else + { + m_p2p.get_peerlist(gray_list, white_list); + } + for (auto & entry : white_list) { if (entry.adr.get_type_id() == epee::net_utils::ipv4_network_address::get_type_id()) res.white_list.emplace_back(entry.id, entry.adr.as<epee::net_utils::ipv4_network_address>().ip(), entry.adr.as<epee::net_utils::ipv4_network_address>().port(), entry.last_seen, entry.pruning_seed, entry.rpc_port); else if (entry.adr.get_type_id() == epee::net_utils::ipv6_network_address::get_type_id()) - { res.white_list.emplace_back(entry.id, entry.adr.as<epee::net_utils::ipv6_network_address>().host_str(), entry.adr.as<epee::net_utils::ipv6_network_address>().port(), entry.last_seen, entry.pruning_seed, entry.rpc_port); - } else res.white_list.emplace_back(entry.id, entry.adr.str(), entry.last_seen, entry.pruning_seed, entry.rpc_port); } - res.gray_list.reserve(gray_list.size()); for (auto & entry : gray_list) { if (entry.adr.get_type_id() == epee::net_utils::ipv4_network_address::get_type_id()) res.gray_list.emplace_back(entry.id, entry.adr.as<epee::net_utils::ipv4_network_address>().ip(), entry.adr.as<epee::net_utils::ipv4_network_address>().port(), entry.last_seen, entry.pruning_seed, entry.rpc_port); else if (entry.adr.get_type_id() == epee::net_utils::ipv6_network_address::get_type_id()) - res.white_list.emplace_back(entry.id, entry.adr.as<epee::net_utils::ipv6_network_address>().host_str(), + res.gray_list.emplace_back(entry.id, entry.adr.as<epee::net_utils::ipv6_network_address>().host_str(), entry.adr.as<epee::net_utils::ipv6_network_address>().port(), entry.last_seen, entry.pruning_seed, entry.rpc_port); else res.gray_list.emplace_back(entry.id, entry.adr.str(), entry.last_seen, entry.pruning_seed, entry.rpc_port); diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 05bfb1a6a..aed967efb 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -87,7 +87,7 @@ namespace cryptonote // advance which version they will stop working with // Don't go over 32767 for any of these #define CORE_RPC_VERSION_MAJOR 2 -#define CORE_RPC_VERSION_MINOR 8 +#define CORE_RPC_VERSION_MINOR 9 #define MAKE_CORE_RPC_VERSION(major,minor) (((major)<<16)|(minor)) #define CORE_RPC_VERSION MAKE_CORE_RPC_VERSION(CORE_RPC_VERSION_MAJOR, CORE_RPC_VERSION_MINOR) @@ -1230,7 +1230,10 @@ namespace cryptonote { struct request_t { + bool public_only; + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE_OPT(public_only, true) END_KV_SERIALIZE_MAP() }; typedef epee::misc_utils::struct_init<request_t> request; diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 9bae6c028..5d7321e48 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -201,11 +201,11 @@ namespace const char* USAGE_SET_DESCRIPTION("set_description [free text note]"); const char* USAGE_SIGN("sign <filename>"); const char* USAGE_VERIFY("verify <filename> <address> <signature>"); - const char* USAGE_EXPORT_KEY_IMAGES("export_key_images <filename>"); + const char* USAGE_EXPORT_KEY_IMAGES("export_key_images [all] <filename>"); const char* USAGE_IMPORT_KEY_IMAGES("import_key_images <filename>"); const char* USAGE_HW_KEY_IMAGES_SYNC("hw_key_images_sync"); const char* USAGE_HW_RECONNECT("hw_reconnect"); - const char* USAGE_EXPORT_OUTPUTS("export_outputs <filename>"); + const char* USAGE_EXPORT_OUTPUTS("export_outputs [all] <filename>"); const char* USAGE_IMPORT_OUTPUTS("import_outputs <filename>"); const char* USAGE_SHOW_TRANSFER("show_transfer <txid>"); const char* USAGE_MAKE_MULTISIG("make_multisig <threshold> <string1> [<string>...]"); @@ -803,6 +803,12 @@ bool simple_wallet::encrypted_seed(const std::vector<std::string> &args/* = std: return print_seed(true); } +bool simple_wallet::restore_height(const std::vector<std::string> &args/* = std::vector<std::string>()*/) +{ + success_msg_writer() << m_wallet->get_refresh_from_block_height(); + return true; +} + bool simple_wallet::seed_set_language(const std::vector<std::string> &args/* = std::vector<std::string>()*/) { if (m_wallet->key_on_device()) @@ -2689,7 +2695,7 @@ bool simple_wallet::set_device_name(const std::vector<std::string> &args/* = std return true; } - m_wallet->device_name(args[0]); + m_wallet->device_name(args[1]); bool r = false; try { r = m_wallet->reconnect_device(); @@ -2845,6 +2851,9 @@ simple_wallet::simple_wallet() m_cmd_binder.set_handler("seed", boost::bind(&simple_wallet::seed, this, _1), tr("Display the Electrum-style mnemonic seed")); + m_cmd_binder.set_handler("restore_height", + boost::bind(&simple_wallet::restore_height, this, _1), + tr("Display the restore height")); m_cmd_binder.set_handler("set", boost::bind(&simple_wallet::set_variable, this, _1), tr(USAGE_SET_VARIABLE), @@ -2881,6 +2890,8 @@ simple_wallet::simple_wallet() " Whether to warn if there is transaction backlog.\n " "confirm-backlog-threshold [n]\n " " Set a threshold for confirm-backlog to only warn if the transaction backlog is greater than n blocks.\n " + "confirm-export-overwrite <1|0>\n " + " Whether to warn if the file to be exported already exists.\n " "refresh-from-block-height [n]\n " " Set the height before which to ignore blocks.\n " "auto-low-priority <1|0>\n " @@ -2888,12 +2899,20 @@ simple_wallet::simple_wallet() "segregate-pre-fork-outputs <1|0>\n " " Set this if you intend to spend outputs on both Monero AND a key reusing fork.\n " "key-reuse-mitigation2 <1|0>\n " - " Set this if you are not sure whether you will spend on a key reusing Monero fork later.\n" + " Set this if you are not sure whether you will spend on a key reusing Monero fork later.\n " "subaddress-lookahead <major>:<minor>\n " " Set the lookahead sizes for the subaddress hash table.\n " " Set this if you are not sure whether you will spend on a key reusing Monero fork later.\n " "segregation-height <n>\n " - " Set to the height of a key reusing fork you want to use, 0 to use default.")); + " Set to the height of a key reusing fork you want to use, 0 to use default.\n " + "ignore-fractional-outputs <1|0>\n " + " Whether to ignore fractional outputs that result in net loss when spending due to fee.\n " + "track-uses <1|0>\n " + " Whether to keep track of owned outputs uses.\n " + "setup-background-mining <1|0>\n " + " Whether to enable background mining. Set this to support the network and to get a chance to receive new monero.\n " + "device-name <device_name[:device_spec]>\n " + " Device name for hardware wallet.")); m_cmd_binder.set_handler("encrypted_seed", boost::bind(&simple_wallet::encrypted_seed, this, _1), tr("Display the encrypted Electrum-style mnemonic seed.")); @@ -3130,7 +3149,7 @@ simple_wallet::simple_wallet() tr("Available options:\n " "auto-send <1|0>\n " " Whether to automatically send newly generated messages right away.\n ")); - m_cmd_binder.set_handler("mms send_message_config", + m_cmd_binder.set_handler("mms send_signer_config", boost::bind(&simple_wallet::mms, this, _1), tr(USAGE_MMS_SEND_SIGNER_CONFIG), tr("Send completed signer config to all other authorized signers")); @@ -3257,8 +3276,8 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args) success_msg_writer() << "segregation-height = " << m_wallet->segregation_height(); success_msg_writer() << "ignore-fractional-outputs = " << m_wallet->ignore_fractional_outputs(); success_msg_writer() << "track-uses = " << m_wallet->track_uses(); - success_msg_writer() << "setup-background-mining = " << setup_background_mining_string + tr(" (set this to support the network and to get a chance to receive new monero)"); - success_msg_writer() << "device_name = " << m_wallet->device_name(); + success_msg_writer() << "setup-background-mining = " << setup_background_mining_string; + success_msg_writer() << "device-name = " << m_wallet->device_name(); return true; } else @@ -7811,7 +7830,7 @@ bool simple_wallet::get_transfers(std::vector<std::string>& local_args, std::vec uint64_t fee = pd.m_amount_in - pd.m_amount_out; std::vector<std::pair<std::string, uint64_t>> destinations; for (const auto &d: pd.m_dests) { - destinations.push_back({get_account_address_as_str(m_wallet->nettype(), d.is_subaddress, d.addr), d.amount}); + destinations.push_back({d.address(m_wallet->nettype(), pd.m_payment_id), d.amount}); } std::string payment_id = string_tools::pod_to_hex(i->second.m_payment_id); if (payment_id.substr(16).find_first_not_of('0') == std::string::npos) @@ -7887,7 +7906,7 @@ bool simple_wallet::get_transfers(std::vector<std::string>& local_args, std::vec uint64_t fee = amount - pd.m_amount_out; std::vector<std::pair<std::string, uint64_t>> destinations; for (const auto &d: pd.m_dests) { - destinations.push_back({get_account_address_as_str(m_wallet->nettype(), d.is_subaddress, d.addr), d.amount}); + destinations.push_back({d.address(m_wallet->nettype(), pd.m_payment_id), d.amount}); } std::string payment_id = string_tools::pod_to_hex(i->second.m_payment_id); if (payment_id.substr(16).find_first_not_of('0') == std::string::npos) @@ -9044,21 +9063,31 @@ bool simple_wallet::verify(const std::vector<std::string> &args) return true; } //---------------------------------------------------------------------------------------------------- -bool simple_wallet::export_key_images(const std::vector<std::string> &args) +bool simple_wallet::export_key_images(const std::vector<std::string> &args_) { if (m_wallet->key_on_device()) { fail_msg_writer() << tr("command not supported by HW wallet"); return true; } - if (args.size() != 1) + auto args = args_; + + if (m_wallet->watch_only()) { - PRINT_USAGE(USAGE_EXPORT_KEY_IMAGES); + fail_msg_writer() << tr("wallet is watch-only and cannot export key images"); return true; } - if (m_wallet->watch_only()) + + bool all = false; + if (args.size() >= 2 && args[0] == "all") { - fail_msg_writer() << tr("wallet is watch-only and cannot export key images"); + all = true; + args.erase(args.begin()); + } + + if (args.size() != 1) + { + PRINT_USAGE(USAGE_EXPORT_KEY_IMAGES); return true; } @@ -9070,7 +9099,7 @@ bool simple_wallet::export_key_images(const std::vector<std::string> &args) try { - if (!m_wallet->export_key_images(filename)) + if (!m_wallet->export_key_images(filename, all)) { fail_msg_writer() << tr("failed to save file ") << filename; return true; @@ -9195,13 +9224,22 @@ bool simple_wallet::hw_reconnect(const std::vector<std::string> &args) return true; } //---------------------------------------------------------------------------------------------------- -bool simple_wallet::export_outputs(const std::vector<std::string> &args) +bool simple_wallet::export_outputs(const std::vector<std::string> &args_) { if (m_wallet->key_on_device()) { fail_msg_writer() << tr("command not supported by HW wallet"); return true; } + auto args = args_; + + bool all = false; + if (args.size() >= 2 && args[0] == "all") + { + all = true; + args.erase(args.begin()); + } + if (args.size() != 1) { PRINT_USAGE(USAGE_EXPORT_OUTPUTS); @@ -9216,7 +9254,7 @@ bool simple_wallet::export_outputs(const std::vector<std::string> &args) try { - std::string data = m_wallet->export_outputs_to_str(); + std::string data = m_wallet->export_outputs_to_str(all); bool r = epee::file_io_utils::save_string_to_file(filename, data); if (!r) { @@ -9343,7 +9381,7 @@ bool simple_wallet::show_transfer(const std::vector<std::string> &args) for (const auto &d: pd.m_dests) { if (!dests.empty()) dests += ", "; - dests += get_account_address_as_str(m_wallet->nettype(), d.is_subaddress, d.addr) + ": " + print_money(d.amount); + dests += d.address(m_wallet->nettype(), pd.m_payment_id) + ": " + print_money(d.amount); } std::string payment_id = string_tools::pod_to_hex(i->second.m_payment_id); if (payment_id.substr(16).find_first_not_of('0') == std::string::npos) diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h index 4bf7fa334..2de390666 100644 --- a/src/simplewallet/simplewallet.h +++ b/src/simplewallet/simplewallet.h @@ -109,6 +109,7 @@ namespace cryptonote bool spendkey(const std::vector<std::string> &args = std::vector<std::string>()); bool seed(const std::vector<std::string> &args = std::vector<std::string>()); bool encrypted_seed(const std::vector<std::string> &args = std::vector<std::string>()); + bool restore_height(const std::vector<std::string> &args = std::vector<std::string>()); /*! * \brief Sets seed language. diff --git a/src/wallet/api/transaction_history.cpp b/src/wallet/api/transaction_history.cpp index f4ad8b1f6..ad7029a3c 100644 --- a/src/wallet/api/transaction_history.cpp +++ b/src/wallet/api/transaction_history.cpp @@ -181,7 +181,7 @@ void TransactionHistoryImpl::refresh() // single output transaction might contain multiple transfers for (const auto &d: pd.m_dests) { - ti->m_transfers.push_back({d.amount, get_account_address_as_str(m_wallet->m_wallet->nettype(), d.is_subaddress, d.addr)}); + ti->m_transfers.push_back({d.amount, d.address(m_wallet->m_wallet->nettype(), pd.m_payment_id)}); } m_history.push_back(ti); } diff --git a/src/wallet/message_store.cpp b/src/wallet/message_store.cpp index 7381005c1..96d4ef3ce 100644 --- a/src/wallet/message_store.cpp +++ b/src/wallet/message_store.cpp @@ -397,10 +397,9 @@ void message_store::stop_auto_config() for (uint32_t i = 0; i < m_num_authorized_signers; ++i) { authorized_signer &m = m_signers[i]; - if (!m.me && !m.auto_config_transport_address.empty()) + if (!m.auto_config_transport_address.empty()) { - // Try to delete those "unused API" addresses in PyBitmessage, especially since - // it seems it's not possible to delete them interactively, only to "disable" them + // Try to delete the chan that was used for auto-config m_transporter.delete_transport_address(m.auto_config_transport_address); } m.auto_config_token.clear(); @@ -429,14 +428,7 @@ void message_store::setup_signer_for_auto_config(uint32_t index, const std::stri m.auto_config_token = token; crypto::hash_to_scalar(token.data(), token.size(), m.auto_config_secret_key); crypto::secret_key_to_public_key(m.auto_config_secret_key, m.auto_config_public_key); - if (receiving) - { - m.auto_config_transport_address = m_transporter.derive_and_receive_transport_address(m.auto_config_token); - } - else - { - m.auto_config_transport_address = m_transporter.derive_transport_address(m.auto_config_token); - } + m.auto_config_transport_address = m_transporter.derive_transport_address(m.auto_config_token); } bool message_store::get_signer_index_by_monero_address(const cryptonote::account_public_address &monero_address, uint32_t &index) const diff --git a/src/wallet/message_transporter.cpp b/src/wallet/message_transporter.cpp index 2f8188a3c..cf9b45b37 100644 --- a/src/wallet/message_transporter.cpp +++ b/src/wallet/message_transporter.cpp @@ -192,47 +192,47 @@ bool message_transporter::delete_message(const std::string &transport_id) return true; } -// Deterministically derive a transport / Bitmessage address from 'seed' (the 10-hex-digits -// auto-config token will be used), but do not set it up for receiving in PyBitmessage as -// well, because it's possible the address will only ever be used to SEND auto-config data +// Deterministically derive a new transport address from 'seed' (the 10-hex-digits auto-config +// token will be used) and set it up for sending and receiving +// In a first attempt a normal Bitmessage address was used here, but it turned out the +// key exchange necessary to put it into service could take a long time or even did not +// work out at all sometimes. Also there were problems when deleting those temporary +// addresses again after auto-config. Now a chan is used which avoids all these drawbacks +// quite nicely. std::string message_transporter::derive_transport_address(const std::string &seed) { + // Don't use the seed directly as chan name; that would be too dangerous, e.g. in the + // case of a PyBitmessage instance used by multiple unrelated people + // If an auto-config token gets hashed in another context use different salt instead of "chan" + std::string salted_seed = seed + "chan"; + std::string chan_name = epee::string_tools::pod_to_hex(crypto::cn_fast_hash(salted_seed.data(), salted_seed.size())); + + // Calculate the Bitmessage address that the chan will get for being able to + // use 'joinChain', as 'createChan' will fail and not tell the address if the chan + // already exists (which it can if all auto-config participants share a PyBitmessage + // instance). 'joinChan' will also fail in that case, but that won't matter. std::string request; start_xml_rpc_cmd(request, "getDeterministicAddress"); - add_xml_rpc_base64_param(request, seed); + add_xml_rpc_base64_param(request, chan_name); add_xml_rpc_integer_param(request, 4); // addressVersionNumber add_xml_rpc_integer_param(request, 1); // streamNumber end_xml_rpc_cmd(request); std::string answer; post_request(request, answer); std::string address = get_str_between_tags(answer, "<string>", "</string>"); - return address; -} - -// Derive a transport address and configure it for receiving in PyBitmessage, typically -// for receiving auto-config messages by the wallet of the auto-config organizer -std::string message_transporter::derive_and_receive_transport_address(const std::string &seed) -{ - // We need to call both "get_deterministic_address" AND "createDeterministicAddresses" - // because we won't get back the address from the latter call if it exists already - std::string address = derive_transport_address(seed); - std::string request; - start_xml_rpc_cmd(request, "createDeterministicAddresses"); - add_xml_rpc_base64_param(request, seed); - add_xml_rpc_integer_param(request, 1); // numberOfAddresses - add_xml_rpc_integer_param(request, 4); // addressVersionNumber + start_xml_rpc_cmd(request, "joinChan"); + add_xml_rpc_base64_param(request, chan_name); + add_xml_rpc_string_param(request, address); end_xml_rpc_cmd(request); - std::string answer; post_request(request, answer); - return address; } bool message_transporter::delete_transport_address(const std::string &transport_address) { std::string request; - start_xml_rpc_cmd(request, "deleteAddress"); + start_xml_rpc_cmd(request, "leaveChan"); add_xml_rpc_string_param(request, transport_address); end_xml_rpc_cmd(request); std::string answer; @@ -270,7 +270,22 @@ bool message_transporter::post_request(const std::string &request, std::string & std::string string_value = get_str_between_tags(answer, "<string>", "</string>"); if ((string_value.find("API Error") == 0) || (string_value.find("RPC ") == 0)) { - THROW_WALLET_EXCEPTION(tools::error::bitmessage_api_error, string_value); + if ((string_value.find("API Error 0021") == 0) && (request.find("joinChan") != std::string::npos)) + { + // Error that occurs if one tries to join an already joined chan, which can happen + // if several auto-config participants share one PyBitmessage instance: As a little + // hack simply ignore the error. (A clean solution would be to check for the chan + // with 'listAddresses2', but parsing the returned array is much more complicated.) + } + else if ((string_value.find("API Error 0013") == 0) && (request.find("leaveChan") != std::string::npos)) + { + // Error that occurs if one tries to leave an already left / deleted chan, which can happen + // if several auto-config participants share one PyBitmessage instance: Also ignore. + } + else + { + THROW_WALLET_EXCEPTION(tools::error::bitmessage_api_error, string_value); + } } return r; diff --git a/src/wallet/message_transporter.h b/src/wallet/message_transporter.h index 736fc9b63..28c099d87 100644 --- a/src/wallet/message_transporter.h +++ b/src/wallet/message_transporter.h @@ -91,7 +91,6 @@ public: bool delete_message(const std::string &transport_id); void stop() { m_run.store(false, std::memory_order_relaxed); } std::string derive_transport_address(const std::string &seed); - std::string derive_and_receive_transport_address(const std::string &seed); bool delete_transport_address(const std::string &transport_address); private: diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 117ad4ea8..9782e4b1e 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -11607,10 +11607,10 @@ crypto::public_key wallet2::get_tx_pub_key_from_received_outs(const tools::walle return tx_pub_key; } -bool wallet2::export_key_images(const std::string &filename) const +bool wallet2::export_key_images(const std::string &filename, bool all) const { PERF_TIMER(export_key_images); - std::pair<size_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> ski = export_key_images(); + std::pair<size_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> ski = export_key_images(all); std::string magic(KEY_IMAGE_EXPORT_FILE_MAGIC, strlen(KEY_IMAGE_EXPORT_FILE_MAGIC)); const cryptonote::account_public_address &keys = get_account().get_keys().m_account_address; const uint32_t offset = ski.first; diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index a6d042297..c2e34dd76 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -1175,7 +1175,7 @@ private: void import_payments_out(const std::list<std::pair<crypto::hash,wallet2::confirmed_transfer_details>> &confirmed_payments); std::tuple<size_t, crypto::hash, std::vector<crypto::hash>> export_blockchain() const; void import_blockchain(const std::tuple<size_t, crypto::hash, std::vector<crypto::hash>> &bc); - bool export_key_images(const std::string &filename) const; + bool export_key_images(const std::string &filename, bool all = false) const; std::pair<size_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> export_key_images(bool all = false) const; uint64_t import_key_images(const std::vector<std::pair<crypto::key_image, crypto::signature>> &signed_key_images, size_t offset, uint64_t &spent, uint64_t &unspent, bool check_spent = true); uint64_t import_key_images(const std::string &filename, uint64_t &spent, uint64_t &unspent); diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index 844ecf90c..c64b662f3 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -352,7 +352,7 @@ namespace tools entry.destinations.push_back(wallet_rpc::transfer_destination()); wallet_rpc::transfer_destination &td = entry.destinations.back(); td.amount = d.amount; - td.address = d.original.empty() ? get_account_address_as_str(m_wallet->nettype(), d.is_subaddress, d.addr) : d.original; + td.address = d.address(m_wallet->nettype(), pd.m_payment_id); } entry.type = "out"; @@ -382,7 +382,7 @@ namespace tools entry.destinations.push_back(wallet_rpc::transfer_destination()); wallet_rpc::transfer_destination &td = entry.destinations.back(); td.amount = d.amount; - td.address = d.original.empty() ? get_account_address_as_str(m_wallet->nettype(), d.is_subaddress, d.addr) : d.original; + td.address = d.address(m_wallet->nettype(), pd.m_payment_id); } entry.type = is_failed ? "failed" : "pending"; |