aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/blockchain_db/blockchain_db.h3
-rw-r--r--src/blockchain_db/lmdb/db_lmdb.cpp11
-rw-r--r--src/blockchain_db/lmdb/db_lmdb.h3
-rw-r--r--src/common/CMakeLists.txt1
-rw-r--r--src/common/util.cpp39
-rw-r--r--src/crypto/slow-hash.c2
-rw-r--r--src/cryptonote_core/blockchain.cpp4
-rw-r--r--src/cryptonote_core/blockchain.h3
-rw-r--r--src/cryptonote_core/cryptonote_core.cpp5
-rw-r--r--src/cryptonote_core/cryptonote_core.h7
-rw-r--r--src/cryptonote_protocol/cryptonote_protocol_handler.inl2
-rw-r--r--src/daemon/command_parser_executor.cpp13
-rw-r--r--src/daemon/command_parser_executor.h2
-rw-r--r--src/daemon/command_server.cpp5
-rw-r--r--src/daemon/main.cpp45
-rw-r--r--src/daemon/rpc_command_executor.cpp12
-rw-r--r--src/device/device_default.hpp2
-rw-r--r--src/device/device_ledger.hpp2
-rw-r--r--src/p2p/net_node.h4
-rw-r--r--src/p2p/net_node.inl13
-rw-r--r--src/rpc/core_rpc_server.cpp36
-rw-r--r--src/rpc/core_rpc_server_commands_defs.h4
-rw-r--r--src/simplewallet/simplewallet.cpp15
-rw-r--r--src/simplewallet/simplewallet.h1
-rw-r--r--src/wallet/api/wallet2_api.h14
-rw-r--r--src/wallet/api/wallet_manager.cpp44
-rw-r--r--src/wallet/api/wallet_manager.h16
-rw-r--r--src/wallet/wallet2.cpp14
28 files changed, 217 insertions, 105 deletions
diff --git a/src/blockchain_db/blockchain_db.h b/src/blockchain_db/blockchain_db.h
index d7230f644..1a23a9ada 100644
--- a/src/blockchain_db/blockchain_db.h
+++ b/src/blockchain_db/blockchain_db.h
@@ -1490,10 +1490,11 @@ public:
* @param amounts optional set of amounts to lookup
* @param unlocked whether to restrict count to unlocked outputs
* @param recent_cutoff timestamp to determine whether an output is recent
+ * @param min_count return only amounts with at least that many instances
*
* @return a set of amount/instances
*/
- virtual std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>> get_output_histogram(const std::vector<uint64_t> &amounts, bool unlocked, uint64_t recent_cutoff) const = 0;
+ virtual std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>> get_output_histogram(const std::vector<uint64_t> &amounts, bool unlocked, uint64_t recent_cutoff, uint64_t min_count) const = 0;
/**
* @brief is BlockchainDB in read-only mode?
diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp
index 9a755fb0c..5672a34f6 100644
--- a/src/blockchain_db/lmdb/db_lmdb.cpp
+++ b/src/blockchain_db/lmdb/db_lmdb.cpp
@@ -3086,7 +3086,7 @@ void BlockchainLMDB::get_output_tx_and_index(const uint64_t& amount, const std::
LOG_PRINT_L3("db3: " << db3);
}
-std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>> BlockchainLMDB::get_output_histogram(const std::vector<uint64_t> &amounts, bool unlocked, uint64_t recent_cutoff) const
+std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>> BlockchainLMDB::get_output_histogram(const std::vector<uint64_t> &amounts, bool unlocked, uint64_t recent_cutoff, uint64_t min_count) const
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
@@ -3112,7 +3112,8 @@ std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>> BlockchainLMDB::get
mdb_size_t num_elems = 0;
mdb_cursor_count(m_cur_output_amounts, &num_elems);
uint64_t amount = *(const uint64_t*)k.mv_data;
- histogram[amount] = std::make_tuple(num_elems, 0, 0);
+ if (num_elems >= min_count)
+ histogram[amount] = std::make_tuple(num_elems, 0, 0);
}
}
else
@@ -3123,13 +3124,15 @@ std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>> BlockchainLMDB::get
int ret = mdb_cursor_get(m_cur_output_amounts, &k, &v, MDB_SET);
if (ret == MDB_NOTFOUND)
{
- histogram[amount] = std::make_tuple(0, 0, 0);
+ if (0 >= min_count)
+ histogram[amount] = std::make_tuple(0, 0, 0);
}
else if (ret == MDB_SUCCESS)
{
mdb_size_t num_elems = 0;
mdb_cursor_count(m_cur_output_amounts, &num_elems);
- histogram[amount] = std::make_tuple(num_elems, 0, 0);
+ if (num_elems >= min_count)
+ histogram[amount] = std::make_tuple(num_elems, 0, 0);
}
else
{
diff --git a/src/blockchain_db/lmdb/db_lmdb.h b/src/blockchain_db/lmdb/db_lmdb.h
index 0aa4bb86e..9a20c0f1e 100644
--- a/src/blockchain_db/lmdb/db_lmdb.h
+++ b/src/blockchain_db/lmdb/db_lmdb.h
@@ -287,10 +287,11 @@ public:
* @param amounts optional set of amounts to lookup
* @param unlocked whether to restrict count to unlocked outputs
* @param recent_cutoff timestamp to determine which outputs are recent
+ * @param min_count return only amounts with at least that many instances
*
* @return a set of amount/instances
*/
- std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>> get_output_histogram(const std::vector<uint64_t> &amounts, bool unlocked, uint64_t recent_cutoff) const;
+ std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>> get_output_histogram(const std::vector<uint64_t> &amounts, bool unlocked, uint64_t recent_cutoff, uint64_t min_count) const;
private:
void do_resize(uint64_t size_increase=0);
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 66fd8d7ad..808ef7630 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -87,6 +87,7 @@ target_link_libraries(common
${Boost_SYSTEM_LIBRARY}
${Boost_THREAD_LIBRARY}
${Boost_REGEX_LIBRARY}
+ ${Boost_CHRONO_LIBRARY}
PRIVATE
${OPENSSL_LIBRARIES}
${EXTRA_LIBRARIES})
diff --git a/src/common/util.cpp b/src/common/util.cpp
index 1877acb57..7e77e19b1 100644
--- a/src/common/util.cpp
+++ b/src/common/util.cpp
@@ -43,6 +43,7 @@ using namespace epee;
#include "crypto/crypto.h"
#include "util.h"
+#include "stack_trace.h"
#include "memwipe.h"
#include "cryptonote_config.h"
#include "net/http_client.h" // epee::net_utils::...
@@ -560,10 +561,48 @@ std::string get_nix_version_display_string()
}
return false;
}
+
+#ifdef STACK_TRACE
+#ifdef _WIN32
+ // https://stackoverflow.com/questions/1992816/how-to-handle-seg-faults-under-windows
+ static LONG WINAPI windows_crash_handler(PEXCEPTION_POINTERS pExceptionInfo)
+ {
+ tools::log_stack_trace("crashing");
+ exit(1);
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+ static void setup_crash_dump()
+ {
+ SetUnhandledExceptionFilter(windows_crash_handler);
+ }
+#else
+ static void posix_crash_handler(int signal)
+ {
+ tools::log_stack_trace(("crashing with fatal signal " + std::to_string(signal)).c_str());
+#ifdef NDEBUG
+ _exit(1);
+#else
+ abort();
+#endif
+ }
+ static void setup_crash_dump()
+ {
+ signal(SIGSEGV, posix_crash_handler);
+ signal(SIGBUS, posix_crash_handler);
+ signal(SIGILL, posix_crash_handler);
+ signal(SIGFPE, posix_crash_handler);
+ }
+#endif
+#else
+ static void setup_crash_dump() {}
+#endif
+
bool on_startup()
{
mlog_configure("", true);
+ setup_crash_dump();
+
sanitize_locale();
#ifdef __GLIBC__
diff --git a/src/crypto/slow-hash.c b/src/crypto/slow-hash.c
index d7dcbd274..35e98f2f5 100644
--- a/src/crypto/slow-hash.c
+++ b/src/crypto/slow-hash.c
@@ -524,7 +524,7 @@ void slow_hash_free_state(void)
else
{
#if defined(_MSC_VER) || defined(__MINGW32__)
- VirtualFree(hp_state, MEMORY, MEM_RELEASE);
+ VirtualFree(hp_state, 0, MEM_RELEASE);
#else
munmap(hp_state, MEMORY);
#endif
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp
index f02a1f8d6..25e97f71f 100644
--- a/src/cryptonote_core/blockchain.cpp
+++ b/src/cryptonote_core/blockchain.cpp
@@ -4322,9 +4322,9 @@ uint64_t Blockchain::get_difficulty_target() const
return get_current_hard_fork_version() < 2 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET_V2;
}
-std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>> Blockchain:: get_output_histogram(const std::vector<uint64_t> &amounts, bool unlocked, uint64_t recent_cutoff) const
+std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>> Blockchain:: get_output_histogram(const std::vector<uint64_t> &amounts, bool unlocked, uint64_t recent_cutoff, uint64_t min_count) const
{
- return m_db->get_output_histogram(amounts, unlocked, recent_cutoff);
+ return m_db->get_output_histogram(amounts, unlocked, recent_cutoff, min_count);
}
std::list<std::pair<Blockchain::block_extended_info,uint64_t>> Blockchain::get_alternative_chains() const
diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h
index 4423199de..61096fb26 100644
--- a/src/cryptonote_core/blockchain.h
+++ b/src/cryptonote_core/blockchain.h
@@ -827,10 +827,11 @@ namespace cryptonote
* @param amounts optional set of amounts to lookup
* @param unlocked whether to restrict instances to unlocked ones
* @param recent_cutoff timestamp to consider outputs as recent
+ * @param min_count return only amounts with at least that many instances
*
* @return a set of amount/instances
*/
- std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>> get_output_histogram(const std::vector<uint64_t> &amounts, bool unlocked, uint64_t recent_cutoff) const;
+ std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>> get_output_histogram(const std::vector<uint64_t> &amounts, bool unlocked, uint64_t recent_cutoff, uint64_t min_count = 0) const;
/**
* @brief perform a check on all key images in the blockchain
diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp
index 4d852fc99..17400ab68 100644
--- a/src/cryptonote_core/cryptonote_core.cpp
+++ b/src/cryptonote_core/cryptonote_core.cpp
@@ -1418,6 +1418,11 @@ namespace cryptonote
return true;
}
//-----------------------------------------------------------------------------------------------
+ uint8_t core::get_ideal_hard_fork_version() const
+ {
+ return get_blockchain_storage().get_ideal_hard_fork_version();
+ }
+ //-----------------------------------------------------------------------------------------------
uint8_t core::get_ideal_hard_fork_version(uint64_t height) const
{
return get_blockchain_storage().get_ideal_hard_fork_version(height);
diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h
index abf79be1d..ff056c2a2 100644
--- a/src/cryptonote_core/cryptonote_core.h
+++ b/src/cryptonote_core/cryptonote_core.h
@@ -642,6 +642,13 @@ namespace cryptonote
uint64_t get_target_blockchain_height() const;
/**
+ * @brief returns the newest hardfork version known to the blockchain
+ *
+ * @return the version
+ */
+ uint8_t get_ideal_hard_fork_version() const;
+
+ /**
* @brief return the ideal hard fork version for a given block height
*
* @return what it says above
diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl
index ca3d35f16..711605597 100644
--- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl
+++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl
@@ -271,7 +271,7 @@ namespace cryptonote
const uint8_t version = m_core.get_ideal_hard_fork_version(hshd.current_height - 1);
if (version >= 6 && version != hshd.top_version)
{
- if (version < hshd.top_version)
+ if (version < hshd.top_version && version == m_core.get_ideal_hard_fork_version())
MCLOG_RED(el::Level::Warning, "global", context << " peer claims higher version that we think (" <<
(unsigned)hshd.top_version << " for " << (hshd.current_height - 1) << " instead of " << (unsigned)version <<
") - we may be forked from the network and a software upgrade may be needed");
diff --git a/src/daemon/command_parser_executor.cpp b/src/daemon/command_parser_executor.cpp
index 7a89ebc0c..8b51b9b85 100644
--- a/src/daemon/command_parser_executor.cpp
+++ b/src/daemon/command_parser_executor.cpp
@@ -27,6 +27,7 @@
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "common/dns_utils.h"
+#include "version.h"
#include "daemon/command_parser_executor.h"
#undef MONERO_DEFAULT_LOG_CATEGORY
@@ -379,8 +380,6 @@ bool t_command_parser_executor::set_limit(const std::vector<std::string>& args)
std::cout << "failed to parse argument" << std::endl;
return false;
}
- if (limit > 0)
- limit *= 1024;
return m_executor.set_limit(limit, limit);
}
@@ -399,8 +398,6 @@ bool t_command_parser_executor::set_limit_up(const std::vector<std::string>& arg
std::cout << "failed to parse argument" << std::endl;
return false;
}
- if (limit > 0)
- limit *= 1024;
return m_executor.set_limit(0, limit);
}
@@ -419,8 +416,6 @@ bool t_command_parser_executor::set_limit_down(const std::vector<std::string>& a
std::cout << "failed to parse argument" << std::endl;
return false;
}
- if (limit > 0)
- limit *= 1024;
return m_executor.set_limit(limit, 0);
}
@@ -664,4 +659,10 @@ bool t_command_parser_executor::sync_info(const std::vector<std::string>& args)
return m_executor.sync_info();
}
+bool t_command_parser_executor::version(const std::vector<std::string>& args)
+{
+ std::cout << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << std::endl;
+ return true;
+}
+
} // namespace daemonize
diff --git a/src/daemon/command_parser_executor.h b/src/daemon/command_parser_executor.h
index 2c09a4748..a70070171 100644
--- a/src/daemon/command_parser_executor.h
+++ b/src/daemon/command_parser_executor.h
@@ -138,6 +138,8 @@ public:
bool relay_tx(const std::vector<std::string>& args);
bool sync_info(const std::vector<std::string>& args);
+
+ bool version(const std::vector<std::string>& args);
};
} // namespace daemonize
diff --git a/src/daemon/command_server.cpp b/src/daemon/command_server.cpp
index a50dbea69..144603597 100644
--- a/src/daemon/command_server.cpp
+++ b/src/daemon/command_server.cpp
@@ -280,6 +280,11 @@ t_command_server::t_command_server(
, std::bind(&t_command_parser_executor::sync_info, &m_parser, p::_1)
, "Print information about the blockchain sync state."
);
+ m_command_lookup.set_handler(
+ "version"
+ , std::bind(&t_command_parser_executor::version, &m_parser, p::_1)
+ , "Print version information."
+ );
}
bool t_command_server::process_command_str(const std::string& cmd)
diff --git a/src/daemon/main.cpp b/src/daemon/main.cpp
index 50384b2a6..49494e889 100644
--- a/src/daemon/main.cpp
+++ b/src/daemon/main.cpp
@@ -138,6 +138,28 @@ int main(int argc, char const * argv[])
return 0;
}
+ std::string config = command_line::get_arg(vm, daemon_args::arg_config_file);
+ boost::filesystem::path config_path(config);
+ boost::system::error_code ec;
+ if (bf::exists(config_path, ec))
+ {
+ try
+ {
+ po::store(po::parse_config_file<char>(config_path.string<std::string>().c_str(), core_settings), vm);
+ }
+ catch (const std::exception &e)
+ {
+ // log system isn't initialized yet
+ std::cerr << "Error parsing config file: " << e.what() << std::endl;
+ throw;
+ }
+ }
+ else if (!command_line::is_arg_defaulted(vm, daemon_args::arg_config_file))
+ {
+ std::cerr << "Can't find config file " << config << std::endl;
+ return 1;
+ }
+
const bool testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
const bool stagenet = command_line::get_arg(vm, cryptonote::arg_stagenet_on);
if (testnet && stagenet)
@@ -170,29 +192,6 @@ int main(int argc, char const * argv[])
//bf::path relative_path_base = daemonizer::get_relative_path_base(vm);
bf::path relative_path_base = data_dir;
- std::string config = command_line::get_arg(vm, daemon_args::arg_config_file);
-
- boost::filesystem::path data_dir_path(data_dir);
- boost::filesystem::path config_path(config);
- if (!config_path.has_parent_path())
- {
- config_path = data_dir / config_path;
- }
-
- boost::system::error_code ec;
- if (bf::exists(config_path, ec))
- {
- try
- {
- po::store(po::parse_config_file<char>(config_path.string<std::string>().c_str(), core_settings), vm);
- }
- catch (const std::exception &e)
- {
- // log system isn't initialized yet
- std::cerr << "Error parsing config file: " << e.what() << std::endl;
- throw;
- }
- }
po::notify(vm);
// log_file_path
diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp
index 73b8d1a18..64ce3a406 100644
--- a/src/daemon/rpc_command_executor.cpp
+++ b/src/daemon/rpc_command_executor.cpp
@@ -1176,8 +1176,8 @@ bool t_rpc_command_executor::get_limit()
}
}
- tools::msg_writer() << "limit-down is " << res.limit_down/1024 << " kB/s";
- tools::msg_writer() << "limit-up is " << res.limit_up/1024 << " kB/s";
+ tools::msg_writer() << "limit-down is " << res.limit_down << " kB/s";
+ tools::msg_writer() << "limit-up is " << res.limit_up << " kB/s";
return true;
}
@@ -1207,8 +1207,8 @@ bool t_rpc_command_executor::set_limit(int64_t limit_down, int64_t limit_up)
}
}
- tools::msg_writer() << "Set limit-down to " << res.limit_down/1024 << " kB/s";
- tools::msg_writer() << "Set limit-up to " << res.limit_up/1024 << " kB/s";
+ tools::msg_writer() << "Set limit-down to " << res.limit_down << " kB/s";
+ tools::msg_writer() << "Set limit-up to " << res.limit_up << " kB/s";
return true;
}
@@ -1235,7 +1235,7 @@ bool t_rpc_command_executor::get_limit_up()
}
}
- tools::msg_writer() << "limit-up is " << res.limit_up/1024 << " kB/s";
+ tools::msg_writer() << "limit-up is " << res.limit_up << " kB/s";
return true;
}
@@ -1262,7 +1262,7 @@ bool t_rpc_command_executor::get_limit_down()
}
}
- tools::msg_writer() << "limit-down is " << res.limit_down/1024 << " kB/s";
+ tools::msg_writer() << "limit-down is " << res.limit_down << " kB/s";
return true;
}
diff --git a/src/device/device_default.hpp b/src/device/device_default.hpp
index 649fed862..771fbba72 100644
--- a/src/device/device_default.hpp
+++ b/src/device/device_default.hpp
@@ -93,7 +93,7 @@ namespace hw {
bool sc_secret_add(crypto::secret_key &r, const crypto::secret_key &a, const crypto::secret_key &b) override;
crypto::secret_key generate_keys(crypto::public_key &pub, crypto::secret_key &sec, const crypto::secret_key& recovery_key = crypto::secret_key(), bool recover = false) override;
bool generate_key_derivation(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_derivation &derivation) override;
- bool conceal_derivation(crypto::key_derivation &derivation, const crypto::public_key &tx_pub_key, const std::vector<crypto::public_key> &additional_tx_pub_keys, const crypto::key_derivation &main_derivation, const std::vector<crypto::key_derivation> &additional_derivations);
+ bool conceal_derivation(crypto::key_derivation &derivation, const crypto::public_key &tx_pub_key, const std::vector<crypto::public_key> &additional_tx_pub_keys, const crypto::key_derivation &main_derivation, const std::vector<crypto::key_derivation> &additional_derivations) override;
bool derivation_to_scalar(const crypto::key_derivation &derivation, const size_t output_index, crypto::ec_scalar &res) override;
bool derive_secret_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::secret_key &sec, crypto::secret_key &derived_sec) override;
bool derive_public_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::public_key &pub, crypto::public_key &derived_pub) override;
diff --git a/src/device/device_ledger.hpp b/src/device/device_ledger.hpp
index 9f73bd070..f1fcaab87 100644
--- a/src/device/device_ledger.hpp
+++ b/src/device/device_ledger.hpp
@@ -169,7 +169,7 @@ namespace hw {
bool sc_secret_add(crypto::secret_key &r, const crypto::secret_key &a, const crypto::secret_key &b) override;
crypto::secret_key generate_keys(crypto::public_key &pub, crypto::secret_key &sec, const crypto::secret_key& recovery_key = crypto::secret_key(), bool recover = false) override;
bool generate_key_derivation(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_derivation &derivation) override;
- bool conceal_derivation(crypto::key_derivation &derivation, const crypto::public_key &tx_pub_key, const std::vector<crypto::public_key> &additional_tx_pub_keys, const crypto::key_derivation &main_derivation, const std::vector<crypto::key_derivation> &additional_derivations);
+ bool conceal_derivation(crypto::key_derivation &derivation, const crypto::public_key &tx_pub_key, const std::vector<crypto::public_key> &additional_tx_pub_keys, const crypto::key_derivation &main_derivation, const std::vector<crypto::key_derivation> &additional_derivations) override;
bool derivation_to_scalar(const crypto::key_derivation &derivation, const size_t output_index, crypto::ec_scalar &res) override;
bool derive_secret_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::secret_key &sec, crypto::secret_key &derived_sec) override;
bool derive_public_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::public_key &pub, crypto::public_key &derived_pub) override;
diff --git a/src/p2p/net_node.h b/src/p2p/net_node.h
index 3010b43ad..4606f66ee 100644
--- a/src/p2p/net_node.h
+++ b/src/p2p/net_node.h
@@ -334,8 +334,8 @@ namespace nodetool
cryptonote::network_type m_nettype;
};
- const int64_t default_limit_up = 2048;
- const int64_t default_limit_down = 8192;
+ const int64_t default_limit_up = 2048; // kB/s
+ const int64_t default_limit_down = 8192; // kB/s
extern const command_line::arg_descriptor<std::string> arg_p2p_bind_ip;
extern const command_line::arg_descriptor<std::string, false, true, 2> arg_p2p_bind_port;
extern const command_line::arg_descriptor<uint32_t> arg_p2p_external_port;
diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl
index 3b0d1c394..9b21705ec 100644
--- a/src/p2p/net_node.inl
+++ b/src/p2p/net_node.inl
@@ -49,16 +49,9 @@
#include "storages/levin_abstract_invoke2.h"
#include "cryptonote_core/cryptonote_core.h"
-// We have to look for miniupnpc headers in different places, dependent on if its compiled or external
-#ifdef UPNP_STATIC
- #include <miniupnpc/miniupnpc.h>
- #include <miniupnpc/upnpcommands.h>
- #include <miniupnpc/upnperrors.h>
-#else
- #include "miniupnpc.h"
- #include "upnpcommands.h"
- #include "upnperrors.h"
-#endif
+#include <miniupnp/miniupnpc/miniupnpc.h>
+#include <miniupnp/miniupnpc/upnpcommands.h>
+#include <miniupnp/miniupnpc/upnperrors.h>
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "net.p2p"
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index 79792e387..3645c494e 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -1728,7 +1728,7 @@ namespace cryptonote
std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>> histogram;
try
{
- histogram = m_core.get_blockchain_storage().get_output_histogram(req.amounts, req.unlocked, req.recent_cutoff);
+ histogram = m_core.get_blockchain_storage().get_output_histogram(req.amounts, req.unlocked, req.recent_cutoff, req.min_count);
}
catch (const std::exception &e)
{
@@ -2082,10 +2082,27 @@ namespace cryptonote
//------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::on_get_output_distribution(const COMMAND_RPC_GET_OUTPUT_DISTRIBUTION::request& req, COMMAND_RPC_GET_OUTPUT_DISTRIBUTION::response& res, epee::json_rpc::error& error_resp)
{
+ PERF_TIMER(on_get_output_distribution);
try
{
for (uint64_t amount: req.amounts)
{
+ static struct D
+ {
+ boost::mutex mutex;
+ std::vector<uint64_t> cached_distribution;
+ uint64_t cached_from, cached_to, cached_start_height, cached_base;
+ bool cached;
+ D(): cached_from(0), cached_to(0), cached_start_height(0), cached_base(0), cached(false) {}
+ } d;
+ boost::unique_lock<boost::mutex> lock(d.mutex);
+
+ if (d.cached && amount == 0 && d.cached_from == req.from_height && d.cached_to == req.to_height)
+ {
+ res.distributions.push_back({amount, d.cached_start_height, d.cached_distribution, d.cached_base});
+ continue;
+ }
+
std::vector<uint64_t> distribution;
uint64_t start_height, base;
if (!m_core.get_output_distribution(amount, req.from_height, start_height, distribution, base))
@@ -2094,12 +2111,29 @@ namespace cryptonote
error_resp.message = "Failed to get rct distribution";
return false;
}
+ if (req.to_height > 0 && req.to_height >= req.from_height)
+ {
+ uint64_t offset = std::max(req.from_height, start_height);
+ if (offset <= req.to_height && req.to_height - offset + 1 < distribution.size())
+ distribution.resize(req.to_height - offset + 1);
+ }
if (req.cumulative)
{
distribution[0] += base;
for (size_t n = 1; n < distribution.size(); ++n)
distribution[n] += distribution[n-1];
}
+
+ if (amount == 0)
+ {
+ d.cached_from = req.from_height;
+ d.cached_to = req.to_height;
+ d.cached_distribution = distribution;
+ d.cached_start_height = start_height;
+ d.cached_base = base;
+ d.cached = true;
+ }
+
res.distributions.push_back({amount, start_height, std::move(distribution), base});
}
}
diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h
index df5b4893f..250c88e90 100644
--- a/src/rpc/core_rpc_server_commands_defs.h
+++ b/src/rpc/core_rpc_server_commands_defs.h
@@ -1705,7 +1705,7 @@ namespace cryptonote
{
struct request
{
- int64_t limit_down;
+ int64_t limit_down; // all limits (for get and set) are kB/s
int64_t limit_up;
BEGIN_KV_SERIALIZE_MAP()
@@ -2212,11 +2212,13 @@ namespace cryptonote
{
std::vector<uint64_t> amounts;
uint64_t from_height;
+ uint64_t to_height;
bool cumulative;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(amounts)
KV_SERIALIZE_OPT(from_height, (uint64_t)0)
+ KV_SERIALIZE_OPT(to_height, (uint64_t)0)
KV_SERIALIZE_OPT(cumulative, false)
END_KV_SERIALIZE_MAP()
};
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index 33615ffe2..639b394f3 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -62,6 +62,7 @@
#include "ringct/rctSigs.h"
#include "multisig/multisig.h"
#include "wallet/wallet_args.h"
+#include "version.h"
#include <stdexcept>
#ifdef WIN32
@@ -1584,6 +1585,12 @@ bool simple_wallet::save_known_rings(const std::vector<std::string> &args)
return true;
}
+bool simple_wallet::version(const std::vector<std::string> &args)
+{
+ message_writer() << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")";
+ return true;
+}
+
bool simple_wallet::set_always_confirm_transfers(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
{
const auto pwd_container = get_and_verify_password();
@@ -2074,8 +2081,8 @@ simple_wallet::simple_wallet()
tr("Donate <amount> to the development team (donate.getmonero.org)."));
m_cmd_binder.set_handler("sign_transfer",
boost::bind(&simple_wallet::sign_transfer, this, _1),
- tr("sign_transfer <file>"),
- tr("Sign a transaction from a <file>."));
+ tr("sign_transfer [export]"),
+ tr("Sign a transaction from a file."));
m_cmd_binder.set_handler("submit_transfer",
boost::bind(&simple_wallet::submit_transfer, this, _1),
tr("Submit a signed transaction from a file."));
@@ -2335,6 +2342,10 @@ simple_wallet::simple_wallet()
boost::bind(&simple_wallet::blackballed, this, _1),
tr("blackballed <output public key>"),
tr("Checks whether an output is blackballed"));
+ m_cmd_binder.set_handler("version",
+ boost::bind(&simple_wallet::version, this, _1),
+ tr("version"),
+ tr("Returns version information"));
m_cmd_binder.set_handler("help",
boost::bind(&simple_wallet::help, this, _1),
tr("help [<command>]"),
diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h
index f26f69353..39a91c5f5 100644
--- a/src/simplewallet/simplewallet.h
+++ b/src/simplewallet/simplewallet.h
@@ -218,6 +218,7 @@ namespace cryptonote
bool blackball(const std::vector<std::string>& args);
bool unblackball(const std::vector<std::string>& args);
bool blackballed(const std::vector<std::string>& args);
+ bool version(const std::vector<std::string>& args);
uint64_t get_daemon_blockchain_height(std::string& err);
bool try_connect_to_daemon(bool silent = false, uint32_t* version = nullptr);
diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h
index d4e41c5aa..617b6035a 100644
--- a/src/wallet/api/wallet2_api.h
+++ b/src/wallet/api/wallet2_api.h
@@ -956,25 +956,25 @@ struct WalletManager
virtual void setDaemonAddress(const std::string &address) = 0;
//! returns whether the daemon can be reached, and its version number
- virtual bool connected(uint32_t *version = NULL) const = 0;
+ virtual bool connected(uint32_t *version = NULL) = 0;
//! returns current blockchain height
- virtual uint64_t blockchainHeight() const = 0;
+ virtual uint64_t blockchainHeight() = 0;
//! returns current blockchain target height
- virtual uint64_t blockchainTargetHeight() const = 0;
+ virtual uint64_t blockchainTargetHeight() = 0;
//! returns current network difficulty
- virtual uint64_t networkDifficulty() const = 0;
+ virtual uint64_t networkDifficulty() = 0;
//! returns current mining hash rate (0 if not mining)
- virtual double miningHashRate() const = 0;
+ virtual double miningHashRate() = 0;
//! returns current block target
- virtual uint64_t blockTarget() const = 0;
+ virtual uint64_t blockTarget() = 0;
//! returns true iff mining
- virtual bool isMining() const = 0;
+ virtual bool isMining() = 0;
//! starts mining with the set number of threads
virtual bool startMining(const std::string &address, uint32_t threads = 1, bool background_mining = false, bool ignore_battery = true) = 0;
diff --git a/src/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp
index 80f5780b5..a63716576 100644
--- a/src/wallet/api/wallet_manager.cpp
+++ b/src/wallet/api/wallet_manager.cpp
@@ -47,15 +47,6 @@ namespace epee {
unsigned int g_test_dbg_lock_sleep = 0;
}
-namespace {
- template<typename Request, typename Response>
- bool connect_and_invoke(const std::string& address, const std::string& path, const Request& request, Response& response)
- {
- epee::net_utils::http::http_simple_client client{};
- return client.set_server(address, boost::none) && epee::net_utils::invoke_http_json(path, request, response, client);
- }
-}
-
namespace Monero {
Wallet *WalletManagerImpl::createWallet(const std::string &path, const std::string &password,
@@ -193,16 +184,19 @@ std::string WalletManagerImpl::errorString() const
void WalletManagerImpl::setDaemonAddress(const std::string &address)
{
m_daemonAddress = address;
+ if(m_http_client.is_connected())
+ m_http_client.disconnect();
+ m_http_client.set_server(address, boost::none);
}
-bool WalletManagerImpl::connected(uint32_t *version) const
+bool WalletManagerImpl::connected(uint32_t *version)
{
epee::json_rpc::request<cryptonote::COMMAND_RPC_GET_VERSION::request> req_t = AUTO_VAL_INIT(req_t);
epee::json_rpc::response<cryptonote::COMMAND_RPC_GET_VERSION::response, std::string> resp_t = AUTO_VAL_INIT(resp_t);
req_t.jsonrpc = "2.0";
req_t.id = epee::serialization::storage_entry(0);
req_t.method = "get_version";
- if (!connect_and_invoke(m_daemonAddress, "/json_rpc", req_t, resp_t))
+ if (!epee::net_utils::invoke_http_json("/json_rpc", req_t, resp_t, m_http_client))
return false;
if (version)
@@ -210,65 +204,65 @@ bool WalletManagerImpl::connected(uint32_t *version) const
return true;
}
-uint64_t WalletManagerImpl::blockchainHeight() const
+uint64_t WalletManagerImpl::blockchainHeight()
{
cryptonote::COMMAND_RPC_GET_INFO::request ireq;
cryptonote::COMMAND_RPC_GET_INFO::response ires;
- if (!connect_and_invoke(m_daemonAddress, "/getinfo", ireq, ires))
+ if (!epee::net_utils::invoke_http_json("/getinfo", ireq, ires, m_http_client))
return 0;
return ires.height;
}
-uint64_t WalletManagerImpl::blockchainTargetHeight() const
+uint64_t WalletManagerImpl::blockchainTargetHeight()
{
cryptonote::COMMAND_RPC_GET_INFO::request ireq;
cryptonote::COMMAND_RPC_GET_INFO::response ires;
- if (!connect_and_invoke(m_daemonAddress, "/getinfo", ireq, ires))
+ if (!epee::net_utils::invoke_http_json("/getinfo", ireq, ires, m_http_client))
return 0;
return ires.target_height >= ires.height ? ires.target_height : ires.height;
}
-uint64_t WalletManagerImpl::networkDifficulty() const
+uint64_t WalletManagerImpl::networkDifficulty()
{
cryptonote::COMMAND_RPC_GET_INFO::request ireq;
cryptonote::COMMAND_RPC_GET_INFO::response ires;
- if (!connect_and_invoke(m_daemonAddress, "/getinfo", ireq, ires))
+ if (!epee::net_utils::invoke_http_json("/getinfo", ireq, ires, m_http_client))
return 0;
return ires.difficulty;
}
-double WalletManagerImpl::miningHashRate() const
+double WalletManagerImpl::miningHashRate()
{
cryptonote::COMMAND_RPC_MINING_STATUS::request mreq;
cryptonote::COMMAND_RPC_MINING_STATUS::response mres;
epee::net_utils::http::http_simple_client http_client;
- if (!connect_and_invoke(m_daemonAddress, "/mining_status", mreq, mres))
+ if (!epee::net_utils::invoke_http_json("/mining_status", mreq, mres, m_http_client))
return 0.0;
if (!mres.active)
return 0.0;
return mres.speed;
}
-uint64_t WalletManagerImpl::blockTarget() const
+uint64_t WalletManagerImpl::blockTarget()
{
cryptonote::COMMAND_RPC_GET_INFO::request ireq;
cryptonote::COMMAND_RPC_GET_INFO::response ires;
- if (!connect_and_invoke(m_daemonAddress, "/getinfo", ireq, ires))
+ if (!epee::net_utils::invoke_http_json("/getinfo", ireq, ires, m_http_client))
return 0;
return ires.target;
}
-bool WalletManagerImpl::isMining() const
+bool WalletManagerImpl::isMining()
{
cryptonote::COMMAND_RPC_MINING_STATUS::request mreq;
cryptonote::COMMAND_RPC_MINING_STATUS::response mres;
- if (!connect_and_invoke(m_daemonAddress, "/mining_status", mreq, mres))
+ if (!epee::net_utils::invoke_http_json("/mining_status", mreq, mres, m_http_client))
return false;
return mres.active;
}
@@ -283,7 +277,7 @@ bool WalletManagerImpl::startMining(const std::string &address, uint32_t threads
mreq.ignore_battery = ignore_battery;
mreq.do_background_mining = background_mining;
- if (!connect_and_invoke(m_daemonAddress, "/start_mining", mreq, mres))
+ if (!epee::net_utils::invoke_http_json("/start_mining", mreq, mres, m_http_client))
return false;
return mres.status == CORE_RPC_STATUS_OK;
}
@@ -293,7 +287,7 @@ bool WalletManagerImpl::stopMining()
cryptonote::COMMAND_RPC_STOP_MINING::request mreq;
cryptonote::COMMAND_RPC_STOP_MINING::response mres;
- if (!connect_and_invoke(m_daemonAddress, "/stop_mining", mreq, mres))
+ if (!epee::net_utils::invoke_http_json("/stop_mining", mreq, mres, m_http_client))
return false;
return mres.status == CORE_RPC_STATUS_OK;
}
diff --git a/src/wallet/api/wallet_manager.h b/src/wallet/api/wallet_manager.h
index 409a6d499..26238b658 100644
--- a/src/wallet/api/wallet_manager.h
+++ b/src/wallet/api/wallet_manager.h
@@ -30,6 +30,7 @@
#include "wallet/api/wallet2_api.h"
+#include "net/http_client.h"
#include <string>
namespace Monero {
@@ -69,13 +70,13 @@ public:
std::vector<std::string> findWallets(const std::string &path);
std::string errorString() const;
void setDaemonAddress(const std::string &address);
- bool connected(uint32_t *version = NULL) const;
- uint64_t blockchainHeight() const;
- uint64_t blockchainTargetHeight() const;
- uint64_t networkDifficulty() const;
- double miningHashRate() const;
- uint64_t blockTarget() const;
- bool isMining() const;
+ bool connected(uint32_t *version = NULL);
+ uint64_t blockchainHeight();
+ uint64_t blockchainTargetHeight();
+ uint64_t networkDifficulty();
+ double miningHashRate();
+ uint64_t blockTarget();
+ bool isMining();
bool startMining(const std::string &address, uint32_t threads = 1, bool background_mining = false, bool ignore_battery = true);
bool stopMining();
std::string resolveOpenAlias(const std::string &address, bool &dnssec_valid) const;
@@ -84,6 +85,7 @@ private:
WalletManagerImpl() {}
friend struct WalletManagerFactory;
std::string m_daemonAddress;
+ epee::net_utils::http::http_simple_client m_http_client;
std::string m_errorString;
};
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 3883de6d9..d53ed82a9 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -2421,7 +2421,7 @@ void wallet2::detach_blockchain(uint64_t height)
// size 1 2 3 4 5 6 7 8 9
// block 0 1 2 3 4 5 6 7 8
// C
- THROW_WALLET_EXCEPTION_IF(height <= m_checkpoints.get_max_height() && m_blockchain.size() > m_checkpoints.get_max_height(),
+ THROW_WALLET_EXCEPTION_IF(height < m_blockchain.offset() && m_blockchain.size() > m_blockchain.offset(),
error::wallet_internal_error, "Daemon claims reorg below last checkpoint");
size_t transfers_detached = 0;
@@ -3875,6 +3875,11 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
void wallet2::trim_hashchain()
{
uint64_t height = m_checkpoints.get_max_height();
+
+ for (const transfer_details &td: m_transfers)
+ if (td.m_block_height < height)
+ height = td.m_block_height;
+
if (!m_blockchain.empty() && m_blockchain.size() == m_blockchain.offset())
{
MINFO("Fixing empty hashchain");
@@ -5905,9 +5910,10 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
auto end = std::unique(req_t.amounts.begin(), req_t.amounts.end());
req_t.amounts.resize(std::distance(req_t.amounts.begin(), end));
req_t.from_height = std::max<uint64_t>(segregation_fork_height, RECENT_OUTPUT_BLOCKS) - RECENT_OUTPUT_BLOCKS;
+ req_t.to_height = segregation_fork_height + 1;
req_t.cumulative = true;
m_daemon_rpc_mutex.lock();
- bool r = net_utils::invoke_http_json_rpc("/json_rpc", "get_output_distribution", req_t, resp_t, m_http_client, rpc_timeout);
+ bool r = net_utils::invoke_http_json_rpc("/json_rpc", "get_output_distribution", req_t, resp_t, m_http_client, rpc_timeout * 1000);
m_daemon_rpc_mutex.unlock();
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "transfer_selected");
THROW_WALLET_EXCEPTION_IF(resp_t.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "get_output_distribution");
@@ -5924,6 +5930,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
{
THROW_WALLET_EXCEPTION_IF(d.start_height > segregation_fork_height, error::get_output_distribution, "Distribution start_height too high");
THROW_WALLET_EXCEPTION_IF(segregation_fork_height - d.start_height >= d.distribution.size(), error::get_output_distribution, "Distribution size too small");
+ THROW_WALLET_EXCEPTION_IF(segregation_fork_height - RECENT_OUTPUT_BLOCKS - d.start_height >= d.distribution.size(), error::get_output_distribution, "Distribution size too small");
THROW_WALLET_EXCEPTION_IF(segregation_fork_height <= RECENT_OUTPUT_BLOCKS, error::wallet_internal_error, "Fork height too low");
THROW_WALLET_EXCEPTION_IF(segregation_fork_height - RECENT_OUTPUT_BLOCKS < d.start_height, error::get_output_distribution, "Bad start height");
uint64_t till_fork = d.distribution[segregation_fork_height - d.start_height];
@@ -8135,6 +8142,7 @@ std::vector<size_t> wallet2::select_available_outputs_from_histogram(uint64_t co
req_t.min_count = count;
req_t.max_count = 0;
req_t.unlocked = unlocked;
+ req_t.recent_cutoff = 0;
bool r = net_utils::invoke_http_json_rpc("/json_rpc", "get_output_histogram", req_t, resp_t, m_http_client, rpc_timeout);
m_daemon_rpc_mutex.unlock();
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "select_available_outputs_from_histogram");
@@ -8171,6 +8179,8 @@ uint64_t wallet2::get_num_rct_outputs()
req_t.amounts.push_back(0);
req_t.min_count = 0;
req_t.max_count = 0;
+ req_t.unlocked = true;
+ req_t.recent_cutoff = 0;
bool r = net_utils::invoke_http_json_rpc("/json_rpc", "get_output_histogram", req_t, resp_t, m_http_client, rpc_timeout);
m_daemon_rpc_mutex.unlock();
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "get_num_rct_outputs");