From f6dbb967f8a8207b70d8c1f6269fabc237f7c535 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 21 Mar 2018 19:00:27 +0000 Subject: [PATCH 01/42] simplewallet: add --untrusted-daemon option --- src/simplewallet/simplewallet.cpp | 56 ++++++++++++++++++------------- src/simplewallet/simplewallet.h | 3 +- 2 files changed, 34 insertions(+), 25 deletions(-) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index d573f317b..f8b34f8a4 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -131,6 +131,7 @@ namespace const command_line::arg_descriptor arg_restore_multisig_wallet = {"restore-multisig-wallet", sw::tr("Recover multisig wallet using Electrum-style mnemonic seed"), false}; const command_line::arg_descriptor arg_non_deterministic = {"non-deterministic", sw::tr("Generate non-deterministic view and spend keys"), false}; const command_line::arg_descriptor arg_trusted_daemon = {"trusted-daemon", sw::tr("Enable commands which rely on a trusted daemon"), false}; + const command_line::arg_descriptor arg_untrusted_daemon = {"untrusted-daemon", sw::tr("Disable commands which rely on a trusted daemon"), false}; const command_line::arg_descriptor arg_allow_mismatched_daemon_version = {"allow-mismatched-daemon-version", sw::tr("Allow communicating with a daemon that uses a different RPC version"), false}; const command_line::arg_descriptor arg_restore_height = {"restore-height", sw::tr("Restore from specific blockchain height"), 0}; const command_line::arg_descriptor arg_do_not_relay = {"do-not-relay", sw::tr("The newly created transaction will not be relayed to the monero network"), false}; @@ -1077,7 +1078,7 @@ bool simple_wallet::import_multisig(const std::vector &args) fail_msg_writer() << tr("Failed to import multisig info: ") << e.what(); return true; } - if (m_trusted_daemon) + if (is_daemon_trusted()) { try { @@ -1229,7 +1230,7 @@ bool simple_wallet::submit_multisig(const std::vector &args) } catch (const std::exception &e) { - handle_transfer_exception(std::current_exception(), m_trusted_daemon); + handle_transfer_exception(std::current_exception(), is_daemon_trusted()); } catch (...) { @@ -3117,18 +3118,21 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm) return false; } - // set --trusted-daemon if local - try + // set --trusted-daemon if local and not overridden + if (!m_trusted_daemon) { - if (tools::is_local_address(m_wallet->get_daemon_address())) + try { - MINFO(tr("Daemon is local, assuming trusted")); - m_trusted_daemon = true; + if (tools::is_local_address(m_wallet->get_daemon_address())) + { + MINFO(tr("Daemon is local, assuming trusted")); + m_trusted_daemon = true; + } } + catch (const std::exception &e) { } } - catch (const std::exception &e) { } - if (!m_trusted_daemon) + if (!is_daemon_trusted()) message_writer() << (boost::format(tr("Warning: using an untrusted daemon at %s, privacy will be lessened")) % m_wallet->get_daemon_address()).str(); if (m_wallet->get_ring_database().empty()) @@ -3162,7 +3166,10 @@ bool simple_wallet::handle_command_line(const boost::program_options::variables_ m_restore_deterministic_wallet = command_line::get_arg(vm, arg_restore_deterministic_wallet); m_restore_multisig_wallet = command_line::get_arg(vm, arg_restore_multisig_wallet); m_non_deterministic = command_line::get_arg(vm, arg_non_deterministic); - m_trusted_daemon = command_line::get_arg(vm, arg_trusted_daemon); + if (!command_line::is_arg_defaulted(vm, arg_trusted_daemon) || !command_line::is_arg_defaulted(vm, arg_untrusted_daemon)) + m_trusted_daemon = command_line::get_arg(vm, arg_trusted_daemon) && !command_line::get_arg(vm, arg_untrusted_daemon); + if (!command_line::is_arg_defaulted(vm, arg_trusted_daemon) && !command_line::is_arg_defaulted(vm, arg_untrusted_daemon)) + message_writer() << tr("--trusted-daemon and --untrusted-daemon are both seen, assuming untrusted"); m_allow_mismatched_daemon_version = command_line::get_arg(vm, arg_allow_mismatched_daemon_version); m_restore_height = command_line::get_arg(vm, arg_restore_height); m_do_not_relay = command_line::get_arg(vm, arg_do_not_relay); @@ -3649,7 +3656,7 @@ bool simple_wallet::save_watch_only(const std::vector &args/* = std //---------------------------------------------------------------------------------------------------- bool simple_wallet::start_mining(const std::vector& args) { - if (!m_trusted_daemon) + if (!is_daemon_trusted()) { fail_msg_writer() << tr("this command requires a trusted daemon. Enable with --trusted-daemon"); return true; @@ -4145,7 +4152,7 @@ bool simple_wallet::show_blockchain_height(const std::vector& args) //---------------------------------------------------------------------------------------------------- bool simple_wallet::rescan_spent(const std::vector &args) { - if (!m_trusted_daemon) + if (!is_daemon_trusted()) { fail_msg_writer() << tr("this command requires a trusted daemon. Enable with --trusted-daemon"); return true; @@ -4491,16 +4498,16 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vectorcreate_transactions_2(dsts, fake_outs_count, unlock_block /* unlock_time */, priority, extra, m_current_subaddress_account, subaddr_indices, m_trusted_daemon); + ptx_vector = m_wallet->create_transactions_2(dsts, fake_outs_count, unlock_block /* unlock_time */, priority, extra, m_current_subaddress_account, subaddr_indices, is_daemon_trusted()); break; case TransferNew: - ptx_vector = m_wallet->create_transactions_2(dsts, fake_outs_count, 0 /* unlock_time */, priority, extra, m_current_subaddress_account, subaddr_indices, m_trusted_daemon); + ptx_vector = m_wallet->create_transactions_2(dsts, fake_outs_count, 0 /* unlock_time */, priority, extra, m_current_subaddress_account, subaddr_indices, is_daemon_trusted()); break; default: LOG_ERROR("Unknown transfer method, using original"); /* FALLTHRU */ case TransferOriginal: - ptx_vector = m_wallet->create_transactions(dsts, fake_outs_count, 0 /* unlock_time */, priority, extra, m_trusted_daemon); + ptx_vector = m_wallet->create_transactions(dsts, fake_outs_count, 0 /* unlock_time */, priority, extra, is_daemon_trusted()); break; } @@ -4676,7 +4683,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector &args_) try { // figure out what tx will be necessary - auto ptx_vector = m_wallet->create_unmixable_sweep_transactions(m_trusted_daemon); + auto ptx_vector = m_wallet->create_unmixable_sweep_transactions(is_daemon_trusted()); if (ptx_vector.empty()) { @@ -4784,7 +4791,7 @@ bool simple_wallet::sweep_unmixable(const std::vector &args_) } catch (const std::exception &e) { - handle_transfer_exception(std::current_exception(), m_trusted_daemon); + handle_transfer_exception(std::current_exception(), is_daemon_trusted()); } catch (...) { @@ -4933,7 +4940,7 @@ bool simple_wallet::sweep_main(uint64_t below, const std::vector &a try { // figure out what tx will be necessary - auto ptx_vector = m_wallet->create_transactions_all(below, info.address, info.is_subaddress, fake_outs_count, 0 /* unlock_time */, priority, extra, m_current_subaddress_account, subaddr_indices, m_trusted_daemon); + auto ptx_vector = m_wallet->create_transactions_all(below, info.address, info.is_subaddress, fake_outs_count, 0 /* unlock_time */, priority, extra, m_current_subaddress_account, subaddr_indices, is_daemon_trusted()); if (ptx_vector.empty()) { @@ -5017,7 +5024,7 @@ bool simple_wallet::sweep_main(uint64_t below, const std::vector &a } catch (const std::exception& e) { - handle_transfer_exception(std::current_exception(), m_trusted_daemon); + handle_transfer_exception(std::current_exception(), is_daemon_trusted()); } catch (...) { @@ -5146,7 +5153,7 @@ bool simple_wallet::sweep_single(const std::vector &args_) try { // figure out what tx will be necessary - auto ptx_vector = m_wallet->create_transactions_single(ki, info.address, info.is_subaddress, fake_outs_count, 0 /* unlock_time */, priority, extra, m_trusted_daemon); + auto ptx_vector = m_wallet->create_transactions_single(ki, info.address, info.is_subaddress, fake_outs_count, 0 /* unlock_time */, priority, extra, is_daemon_trusted()); if (ptx_vector.empty()) { @@ -5216,7 +5223,7 @@ bool simple_wallet::sweep_single(const std::vector &args_) } catch (const std::exception& e) { - handle_transfer_exception(std::current_exception(), m_trusted_daemon); + handle_transfer_exception(std::current_exception(), is_daemon_trusted()); } catch (...) { @@ -5521,7 +5528,7 @@ bool simple_wallet::submit_transfer(const std::vector &args_) } catch (const std::exception& e) { - handle_transfer_exception(std::current_exception(), m_trusted_daemon); + handle_transfer_exception(std::current_exception(), is_daemon_trusted()); } catch (...) { @@ -7109,7 +7116,7 @@ bool simple_wallet::import_key_images(const std::vector &args) fail_msg_writer() << tr("command not supported by HW wallet"); return true; } - if (!m_trusted_daemon) + if (!is_daemon_trusted()) { fail_msg_writer() << tr("this command requires a trusted daemon. Enable with --trusted-daemon"); return true; @@ -7495,6 +7502,7 @@ int main(int argc, char* argv[]) command_line::add_arg(desc_params, arg_non_deterministic ); command_line::add_arg(desc_params, arg_electrum_seed ); command_line::add_arg(desc_params, arg_trusted_daemon); + command_line::add_arg(desc_params, arg_untrusted_daemon); command_line::add_arg(desc_params, arg_allow_mismatched_daemon_version); command_line::add_arg(desc_params, arg_restore_height); command_line::add_arg(desc_params, arg_do_not_relay); diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h index 39a91c5f5..7a788d432 100644 --- a/src/simplewallet/simplewallet.h +++ b/src/simplewallet/simplewallet.h @@ -229,6 +229,7 @@ namespace cryptonote bool print_ring_members(const std::vector& ptx_vector, std::ostream& ostr); std::string get_prompt() const; bool print_seed(bool encrypted); + bool is_daemon_trusted() const { return *m_trusted_daemon; } /*! * \brief Prints the seed with a nice message @@ -331,7 +332,7 @@ namespace cryptonote bool m_restore_deterministic_wallet; // recover flag bool m_restore_multisig_wallet; // recover flag bool m_non_deterministic; // old 2-random generation - bool m_trusted_daemon; + boost::optional m_trusted_daemon; bool m_allow_mismatched_daemon_version; bool m_restoring; // are we restoring, by whatever method? uint64_t m_restore_height; // optional From f6896d9974ec6a6c79f18892ee0224713bec105c Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 18 May 2018 09:38:38 +0100 Subject: [PATCH 02/42] core: lock incoming tx lock when checking the txpool and chain This gets rid of an innocuous race trying to add the same tx twice to the txpool --- src/cryptonote_core/cryptonote_core.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 668e7a2b7..6bfe2c182 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -676,6 +676,7 @@ namespace cryptonote bool core::handle_incoming_txs(const std::list& tx_blobs, std::vector& tvc, bool keeped_by_block, bool relayed, bool do_not_relay) { TRY_ENTRY(); + CRITICAL_REGION_LOCAL(m_incoming_tx_lock); struct result { bool res; cryptonote::transaction tx; crypto::hash hash; crypto::hash prefix_hash; bool in_txpool; bool in_blockchain; }; std::vector results(tx_blobs.size()); From e04ae088e8b92fe80ca8006bdf86e306a6b9ca53 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Thu, 24 May 2018 09:12:16 +0100 Subject: [PATCH 03/42] fix build with GCC 8.1.0 --- src/cryptonote_basic/account.cpp | 2 +- src/daemon/rpc_command_executor.cpp | 2 +- src/rpc/core_rpc_server_commands_defs.h | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/cryptonote_basic/account.cpp b/src/cryptonote_basic/account.cpp index bab991d19..aac6ec22b 100644 --- a/src/cryptonote_basic/account.cpp +++ b/src/cryptonote_basic/account.cpp @@ -157,7 +157,7 @@ DISABLE_VS_WARNINGS(4244 4345) void account_base::create_from_viewkey(const cryptonote::account_public_address& address, const crypto::secret_key& viewkey) { crypto::secret_key fake; - memset(&fake, 0, sizeof(fake)); + memset(&unwrap(fake), 0, sizeof(fake)); create_from_keys(address, fake, viewkey); } //----------------------------------------------------------------- diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp index 2efb501ea..c6dd9f538 100644 --- a/src/daemon/rpc_command_executor.cpp +++ b/src/daemon/rpc_command_executor.cpp @@ -973,7 +973,7 @@ bool t_rpc_command_executor::print_transaction_pool_stats() { } else { - memset(&res.pool_stats, 0, sizeof(res.pool_stats)); + res.pool_stats = {}; if (!m_rpc_server->on_get_transaction_pool_stats(req, res, false) || res.status != CORE_RPC_STATUS_OK) { tools::fail_msg_writer() << make_error(fail_message, res.status); diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 250c88e90..1227afef5 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -1554,6 +1554,8 @@ namespace cryptonote std::vector histo; uint32_t num_double_spends; + txpool_stats(): bytes_total(0), bytes_min(0), bytes_max(0), bytes_med(0), fee_total(0), oldest(0), txs_total(0), num_failing(0), num_10m(0), num_not_relayed(0), histo_98pc(0), num_double_spends(0) {} + BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(bytes_total) KV_SERIALIZE(bytes_min) From 81e39263043c34de5806e955b6c8ffbac7cac819 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 28 May 2018 14:55:09 +0100 Subject: [PATCH 04/42] disable file size sanity check when loading the wallet cache --- contrib/epee/include/file_io_utils.h | 6 +++--- src/wallet/wallet2.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/contrib/epee/include/file_io_utils.h b/contrib/epee/include/file_io_utils.h index 196610674..0afff800f 100644 --- a/contrib/epee/include/file_io_utils.h +++ b/contrib/epee/include/file_io_utils.h @@ -128,7 +128,7 @@ namespace file_io_utils inline - bool load_file_to_string(const std::string& path_to_file, std::string& target_str) + bool load_file_to_string(const std::string& path_to_file, std::string& target_str, size_t max_size = 1000000000) { #ifdef WIN32 WCHAR wide_path[1000]; @@ -139,7 +139,7 @@ namespace file_io_utils if (file_handle == INVALID_HANDLE_VALUE) return false; DWORD file_size = GetFileSize(file_handle, NULL); - if ((file_size == INVALID_FILE_SIZE) || (file_size > 1000000000)) { + if ((file_size == INVALID_FILE_SIZE) || (uint64_t)file_size > (uint64_t)max_size) { CloseHandle(file_handle); return false; } @@ -159,7 +159,7 @@ namespace file_io_utils std::ifstream::pos_type file_size = fstream.tellg(); - if(file_size > 1000000000) + if((uint64_t)file_size > (uint64_t)max_size) // ensure a large domain for comparison, and negative -> too large return false;//don't go crazy size_t file_size_t = static_cast(file_size); diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index b29aea17b..78cd0cf10 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -3772,7 +3772,7 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass { wallet2::cache_file_data cache_file_data; std::string buf; - bool r = epee::file_io_utils::load_file_to_string(m_wallet_file, buf); + bool r = epee::file_io_utils::load_file_to_string(m_wallet_file, buf, std::numeric_limits::max()); THROW_WALLET_EXCEPTION_IF(!r, error::file_read_error, m_wallet_file); // try to read it as an encrypted cache From 740085271b65b50a48dd800f87a37d3406f6102e Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Thu, 31 May 2018 12:13:03 +0100 Subject: [PATCH 05/42] daemon: fix readline interfering with std::cerr usage Once readline is initialized, std::cerr's operator<< will output a 0xff byte for unknown reasons. --- src/daemon/main.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/daemon/main.cpp b/src/daemon/main.cpp index 49494e889..fd70c367c 100644 --- a/src/daemon/main.cpp +++ b/src/daemon/main.cpp @@ -262,6 +262,9 @@ int main(int argc, char const * argv[]) } else { +#ifdef HAVE_READLINE + rdln::suspend_readline pause_readline; +#endif std::cerr << "Unknown command: " << command.front() << std::endl; return 1; } From 1d3874dabf3c3abf486f2ad9e68866d9cb9cd56c Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 1 Jun 2018 21:09:46 +0100 Subject: [PATCH 06/42] epee: fix detection of 172.16.0.0/172.31.255.255 local IP range --- contrib/epee/include/net/local_ip.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/epee/include/net/local_ip.h b/contrib/epee/include/net/local_ip.h index 0d458963c..52c5855b9 100644 --- a/contrib/epee/include/net/local_ip.h +++ b/contrib/epee/include/net/local_ip.h @@ -48,7 +48,7 @@ namespace epee if( (ip | 0xffffff00) == 0xffffffac) { - uint32_t second_num = (ip << 8) & 0xff000000; + uint32_t second_num = (ip >> 8) & 0xff; if(second_num >= 16 && second_num <= 31 ) return true; } From 8e64b616636e99c7911434289ad2df2d9506ac11 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 1 Jun 2018 21:52:04 +0100 Subject: [PATCH 07/42] blockchain: return error when requesting non existent output avoids RPC thread dying, causing the wallet to timeout --- src/cryptonote_core/blockchain.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index d3adc364b..3415d1d74 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -1941,14 +1941,21 @@ bool Blockchain::get_outs(const COMMAND_RPC_GET_OUTPUTS_BIN::request& req, COMMA res.outs.clear(); res.outs.reserve(req.outputs.size()); - for (const auto &i: req.outputs) + try { - // get tx_hash, tx_out_index from DB - const output_data_t od = m_db->get_output_key(i.amount, i.index); - tx_out_index toi = m_db->get_output_tx_and_index(i.amount, i.index); - bool unlocked = is_tx_spendtime_unlocked(m_db->get_tx_unlock_time(toi.first)); + for (const auto &i: req.outputs) + { + // get tx_hash, tx_out_index from DB + const output_data_t od = m_db->get_output_key(i.amount, i.index); + tx_out_index toi = m_db->get_output_tx_and_index(i.amount, i.index); + bool unlocked = is_tx_spendtime_unlocked(m_db->get_tx_unlock_time(toi.first)); - res.outs.push_back({od.pubkey, od.commitment, unlocked, od.height, toi.first}); + res.outs.push_back({od.pubkey, od.commitment, unlocked, od.height, toi.first}); + } + } + catch (const std::exception &e) + { + return false; } return true; } From 1380b70e74de8a665bb06eb33a3ea613230a075c Mon Sep 17 00:00:00 2001 From: "rockhouse@users.noreply.github.com" Date: Mon, 4 Jun 2018 12:02:06 +0200 Subject: [PATCH 08/42] Fixes #3645: error on freebsd lambda return values forced to std::string --- src/blockchain_utilities/blockchain_blackball.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/blockchain_utilities/blockchain_blackball.cpp b/src/blockchain_utilities/blockchain_blackball.cpp index 1243822bb..a613d73ad 100644 --- a/src/blockchain_utilities/blockchain_blackball.cpp +++ b/src/blockchain_utilities/blockchain_blackball.cpp @@ -165,7 +165,7 @@ int main(int argc, char* argv[]) "blackball-db-dir", "Specify blackball database directory", get_default_db_path(), {{ &arg_testnet_on, &arg_stagenet_on }}, - [](std::array testnet_stagenet, bool defaulted, std::string val) { + [](std::array testnet_stagenet, bool defaulted, std::string val)->std::string { if (testnet_stagenet[0]) return (boost::filesystem::path(val) / "testnet").string(); else if (testnet_stagenet[1]) From 233a1ead224bbfc2acbeec3c505c051e01eca98f Mon Sep 17 00:00:00 2001 From: stoffu Date: Mon, 4 Jun 2018 20:46:24 +0900 Subject: [PATCH 09/42] blockchain: pop forked blocks only when DB is not read-only --- src/cryptonote_core/blockchain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 3415d1d74..ee9c8bb4a 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -442,7 +442,7 @@ bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline m_db->block_txn_stop(); uint64_t num_popped_blocks = 0; - while (true) + while (!m_db->is_read_only()) { const uint64_t top_height = m_db->height() - 1; const crypto::hash top_id = m_db->top_block_hash(); From 85d2ae4ad7f9ef162d68f46e9297407d24d6b383 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 5 Jun 2018 10:45:01 +0100 Subject: [PATCH 10/42] simplewallet: add optional trusted/untrusted argument to set_daemon Otherwise the previous daemon's trustedness would carry over. If not specified, the local address check is performed again. --- src/simplewallet/simplewallet.cpp | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index f8b34f8a4..3a2d020d0 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -2028,7 +2028,7 @@ simple_wallet::simple_wallet() tr("Stop mining in the daemon.")); m_cmd_binder.set_handler("set_daemon", boost::bind(&simple_wallet::set_daemon, this, _1), - tr("set_daemon [:]"), + tr("set_daemon [:] [trusted|untrusted]"), tr("Set another daemon to connect to.")); m_cmd_binder.set_handler("save_bc", boost::bind(&simple_wallet::save_bc, this, _1), @@ -3767,6 +3767,33 @@ bool simple_wallet::set_daemon(const std::vector& args) } LOCK_IDLE_SCOPE(); m_wallet->init(daemon_url); + + if (args.size() == 2) + { + if (args[1] == "trusted") + m_trusted_daemon = true; + else if (args[1] == "untrusted") + m_trusted_daemon = false; + else + { + fail_msg_writer() << tr("Expected trusted or untrusted, got ") << args[1] << ": assuming untrusted"; + m_trusted_daemon = false; + } + } + else + { + m_trusted_daemon = false; + try + { + if (tools::is_local_address(m_wallet->get_daemon_address())) + { + MINFO(tr("Daemon is local, assuming trusted")); + m_trusted_daemon = true; + } + } + catch (const std::exception &e) { } + } + success_msg_writer() << boost::format("Daemon set to %s, %s") % daemon_url % (*m_trusted_daemon ? tr("trusted") : tr("untrusted")); } else { fail_msg_writer() << tr("This does not seem to be a valid daemon URL."); } From 082e0a1bef720c83068b31344387f74c1d86063c Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 5 Jun 2018 11:32:35 +0100 Subject: [PATCH 11/42] util: consider Tor/I2P addresses to be non local --- src/common/util.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/common/util.cpp b/src/common/util.cpp index 7e77e19b1..d17d24928 100644 --- a/src/common/util.cpp +++ b/src/common/util.cpp @@ -657,6 +657,13 @@ std::string get_nix_version_display_string() bool is_local_address(const std::string &address) { + // always assume Tor/I2P addresses to be untrusted by default + if (boost::ends_with(address, ".onion") || boost::ends_with(address, ".i2p")) + { + MDEBUG("Address '" << address << "' is Tor/I2P, non local"); + return false; + } + // extract host epee::net_utils::http::url_content u_c; if (!epee::net_utils::parse_url(address, u_c)) From b85169a5b6351279319345399bdc5402f4977836 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 5 Jun 2018 16:54:46 +0100 Subject: [PATCH 12/42] README: mention --untrusted-daemon when connecting the wallet to a daemon on a tor hidden service --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 197c560dc..067871a48 100644 --- a/README.md +++ b/README.md @@ -547,6 +547,8 @@ setting the following configuration parameters and environment variables: as well. * Do NOT pass `--detach` when running through torsocks with systemd, (see [utils/systemd/monerod.service](utils/systemd/monerod.service) for details). +* If you use the wallet with a Tor daemon via the loopback IP (eg, 127.0.0.1:9050), + then use `--untrusted-daemon` unless it is your own hidden service. Example command line to start monerod through Tor: From 4e2b279a940e09fd90525f3afa91176ff40b7c6b Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 5 Jun 2018 19:59:45 +0100 Subject: [PATCH 13/42] tx_pool: initialize bitflags padding since it gets written to storage Avoids valgrind reporting uninitialized data usage --- src/blockchain_db/blockchain_db.h | 1 + src/cryptonote_core/tx_pool.cpp | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/blockchain_db/blockchain_db.h b/src/blockchain_db/blockchain_db.h index 1ed715315..442ae9e8b 100644 --- a/src/blockchain_db/blockchain_db.h +++ b/src/blockchain_db/blockchain_db.h @@ -148,6 +148,7 @@ struct txpool_tx_meta_t uint8_t relayed; uint8_t do_not_relay; uint8_t double_spend_seen: 1; + uint8_t bf_padding: 7; uint8_t padding[76]; // till 192 bytes }; diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index 5dfbc1dd4..684a6b363 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -239,6 +239,7 @@ namespace cryptonote meta.relayed = relayed; meta.do_not_relay = do_not_relay; meta.double_spend_seen = have_tx_keyimges_as_spent(tx); + meta.bf_padding = 0; memset(meta.padding, 0, sizeof(meta.padding)); try { @@ -278,6 +279,7 @@ namespace cryptonote meta.relayed = relayed; meta.do_not_relay = do_not_relay; meta.double_spend_seen = false; + meta.bf_padding = 0; memset(meta.padding, 0, sizeof(meta.padding)); try From 7ce841cc2ffa03ee2793c8c1b45e7da1c18d9f8e Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 6 Jun 2018 10:12:45 +0100 Subject: [PATCH 14/42] wallet: do not log by default if we're not asked to log to console This means monero-wallet-rpc still does, but the user level program does not. --- src/wallet/wallet_args.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/wallet/wallet_args.cpp b/src/wallet/wallet_args.cpp index a6ff63dd3..66a0f594b 100644 --- a/src/wallet/wallet_args.cpp +++ b/src/wallet/wallet_args.cpp @@ -179,6 +179,10 @@ namespace wallet_args { mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str()); } + else if (!log_to_console) + { + mlog_set_categories(""); + } if (notice) Print(print) << notice << ENDL; From 009feaca798162593bb5d9038d16e69d70a2f66a Mon Sep 17 00:00:00 2001 From: stoffu Date: Wed, 6 Jun 2018 20:33:01 +0900 Subject: [PATCH 15/42] wallet2: fix get_approximate_blockchain_height for stagenet --- src/wallet/wallet2.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 78cd0cf10..9f2c73ec2 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -9145,9 +9145,9 @@ uint64_t wallet2::get_daemon_blockchain_target_height(string &err) uint64_t wallet2::get_approximate_blockchain_height() const { // time of v2 fork - const time_t fork_time = m_nettype == TESTNET ? 1448285909 : m_nettype == STAGENET ? (time_t)-1/*TODO*/ : 1458748658; + const time_t fork_time = m_nettype == TESTNET ? 1448285909 : m_nettype == STAGENET ? 1520937818 : 1458748658; // v2 fork block - const uint64_t fork_block = m_nettype == TESTNET ? 624634 : m_nettype == STAGENET ? (uint64_t)-1/*TODO*/ : 1009827; + const uint64_t fork_block = m_nettype == TESTNET ? 624634 : m_nettype == STAGENET ? 32000 : 1009827; // avg seconds per block const int seconds_per_block = DIFFICULTY_TARGET_V2; // Calculated blockchain height From 505fde2e09f0ec72201f50683296c8b542380694 Mon Sep 17 00:00:00 2001 From: Gingeropolous Date: Fri, 8 Jun 2018 16:05:50 -0400 Subject: [PATCH 16/42] Update readme to include pcslite dependency Update readme to include pcslite dependency --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 067871a48..6192d12c5 100644 --- a/README.md +++ b/README.md @@ -188,6 +188,7 @@ library archives (`.a`). | GTest | 1.5 | YES | `libgtest-dev`^ | `gtest` | `gtest-devel` | YES | Test suite | | Doxygen | any | NO | `doxygen` | `doxygen` | `doxygen` | YES | Documentation | | Graphviz | any | NO | `graphviz` | `graphviz` | `graphviz` | YES | Documentation | +| pcsclite | ? | NO | `libpcsclite-dev` | ? | `pcsc-lite pcsc-lite-devel` | NO | Ledger | [^] On Debian/Ubuntu `libgtest-dev` only includes sources and headers. You must From 9c2f09df51f86ad9e62163584cb262da98ffac60 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sat, 26 May 2018 23:38:08 +0100 Subject: [PATCH 17/42] epee: fallback to a counter if gmtime fails when rotating logs --- contrib/epee/src/mlog.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contrib/epee/src/mlog.cpp b/contrib/epee/src/mlog.cpp index fb0b4ac2b..0c810729d 100644 --- a/contrib/epee/src/mlog.cpp +++ b/contrib/epee/src/mlog.cpp @@ -47,6 +47,7 @@ using namespace epee; static std::string generate_log_filename(const char *base) { std::string filename(base); + static unsigned int fallback_counter = 0; char tmp[200]; struct tm tm; time_t now = time(NULL); @@ -56,7 +57,7 @@ static std::string generate_log_filename(const char *base) #else (!gmtime_r(&now, &tm)) #endif - strcpy(tmp, "unknown"); + snprintf(tmp, sizeof(tmp), "part-%u", ++fallback_counter); else strftime(tmp, sizeof(tmp), "%Y-%m-%d-%H-%M-%S", &tm); tmp[sizeof(tmp) - 1] = 0; From 04abe99f815d42919db68a9683bd94dc9dc6c553 Mon Sep 17 00:00:00 2001 From: stoffu Date: Sun, 10 Jun 2018 20:00:59 +0900 Subject: [PATCH 18/42] simplewallet: don't confirm missing payment ID when sending to only subaddresses --- src/simplewallet/simplewallet.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 3a2d020d0..6298d284d 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -4453,6 +4453,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector dsts; + size_t num_subaddresses = 0; for (size_t i = 0; i < local_args.size(); i += 2) { cryptonote::address_parse_info info; @@ -4464,6 +4465,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vectorconfirm_missing_payment_id()) + if (!payment_id_seen && m_wallet->confirm_missing_payment_id() && dsts.size() > num_subaddresses) { std::string accepted = input_line(tr("No payment id is included with this transaction. Is this okay? (Y/Yes/N/No): ")); if (std::cin.eof()) @@ -4949,7 +4951,7 @@ bool simple_wallet::sweep_main(uint64_t below, const std::vector &a } // prompt is there is no payment id and confirmation is required - if (!payment_id_seen && m_wallet->confirm_missing_payment_id()) + if (!payment_id_seen && m_wallet->confirm_missing_payment_id() && !info.is_subaddress) { std::string accepted = input_line(tr("No payment id is included with this transaction. Is this okay? (Y/Yes/N/No): ")); if (std::cin.eof()) @@ -5162,7 +5164,7 @@ bool simple_wallet::sweep_single(const std::vector &args_) } // prompt if there is no payment id and confirmation is required - if (!payment_id_seen && m_wallet->confirm_missing_payment_id()) + if (!payment_id_seen && m_wallet->confirm_missing_payment_id() && !info.is_subaddress) { std::string accepted = input_line(tr("No payment id is included with this transaction. Is this okay? (Y/Yes/N/No): ")); if (std::cin.eof()) From d099dba9e1df74cefea9f5c1c75bb0b1c7bdace4 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Thu, 7 Jun 2018 12:43:10 +0100 Subject: [PATCH 19/42] epee: adaptive connection timeout system a connection's timeout is halved for every extra connection from the same host. Also keep track of when we don't need to use a connection anymore, so we can close it and free the resource for another connection. Also use the longer timeout for non routable local addresses. --- .../epee/include/net/abstract_tcp_server2.h | 10 ++- .../epee/include/net/abstract_tcp_server2.inl | 80 +++++++++++++++---- .../include/net/http_protocol_handler.inl | 3 +- contrib/epee/include/net/net_utils_base.h | 1 + tests/fuzz/levin.cpp | 1 + .../epee_levin_protocol_handler_async.cpp | 1 + 6 files changed, 77 insertions(+), 19 deletions(-) diff --git a/contrib/epee/include/net/abstract_tcp_server2.h b/contrib/epee/include/net/abstract_tcp_server2.h index 2f7325be5..7ca6ac872 100644 --- a/contrib/epee/include/net/abstract_tcp_server2.h +++ b/contrib/epee/include/net/abstract_tcp_server2.h @@ -119,6 +119,7 @@ namespace net_utils //----------------- i_service_endpoint --------------------- virtual bool do_send(const void* ptr, size_t cb); ///< (see do_send from i_service_endpoint) virtual bool do_send_chunk(const void* ptr, size_t cb); ///< will send (or queue) a part of data + virtual bool send_done(); virtual bool close(); virtual bool call_run_once_service_io(); virtual bool request_callback(); @@ -137,8 +138,11 @@ namespace net_utils /// reset connection timeout timer and callback void reset_timer(boost::posix_time::milliseconds ms, bool add); - boost::posix_time::milliseconds get_default_time() const; - boost::posix_time::milliseconds get_timeout_from_bytes_read(size_t bytes) const; + boost::posix_time::milliseconds get_default_timeout(); + boost::posix_time::milliseconds get_timeout_from_bytes_read(size_t bytes); + + /// host connection count tracking + unsigned int host_count(const std::string &host, int delta = 0); /// Buffer for incoming data. boost::array buffer_; @@ -165,6 +169,8 @@ namespace net_utils boost::asio::deadline_timer m_timer; bool m_local; + bool m_ready_to_close; + std::string m_host; public: void setRpcStation(); diff --git a/contrib/epee/include/net/abstract_tcp_server2.inl b/contrib/epee/include/net/abstract_tcp_server2.inl index 91a94c21e..134bb4199 100644 --- a/contrib/epee/include/net/abstract_tcp_server2.inl +++ b/contrib/epee/include/net/abstract_tcp_server2.inl @@ -56,8 +56,8 @@ #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "net" -#define DEFAULT_TIMEOUT_MS_LOCAL boost::posix_time::milliseconds(120000) // 2 minutes -#define DEFAULT_TIMEOUT_MS_REMOTE boost::posix_time::milliseconds(10000) // 10 seconds +#define DEFAULT_TIMEOUT_MS_LOCAL 1800000 // 30 minutes +#define DEFAULT_TIMEOUT_MS_REMOTE 300000 // 5 minutes #define TIMEOUT_EXTRA_MS_PER_BYTE 0.2 PRAGMA_WARNING_PUSH @@ -86,7 +86,8 @@ PRAGMA_WARNING_DISABLE_VS(4355) m_throttle_speed_in("speed_in", "throttle_speed_in"), m_throttle_speed_out("speed_out", "throttle_speed_out"), m_timer(io_service), - m_local(false) + m_local(false), + m_ready_to_close(false) { MDEBUG("test, connection constructor set m_connection_type="<(); const unsigned long ip_{boost::asio::detail::socket_ops::host_to_network_long(remote_ep.address().to_v4().to_ulong())}; - m_local = epee::net_utils::is_ip_loopback(ip_); + m_local = epee::net_utils::is_ip_loopback(ip_) || epee::net_utils::is_ip_local(ip_); // create a random uuid boost::uuids::uuid random_uuid; @@ -165,9 +166,12 @@ PRAGMA_WARNING_DISABLE_VS(4355) return false; } + m_host = context.m_remote_address.host_str(); + try { host_count(m_host, 1); } catch(...) { /* ignore */ } + m_protocol_handler.after_init_connection(); - reset_timer(get_default_time(), false); + reset_timer(get_default_timeout(), false); socket_.async_read_some(boost::asio::buffer(buffer_), strand_.wrap( @@ -324,6 +328,7 @@ PRAGMA_WARNING_DISABLE_VS(4355) logger_handle_net_read(bytes_transferred); context.m_last_recv = time(NULL); context.m_recv_cnt += bytes_transferred; + m_ready_to_close = false; bool recv_res = m_protocol_handler.handle_recv(buffer_.data(), bytes_transferred); if(!recv_res) { @@ -356,6 +361,13 @@ PRAGMA_WARNING_DISABLE_VS(4355) _dbg3("[sock " << socket_.native_handle() << "] Some problems at read: " << e.message() << ':' << e.value()); shutdown(); } + else + { + _dbg3("[sock " << socket_.native_handle() << "] peer closed connection"); + if (m_ready_to_close) + shutdown(); + } + m_ready_to_close = true; } // If an error occurs then no new asynchronous operations are started. This // means that all shared_ptr references to the connection object will @@ -531,7 +543,7 @@ PRAGMA_WARNING_DISABLE_VS(4355) if(m_send_que.size() > 1) { // active operation should be in progress, nothing to do, just wait last operation callback auto size_now = cb; - MDEBUG("do_send() NOW just queues: packet="<::handle_write, self, _1, _2) @@ -566,29 +578,51 @@ PRAGMA_WARNING_DISABLE_VS(4355) return true; - CATCH_ENTRY_L0("connection::do_send", false); + CATCH_ENTRY_L0("connection::do_send_chunk", false); } // do_send_chunk //--------------------------------------------------------------------------------- template - boost::posix_time::milliseconds connection::get_default_time() const + boost::posix_time::milliseconds connection::get_default_timeout() { + unsigned count; + try { count = host_count(m_host); } catch (...) { count = 0; } + const unsigned shift = std::min(std::max(count, 1u) - 1, 8u); + boost::posix_time::milliseconds timeout(0); if (m_local) - return DEFAULT_TIMEOUT_MS_LOCAL; + timeout = boost::posix_time::milliseconds(DEFAULT_TIMEOUT_MS_LOCAL >> shift); else - return DEFAULT_TIMEOUT_MS_REMOTE; + timeout = boost::posix_time::milliseconds(DEFAULT_TIMEOUT_MS_REMOTE >> shift); + return timeout; } //--------------------------------------------------------------------------------- template - boost::posix_time::milliseconds connection::get_timeout_from_bytes_read(size_t bytes) const + boost::posix_time::milliseconds connection::get_timeout_from_bytes_read(size_t bytes) { boost::posix_time::milliseconds ms = (boost::posix_time::milliseconds)(unsigned)(bytes * TIMEOUT_EXTRA_MS_PER_BYTE); ms += m_timer.expires_from_now(); - if (ms > get_default_time()) - ms = get_default_time(); + if (ms > get_default_timeout()) + ms = get_default_timeout(); return ms; } //--------------------------------------------------------------------------------- template + unsigned int connection::host_count(const std::string &host, int delta) + { + static boost::mutex hosts_mutex; + CRITICAL_REGION_LOCAL(hosts_mutex); + static std::map hosts; + unsigned int &val = hosts[host]; + if (delta > 0) + MTRACE("New connection from host " << host << ": " << val); + else if (delta < 0) + MTRACE("Closed connection from host " << host << ": " << val); + CHECK_AND_ASSERT_THROW_MES(delta >= 0 || val >= (unsigned)-delta, "Count would go negative"); + CHECK_AND_ASSERT_THROW_MES(delta <= 0 || val <= std::numeric_limits::max() - (unsigned)delta, "Count would wrap"); + val += delta; + return val; + } + //--------------------------------------------------------------------------------- + template void connection::reset_timer(boost::posix_time::milliseconds ms, bool add) { if (m_connection_type != e_connection_type_RPC) @@ -621,6 +655,11 @@ PRAGMA_WARNING_DISABLE_VS(4355) socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec); m_was_shutdown = true; m_protocol_handler.release_protocol(); + if (!m_host.empty()) + { + try { host_count(m_host, -1); } catch (...) { /* ignore */ } + m_host = ""; + } return true; } //--------------------------------------------------------------------------------- @@ -645,6 +684,15 @@ PRAGMA_WARNING_DISABLE_VS(4355) } //--------------------------------------------------------------------------------- template + bool connection::send_done() + { + if (m_ready_to_close) + return close(); + m_ready_to_close = true; + return true; + } + //--------------------------------------------------------------------------------- + template bool connection::cancel() { return close(); @@ -687,7 +735,7 @@ PRAGMA_WARNING_DISABLE_VS(4355) }else { //have more data to send - reset_timer(get_default_time(), false); + reset_timer(get_default_timeout(), false); auto size_now = m_send_que.front().size(); MDEBUG("handle_write() NOW SENDS: packet="<do_send((void*)response_data.data(), response_data.size()); if ((response.m_body.size() && (query_info.m_http_method != http::http_method_head)) || (query_info.m_http_method == http::http_method_options)) m_psnd_hndlr->do_send((void*)response.m_body.data(), response.m_body.size()); + m_psnd_hndlr->send_done(); return res; } //----------------------------------------------------------------------------------- diff --git a/contrib/epee/include/net/net_utils_base.h b/contrib/epee/include/net/net_utils_base.h index 7615786be..a133942fb 100644 --- a/contrib/epee/include/net/net_utils_base.h +++ b/contrib/epee/include/net/net_utils_base.h @@ -281,6 +281,7 @@ namespace net_utils { virtual bool do_send(const void* ptr, size_t cb)=0; virtual bool close()=0; + virtual bool send_done()=0; virtual bool call_run_once_service_io()=0; virtual bool request_callback()=0; virtual boost::asio::io_service& get_io_service()=0; diff --git a/tests/fuzz/levin.cpp b/tests/fuzz/levin.cpp index 6a164dda9..4ced1837f 100644 --- a/tests/fuzz/levin.cpp +++ b/tests/fuzz/levin.cpp @@ -158,6 +158,7 @@ namespace } virtual bool close() { return true; } + virtual bool send_done() { return true; } virtual bool call_run_once_service_io() { return true; } virtual bool request_callback() { return true; } virtual boost::asio::io_service& get_io_service() { return m_io_service; } diff --git a/tests/unit_tests/epee_levin_protocol_handler_async.cpp b/tests/unit_tests/epee_levin_protocol_handler_async.cpp index 38a8360d7..72d8f3205 100644 --- a/tests/unit_tests/epee_levin_protocol_handler_async.cpp +++ b/tests/unit_tests/epee_levin_protocol_handler_async.cpp @@ -150,6 +150,7 @@ namespace } virtual bool close() { /*std::cout << "test_connection::close()" << std::endl; */return true; } + virtual bool send_done() { /*std::cout << "test_connection::send_done()" << std::endl; */return true; } virtual bool call_run_once_service_io() { std::cout << "test_connection::call_run_once_service_io()" << std::endl; return true; } virtual bool request_callback() { std::cout << "test_connection::request_callback()" << std::endl; return true; } virtual boost::asio::io_service& get_io_service() { std::cout << "test_connection::get_io_service()" << std::endl; return m_io_service; } From 5e180c73f84bdadb43e604d3aa4b8da8912a720a Mon Sep 17 00:00:00 2001 From: stoffu Date: Tue, 12 Jun 2018 12:06:51 +0900 Subject: [PATCH 20/42] wallet2: use correct fee for split txes --- src/wallet/wallet2.cpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 9f2c73ec2..398e33187 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -7340,8 +7340,11 @@ std::vector wallet2::create_transactions_2(std::vector> outs; + TX() : bytes(0), needed_fee(0) {} + void add(const account_public_address &addr, bool is_subaddress, uint64_t amount, unsigned int original_output_index, bool merge_destinations) { if (merge_destinations) { @@ -7734,6 +7737,7 @@ std::vector wallet2::create_transactions_2(std::vector> &outs, */ unlock_time, /* CONST uint64_t unlock_time, */ - needed_fee, /* CONST uint64_t fee, */ + tx.needed_fee, /* CONST uint64_t fee, */ extra, /* const std::vector& extra, */ test_tx, /* OUT cryptonote::transaction& tx, */ test_ptx, /* OUT cryptonote::transaction& tx, */ @@ -7796,7 +7800,7 @@ skip_tx: fake_outs_count, tx.outs, unlock_time, - needed_fee, + tx.needed_fee, extra, detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), @@ -7817,7 +7821,7 @@ skip_tx: for (size_t idx: tx.selected_transfers) tx_money += m_transfers[idx].amount(); LOG_PRINT_L1(" Transaction " << (1+std::distance(txes.begin(), i)) << "/" << txes.size() << - ": " << get_size_string(tx.bytes) << ", sending " << print_money(tx_money) << " in " << tx.selected_transfers.size() << + " " << get_transaction_hash(tx.ptx.tx) << ": " << get_size_string(tx.bytes) << ", sending " << print_money(tx_money) << " in " << tx.selected_transfers.size() << " outputs to " << tx.dsts.size() << " destination(s), including " << print_money(tx.ptx.fee) << " fee, " << print_money(tx.ptx.change_dts.amount) << " change"); ptx_vector.push_back(tx.ptx); @@ -7916,7 +7920,10 @@ std::vector wallet2::create_transactions_from(const crypton cryptonote::transaction tx; pending_tx ptx; size_t bytes; + uint64_t needed_fee; std::vector> outs; + + TX() : bytes(0), needed_fee(0) {} }; std::vector txes; uint64_t needed_fee, available_for_fee = 0; @@ -8014,6 +8021,7 @@ std::vector wallet2::create_transactions_from(const crypton tx.ptx = test_ptx; tx.bytes = txBlob.size(); tx.outs = outs; + tx.needed_fee = needed_fee; accumulated_fee += test_ptx.fee; accumulated_change += test_ptx.change_dts.amount; if (!unused_transfers_indices.empty() || !unused_dust_indices.empty()) @@ -8034,10 +8042,10 @@ std::vector wallet2::create_transactions_from(const crypton cryptonote::transaction test_tx; pending_tx test_ptx; if (use_rct) { - transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, tx.outs, unlock_time, needed_fee, extra, + transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, tx.outs, unlock_time, tx.needed_fee, extra, test_tx, test_ptx, bulletproof); } else { - transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, tx.outs, unlock_time, needed_fee, extra, + transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, tx.outs, unlock_time, tx.needed_fee, extra, detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx); } auto txBlob = t_serializable_object_to_blob(test_ptx.tx); @@ -8054,7 +8062,7 @@ std::vector wallet2::create_transactions_from(const crypton for (size_t idx: tx.selected_transfers) tx_money += m_transfers[idx].amount(); LOG_PRINT_L1(" Transaction " << (1+std::distance(txes.begin(), i)) << "/" << txes.size() << - ": " << get_size_string(tx.bytes) << ", sending " << print_money(tx_money) << " in " << tx.selected_transfers.size() << + " " << get_transaction_hash(tx.ptx.tx) << ": " << get_size_string(tx.bytes) << ", sending " << print_money(tx_money) << " in " << tx.selected_transfers.size() << " outputs to " << tx.dsts.size() << " destination(s), including " << print_money(tx.ptx.fee) << " fee, " << print_money(tx.ptx.change_dts.amount) << " change"); ptx_vector.push_back(tx.ptx); From e70d80e820a1fdbb3585eb003f3f3e7a73e111ef Mon Sep 17 00:00:00 2001 From: stoffu Date: Wed, 13 Jun 2018 01:06:44 +0900 Subject: [PATCH 21/42] wallet2: use decoded amount when reporting repeated output key --- src/wallet/wallet2.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 398e33187..5266c5bde 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -1299,20 +1299,20 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote m_callback->on_money_received(height, txid, tx, td.m_amount, td.m_subaddr_index); } } - else if (m_transfers[kit->second].m_spent || m_transfers[kit->second].amount() >= tx.vout[o].amount) + else if (m_transfers[kit->second].m_spent || m_transfers[kit->second].amount() >= tx_scan_info[o].amount) { LOG_ERROR("Public key " << epee::string_tools::pod_to_hex(kit->first) - << " from received " << print_money(tx.vout[o].amount) << " output already exists with " + << " from received " << print_money(tx_scan_info[o].amount) << " output already exists with " << (m_transfers[kit->second].m_spent ? "spent" : "unspent") << " " - << print_money(m_transfers[kit->second].amount()) << ", received output ignored"); + << print_money(m_transfers[kit->second].amount()) << " in tx " << m_transfers[kit->second].m_txid << ", received output ignored"); } else { LOG_ERROR("Public key " << epee::string_tools::pod_to_hex(kit->first) - << " from received " << print_money(tx.vout[o].amount) << " output already exists with " + << " from received " << print_money(tx_scan_info[o].amount) << " output already exists with " << print_money(m_transfers[kit->second].amount()) << ", replacing with new output"); // The new larger output replaced a previous smaller one - tx_money_got_in_outs[tx_scan_info[o].received->index] -= tx.vout[o].amount; + tx_money_got_in_outs[tx_scan_info[o].received->index] -= tx_scan_info[o].amount; if (!pool) { From afa669656b943f225fd16d113cef156941b64977 Mon Sep 17 00:00:00 2001 From: stoffu Date: Tue, 12 Jun 2018 12:44:40 +0900 Subject: [PATCH 22/42] wallet: allow unspendable unmixable outputs to be discarded --- src/simplewallet/simplewallet.cpp | 14 ++++++++++++++ src/wallet/wallet2.cpp | 10 ++++++++++ src/wallet/wallet2.h | 1 + 3 files changed, 25 insertions(+) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 6298d284d..b0bb44acc 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -4818,6 +4818,20 @@ bool simple_wallet::sweep_unmixable(const std::vector &args_) commit_or_save(ptx_vector, m_do_not_relay); } } + catch (const tools::error::not_enough_unlocked_money& e) + { + fail_msg_writer() << tr("Not enough money in unlocked balance"); + std::string accepted = input_line((boost::format(tr("Discarding %s of unmixable outputs that cannot be spent, which can be undone by \"rescan_spent\". Is this okay? (Y/Yes/N/No): ")) % print_money(e.available())).str()); + if (std::cin.eof()) + return true; + if (command_line::is_yes(accepted)) + { + try + { + m_wallet->discard_unmixable_outputs(is_daemon_trusted()); + } catch (...) {} + } + } catch (const std::exception &e) { handle_transfer_exception(std::current_exception(), is_daemon_trusted()); diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 5266c5bde..8cace3f2b 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -8249,6 +8249,16 @@ std::vector wallet2::create_unmixable_sweep_transactions(bo return create_transactions_from(m_account_public_address, false, unmixable_transfer_outputs, unmixable_dust_outputs, 0 /*fake_outs_count */, 0 /* unlock_time */, 1 /*priority */, std::vector(), trusted_daemon); } +//---------------------------------------------------------------------------------------------------- +void wallet2::discard_unmixable_outputs(bool trusted_daemon) +{ + // may throw + std::vector unmixable_outputs = select_available_unmixable_outputs(trusted_daemon); + for (size_t idx : unmixable_outputs) + { + m_transfers[idx].m_spent = true; + } +} bool wallet2::get_tx_key(const crypto::hash &txid, crypto::secret_key &tx_key, std::vector &additional_tx_keys) const { diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 69b63876a..97a5df5a2 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -704,6 +704,7 @@ namespace tools bool sign_multisig_tx(multisig_tx_set &exported_txs, std::vector &txids); bool sign_multisig_tx_to_file(multisig_tx_set &exported_txs, const std::string &filename, std::vector &txids); std::vector create_unmixable_sweep_transactions(bool trusted_daemon); + void discard_unmixable_outputs(bool trusted_daemon); bool check_connection(uint32_t *version = NULL, uint32_t timeout = 200000); void get_transfers(wallet2::transfer_container& incoming_transfers) const; void get_payments(const crypto::hash& payment_id, std::list& payments, uint64_t min_height = 0, const boost::optional& subaddr_account = boost::none, const std::set& subaddr_indices = {}) const; From ed366efb8c2ccf9c46f74efe48001b3b1393c5a8 Mon Sep 17 00:00:00 2001 From: Jethro Grassie Date: Wed, 9 May 2018 21:48:19 -0400 Subject: [PATCH 23/42] add disclaimer about 3rd party packages Demoted the 3rd party maintained package installs to after compiling from repository source and removed the broken Homebrew package instructions. --- README.md | 83 +++++++++++++++++++++++++++---------------------------- 1 file changed, 40 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index 6192d12c5..8d9896abf 100644 --- a/README.md +++ b/README.md @@ -113,49 +113,6 @@ X's indicate that these details have not been determined as of commit date. Approximately three months prior to a scheduled software upgrade, a branch from Master will be created with the new release version tag. Pull requests that address bugs should then be made to both Master and the new release branch. Pull requests that require extensive review and testing (generally, optimizations and new features) should *not* be made to the release branch. -## Installing Monero from a package - -Packages are available for - -* Ubuntu and [snap supported](https://snapcraft.io/docs/core/install) systems, via a community contributed build. - - snap install monero --beta - -Installing a snap is very quick. Snaps are secure. They are isolated with all of their dependencies. Snaps also auto update when a new version is released. - -* Arch Linux (via [AUR](https://aur.archlinux.org/)): - - Stable release: [`monero`](https://aur.archlinux.org/packages/monero) - - Bleeding edge: [`monero-git`](https://aur.archlinux.org/packages/monero-git) - -* Void Linux: - - xbps-install -S monero - -* GuixSD - - guix package -i monero - -* OS X via [Homebrew](http://brew.sh) - - brew tap sammy007/cryptonight - brew install monero --build-from-source - -* Docker - - # Build using all available cores - docker build -t monero . - - # or build using a specific number of cores (reduce RAM requirement) - docker build --build-arg NPROC=1 -t monero . - - # either run in foreground - docker run -it -v /monero/chain:/root/.bitmonero -v /monero/wallet:/wallet -p 18080:18080 monero - - # or in background - docker run -it -d -v /monero/chain:/root/.bitmonero -v /monero/wallet:/wallet -p 18080:18080 monero - -Packaging for your favorite distribution would be a welcome contribution! - ## Compiling Monero from source ### Dependencies @@ -495,6 +452,46 @@ By default, in either dynamically or statically linked builds, binaries target t * ```make release-static-win64``` builds binaries on 64-bit Windows portable across 64-bit Windows systems * ```make release-static-win32``` builds binaries on 64-bit or 32-bit Windows portable across 32-bit Windows systems +## Installing Monero from a package + +**DISCLAIMER: These packages are not part of this repository or maintained by this project's contributors, and as such, do not go through the same review process to ensure their trustworthiness and security.** + +Packages are available for + +* Ubuntu and [snap supported](https://snapcraft.io/docs/core/install) systems, via a community contributed build. + + snap install monero --beta + +Installing a snap is very quick. Snaps are secure. They are isolated with all of their dependencies. Snaps also auto update when a new version is released. + +* Arch Linux (via [AUR](https://aur.archlinux.org/)): + - Stable release: [`monero`](https://aur.archlinux.org/packages/monero) + - Bleeding edge: [`monero-git`](https://aur.archlinux.org/packages/monero-git) + +* Void Linux: + + xbps-install -S monero + +* GuixSD + + guix package -i monero + +* Docker + + # Build using all available cores + docker build -t monero . + + # or build using a specific number of cores (reduce RAM requirement) + docker build --build-arg NPROC=1 -t monero . + + # either run in foreground + docker run -it -v /monero/chain:/root/.bitmonero -v /monero/wallet:/wallet -p 18080:18080 monero + + # or in background + docker run -it -d -v /monero/chain:/root/.bitmonero -v /monero/wallet:/wallet -p 18080:18080 monero + +Packaging for your favorite distribution would be a welcome contribution! + ## Running monerod The build places the binary in `bin/` sub-directory within the build directory From fbdc30966b51b5a518b1c40f393b675b4e314776 Mon Sep 17 00:00:00 2001 From: stoffu Date: Mon, 4 Jun 2018 19:18:18 +0900 Subject: [PATCH 24/42] wallet2: lower default for subaddress lookahead when restoring with hardware --- src/wallet/wallet2.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 8cace3f2b..2329839ec 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -3260,6 +3260,12 @@ void wallet2::restore(const std::string& wallet_, const epee::wipeable_string& p cryptonote::block b; generate_genesis(b); m_blockchain.push_back(get_block_hash(b)); + if (m_subaddress_lookahead_major == SUBADDRESS_LOOKAHEAD_MAJOR && m_subaddress_lookahead_minor == SUBADDRESS_LOOKAHEAD_MINOR) + { + // the default lookahead setting (50:200) is clearly too much for hardware wallet + m_subaddress_lookahead_major = 5; + m_subaddress_lookahead_minor = 20; + } add_subaddress_account(tr("Primary account")); if (!wallet_.empty()) { store(); From 9e9cd108a37fae2a7808738afbea4c42bd96d63d Mon Sep 17 00:00:00 2001 From: stoffu Date: Mon, 4 Jun 2018 16:54:35 +0900 Subject: [PATCH 25/42] Move parse_subaddress_lookahead() from simplewallet.cpp to util.cpp --- src/common/util.cpp | 18 ++++++++++++++++++ src/common/util.h | 3 +++ src/simplewallet/simplewallet.cpp | 17 +++-------------- 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/common/util.cpp b/src/common/util.cpp index d17d24928..8e4ea7fa5 100644 --- a/src/common/util.cpp +++ b/src/common/util.cpp @@ -757,4 +757,22 @@ std::string get_nix_version_display_string() return false; return true; } + + boost::optional> parse_subaddress_lookahead(const std::string& str) + { + auto pos = str.find(":"); + bool r = pos != std::string::npos; + uint32_t major; + r = r && epee::string_tools::get_xtype_from_string(major, str.substr(0, pos)); + uint32_t minor; + r = r && epee::string_tools::get_xtype_from_string(minor, str.substr(pos + 1)); + if (r) + { + return std::make_pair(major, minor); + } + else + { + return {}; + } + } } diff --git a/src/common/util.h b/src/common/util.h index d3ba47a4f..0bf5c941e 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -212,4 +213,6 @@ namespace tools bool sha256sum(const uint8_t *data, size_t len, crypto::hash &hash); bool sha256sum(const std::string &filename, crypto::hash &hash); + + boost::optional> parse_subaddress_lookahead(const std::string& str); } diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index b0bb44acc..3ce48fe7b 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -381,21 +381,10 @@ namespace boost::optional> parse_subaddress_lookahead(const std::string& str) { - auto pos = str.find(":"); - bool r = pos != std::string::npos; - uint32_t major; - r = r && epee::string_tools::get_xtype_from_string(major, str.substr(0, pos)); - uint32_t minor; - r = r && epee::string_tools::get_xtype_from_string(minor, str.substr(pos + 1)); - if (r) - { - return std::make_pair(major, minor); - } - else - { + auto r = tools::parse_subaddress_lookahead(str); + if (!r) fail_msg_writer() << tr("invalid format for subaddress lookahead; must be :"); - return {}; - } + return r; } void handle_transfer_exception(const std::exception_ptr &e, bool trusted_daemon) From 8fb50b738f09e8c883294f367cbfec0bcbf7264f Mon Sep 17 00:00:00 2001 From: stoffu Date: Mon, 4 Jun 2018 16:58:13 +0900 Subject: [PATCH 26/42] Wallet API: add support for wallet creation from hardware device --- src/wallet/api/wallet.cpp | 32 ++++++++++++++++++++++++++++++- src/wallet/api/wallet.h | 6 ++++++ src/wallet/api/wallet2_api.h | 32 +++++++++++++++++++++++++++++++ src/wallet/api/wallet_manager.cpp | 20 +++++++++++++++++++ src/wallet/api/wallet_manager.h | 6 ++++++ 5 files changed, 95 insertions(+), 1 deletion(-) diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index 367011eaa..c0a5e4780 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -338,6 +338,7 @@ WalletImpl::WalletImpl(NetworkType nettype) , m_trustedDaemon(false) , m_wallet2Callback(nullptr) , m_recoveringFromSeed(false) + , m_recoveringFromDevice(false) , m_synchronized(false) , m_rebuildWalletCache(false) , m_is_connected(false) @@ -385,6 +386,7 @@ bool WalletImpl::create(const std::string &path, const std::string &password, co clearStatus(); m_recoveringFromSeed = false; + m_recoveringFromDevice = false; bool keys_file_exists; bool wallet_file_exists; tools::wallet2::wallet_exists(path, keys_file_exists, wallet_file_exists); @@ -584,11 +586,28 @@ bool WalletImpl::recoverFromKeysWithPassword(const std::string &path, return true; } +bool WalletImpl::recoverFromDevice(const std::string &path, const std::string &password, const std::string &device_name) +{ + clearStatus(); + m_recoveringFromSeed = false; + m_recoveringFromDevice = true; + try + { + m_wallet->restore(path, password, device_name); + LOG_PRINT_L1("Generated new wallet from device: " + device_name); + } + catch (const std::exception& e) { + setStatusError(string(tr("failed to generate new wallet: ")) + e.what()); + return false; + } + return true; +} bool WalletImpl::open(const std::string &path, const std::string &password) { clearStatus(); m_recoveringFromSeed = false; + m_recoveringFromDevice = false; try { // TODO: handle "deprecated" // Check if wallet cache exists @@ -628,6 +647,7 @@ bool WalletImpl::recover(const std::string &path, const std::string &password, c } m_recoveringFromSeed = true; + m_recoveringFromDevice = false; crypto::secret_key recovery_key; std::string old_language; if (!crypto::ElectrumWords::words_to_bytes(seed, recovery_key, old_language)) { @@ -837,6 +857,16 @@ void WalletImpl::setRecoveringFromSeed(bool recoveringFromSeed) m_recoveringFromSeed = recoveringFromSeed; } +void WalletImpl::setRecoveringFromDevice(bool recoveringFromDevice) +{ + m_recoveringFromDevice = recoveringFromDevice; +} + +void WalletImpl::setSubaddressLookahead(uint32_t major, uint32_t minor) +{ + m_wallet->set_subaddress_lookahead(major, minor); +} + uint64_t WalletImpl::balance(uint32_t accountIndex) const { return m_wallet->balance(accountIndex); @@ -1839,7 +1869,7 @@ bool WalletImpl::isNewWallet() const // with the daemon (pull hashes instead of pull blocks). // If wallet cache is rebuilt, creation height stored in .keys is used. // Watch only wallet is a copy of an existing wallet. - return !(blockChainHeight() > 1 || m_recoveringFromSeed || m_rebuildWalletCache) && !watchOnly(); + return !(blockChainHeight() > 1 || m_recoveringFromSeed || m_recoveringFromDevice || m_rebuildWalletCache) && !watchOnly(); } bool WalletImpl::doInit(const string &daemon_address, uint64_t upper_transaction_size_limit, bool ssl) diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h index 4929c9673..6ad372357 100644 --- a/src/wallet/api/wallet.h +++ b/src/wallet/api/wallet.h @@ -76,6 +76,9 @@ public: const std::string &address_string, const std::string &viewkey_string, const std::string &spendkey_string = ""); + bool recoverFromDevice(const std::string &path, + const std::string &password, + const std::string &device_name); bool close(bool store = true); std::string seed() const; std::string getSeedLanguage() const; @@ -113,6 +116,8 @@ public: void setRefreshFromBlockHeight(uint64_t refresh_from_block_height); uint64_t getRefreshFromBlockHeight() const { return m_wallet->get_refresh_from_block_height(); }; void setRecoveringFromSeed(bool recoveringFromSeed); + void setRecoveringFromDevice(bool recoveringFromDevice) override; + void setSubaddressLookahead(uint32_t major, uint32_t minor) override; bool watchOnly() const; bool rescanSpent(); NetworkType nettype() const {return static_cast(m_wallet->nettype());} @@ -216,6 +221,7 @@ private: // so it shouldn't be considered as new and pull blocks (slow-refresh) // instead of pulling hashes (fast-refresh) std::atomic m_recoveringFromSeed; + std::atomic m_recoveringFromDevice; std::atomic m_synchronized; std::atomic m_rebuildWalletCache; // cache connection status to avoid unnecessary RPC calls diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h index 4fbc7298a..546ce16ae 100644 --- a/src/wallet/api/wallet2_api.h +++ b/src/wallet/api/wallet2_api.h @@ -468,6 +468,21 @@ struct Wallet */ virtual void setRecoveringFromSeed(bool recoveringFromSeed) = 0; + /*! + * \brief setRecoveringFromDevice - set state to recovering from device + * + * \param recoveringFromDevice - true/false + */ + virtual void setRecoveringFromDevice(bool recoveringFromDevice) = 0; + + /*! + * \brief setSubaddressLookahead - set size of subaddress lookahead + * + * \param major - size fot the major index + * \param minor - size fot the minor index + */ + virtual void setSubaddressLookahead(uint32_t major, uint32_t minor) = 0; + /** * @brief connectToDaemon - connects to the daemon. TODO: check if it can be removed * @return @@ -916,6 +931,23 @@ struct WalletManager return createWalletFromKeys(path, language, testnet ? TESTNET : MAINNET, restoreHeight, addressString, viewKeyString, spendKeyString); } + /*! + * \brief creates wallet using hardware device. + * \param path Name of wallet file to be created + * \param password Password of wallet file + * \param nettype Network type + * \param deviceName Device name + * \param restoreHeight restore from start height (0 sets to current height) + * \param subaddressLookahead Size of subaddress lookahead (empty sets to some default low value) + * \return Wallet instance (Wallet::status() needs to be called to check if recovered successfully) + */ + virtual Wallet * createWalletFromDevice(const std::string &path, + const std::string &password, + NetworkType nettype, + const std::string &deviceName, + uint64_t restoreHeight = 0, + const std::string &subaddressLookahead = "") = 0; + /*! * \brief Closes wallet. In case operation succeeded, wallet object deleted. in case operation failed, wallet object not deleted * \param wallet previously opened / created wallet instance diff --git a/src/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp index a63716576..99eadc82f 100644 --- a/src/wallet/api/wallet_manager.cpp +++ b/src/wallet/api/wallet_manager.cpp @@ -114,6 +114,26 @@ Wallet *WalletManagerImpl::createWalletFromKeys(const std::string &path, return wallet; } +Wallet *WalletManagerImpl::createWalletFromDevice(const std::string &path, + const std::string &password, + NetworkType nettype, + const std::string &deviceName, + uint64_t restoreHeight, + const std::string &subaddressLookahead) +{ + WalletImpl * wallet = new WalletImpl(nettype); + if(restoreHeight > 0){ + wallet->setRefreshFromBlockHeight(restoreHeight); + } + auto lookahead = tools::parse_subaddress_lookahead(subaddressLookahead); + if (lookahead) + { + wallet->setSubaddressLookahead(lookahead->first, lookahead->second); + } + wallet->recoverFromDevice(path, password, deviceName); + return wallet; +} + bool WalletManagerImpl::closeWallet(Wallet *wallet, bool store) { WalletImpl * wallet_ = dynamic_cast(wallet); diff --git a/src/wallet/api/wallet_manager.h b/src/wallet/api/wallet_manager.h index 26238b658..19aad9ee3 100644 --- a/src/wallet/api/wallet_manager.h +++ b/src/wallet/api/wallet_manager.h @@ -64,6 +64,12 @@ public: const std::string &addressString, const std::string &viewKeyString, const std::string &spendKeyString = ""); + virtual Wallet * createWalletFromDevice(const std::string &path, + const std::string &password, + NetworkType nettype, + const std::string &deviceName, + uint64_t restoreHeight = 0, + const std::string &subaddressLookahead = "") override; virtual bool closeWallet(Wallet *wallet, bool store = true); bool walletExists(const std::string &path); bool verifyWalletPassword(const std::string &keys_file_name, const std::string &password, bool no_spend_key) const; From e93058b41ca6c6dc999a73c60fb2b852fd126e85 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 3 Jul 2018 11:58:54 +0100 Subject: [PATCH 27/42] wallet_api: fixups to build on the branch --- src/wallet/api/wallet.cpp | 3 ++- src/wallet/api/wallet.h | 4 ++-- src/wallet/api/wallet_manager.h | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index c0a5e4780..4ac59d718 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -597,7 +597,8 @@ bool WalletImpl::recoverFromDevice(const std::string &path, const std::string &p LOG_PRINT_L1("Generated new wallet from device: " + device_name); } catch (const std::exception& e) { - setStatusError(string(tr("failed to generate new wallet: ")) + e.what()); + m_errorString = string(tr("failed to generate new wallet: ")) + e.what(); + m_status = Status_Error; return false; } return true; diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h index 6ad372357..0801f7b23 100644 --- a/src/wallet/api/wallet.h +++ b/src/wallet/api/wallet.h @@ -116,8 +116,8 @@ public: void setRefreshFromBlockHeight(uint64_t refresh_from_block_height); uint64_t getRefreshFromBlockHeight() const { return m_wallet->get_refresh_from_block_height(); }; void setRecoveringFromSeed(bool recoveringFromSeed); - void setRecoveringFromDevice(bool recoveringFromDevice) override; - void setSubaddressLookahead(uint32_t major, uint32_t minor) override; + void setRecoveringFromDevice(bool recoveringFromDevice); + void setSubaddressLookahead(uint32_t major, uint32_t minor); bool watchOnly() const; bool rescanSpent(); NetworkType nettype() const {return static_cast(m_wallet->nettype());} diff --git a/src/wallet/api/wallet_manager.h b/src/wallet/api/wallet_manager.h index 19aad9ee3..18c0740d9 100644 --- a/src/wallet/api/wallet_manager.h +++ b/src/wallet/api/wallet_manager.h @@ -69,7 +69,7 @@ public: NetworkType nettype, const std::string &deviceName, uint64_t restoreHeight = 0, - const std::string &subaddressLookahead = "") override; + const std::string &subaddressLookahead = ""); virtual bool closeWallet(Wallet *wallet, bool store = true); bool walletExists(const std::string &path); bool verifyWalletPassword(const std::string &keys_file_name, const std::string &password, bool no_spend_key) const; From bea06d1a329fd7a36ddd87b47e582406ccd0f0ac Mon Sep 17 00:00:00 2001 From: stoffu Date: Mon, 25 Jun 2018 09:44:07 +0900 Subject: [PATCH 28/42] epee.string_tools: add conversion between UTF-8 and UTF-16 --- contrib/epee/include/file_io_utils.h | 25 ++++++++------------ contrib/epee/include/string_tools.h | 35 ++++++++++++++++++++++++++++ src/common/util.cpp | 31 ++++++++++++++---------- 3 files changed, 64 insertions(+), 27 deletions(-) diff --git a/contrib/epee/include/file_io_utils.h b/contrib/epee/include/file_io_utils.h index 0afff800f..3c4ae1493 100644 --- a/contrib/epee/include/file_io_utils.h +++ b/contrib/epee/include/file_io_utils.h @@ -33,6 +33,7 @@ #include #ifdef WIN32 #include +#include "string_tools.h" #endif // On Windows there is a problem with non-ASCII characters in path and file names @@ -72,11 +73,9 @@ namespace file_io_utils bool save_string_to_file(const std::string& path_to_file, const std::string& str) { #ifdef WIN32 - WCHAR wide_path[1000]; - int chars = MultiByteToWideChar(CP_UTF8, 0, path_to_file.c_str(), path_to_file.size() + 1, wide_path, 1000); - if (chars == 0) - return false; - HANDLE file_handle = CreateFileW(wide_path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + std::wstring wide_path; + try { wide_path = string_tools::utf8_to_utf16(path_to_file); } catch (...) { return false; } + HANDLE file_handle = CreateFileW(wide_path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (file_handle == INVALID_HANDLE_VALUE) return false; DWORD bytes_written; @@ -131,11 +130,9 @@ namespace file_io_utils bool load_file_to_string(const std::string& path_to_file, std::string& target_str, size_t max_size = 1000000000) { #ifdef WIN32 - WCHAR wide_path[1000]; - int chars = MultiByteToWideChar(CP_UTF8, 0, path_to_file.c_str(), path_to_file.size() + 1, wide_path, 1000); - if (chars == 0) - return false; - HANDLE file_handle = CreateFileW(wide_path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + std::wstring wide_path; + try { wide_path = string_tools::utf8_to_utf16(path_to_file); } catch (...) { return false; } + HANDLE file_handle = CreateFileW(wide_path.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (file_handle == INVALID_HANDLE_VALUE) return false; DWORD file_size = GetFileSize(file_handle, NULL); @@ -202,11 +199,9 @@ namespace file_io_utils bool get_file_size(const std::string& path_to_file, uint64_t &size) { #ifdef WIN32 - WCHAR wide_path[1000]; - int chars = MultiByteToWideChar(CP_UTF8, 0, path_to_file.c_str(), path_to_file.size() + 1, wide_path, 1000); - if (chars == 0) - return false; - HANDLE file_handle = CreateFileW(wide_path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + std::wstring wide_path; + try { wide_path = string_tools::utf8_to_utf16(path_to_file); } catch (...) { return false; } + HANDLE file_handle = CreateFileW(wide_path.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (file_handle == INVALID_HANDLE_VALUE) return false; LARGE_INTEGER file_size; diff --git a/contrib/epee/include/string_tools.h b/contrib/epee/include/string_tools.h index 63705e401..8d8603076 100644 --- a/contrib/epee/include/string_tools.h +++ b/contrib/epee/include/string_tools.h @@ -381,6 +381,41 @@ POP_WARNINGS res = str.substr(0, pos); return res; } + //---------------------------------------------------------------------------- +#ifdef _WIN32 + inline std::wstring utf8_to_utf16(const std::string& str) + { + if (str.empty()) + return {}; + int wstr_size = MultiByteToWideChar(CP_UTF8, 0, &str[0], str.size(), NULL, 0); + if (wstr_size == 0) + { + throw std::runtime_error(std::error_code(GetLastError(), std::system_category()).message()); + } + std::wstring wstr(wstr_size, wchar_t{}); + if (!MultiByteToWideChar(CP_UTF8, 0, &str[0], str.size(), &wstr[0], wstr_size)) + { + throw std::runtime_error(std::error_code(GetLastError(), std::system_category()).message()); + } + return wstr; + } + inline std::string utf16_to_utf8(const std::wstring& wstr) + { + if (wstr.empty()) + return {}; + int str_size = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], wstr.size(), NULL, 0, NULL, NULL); + if (str_size == 0) + { + throw std::runtime_error(std::error_code(GetLastError(), std::system_category()).message()); + } + std::string str(str_size, char{}); + if (!WideCharToMultiByte(CP_UTF8, 0, &wstr[0], wstr.size(), &str[0], str_size, NULL, NULL)) + { + throw std::runtime_error(std::error_code(GetLastError(), std::system_category()).message()); + } + return str; + } +#endif } } #endif //_STRING_TOOLS_H_ diff --git a/src/common/util.cpp b/src/common/util.cpp index 8e4ea7fa5..17bc7a21d 100644 --- a/src/common/util.cpp +++ b/src/common/util.cpp @@ -440,10 +440,15 @@ std::string get_nix_version_display_string() if (SHGetSpecialFolderPathW(NULL, psz_path, nfolder, iscreate)) { - int size_needed = WideCharToMultiByte(CP_UTF8, 0, psz_path, wcslen(psz_path), NULL, 0, NULL, NULL); - std::string folder_name(size_needed, 0); - WideCharToMultiByte(CP_UTF8, 0, psz_path, wcslen(psz_path), &folder_name[0], size_needed, NULL, NULL); - return folder_name; + try + { + return string_tools::utf16_to_utf8(psz_path); + } + catch (const std::exception &e) + { + MERROR("utf16_to_utf8 failed: " << e.what()); + return ""; + } } LOG_ERROR("SHGetSpecialFolderPathW() failed, could not obtain requested path."); @@ -504,18 +509,20 @@ std::string get_nix_version_display_string() int code; #if defined(WIN32) // Maximizing chances for success - WCHAR wide_replacement_name[1000]; - MultiByteToWideChar(CP_UTF8, 0, replacement_name.c_str(), replacement_name.size() + 1, wide_replacement_name, 1000); - WCHAR wide_replaced_name[1000]; - MultiByteToWideChar(CP_UTF8, 0, replaced_name.c_str(), replaced_name.size() + 1, wide_replaced_name, 1000); - - DWORD attributes = ::GetFileAttributesW(wide_replaced_name); + std::wstring wide_replacement_name; + try { wide_replacement_name = string_tools::utf8_to_utf16(replacement_name); } + catch (...) { return std::error_code(GetLastError(), std::system_category()); } + std::wstring wide_replaced_name; + try { wide_replaced_name = string_tools::utf8_to_utf16(replaced_name); } + catch (...) { return std::error_code(GetLastError(), std::system_category()); } + + DWORD attributes = ::GetFileAttributesW(wide_replaced_name.c_str()); if (INVALID_FILE_ATTRIBUTES != attributes) { - ::SetFileAttributesW(wide_replaced_name, attributes & (~FILE_ATTRIBUTE_READONLY)); + ::SetFileAttributesW(wide_replaced_name.c_str(), attributes & (~FILE_ATTRIBUTE_READONLY)); } - bool ok = 0 != ::MoveFileExW(wide_replacement_name, wide_replaced_name, MOVEFILE_REPLACE_EXISTING); + bool ok = 0 != ::MoveFileExW(wide_replacement_name.c_str(), wide_replaced_name.c_str(), MOVEFILE_REPLACE_EXISTING); code = ok ? 0 : static_cast(::GetLastError()); #else bool ok = 0 == std::rename(replacement_name.c_str(), replaced_name.c_str()); From e5ac16b0772b9c2005340acd5d9542a2e6986bfc Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 12 Jun 2018 07:25:01 +0100 Subject: [PATCH 29/42] abstract_tcp_server2: restart async accept on error --- .../epee/include/net/abstract_tcp_server2.inl | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/contrib/epee/include/net/abstract_tcp_server2.inl b/contrib/epee/include/net/abstract_tcp_server2.inl index 134bb4199..7f80efb08 100644 --- a/contrib/epee/include/net/abstract_tcp_server2.inl +++ b/contrib/epee/include/net/abstract_tcp_server2.inl @@ -1030,7 +1030,8 @@ POP_WARNINGS void boosted_tcp_server::handle_accept(const boost::system::error_code& e) { MDEBUG("handle_accept"); - TRY_ENTRY(); + try + { if (!e) { if (m_connection_type == e_connection_type_RPC) { @@ -1048,11 +1049,25 @@ POP_WARNINGS conn->start(true, 1 < m_threads_count); conn->save_dbg_log(); - }else + return; + } + else + { + MERROR("Error in boosted_tcp_server::handle_accept: " << e); + } + } + catch (const std::exception &e) { - _erro("Some problems at accept: " << e.message() << ", connections_count = " << m_sock_count); + MERROR("Exception in boosted_tcp_server::handle_accept: " << e.what()); } - CATCH_ENTRY_L0("boosted_tcp_server::handle_accept", void()); + + // error path, if e or exception + _erro("Some problems at accept: " << e.message() << ", connections_count = " << m_sock_count); + misc_utils::sleep_no_w(100); + new_connection_.reset(new connection(io_service_, m_config, m_sock_count, m_sock_number, m_pfilter, m_connection_type)); + acceptor_.async_accept(new_connection_->socket(), + boost::bind(&boosted_tcp_server::handle_accept, this, + boost::asio::placeholders::error)); } //--------------------------------------------------------------------------------- template From 43a124979a22a06adfd6edf2d7d47aa0839900cf Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 15 Jun 2018 20:17:25 +0100 Subject: [PATCH 30/42] wallet2: fix out of sync account tag cache This would cause crashes when trying to tag an account that was just created --- src/wallet/wallet2.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 2329839ec..7b6a3bb38 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -940,6 +940,7 @@ void wallet2::expand_subaddresses(const cryptonote::subaddress_index& index) } m_subaddress_labels.resize(index.major + 1, {"Untitled account"}); m_subaddress_labels[index.major].resize(index.minor + 1); + get_account_tags(); } else if (m_subaddress_labels[index.major].size() <= index.minor) { From 280e1a64bde96e89a9b3b6f3b35e8e0a73ddde27 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Fri, 15 Jun 2018 20:13:19 +0100 Subject: [PATCH 31/42] Fix RPC crashes that didn't check for an open wallet --- src/wallet/wallet_rpc_server.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index a9d211532..57d2e14b0 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -500,6 +500,7 @@ namespace tools //------------------------------------------------------------------------------------------------------------------------------ bool wallet_rpc_server::on_get_account_tags(const wallet_rpc::COMMAND_RPC_GET_ACCOUNT_TAGS::request& req, wallet_rpc::COMMAND_RPC_GET_ACCOUNT_TAGS::response& res, epee::json_rpc::error& er) { + if (!m_wallet) return not_open(er); const std::pair, std::vector> account_tags = m_wallet->get_account_tags(); for (const std::pair& p : account_tags.first) { @@ -518,6 +519,7 @@ namespace tools //------------------------------------------------------------------------------------------------------------------------------ bool wallet_rpc_server::on_tag_accounts(const wallet_rpc::COMMAND_RPC_TAG_ACCOUNTS::request& req, wallet_rpc::COMMAND_RPC_TAG_ACCOUNTS::response& res, epee::json_rpc::error& er) { + if (!m_wallet) return not_open(er); try { m_wallet->set_account_tag(req.accounts, req.tag); @@ -532,6 +534,7 @@ namespace tools //------------------------------------------------------------------------------------------------------------------------------ bool wallet_rpc_server::on_untag_accounts(const wallet_rpc::COMMAND_RPC_UNTAG_ACCOUNTS::request& req, wallet_rpc::COMMAND_RPC_UNTAG_ACCOUNTS::response& res, epee::json_rpc::error& er) { + if (!m_wallet) return not_open(er); try { m_wallet->set_account_tag(req.accounts, ""); @@ -546,6 +549,7 @@ namespace tools //------------------------------------------------------------------------------------------------------------------------------ bool wallet_rpc_server::on_set_account_tag_description(const wallet_rpc::COMMAND_RPC_SET_ACCOUNT_TAG_DESCRIPTION::request& req, wallet_rpc::COMMAND_RPC_SET_ACCOUNT_TAG_DESCRIPTION::response& res, epee::json_rpc::error& er) { + if (!m_wallet) return not_open(er); try { m_wallet->set_account_tag_description(req.tag, req.description); @@ -2054,6 +2058,7 @@ namespace tools //------------------------------------------------------------------------------------------------------------------------------ bool wallet_rpc_server::on_make_uri(const wallet_rpc::COMMAND_RPC_MAKE_URI::request& req, wallet_rpc::COMMAND_RPC_MAKE_URI::response& res, epee::json_rpc::error& er) { + if (!m_wallet) return not_open(er); std::string error; std::string uri = m_wallet->make_uri(req.address, req.payment_id, req.amount, req.tx_description, req.recipient_name, error); if (uri.empty()) @@ -2267,6 +2272,7 @@ namespace tools //------------------------------------------------------------------------------------------------------------------------------ bool wallet_rpc_server::on_stop_mining(const wallet_rpc::COMMAND_RPC_STOP_MINING::request& req, wallet_rpc::COMMAND_RPC_STOP_MINING::response& res, epee::json_rpc::error& er) { + if (!m_wallet) return not_open(er); cryptonote::COMMAND_RPC_STOP_MINING::request daemon_req; cryptonote::COMMAND_RPC_STOP_MINING::response daemon_res; bool r = m_wallet->invoke_http_json("/stop_mining", daemon_req, daemon_res); From 223429f0fd3af9141013a90c5179fa5b34b6a595 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sun, 17 Jun 2018 13:48:12 +0100 Subject: [PATCH 32/42] zmq_server: fix bind call when address and/or port are empty --- src/rpc/zmq_server.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/rpc/zmq_server.cpp b/src/rpc/zmq_server.cpp index 3aee8c4c7..edd3e6669 100644 --- a/src/rpc/zmq_server.cpp +++ b/src/rpc/zmq_server.cpp @@ -104,6 +104,10 @@ bool ZmqServer::addTCPSocket(std::string address, std::string port) rep_socket->setsockopt(ZMQ_RCVTIMEO, &DEFAULT_RPC_RECV_TIMEOUT_MS, sizeof(DEFAULT_RPC_RECV_TIMEOUT_MS)); + if (address.empty()) + address = "*"; + if (port.empty()) + port = "*"; std::string bind_address = addr_prefix + address + std::string(":") + port; rep_socket->bind(bind_address.c_str()); } From 47b42f8b015e1c733ae5a52167dc7a5cc2977a21 Mon Sep 17 00:00:00 2001 From: stoffu Date: Thu, 21 Jun 2018 10:49:03 +0900 Subject: [PATCH 33/42] wallet-rpc.getaddress: throw if index is out of bound --- src/wallet/wallet_rpc_server.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index 57d2e14b0..9c2519d85 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -362,6 +362,7 @@ namespace tools if (!m_wallet) return not_open(er); try { + THROW_WALLET_EXCEPTION_IF(req.account_index >= m_wallet->get_num_subaddress_accounts(), error::account_index_outofbound); res.addresses.clear(); std::vector req_address_index; if (req.address_index.empty()) @@ -377,6 +378,7 @@ namespace tools m_wallet->get_transfers(transfers); for (uint32_t i : req_address_index) { + THROW_WALLET_EXCEPTION_IF(i >= m_wallet->get_num_subaddresses(req.account_index), error::address_index_outofbound); res.addresses.resize(res.addresses.size() + 1); auto& info = res.addresses.back(); const cryptonote::subaddress_index index = {req.account_index, i}; From b323d90f675991571a9cb97a0a3e9727a1811fd2 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sat, 23 Jun 2018 09:20:34 +0100 Subject: [PATCH 34/42] wallet2: fix read buffer overflow in import_key_images --- src/wallet/wallet2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 7b6a3bb38..433a001c3 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -9548,7 +9548,7 @@ uint64_t wallet2::import_key_images(const std::vector spent_txids; // For each spent key image, search for a tx in m_transfers that uses it as input. std::vector swept_transfers; // If such a spending tx wasn't found in m_transfers, this means the spending tx // was created by sweep_all, so we can't know the spent height and other detailed info. - for(size_t i = 0; i < m_transfers.size(); ++i) + for(size_t i = 0; i < signed_key_images.size(); ++i) { transfer_details &td = m_transfers[i]; uint64_t amount = td.amount(); From 0429cabefd260ba74dd5909f045b9d5f10a254be Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sat, 23 Jun 2018 09:53:09 +0100 Subject: [PATCH 35/42] simplewallet: init trusted daemon flag to false when autodetecting --- src/simplewallet/simplewallet.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 3ce48fe7b..9cc3f4604 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -3112,6 +3112,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm) { try { + m_trusted_daemon = false; if (tools::is_local_address(m_wallet->get_daemon_address())) { MINFO(tr("Daemon is local, assuming trusted")); From 076b7e1076f75fa8910e7330de1481becf1b7ce1 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sat, 23 Jun 2018 15:26:22 +0100 Subject: [PATCH 36/42] device_ledger: fix potential buffer overflow from bad size calc --- src/device/device_ledger.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp index c70422887..08ffbb7ca 100644 --- a/src/device/device_ledger.cpp +++ b/src/device/device_ledger.cpp @@ -194,7 +194,8 @@ namespace hw { this->buffer_send[3], this->buffer_send[4] ); - buffer_to_str(strbuffer+strlen(strbuffer), sizeof(strbuffer), (char*)(this->buffer_send+5), this->length_send-5); + const size_t len = strlen(strbuffer); + buffer_to_str(strbuffer+len, sizeof(strbuffer)-len, (char*)(this->buffer_send+5), this->length_send-5); MDEBUG( "CMD :" << strbuffer); } } @@ -206,7 +207,8 @@ namespace hw { this->buffer_recv[this->length_recv-2], this->buffer_recv[this->length_recv-1] ); - buffer_to_str(strbuffer+strlen(strbuffer), sizeof(strbuffer), (char*)(this->buffer_recv), this->length_recv-2); + const size_t len = strlen(strbuffer); + buffer_to_str(strbuffer+len, sizeof(strbuffer)-len, (char*)(this->buffer_recv), this->length_recv-2); MDEBUG( "RESP :" << strbuffer); } From e389101cb220baf996a88f59c746b6a7b0e6e72e Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sat, 23 Jun 2018 15:26:55 +0100 Subject: [PATCH 37/42] device: misc cleanup use snprintf "just in case" where appropriate consistently use unsigned for temp values pass std::string by const ref rather than by value add length check (which can't happen in practice) for memcpy --- src/device/device_ledger.cpp | 6 +++--- src/device/log.cpp | 12 +++++++----- src/device/log.hpp | 8 ++++---- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp index 08ffbb7ca..48045eea3 100644 --- a/src/device/device_ledger.cpp +++ b/src/device/device_ledger.cpp @@ -187,7 +187,7 @@ namespace hw { void device_ledger::logCMD() { if (apdu_verbose) { char strbuffer[1024]; - sprintf(strbuffer, "%.02x %.02x %.02x %.02x %.02x ", + snprintf(strbuffer, sizeof(strbuffer), "%.02x %.02x %.02x %.02x %.02x ", this->buffer_send[0], this->buffer_send[1], this->buffer_send[2], @@ -203,7 +203,7 @@ namespace hw { void device_ledger::logRESP() { if (apdu_verbose) { char strbuffer[1024]; - sprintf(strbuffer, "%.02x%.02x ", + snprintf(strbuffer, sizeof(strbuffer), "%.02x%.02x ", this->buffer_recv[this->length_recv-2], this->buffer_recv[this->length_recv-1] ); @@ -295,7 +295,7 @@ namespace hw { unsigned int device_ledger::exchange(unsigned int ok, unsigned int mask) { LONG rv; - int sw; + unsigned int sw; ASSERT_T0(this->length_send <= BUFFER_SEND_SIZE); logCMD(); diff --git a/src/device/log.cpp b/src/device/log.cpp index cbbcfc953..1707524fb 100644 --- a/src/device/log.cpp +++ b/src/device/log.cpp @@ -45,13 +45,13 @@ namespace hw { } } - void log_hexbuffer(std::string msg, const char* buff, size_t len) { + void log_hexbuffer(const std::string &msg, const char* buff, size_t len) { char logstr[1025]; buffer_to_str(logstr, sizeof(logstr), buff, len); MDEBUG(msg<< ": " << logstr); } - void log_message(std::string msg, std::string info ) { + void log_message(const std::string &msg, const std::string &info ) { MDEBUG(msg << ": " << info); } @@ -122,16 +122,18 @@ namespace hw { rct::keyV decrypt(const rct::keyV &keys) { rct::keyV x ; + x.reserve(keys.size()); for (unsigned int j = 0; j Date: Sat, 23 Jun 2018 15:43:31 +0100 Subject: [PATCH 38/42] device_ledger: fix buffer underflow on bad data from device --- src/device/device_ledger.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp index 48045eea3..f716f8ded 100644 --- a/src/device/device_ledger.cpp +++ b/src/device/device_ledger.cpp @@ -304,6 +304,7 @@ namespace hw { SCARD_PCI_T0, this->buffer_send, this->length_send, NULL, this->buffer_recv, &this->length_recv); ASSERT_RV(rv); + ASSERT_T0(this->length_recv >= 2); ASSERT_T0(this->length_recv <= BUFFER_RECV_SIZE); logRESP(); From 2daf54deebfa7b60f61fd14886c0591d6bb2daf4 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 29 Jun 2018 15:40:19 +0100 Subject: [PATCH 39/42] abstract_tcp_server2: fix use after free --- contrib/epee/include/net/abstract_tcp_server2.inl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/epee/include/net/abstract_tcp_server2.inl b/contrib/epee/include/net/abstract_tcp_server2.inl index 7f80efb08..5b3550005 100644 --- a/contrib/epee/include/net/abstract_tcp_server2.inl +++ b/contrib/epee/include/net/abstract_tcp_server2.inl @@ -653,13 +653,13 @@ PRAGMA_WARNING_DISABLE_VS(4355) m_timer.cancel(); boost::system::error_code ignored_ec; socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec); - m_was_shutdown = true; - m_protocol_handler.release_protocol(); if (!m_host.empty()) { try { host_count(m_host, -1); } catch (...) { /* ignore */ } m_host = ""; } + m_was_shutdown = true; + m_protocol_handler.release_protocol(); return true; } //--------------------------------------------------------------------------------- From 8c331a6d2639732b7807fada2ecdae989034220d Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 11 Jun 2018 12:01:41 +0100 Subject: [PATCH 40/42] wallet2: fix double counting outs if the tx pubkey is duplicated --- src/wallet/wallet2.cpp | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 433a001c3..4477b9713 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -1110,6 +1110,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote // Don't try to extract tx public key if tx has no ouputs size_t pk_index = 0; std::vector tx_scan_info(tx.vout.size()); + std::unordered_set public_keys_seen; while (!tx.vout.empty()) { // if tx.vout is not empty, we loop through all tx pubkeys @@ -1125,6 +1126,13 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote break; } + if (public_keys_seen.find(pub_key_field.pub_key) != public_keys_seen.end()) + { + MWARNING("The same transaction pubkey is present more than once, ignoring extra instance"); + continue; + } + public_keys_seen.insert(pub_key_field.pub_key); + int num_vouts_received = 0; tx_pub_key = pub_key_field.pub_key; tools::threadpool& tpool = tools::threadpool::getInstance(); @@ -1144,13 +1152,16 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote // additional tx pubkeys and derivations for multi-destination transfers involving one or more subaddresses std::vector additional_tx_pub_keys = get_additional_tx_pub_keys_from_extra(tx); std::vector additional_derivations; - for (size_t i = 0; i < additional_tx_pub_keys.size(); ++i) + if (pk_index == 1) { - additional_derivations.push_back({}); - if (!hwdev.generate_key_derivation(additional_tx_pub_keys[i], keys.m_view_secret_key, additional_derivations.back())) + for (size_t i = 0; i < additional_tx_pub_keys.size(); ++i) { - MWARNING("Failed to generate key derivation from tx pubkey, skipping"); - additional_derivations.pop_back(); + additional_derivations.push_back({}); + if (!hwdev.generate_key_derivation(additional_tx_pub_keys[i], keys.m_view_secret_key, additional_derivations.back())) + { + MWARNING("Failed to generate key derivation from tx pubkey, skipping"); + additional_derivations.pop_back(); + } } } hwdev_lock.unlock(); From fc8726f1c3ed3a1e995a47789b7b12962bbb5200 Mon Sep 17 00:00:00 2001 From: cornfeedhobo Date: Sun, 18 Mar 2018 18:07:10 -0500 Subject: [PATCH 41/42] fix sha256sum check, which requires two spaces. added set -ex to catch this, and other, errors in the future. --- Dockerfile | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/Dockerfile b/Dockerfile index b64af42ed..e36e20826 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,7 +3,8 @@ # builder stage FROM ubuntu:16.04 as builder -RUN apt-get update && \ +RUN set -ex && \ + apt-get update && \ apt-get --no-install-recommends --yes install \ ca-certificates \ cmake \ @@ -24,8 +25,9 @@ WORKDIR /usr/local ARG BOOST_VERSION=1_66_0 ARG BOOST_VERSION_DOT=1.66.0 ARG BOOST_HASH=5721818253e6a0989583192f96782c4a98eb6204965316df9f5ad75819225ca9 -RUN curl -s -L -o boost_${BOOST_VERSION}.tar.bz2 https://dl.bintray.com/boostorg/release/${BOOST_VERSION_DOT}/source/boost_${BOOST_VERSION}.tar.bz2 \ - && echo "${BOOST_HASH} boost_${BOOST_VERSION}.tar.bz2" | sha256sum -c \ +RUN set -ex \ + && curl -s -L -o boost_${BOOST_VERSION}.tar.bz2 https://dl.bintray.com/boostorg/release/${BOOST_VERSION_DOT}/source/boost_${BOOST_VERSION}.tar.bz2 \ + && echo "${BOOST_HASH} boost_${BOOST_VERSION}.tar.bz2" | sha256sum -c \ && tar -xvf boost_${BOOST_VERSION}.tar.bz2 \ && cd boost_${BOOST_VERSION} \ && ./bootstrap.sh \ @@ -35,8 +37,9 @@ ENV BOOST_ROOT /usr/local/boost_${BOOST_VERSION} # OpenSSL ARG OPENSSL_VERSION=1.0.2n ARG OPENSSL_HASH=370babb75f278c39e0c50e8c4e7493bc0f18db6867478341a832a982fd15a8fe -RUN curl -s -O https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz \ - && echo "${OPENSSL_HASH} openssl-${OPENSSL_VERSION}.tar.gz" | sha256sum -c \ +RUN set -ex \ + && curl -s -O https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz \ + && echo "${OPENSSL_HASH} openssl-${OPENSSL_VERSION}.tar.gz" | sha256sum -c \ && tar -xzf openssl-${OPENSSL_VERSION}.tar.gz \ && cd openssl-${OPENSSL_VERSION} \ && ./Configure linux-x86_64 no-shared --static -fPIC \ @@ -47,7 +50,8 @@ ENV OPENSSL_ROOT_DIR=/usr/local/openssl-${OPENSSL_VERSION} # ZMQ ARG ZMQ_VERSION=v4.2.3 ARG ZMQ_HASH=3226b8ebddd9c6c738ba42986822c26418a49afb -RUN git clone https://github.com/zeromq/libzmq.git -b ${ZMQ_VERSION} \ +RUN set -ex \ + && git clone https://github.com/zeromq/libzmq.git -b ${ZMQ_VERSION} \ && cd libzmq \ && test `git rev-parse HEAD` = ${ZMQ_HASH} || exit 1 \ && ./autogen.sh \ @@ -58,7 +62,8 @@ RUN git clone https://github.com/zeromq/libzmq.git -b ${ZMQ_VERSION} \ # zmq.hpp ARG CPPZMQ_HASH=6aa3ab686e916cb0e62df7fa7d12e0b13ae9fae6 -RUN git clone https://github.com/zeromq/cppzmq.git -b ${ZMQ_VERSION} \ +RUN set -ex \ + && git clone https://github.com/zeromq/cppzmq.git -b ${ZMQ_VERSION} \ && cd cppzmq \ && test `git rev-parse HEAD` = ${CPPZMQ_HASH} || exit 1 \ && mv *.hpp /usr/local/include @@ -66,8 +71,9 @@ RUN git clone https://github.com/zeromq/cppzmq.git -b ${ZMQ_VERSION} \ # Readline ARG READLINE_VERSION=7.0 ARG READLINE_HASH=750d437185286f40a369e1e4f4764eda932b9459b5ec9a731628393dd3d32334 -RUN curl -s -O https://ftp.gnu.org/gnu/readline/readline-${READLINE_VERSION}.tar.gz \ - && echo "${READLINE_HASH} readline-${READLINE_VERSION}.tar.gz" | sha256sum -c \ +RUN set -ex \ + && curl -s -O https://ftp.gnu.org/gnu/readline/readline-${READLINE_VERSION}.tar.gz \ + && echo "${READLINE_HASH} readline-${READLINE_VERSION}.tar.gz" | sha256sum -c \ && tar -xzf readline-${READLINE_VERSION}.tar.gz \ && cd readline-${READLINE_VERSION} \ && CFLAGS="-fPIC" CXXFLAGS="-fPIC" ./configure \ @@ -77,7 +83,8 @@ RUN curl -s -O https://ftp.gnu.org/gnu/readline/readline-${READLINE_VERSION}.tar # Sodium ARG SODIUM_VERSION=1.0.16 ARG SODIUM_HASH=675149b9b8b66ff44152553fb3ebf9858128363d -RUN git clone https://github.com/jedisct1/libsodium.git -b ${SODIUM_VERSION} \ +RUN set -ex \ + && git clone https://github.com/jedisct1/libsodium.git -b ${SODIUM_VERSION} \ && cd libsodium \ && test `git rev-parse HEAD` = ${SODIUM_HASH} || exit 1 \ && ./autogen.sh \ @@ -90,13 +97,18 @@ WORKDIR /src COPY . . ARG NPROC -RUN rm -rf build && \ - if [ -z "$NPROC" ];then make -j$(nproc) release-static;else make -j$NPROC release-static;fi +RUN set -ex && \ + rm -rf build && \ + if [ -z "$NPROC" ] ; \ + then make -j$(nproc) release-static ; \ + else make -j$NPROC release-static ; \ + fi # runtime stage FROM ubuntu:16.04 -RUN apt-get update && \ +RUN set -ex && \ + apt-get update && \ apt-get --no-install-recommends --yes install ca-certificates && \ apt-get clean && \ rm -rf /var/lib/apt @@ -114,4 +126,4 @@ VOLUME /wallet EXPOSE 18080 EXPOSE 18081 -ENTRYPOINT ["monerod", "--p2p-bind-ip=0.0.0.0", "--p2p-bind-port=18080", "--rpc-bind-ip=0.0.0.0", "--rpc-bind-port=18081", "--non-interactive", "--confirm-external-bind"] +ENTRYPOINT ["monerod", "--p2p-bind-ip=0.0.0.0", "--p2p-bind-port=18080", "--rpc-bind-ip=0.0.0.0", "--rpc-bind-port=18081", "--non-interactive", "--confirm-external-bind"] From 3a1ad04234d2d9a500e4495bfb4b8f473758e4e5 Mon Sep 17 00:00:00 2001 From: HomDx Date: Tue, 3 Jul 2018 19:44:03 +0300 Subject: [PATCH 42/42] docker: update to new versions of dependencies --- Dockerfile | 37 +++++++++++++++++++++++++++---------- README.md | 3 +++ 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/Dockerfile b/Dockerfile index e36e20826..0decb4fde 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,14 +17,28 @@ RUN set -ex && \ curl \ libtool-bin \ autoconf \ - automake + automake \ + bzip2 WORKDIR /usr/local +#Cmake +ARG CMAKE_VERSION=3.11.4 +ARG CMAKE_VERSION_DOT=v3.11 +ARG CMAKE_HASH=8f864e9f78917de3e1483e256270daabc4a321741592c5b36af028e72bff87f5 +RUN set -ex \ + && curl -s -O https://cmake.org/files/${CMAKE_VERSION_DOT}/cmake-${CMAKE_VERSION}.tar.gz \ + && echo "${CMAKE_HASH} cmake-${CMAKE_VERSION}.tar.gz" | sha256sum -c \ + && tar -xzf cmake-${CMAKE_VERSION}.tar.gz \ + && cd cmake-${CMAKE_VERSION} \ + && ./configure \ + && make \ + && make install + ## Boost -ARG BOOST_VERSION=1_66_0 -ARG BOOST_VERSION_DOT=1.66.0 -ARG BOOST_HASH=5721818253e6a0989583192f96782c4a98eb6204965316df9f5ad75819225ca9 +ARG BOOST_VERSION=1_67_0 +ARG BOOST_VERSION_DOT=1.67.0 +ARG BOOST_HASH=2684c972994ee57fc5632e03bf044746f6eb45d4920c343937a465fd67a5adba RUN set -ex \ && curl -s -L -o boost_${BOOST_VERSION}.tar.bz2 https://dl.bintray.com/boostorg/release/${BOOST_VERSION_DOT}/source/boost_${BOOST_VERSION}.tar.bz2 \ && echo "${BOOST_HASH} boost_${BOOST_VERSION}.tar.bz2" | sha256sum -c \ @@ -35,21 +49,22 @@ RUN set -ex \ ENV BOOST_ROOT /usr/local/boost_${BOOST_VERSION} # OpenSSL -ARG OPENSSL_VERSION=1.0.2n -ARG OPENSSL_HASH=370babb75f278c39e0c50e8c4e7493bc0f18db6867478341a832a982fd15a8fe +ARG OPENSSL_VERSION=1.1.0h +ARG OPENSSL_HASH=5835626cde9e99656585fc7aaa2302a73a7e1340bf8c14fd635a62c66802a517 RUN set -ex \ && curl -s -O https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz \ && echo "${OPENSSL_HASH} openssl-${OPENSSL_VERSION}.tar.gz" | sha256sum -c \ && tar -xzf openssl-${OPENSSL_VERSION}.tar.gz \ && cd openssl-${OPENSSL_VERSION} \ && ./Configure linux-x86_64 no-shared --static -fPIC \ - && make build_crypto build_ssl \ + && make build_generated \ + && make libcrypto.a \ && make install ENV OPENSSL_ROOT_DIR=/usr/local/openssl-${OPENSSL_VERSION} # ZMQ -ARG ZMQ_VERSION=v4.2.3 -ARG ZMQ_HASH=3226b8ebddd9c6c738ba42986822c26418a49afb +ARG ZMQ_VERSION=v4.2.5 +ARG ZMQ_HASH=d062edd8c142384792955796329baf1e5a3377cd RUN set -ex \ && git clone https://github.com/zeromq/libzmq.git -b ${ZMQ_VERSION} \ && cd libzmq \ @@ -61,9 +76,10 @@ RUN set -ex \ && ldconfig # zmq.hpp +ARG CPPZMQ_VERSION=v4.2.3 ARG CPPZMQ_HASH=6aa3ab686e916cb0e62df7fa7d12e0b13ae9fae6 RUN set -ex \ - && git clone https://github.com/zeromq/cppzmq.git -b ${ZMQ_VERSION} \ + && git clone https://github.com/zeromq/cppzmq.git -b ${CPPZMQ_VERSION} \ && cd cppzmq \ && test `git rev-parse HEAD` = ${CPPZMQ_HASH} || exit 1 \ && mv *.hpp /usr/local/include @@ -127,3 +143,4 @@ EXPOSE 18080 EXPOSE 18081 ENTRYPOINT ["monerod", "--p2p-bind-ip=0.0.0.0", "--p2p-bind-port=18080", "--rpc-bind-ip=0.0.0.0", "--rpc-bind-port=18081", "--non-interactive", "--confirm-external-bind"] + diff --git a/README.md b/README.md index 8d9896abf..599b4c5a7 100644 --- a/README.md +++ b/README.md @@ -490,6 +490,9 @@ Installing a snap is very quick. Snaps are secure. They are isolated with all of # or in background docker run -it -d -v /monero/chain:/root/.bitmonero -v /monero/wallet:/wallet -p 18080:18080 monero +* The build needs 3 GB space. +* Wait one hour or more + Packaging for your favorite distribution would be a welcome contribution! ## Running monerod