diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/common/dns_utils.cpp | 8 | ||||
-rw-r--r-- | src/common/dns_utils.h | 4 | ||||
-rw-r--r-- | src/cryptonote_basic/miner.cpp | 112 | ||||
-rw-r--r-- | src/cryptonote_core/cryptonote_core.cpp | 22 | ||||
-rw-r--r-- | src/cryptonote_core/cryptonote_core.h | 9 | ||||
-rw-r--r-- | src/daemonizer/posix_daemonizer.inl | 12 | ||||
-rw-r--r-- | src/daemonizer/posix_fork.cpp | 42 | ||||
-rw-r--r-- | src/daemonizer/posix_fork.h | 15 | ||||
-rw-r--r-- | src/rpc/core_rpc_server.cpp | 22 | ||||
-rw-r--r-- | src/rpc/core_rpc_server.h | 2 | ||||
-rw-r--r-- | src/rpc/core_rpc_server_commands_defs.h | 21 | ||||
-rw-r--r-- | src/simplewallet/simplewallet.cpp | 3 | ||||
-rw-r--r-- | src/wallet/wallet2.cpp | 16 |
13 files changed, 233 insertions, 55 deletions
diff --git a/src/common/dns_utils.cpp b/src/common/dns_utils.cpp index ab38cbbae..979f34b3e 100644 --- a/src/common/dns_utils.cpp +++ b/src/common/dns_utils.cpp @@ -307,12 +307,8 @@ DNSResolver& DNSResolver::instance() { boost::lock_guard<boost::mutex> lock(instance_lock); - static DNSResolver* staticInstance = NULL; - if (staticInstance == NULL) - { - staticInstance = new DNSResolver(); - } - return *staticInstance; + static DNSResolver staticInstance; + return staticInstance; } DNSResolver DNSResolver::create() diff --git a/src/common/dns_utils.h b/src/common/dns_utils.h index 53c0c1c7b..7a093db51 100644 --- a/src/common/dns_utils.h +++ b/src/common/dns_utils.h @@ -101,7 +101,7 @@ public: * * @return A vector of strings containing a TXT record; or an empty vector */ - // TODO: modify this to accomodate DNSSEC + // TODO: modify this to accommodate DNSSEC std::vector<std::string> get_txt_record(const std::string& url, bool& dnssec_available, bool& dnssec_valid); /** @@ -142,7 +142,7 @@ private: * * @return A vector of strings containing the requested record; or an empty vector */ - // TODO: modify this to accomodate DNSSEC + // TODO: modify this to accommodate DNSSEC std::vector<std::string> get_record(const std::string& url, int record_type, std::string (*reader)(const char *,size_t), bool& dnssec_available, bool& dnssec_valid); /** diff --git a/src/cryptonote_basic/miner.cpp b/src/cryptonote_basic/miner.cpp index cd0943618..9248e2e1d 100644 --- a/src/cryptonote_basic/miner.cpp +++ b/src/cryptonote_basic/miner.cpp @@ -846,40 +846,100 @@ namespace cryptonote #elif defined(__linux__) - // i've only tested on UBUNTU, these paths might be different on other systems - // need to figure out a way to make this more flexible - std::string power_supply_path = ""; - const std::string POWER_SUPPLY_STATUS_PATHS[] = - { - "/sys/class/power_supply/ACAD/online", - "/sys/class/power_supply/AC/online", - "/sys/class/power_supply/AC0/online", - "/sys/class/power_supply/ADP0/online" - }; + // Use the power_supply class http://lxr.linux.no/#linux+v4.10.1/Documentation/power/power_supply_class.txt + std::string power_supply_class_path = "/sys/class/power_supply"; - for(const std::string& path : POWER_SUPPLY_STATUS_PATHS) + boost::tribool on_battery = boost::logic::tribool(boost::logic::indeterminate); + if (boost::filesystem::is_directory(power_supply_class_path)) { - if( epee::file_io_utils::is_file_exist(path) ) + const boost::filesystem::directory_iterator end_itr; + for (boost::filesystem::directory_iterator iter(power_supply_class_path); iter != end_itr; ++iter) { - power_supply_path = path; - break; + const boost::filesystem::path& power_supply_path = iter->path(); + if (boost::filesystem::is_directory(power_supply_path)) + { + std::ifstream power_supply_present_stream((power_supply_path / "present").string()); + if (power_supply_present_stream.fail()) + { + LOG_PRINT_L0("Unable to read from " << power_supply_path << " to check if power supply present"); + continue; + } + + if (power_supply_present_stream.get() != '1') + { + LOG_PRINT_L4("Power supply not present at " << power_supply_path); + continue; + } + + boost::filesystem::path power_supply_type_path = power_supply_path / "type"; + if (boost::filesystem::is_regular_file(power_supply_type_path)) + { + std::ifstream power_supply_type_stream(power_supply_type_path.string()); + if (power_supply_type_stream.fail()) + { + LOG_PRINT_L0("Unable to read from " << power_supply_type_path << " to check power supply type"); + continue; + } + + std::string power_supply_type; + std::getline(power_supply_type_stream, power_supply_type); + + // If there is an AC adapter that's present and online we can break early + if (boost::starts_with(power_supply_type, "Mains")) + { + boost::filesystem::path power_supply_online_path = power_supply_path / "online"; + if (boost::filesystem::is_regular_file(power_supply_online_path)) + { + std::ifstream power_supply_online_stream(power_supply_online_path.string()); + if (power_supply_online_stream.fail()) + { + LOG_PRINT_L0("Unable to read from " << power_supply_online_path << " to check ac power supply status"); + continue; + } + + if (power_supply_online_stream.get() == '1') + { + return boost::logic::tribool(false); + } + } + } + else if (boost::starts_with(power_supply_type, "Battery") && boost::logic::indeterminate(on_battery)) + { + boost::filesystem::path power_supply_status_path = power_supply_path / "status"; + if (boost::filesystem::is_regular_file(power_supply_status_path)) + { + std::ifstream power_supply_status_stream(power_supply_status_path.string()); + if (power_supply_status_stream.fail()) + { + LOG_PRINT_L0("Unable to read from " << power_supply_status_path << " to check battery power supply status"); + continue; + } + + // Possible status are Charging, Full, Discharging, Not Charging, and Unknown + // We are only need to handle negative states right now + std::string power_supply_status; + std::getline(power_supply_status_stream, power_supply_status); + if (boost::starts_with(power_supply_status, "Charging") || boost::starts_with(power_supply_status, "Full")) + { + on_battery = boost::logic::tribool(false); + } + + if (boost::starts_with(power_supply_status, "Discharging")) + { + on_battery = boost::logic::tribool(true); + } + } + } + } + } } } - if( power_supply_path.empty() ) + if (boost::logic::indeterminate(on_battery)) { - LOG_ERROR("Couldn't find battery/power status file, can't determine if plugged in!"); - return boost::logic::tribool(boost::logic::indeterminate);; + LOG_ERROR("couldn't query power status from " << power_supply_class_path); } - - std::ifstream power_stream(power_supply_path); - if( power_stream.fail() ) - { - LOG_ERROR("failed to open '" << power_supply_path << "'"); - return boost::logic::tribool(boost::logic::indeterminate);; - } - - return boost::logic::tribool( (power_stream.get() != '1') ); + return on_battery; #endif diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 4cfa52441..da8ec68dd 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -660,6 +660,12 @@ namespace cryptonote return false; } + if (!check_tx_inputs_ring_members_diff(tx)) + { + MERROR_VER("tx uses duplicate ring members"); + return false; + } + if (!check_tx_inputs_keyimages_domain(tx)) { MERROR_VER("tx uses key image not in the valid domain"); @@ -752,6 +758,22 @@ namespace cryptonote return true; } //----------------------------------------------------------------------------------------------- + bool core::check_tx_inputs_ring_members_diff(const transaction& tx) const + { + const uint8_t version = m_blockchain_storage.get_current_hard_fork_version(); + if (version >= 6) + { + for(const auto& in: tx.vin) + { + CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, tokey_in, false); + for (size_t n = 1; n < tokey_in.key_offsets.size(); ++n) + if (tokey_in.key_offsets[n] == 0) + return false; + } + } + return true; + } + //----------------------------------------------------------------------------------------------- bool core::check_tx_inputs_keyimages_domain(const transaction& tx) const { std::unordered_set<crypto::key_image> ki; diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h index e5fbf7f91..4ced91e23 100644 --- a/src/cryptonote_core/cryptonote_core.h +++ b/src/cryptonote_core/cryptonote_core.h @@ -781,6 +781,15 @@ namespace cryptonote bool check_tx_inputs_keyimages_diff(const transaction& tx) const; /** + * @brief verify that each ring uses distinct members + * + * @param tx the transaction to check + * + * @return false if any ring uses duplicate members, true otherwise + */ + bool check_tx_inputs_ring_members_diff(const transaction& tx) const; + + /** * @brief verify that each input key image in a transaction is in * the valid domain * diff --git a/src/daemonizer/posix_daemonizer.inl b/src/daemonizer/posix_daemonizer.inl index f8be15dda..506c7766f 100644 --- a/src/daemonizer/posix_daemonizer.inl +++ b/src/daemonizer/posix_daemonizer.inl @@ -43,6 +43,10 @@ namespace daemonizer "detach" , "Run as daemon" }; + const command_line::arg_descriptor<std::string> arg_pidfile = { + "pidfile" + , "File path to write the daemon's PID to (optional, requires --detach)" + }; const command_line::arg_descriptor<bool> arg_non_interactive = { "non-interactive" , "Run non-interactive" @@ -55,6 +59,7 @@ namespace daemonizer ) { command_line::add_arg(normal_options, arg_detach); + command_line::add_arg(normal_options, arg_pidfile); command_line::add_arg(normal_options, arg_non_interactive); } @@ -80,7 +85,12 @@ namespace daemonizer if (command_line::has_arg(vm, arg_detach)) { tools::success_msg_writer() << "Forking to background..."; - posix::fork(); + std::string pidfile; + if (command_line::has_arg(vm, arg_pidfile)) + { + pidfile = command_line::get_arg(vm, arg_pidfile); + } + posix::fork(pidfile); auto daemon = executor.create_daemon(vm); return daemon.run(); } diff --git a/src/daemonizer/posix_fork.cpp b/src/daemonizer/posix_fork.cpp index d9b4a6d0e..4dff04f3f 100644 --- a/src/daemonizer/posix_fork.cpp +++ b/src/daemonizer/posix_fork.cpp @@ -21,15 +21,43 @@ namespace posix { namespace { - void quit(std::string const & message) + void quit(const std::string & message) { LOG_ERROR(message); throw std::runtime_error(message); } } -void fork() +void fork(const std::string & pidfile) { + // If a PID file is specified, we open the file here, because + // we can't report errors after the fork operation. + // When we fork, we close thise file in each of the parent + // processes. + // Only in the final child process do we write the PID to the + // file (and close it). + std::ofstream pidofs; + if (! pidfile.empty ()) + { + int oldpid; + std::ifstream pidrifs; + pidrifs.open(pidfile, std::fstream::in); + if (! pidrifs.fail()) + { + // Read the PID and send signal 0 to see if the process exists. + if (pidrifs >> oldpid && oldpid > 1 && kill(oldpid, 0) == 0) + { + quit("PID file " + pidfile + " already exists and the PID therein is valid"); + } + pidrifs.close(); + } + + pidofs.open(pidfile, std::fstream::out | std::fstream::trunc); + if (pidofs.fail()) + { + quit("Failed to open specified PID file for writing"); + } + } // Fork the process and have the parent exit. If the process was started // from a shell, this returns control to the user. Forking a new process is // also a prerequisite for the subsequent call to setsid(). @@ -38,7 +66,7 @@ void fork() if (pid > 0) { // We're in the parent process and need to exit. - // + pidofs.close(); // When the exit() function is used, the program terminates without // invoking local variables' destructors. Only global variables are // destroyed. @@ -59,6 +87,7 @@ void fork() { if (pid > 0) { + pidofs.close(); exit(0); } else @@ -67,6 +96,13 @@ void fork() } } + if (! pidofs.fail()) + { + int pid = ::getpid(); + pidofs << pid << std::endl; + pidofs.close(); + } + // Close the standard streams. This decouples the daemon from the terminal // that started it. close(0); diff --git a/src/daemonizer/posix_fork.h b/src/daemonizer/posix_fork.h index 459417d25..77ef4cb19 100644 --- a/src/daemonizer/posix_fork.h +++ b/src/daemonizer/posix_fork.h @@ -1,21 +1,21 @@ // Copyright (c) 2014-2017, The Monero Project -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: -// +// // 1. Redistributions of source code must retain the above copyright notice, this list of // conditions and the following disclaimer. -// +// // 2. Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other // materials provided with the distribution. -// +// // 3. Neither the name of the copyright holder nor the names of its contributors may be // used to endorse or promote products derived from this software without specific // prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL @@ -27,12 +27,13 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #pragma once +#include <string> #ifndef WIN32 namespace posix { -void fork(); +void fork(const std::string & pidfile); } diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 97fe18696..097958d24 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -227,6 +227,28 @@ namespace cryptonote res.status = CORE_RPC_STATUS_OK; return true; } + bool core_rpc_server::on_get_alt_blocks_hashes(const COMMAND_RPC_GET_ALT_BLOCKS_HASHES::request& req, COMMAND_RPC_GET_ALT_BLOCKS_HASHES::response& res) + { + CHECK_CORE_BUSY(); + std::list<block> blks; + + if(!m_core.get_alternative_blocks(blks)) + { + res.status = "Failed"; + return false; + } + + res.blks_hashes.reserve(blks.size()); + + for (auto const& blk: blks) + { + res.blks_hashes.push_back(epee::string_tools::pod_to_hex(get_block_hash(blk))); + } + + MDEBUG("on_get_alt_blocks_hashes: " << blks.size() << " blocks " ); + res.status = CORE_RPC_STATUS_OK; + return true; + } //------------------------------------------------------------------------------------------------------------------------------ bool core_rpc_server::on_get_blocks_by_height(const COMMAND_RPC_GET_BLOCKS_BY_HEIGHT::request& req, COMMAND_RPC_GET_BLOCKS_BY_HEIGHT::response& res) { diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h index 44ac6f07a..cf95b0edf 100644 --- a/src/rpc/core_rpc_server.h +++ b/src/rpc/core_rpc_server.h @@ -81,6 +81,7 @@ namespace cryptonote MAP_URI_AUTO_BIN2("/get_outs.bin", on_get_outs_bin, COMMAND_RPC_GET_OUTPUTS_BIN) MAP_URI_AUTO_BIN2("/getrandom_rctouts.bin", on_get_random_rct_outs, COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS) MAP_URI_AUTO_JON2("/gettransactions", on_get_transactions, COMMAND_RPC_GET_TRANSACTIONS) + MAP_URI_AUTO_JON2("/get_alt_blocks_hashes", on_get_alt_blocks_hashes, COMMAND_RPC_GET_ALT_BLOCKS_HASHES) MAP_URI_AUTO_JON2("/is_key_image_spent", on_is_key_image_spent, COMMAND_RPC_IS_KEY_IMAGE_SPENT) MAP_URI_AUTO_JON2("/sendrawtransaction", on_send_raw_tx, COMMAND_RPC_SEND_RAW_TX) MAP_URI_AUTO_JON2_IF("/start_mining", on_start_mining, COMMAND_RPC_START_MINING, !m_restricted) @@ -128,6 +129,7 @@ namespace cryptonote bool on_get_height(const COMMAND_RPC_GET_HEIGHT::request& req, COMMAND_RPC_GET_HEIGHT::response& res); bool on_get_blocks(const COMMAND_RPC_GET_BLOCKS_FAST::request& req, COMMAND_RPC_GET_BLOCKS_FAST::response& res); + bool on_get_alt_blocks_hashes(const COMMAND_RPC_GET_ALT_BLOCKS_HASHES::request& req, COMMAND_RPC_GET_ALT_BLOCKS_HASHES::response& res); bool on_get_blocks_by_height(const COMMAND_RPC_GET_BLOCKS_BY_HEIGHT::request& req, COMMAND_RPC_GET_BLOCKS_BY_HEIGHT::response& res); bool on_get_hashes(const COMMAND_RPC_GET_HASHES_FAST::request& req, COMMAND_RPC_GET_HASHES_FAST::response& res); bool on_get_transactions(const COMMAND_RPC_GET_TRANSACTIONS::request& req, COMMAND_RPC_GET_TRANSACTIONS::response& res); diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 7a1f5a963..a38952bff 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -49,7 +49,7 @@ namespace cryptonote // advance which version they will stop working with // Don't go over 32767 for any of these #define CORE_RPC_VERSION_MAJOR 1 -#define CORE_RPC_VERSION_MINOR 12 +#define CORE_RPC_VERSION_MINOR 13 #define MAKE_CORE_RPC_VERSION(major,minor) (((major)<<16)|(minor)) #define CORE_RPC_VERSION MAKE_CORE_RPC_VERSION(CORE_RPC_VERSION_MAJOR, CORE_RPC_VERSION_MINOR) @@ -146,6 +146,25 @@ namespace cryptonote }; }; + struct COMMAND_RPC_GET_ALT_BLOCKS_HASHES + { + struct request + { + BEGIN_KV_SERIALIZE_MAP() + END_KV_SERIALIZE_MAP() + }; + + struct response + { + std::vector<std::string> blks_hashes; + std::string status; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(blks_hashes) + KV_SERIALIZE(status) + END_KV_SERIALIZE_MAP() + }; + }; struct COMMAND_RPC_GET_HASHES_FAST { diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index adf2fde80..e7b7559a3 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -2375,7 +2375,8 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri { auto & ptx = ptx_vector.back(); m_wallet->commit_tx(ptx); - success_msg_writer(true) << tr("Money successfully sent, transaction ") << get_transaction_hash(ptx.tx); + success_msg_writer(true) << tr("Transaction successfully submitted, transaction ") << get_transaction_hash(ptx.tx) << ENDL + << tr("You can check its status by using the `show_transfers` command."); // if no exception, remove element from vector ptx_vector.pop_back(); diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 6b1026a55..e5e18302b 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -4359,7 +4359,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp // try to pick outputs not from the same block. We will get two outputs, one for // the destination, and one for change. LOG_PRINT_L2("checking preferred"); - std::vector<size_t> prefered_inputs; + std::vector<size_t> preferred_inputs; uint64_t rct_outs_needed = 2 * (fake_outs_count + 1); rct_outs_needed += 100; // some fudge factor since we don't know how many are locked if (use_rct && get_num_rct_outputs() >= rct_outs_needed) @@ -4367,12 +4367,12 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp // this is used to build a tx that's 1 or 2 inputs, and 2 outputs, which // will get us a known fee. uint64_t estimated_fee = calculate_fee(fee_per_kb, estimate_rct_tx_size(2, fake_outs_count + 1, 2), fee_multiplier); - prefered_inputs = pick_preferred_rct_inputs(needed_money + estimated_fee); - if (!prefered_inputs.empty()) + preferred_inputs = pick_preferred_rct_inputs(needed_money + estimated_fee); + if (!preferred_inputs.empty()) { string s; - for (auto i: prefered_inputs) s += boost::lexical_cast<std::string>(i) + "(" + print_money(m_transfers[i].amount()) + ") "; - LOG_PRINT_L1("Found prefered rct inputs for rct tx: " << s); + for (auto i: preferred_inputs) s += boost::lexical_cast<std::string>(i) + "(" + print_money(m_transfers[i].amount()) + ") "; + LOG_PRINT_L1("Found preferred rct inputs for rct tx: " << s); } } LOG_PRINT_L2("done checking preferred"); @@ -4427,8 +4427,8 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp } pop_if_present(unused_transfers_indices, idx); pop_if_present(unused_dust_indices, idx); - } else if (!prefered_inputs.empty()) { - idx = pop_back(prefered_inputs); + } else if (!preferred_inputs.empty()) { + idx = pop_back(preferred_inputs); pop_if_present(unused_transfers_indices, idx); pop_if_present(unused_dust_indices, idx); } else @@ -4521,7 +4521,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp { uint64_t new_paid_amount = i->amount /*+ test_ptx.fee*/ - needed_fee; LOG_PRINT_L2("Adjusting amount paid to " << get_account_address_as_str(m_testnet, i->addr) << " from " << - print_money(i->amount) << " to " << print_money(new_paid_amount) << " to accomodate " << + print_money(i->amount) << " to " << print_money(new_paid_amount) << " to accommodate " << print_money(needed_fee) << " fee"); dsts[0].amount += i->amount - new_paid_amount; i->amount = new_paid_amount; |