diff --git a/.travis.yml b/.travis.yml index ca3a24ae8..6a9b9b94b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -58,7 +58,7 @@ script: - export TRAVIS_COMMIT_LOG=`git log --format=fuller -1` - OUTDIR=$BASE_OUTDIR/$TRAVIS_PULL_REQUEST/$TRAVIS_JOB_NUMBER-$HOST - if [ -z "$NO_DEPENDS" ]; then $DOCKER_EXEC ccache --max-size=$CCACHE_SIZE; fi - - $DOCKER_EXEC bash -c "mkdir build && cd build && cmake -DCMAKE_TOOLCHAIN_FILE=$TRAVIS_BUILD_DIR/contrib/depends/$HOST/share/toolchain.cmake .. && make $MAKEJOBS" + - $DOCKER_EXEC bash -c "mkdir build && cd build && cmake -DCMAKE_TOOLCHAIN_FILE=$TRAVIS_BUILD_DIR/contrib/depends/$HOST/share/toolchain.cmake -DTRAVIS=true .. && make $MAKEJOBS" - export LD_LIBRARY_PATH=$TRAVIS_BUILD_DIR/contrib/depends/$HOST/lib after_script: - echo $TRAVIS_COMMIT_RANGE diff --git a/CMakeLists.txt b/CMakeLists.txt index 5661f6c65..ed555349f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,6 +41,7 @@ if (IOS) endif() cmake_minimum_required(VERSION 2.8.7) +message(STATUS "CMake version ${CMAKE_VERSION}") project(loki) @@ -144,7 +145,6 @@ if(ARCH_ID STREQUAL "ppc64le") set(PPC64LE 1) set(PPC64 0) set(PPC 0) - endif() if(ARCH_ID STREQUAL "powerpc64" OR ARCH_ID STREQUAL "ppc64") @@ -433,6 +433,8 @@ if (UNIX AND NOT APPLE) # Note that at the time of this writing the -Wstrict-prototypes flag added below will make this fail set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads) + add_c_flag_if_supported(-pthread CMAKE_C_FLAGS) + add_cxx_flag_if_supported(-pthread CMAKE_CXX_FLAGS) endif() # Handle OpenSSL, used for sha256sum on binary updates and light wallet ssl http @@ -522,10 +524,8 @@ if(MSVC) include_directories(SYSTEM src/platform/msc) else() include(TestCXXAcceptsFlag) - if (NOT ARM6) - if(NOT DEPENDS OR DEPENDS AND NOT ARM) - set(ARCH native CACHE STRING "CPU to build for: -march value or 'default' to not pass -march at all") - endif() + if (NOT ARCH) + set(ARCH native CACHE STRING "CPU to build for: -march value or 'default' to not pass -march at all") endif() message(STATUS "Building on ${CMAKE_SYSTEM_PROCESSOR} for ${ARCH}") if(ARCH STREQUAL "default") @@ -887,7 +887,7 @@ endif() include_directories(SYSTEM ${Boost_INCLUDE_DIRS}) if(MINGW) set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wa,-mbig-obj") - set(EXTRA_LIBRARIES mswsock;ws2_32;iphlpapi;crypt32) + set(EXTRA_LIBRARIES mswsock;ws2_32;iphlpapi;crypt32;bcrypt) if(DEPENDS) set(ICU_LIBRARIES ${Boost_LOCALE_LIBRARY} sicuio sicuin sicuuc sicudt sicutu iconv) else() diff --git a/Dockerfile b/Dockerfile index 652ca7529..168ccecc7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -126,6 +126,7 @@ COPY . . ENV USE_SINGLE_BUILDDIR=1 ARG NPROC RUN set -ex && \ + git submodule init && git submodule update && \ rm -rf build && \ if [ -z "$NPROC" ] ; \ then make -j$(nproc) release-static ; \ diff --git a/README.md b/README.md index a1b8887dc..c1fe066ee 100644 --- a/README.md +++ b/README.md @@ -388,7 +388,7 @@ Then you can run make as usual. # Get binaries docker cp loki-android:/src/build/release/bin . -### Building portable statically linked binaries (Cross Compiling) +### Building portable statically linked binaries By default, in either dynamically or statically linked builds, binaries target the specific host processor on which the build happens and are not portable to other processors. Portable binaries can be built using the following targets: @@ -400,6 +400,68 @@ 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 +### Cross Compiling + +You can also cross-compile static binaries on Linux for Windows and macOS with the `depends` system. Go to `contrib/depends` and type: + +* ```make HOST=x86_64-linux-gnu``` for 64-bit linux binaries. +* ```make HOST=x86_64-w64-mingw32``` for 64-bit windows binaries. Requires: python3 nsis g++-mingw-w64-x86-64 wine1.6 bc +* ```make HOST=x86_64-apple-darwin11``` for darwin binaries. Requires: cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev +* ```make HOST=i686-linux-gnu``` for 32-bit linux binaries. Requires: g++-multilib bc +* ```make HOST=i686-w64-mingw32``` for 32-bit windows binaries. Requires: python3 nsis g++-mingw-w64-i686 +* ```make HOST=arm-linux-gnueabihf``` for armv6 binaries. Requires: g++-arm-linux-gnueabihf + +The required packages are the names for each toolchain on apt. Depending on your distro, they may have different names. +Then go back to the source dir and type: + +* ```cmake -DCMAKE_TOOLCHAIN_FILE=`pwd`/contrib/depends//share/toolchain.cmake``` +Where is one of the above mentioned targets. + +Using `depends` might also be easier to compile Monero on Windows than using MSys. Activate Windows Subsystem for Linux (WSL) with a distro (for example Ubuntu), install the apt build-essentials and follow the `depends` steps as depicted above. + +## 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 + +* The build needs 3 GB space. +* Wait one hour or more + +Packaging for your favorite distribution would be a welcome contribution! + ## Running lokid The build places the binary in `bin/` sub-directory within the build directory diff --git a/contrib/depends/toolchain.cmake.in b/contrib/depends/toolchain.cmake.in index f8548a724..66168facb 100644 --- a/contrib/depends/toolchain.cmake.in +++ b/contrib/depends/toolchain.cmake.in @@ -51,7 +51,9 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") SET(APPLE True) SET(BUILD_TAG "mac-x64") SET(BUILD_64 ON) + if(NOT TRAVIS) SET(ARCH "x86_64") + endif() SET(BREW OFF) SET(PORT OFF) SET(CMAKE_OSX_SYSROOT "@sdk@/MacOSX10.11.sdk/") diff --git a/contrib/epee/include/console_handler.h b/contrib/epee/include/console_handler.h index 2ccf5b095..6e7efd1d7 100644 --- a/contrib/epee/include/console_handler.h +++ b/contrib/epee/include/console_handler.h @@ -352,8 +352,11 @@ eof: std::string command; bool get_line_ret = m_stdin_reader.get_line(command); - if (!m_running || m_stdin_reader.eos()) + if (!m_running) + break; + if (m_stdin_reader.eos()) { + MGINFO("EOF on stdin, exiting"); break; } if (!get_line_ret) diff --git a/contrib/epee/include/misc_language.h b/contrib/epee/include/misc_language.h index d5157365c..7e4eb337d 100644 --- a/contrib/epee/include/misc_language.h +++ b/contrib/epee/include/misc_language.h @@ -147,7 +147,8 @@ namespace misc_utils {} ~call_befor_die() { - m_func(); + try { m_func(); } + catch (...) { /* ignore */ } } }; diff --git a/contrib/epee/include/net/abstract_tcp_server2.h b/contrib/epee/include/net/abstract_tcp_server2.h index d773ba2c3..54c54af6b 100644 --- a/contrib/epee/include/net/abstract_tcp_server2.h +++ b/contrib/epee/include/net/abstract_tcp_server2.h @@ -246,7 +246,6 @@ namespace net_utils m_timer(io_serice) {} boost::asio::deadline_timer m_timer; - uint64_t m_period; }; template @@ -262,25 +261,27 @@ namespace net_utils { return m_handler(); } + uint64_t m_period; }; template bool add_idle_handler(t_handler t_callback, uint64_t timeout_ms) { - boost::shared_ptr ptr(new idle_callback_conext(io_service_, t_callback, timeout_ms)); + boost::shared_ptr> ptr(new idle_callback_conext(io_service_, t_callback, timeout_ms)); //needed call handler here ?... ptr->m_timer.expires_from_now(boost::posix_time::milliseconds(ptr->m_period)); - ptr->m_timer.async_wait(boost::bind(&boosted_tcp_server::global_timer_handler, this, ptr)); + ptr->m_timer.async_wait(boost::bind(&boosted_tcp_server::global_timer_handler, this, ptr)); return true; } - bool global_timer_handler(/*const boost::system::error_code& err, */boost::shared_ptr ptr) + template + bool global_timer_handler(/*const boost::system::error_code& err, */boost::shared_ptr> ptr) { //if handler return false - he don't want to be called anymore if(!ptr->call_handler()) return true; ptr->m_timer.expires_from_now(boost::posix_time::milliseconds(ptr->m_period)); - ptr->m_timer.async_wait(boost::bind(&boosted_tcp_server::global_timer_handler, this, ptr)); + ptr->m_timer.async_wait(boost::bind(&boosted_tcp_server::global_timer_handler, this, ptr)); return true; } diff --git a/contrib/epee/include/net/abstract_tcp_server2.inl b/contrib/epee/include/net/abstract_tcp_server2.inl index 9fab7b9e1..039f34793 100644 --- a/contrib/epee/include/net/abstract_tcp_server2.inl +++ b/contrib/epee/include/net/abstract_tcp_server2.inl @@ -43,6 +43,8 @@ #include // TODO #include // TODO #include // TODO +#include "warnings.h" +#include "string_tools.h" #include "misc_language.h" #include "net/local_ip.h" #include "pragma_comp_defs.h" @@ -51,8 +53,6 @@ #include #include -#include "../../../../src/cryptonote_core/cryptonote_core.h" // e.g. for the send_stop_signal() - #undef LOKI_DEFAULT_LOG_CATEGORY #define LOKI_DEFAULT_LOG_CATEGORY "net" @@ -149,10 +149,8 @@ PRAGMA_WARNING_DISABLE_VS(4355) 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_) || epee::net_utils::is_ip_local(ip_); - // create a random uuid - boost::uuids::uuid random_uuid; - // that stuff turns out to be included, even though it's from src... Taking advantage - random_uuid = crypto::rand(); + // create a random uuid, we don't need crypto strength here + const boost::uuids::uuid random_uuid = boost::uuids::random_generator()(); context.set_details(random_uuid, epee::net_utils::ipv4_network_address(ip_, remote_ep.port()), is_income); _dbg3("[sock " << socket_.native_handle() << "] new connection from " << print_connection_context_short(context) << diff --git a/contrib/epee/include/net/connection_basic.hpp b/contrib/epee/include/net/connection_basic.hpp index 095e747a5..7e8750047 100644 --- a/contrib/epee/include/net/connection_basic.hpp +++ b/contrib/epee/include/net/connection_basic.hpp @@ -92,7 +92,6 @@ class connection_basic { // not-templated base class for rapid developmet of som critical_section m_send_que_lock; std::list m_send_que; volatile bool m_is_multithreaded; - double m_start_time; /// Strand to ensure the connection's handlers are not called concurrently. boost::asio::io_service::strand strand_; /// Socket for the connection. @@ -112,8 +111,6 @@ class connection_basic { // not-templated base class for rapid developmet of som void logger_handle_net_write(size_t size); // network data written void logger_handle_net_read(size_t size); // network data read - void set_start_time(); - // config for rate limit static void set_rate_up_limit(uint64_t limit); diff --git a/contrib/epee/include/net/http_protocol_handler.inl b/contrib/epee/include/net/http_protocol_handler.inl index 0175bb6ad..0d1d1349a 100644 --- a/contrib/epee/include/net/http_protocol_handler.inl +++ b/contrib/epee/include/net/http_protocol_handler.inl @@ -32,6 +32,7 @@ #include "string_tools.h" #include "file_io_utils.h" #include "net_parse_helpers.h" +#include "time_helper.h" #undef LOKI_DEFAULT_LOG_CATEGORY #define LOKI_DEFAULT_LOG_CATEGORY "net.http" diff --git a/contrib/epee/include/net/levin_protocol_handler_async.h b/contrib/epee/include/net/levin_protocol_handler_async.h index 0796b76c2..26f0973ae 100644 --- a/contrib/epee/include/net/levin_protocol_handler_async.h +++ b/contrib/epee/include/net/levin_protocol_handler_async.h @@ -99,7 +99,7 @@ public: size_t get_connections_count(); void set_handler(levin_commands_handler* handler, void (*destroy)(levin_commands_handler*) = NULL); - async_protocol_handler_config():m_pcommands_handler(NULL), m_pcommands_handler_destroy(NULL), m_max_packet_size(LEVIN_DEFAULT_MAX_PACKET_SIZE) + async_protocol_handler_config():m_pcommands_handler(NULL), m_pcommands_handler_destroy(NULL), m_max_packet_size(LEVIN_DEFAULT_MAX_PACKET_SIZE), m_invoke_timeout(LEVIN_DEFAULT_TIMEOUT_PRECONFIGURED) {} ~async_protocol_handler_config() { set_handler(NULL, NULL); } void del_out_connections(size_t count); @@ -272,6 +272,8 @@ public: m_wait_count = 0; m_oponent_protocol_ver = 0; m_connection_initialized = false; + m_invoke_buf_ready = 0; + m_invoke_result_code = LEVIN_ERROR_CONNECTION; } virtual ~async_protocol_handler() { diff --git a/contrib/epee/src/connection_basic.cpp b/contrib/epee/src/connection_basic.cpp index 6005904ce..3ef1c1c18 100644 --- a/contrib/epee/src/connection_basic.cpp +++ b/contrib/epee/src/connection_basic.cpp @@ -250,22 +250,15 @@ void connection_basic::sleep_before_packet(size_t packet_size, int phase, int q } } -void connection_basic::set_start_time() { - CRITICAL_REGION_LOCAL( network_throttle_manager::m_lock_get_global_throttle_out ); - m_start_time = network_throttle_manager::get_global_throttle_out().get_time_seconds(); -} void connection_basic::do_send_handler_write(const void* ptr , size_t cb ) { // No sleeping here; sleeping is done once and for all in connection::handle_write MTRACE("handler_write (direct) - before ASIO write, for packet="<::handle_write MTRACE("handler_write (after write, from queue="< +#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING +#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 +#endif +#endif + #include #include #include @@ -117,6 +124,31 @@ static const char *get_default_categories(int level) return categories; } +#ifdef WIN32 +bool EnableVTMode() +{ + // Set output mode to handle virtual terminal sequences + HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); + if (hOut == INVALID_HANDLE_VALUE) + { + return false; + } + + DWORD dwMode = 0; + if (!GetConsoleMode(hOut, &dwMode)) + { + return false; + } + + dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; + if (!SetConsoleMode(hOut, dwMode)) + { + return false; + } + return true; +} +#endif + void mlog_configure(const std::string &filename_base, bool console, const std::size_t max_log_file_size, const std::size_t max_log_files) { el::Configurations c; @@ -202,6 +234,9 @@ void mlog_configure(const std::string &filename_base, bool console, const std::s loki_log = get_default_categories(0); } mlog_set_log(loki_log); +#ifdef WIN32 + EnableVTMode(); +#endif } void mlog_set_categories(const char *categories) diff --git a/contrib/epee/src/network_throttle-detail.cpp b/contrib/epee/src/network_throttle-detail.cpp index fa98b3701..ac807aa30 100644 --- a/contrib/epee/src/network_throttle-detail.cpp +++ b/contrib/epee/src/network_throttle-detail.cpp @@ -146,6 +146,7 @@ network_throttle::network_throttle(const std::string &nameshort, const std::stri m_network_add_cost = 128; m_network_minimal_segment = 256; m_network_max_segment = 1024*1024; + m_start_time = 0; m_any_packet_yet = false; m_slot_size = 1.0; // hard coded in few places m_target_speed = 16 * 1024; // other defaults are probably defined in the command-line parsing code when this class is used e.g. as main global throttle diff --git a/src/blockchain_utilities/CMakeLists.txt b/src/blockchain_utilities/CMakeLists.txt index 90b2672e2..43bd2fe02 100644 --- a/src/blockchain_utilities/CMakeLists.txt +++ b/src/blockchain_utilities/CMakeLists.txt @@ -183,7 +183,7 @@ target_link_libraries(blockchain_blackball set_property(TARGET blockchain_blackball PROPERTY - OUTPUT_NAME "loki-blockchain-blackball") + OUTPUT_NAME "loki-blockchain-mark-spent-outputs") install(TARGETS blockchain_blackball DESTINATION bin) diff --git a/src/blockchain_utilities/blockchain_blackball.cpp b/src/blockchain_utilities/blockchain_blackball.cpp index 13af864a5..ee919c025 100644 --- a/src/blockchain_utilities/blockchain_blackball.cpp +++ b/src/blockchain_utilities/blockchain_blackball.cpp @@ -227,7 +227,7 @@ static void init(std::string cache_filename) bool tx_active = false; int dbr; - MINFO("Creating blackball cache in " << cache_filename); + MINFO("Creating spent output cache in " << cache_filename); tools::create_directories_if_necessary(cache_filename); @@ -1020,7 +1020,7 @@ int main(int argc, char* argv[]) po::options_description desc_cmd_only("Command line options"); po::options_description desc_cmd_sett("Command line options and settings options"); const command_line::arg_descriptor arg_blackball_db_dir = { - "blackball-db-dir", "Specify blackball database directory", + "spent-output-db-dir", "Specify spent output database directory", get_default_db_path(), }; const command_line::arg_descriptor arg_log_level = {"log-level", "0-4 or categories", ""}; @@ -1077,7 +1077,7 @@ int main(int argc, char* argv[]) return 1; } - mlog_configure(mlog_get_default_log_path("loki-blockchain-blackball.log"), true); + mlog_configure(mlog_get_default_log_path("loki-blockchain-find-spent-outputs.log"), true); if (!command_line::is_arg_defaulted(vm, arg_log_level)) mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str()); else @@ -1134,10 +1134,10 @@ int main(int argc, char* argv[]) core_storage[n] = &(blockchain_objects->m_blockchain); } - const std::string cache_dir = (output_file_path / "blackball-cache").string(); + const std::string cache_dir = (output_file_path / "spent-outputs-cache").string(); init(cache_dir); - LOG_PRINT_L0("Scanning for blackballable outputs..."); + LOG_PRINT_L0("Scanning for spent outputs..."); size_t done = 0; @@ -1235,7 +1235,7 @@ int main(int argc, char* argv[]) const std::pair output = std::make_pair(txin.amount, absolute[0]); if (opt_verbose) { - MINFO("Blackballing output " << output.first << "/" << output.second << ", due to being used in a 1-ring"); + MINFO("Marking output " << output.first << "/" << output.second << " as spent, due to being used in a 1-ring"); std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush; } blackballs.push_back(output); @@ -1249,7 +1249,7 @@ int main(int argc, char* argv[]) const std::pair output = std::make_pair(txin.amount, absolute[o]); if (opt_verbose) { - MINFO("Blackballing output " << output.first << "/" << output.second << ", due to being used in " << new_ring.size() << " identical " << new_ring.size() << "-rings"); + MINFO("Marking output " << output.first << "/" << output.second << " as spent, due to being used in " << new_ring.size() << " identical " << new_ring.size() << "-rings"); std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush; } blackballs.push_back(output); @@ -1264,7 +1264,7 @@ int main(int argc, char* argv[]) const std::pair output = std::make_pair(txin.amount, absolute[o]); if (opt_verbose) { - MINFO("Blackballing output " << output.first << "/" << output.second << ", due to being used in " << new_ring.size() << " subsets of " << new_ring.size() << "-rings"); + MINFO("Marking output " << output.first << "/" << output.second << " as spent, due to being used in " << new_ring.size() << " subsets of " << new_ring.size() << "-rings"); std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush; } blackballs.push_back(output); @@ -1300,7 +1300,7 @@ int main(int argc, char* argv[]) const std::pair output = std::make_pair(txin.amount, common[0]); if (opt_verbose) { - MINFO("Blackballing output " << output.first << "/" << output.second << ", due to being used in rings with a single common element"); + MINFO("Marking output " << output.first << "/" << output.second << " as spent, due to being used in rings with a single common element"); std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush; } blackballs.push_back(output); @@ -1412,7 +1412,7 @@ int main(int argc, char* argv[]) const std::pair output = std::make_pair(od.amount, last_unknown); if (opt_verbose) { - MINFO("Blackballing output " << output.first << "/" << output.second << ", due to being used in a " << + MINFO("Marking output " << output.first << "/" << output.second << " as spent, due to being used in a " << absolute.size() << "-ring where all other outputs are known to be spent"); } blackballs.push_back(output); @@ -1440,7 +1440,7 @@ int main(int argc, char* argv[]) skip_secondary_passes: uint64_t diff = get_num_spent_outputs() - start_blackballed_outputs; - LOG_PRINT_L0(std::to_string(diff) << " new outputs blackballed, " << get_num_spent_outputs() << " total outputs blackballed"); + LOG_PRINT_L0(std::to_string(diff) << " new outputs marked as spent, " << get_num_spent_outputs() << " total outputs marked as spent"); MDB_txn *txn; dbr = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn); @@ -1480,7 +1480,7 @@ skip_secondary_passes: mdb_txn_abort(txn); } - LOG_PRINT_L0("Blockchain blackball data exported OK"); + LOG_PRINT_L0("Blockchain spent output data exported OK"); close_db(env0, txn0, cur0, dbi0); close(); return 0; diff --git a/src/common/expect.h b/src/common/expect.h index 326242502..72e4060a7 100644 --- a/src/common/expect.h +++ b/src/common/expect.h @@ -350,7 +350,9 @@ public: using error_type = std::error_code; //! Create a successful object. - expect() = default; + expect() noexcept + : code_() + {} expect(std::error_code const& code) noexcept : code_(code) diff --git a/src/common/password.cpp b/src/common/password.cpp index a8d5141dc..b3c51128f 100644 --- a/src/common/password.cpp +++ b/src/common/password.cpp @@ -60,7 +60,7 @@ namespace DWORD mode_old; ::GetConsoleMode(h_cin, &mode_old); - DWORD mode_new = mode_old & ~((hide_input ? ENABLE_ECHO_INPUT : 0) | ENABLE_LINE_INPUT); + DWORD mode_new = mode_old & ~(hide_input ? ENABLE_ECHO_INPUT : 0); ::SetConsoleMode(h_cin, mode_new); bool r = true; @@ -78,7 +78,11 @@ namespace { break; } - else if (ucs2_ch == L'\n' || ucs2_ch == L'\r') + else if (ucs2_ch == L'\r') + { + continue; + } + else if (ucs2_ch == L'\n') { std::cout << std::endl; break; @@ -158,6 +162,13 @@ namespace if (!aPass.empty()) { aPass.pop_back(); + if (!hide_input) + std::cout << "\b\b\b \b\b\b" << std::flush; + } + else + { + if (!hide_input) + std::cout << "\b\b \b\b" << std::flush; } } else diff --git a/src/common/spawn.cpp b/src/common/spawn.cpp index 59f11675c..0a2ce8387 100644 --- a/src/common/spawn.cpp +++ b/src/common/spawn.cpp @@ -38,6 +38,7 @@ #endif #include "misc_log_ex.h" +#include "util.h" #include "spawn.h" namespace tools @@ -101,6 +102,8 @@ int spawn(const char *filename, const std::vector& args, bool wait) // child if (pid == 0) { + tools::closefrom(3); + close(0); char *envp[] = {NULL}; execve(filename, argv, envp); MERROR("Failed to execve: " << strerror(errno)); diff --git a/src/common/threadpool.cpp b/src/common/threadpool.cpp index ac16845e4..2e24f8fb1 100644 --- a/src/common/threadpool.cpp +++ b/src/common/threadpool.cpp @@ -49,11 +49,19 @@ threadpool::~threadpool() { } void threadpool::stop() { + try { const boost::unique_lock lock(mutex); running = false; has_work.notify_all(); } + catch (...) + { + // if the lock throws, we're just do it without a lock and hope, + // since the alternative is terminate + running = false; + has_work.notify_all(); + } for (size_t i = 0; i lock(mt); if (num) MERROR("wait should have been called before waiter dtor - waiting now"); } + catch (...) { /* ignore */ } try { wait(NULL); diff --git a/src/common/util.cpp b/src/common/util.cpp index ca5ff9306..dd2df108f 100644 --- a/src/common/util.cpp +++ b/src/common/util.cpp @@ -29,6 +29,7 @@ // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +#include #include #ifdef __GLIBC__ @@ -234,7 +235,7 @@ namespace tools MERROR("Failed to open " << filename << ": " << std::error_code(GetLastError(), std::system_category())); } #else - m_fd = open(filename.c_str(), O_RDONLY | O_CREAT, 0666); + m_fd = open(filename.c_str(), O_RDONLY | O_CREAT | O_CLOEXEC, 0666); if (m_fd != -1) { if (flock(m_fd, LOCK_EX | LOCK_NB) == -1) @@ -968,4 +969,23 @@ std::string get_nix_version_display_string() } #endif + void closefrom(int fd) + { +#if defined __FreeBSD__ || defined __OpenBSD__ || defined __NetBSD__ || defined __DragonFly__ + ::closefrom(fd); +#else +#if defined __GLIBC__ + const int sc_open_max = sysconf(_SC_OPEN_MAX); + const int MAX_FDS = std::min(65536, sc_open_max); +#else + const int MAX_FDS = 65536; +#endif + while (fd < MAX_FDS) + { + close(fd); + ++fd; + } +#endif + } + } diff --git a/src/common/util.h b/src/common/util.h index ce773bd38..e793a42b5 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -238,4 +238,6 @@ namespace tools #ifdef _WIN32 std::string input_line_win(); #endif + + void closefrom(int fd); } diff --git a/src/cryptonote_basic/cryptonote_basic.h b/src/cryptonote_basic/cryptonote_basic.h index 596c8fa76..0db7579ae 100644 --- a/src/cryptonote_basic/cryptonote_basic.h +++ b/src/cryptonote_basic/cryptonote_basic.h @@ -196,6 +196,7 @@ namespace cryptonote public: transaction_prefix(){} + bool is_deregister_tx() const { return (version >= version_3_per_output_unlock_times) && is_deregister; } uint64_t get_unlock_time(size_t out_index) const { if (version >= version_3_per_output_unlock_times) @@ -236,7 +237,6 @@ namespace cryptonote void set_hash_valid(bool v) const { hash_valid.store(v,std::memory_order_release); } bool is_blob_size_valid() const { return blob_size_valid.load(std::memory_order_acquire); } void set_blob_size_valid(bool v) const { blob_size_valid.store(v,std::memory_order_release); } - bool is_deregister_tx() const { return (version >= version_3_per_output_unlock_times) && is_deregister; } BEGIN_SERIALIZE_OBJECT() if (!typename Archive::is_saving()) diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp index 916915da2..78d4969ce 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.cpp +++ b/src/cryptonote_basic/cryptonote_format_utils.cpp @@ -203,6 +203,16 @@ namespace cryptonote return true; } //--------------------------------------------------------------- + bool parse_and_validate_tx_prefix_from_blob(const blobdata& tx_blob, transaction_prefix& tx) + { + std::stringstream ss; + ss << tx_blob; + binary_archive ba(ss); + bool r = ::serialization::serialize_noeof(ba, tx); + CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction prefix from blob"); + return true; + } + //--------------------------------------------------------------- bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash) { std::stringstream ss; diff --git a/src/cryptonote_basic/cryptonote_format_utils.h b/src/cryptonote_basic/cryptonote_format_utils.h index db85061f5..563f2b0de 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.h +++ b/src/cryptonote_basic/cryptonote_format_utils.h @@ -52,6 +52,7 @@ namespace cryptonote //--------------------------------------------------------------- void get_transaction_prefix_hash(const transaction_prefix& tx, crypto::hash& h); crypto::hash get_transaction_prefix_hash(const transaction_prefix& tx); + bool parse_and_validate_tx_prefix_from_blob(const blobdata& tx_blob, transaction_prefix& tx); bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash); bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx); bool parse_and_validate_tx_base_from_blob(const blobdata& tx_blob, transaction& tx); diff --git a/src/cryptonote_basic/miner.cpp b/src/cryptonote_basic/miner.cpp index 9786cc35a..5995d117f 100644 --- a/src/cryptonote_basic/miner.cpp +++ b/src/cryptonote_basic/miner.cpp @@ -200,7 +200,7 @@ namespace cryptonote float hr = static_cast(total_hr)/static_cast(m_last_hash_rates.size()); const auto flags = std::cout.flags(); const auto precision = std::cout.precision(); - std::cout << "hashrate: " << std::setprecision(4) << std::fixed << hr << flags << precision << ENDL; + std::cout << "hashrate: " << std::setprecision(4) << std::fixed << hr << std::setiosflags(flags) << std::setprecision(precision) << ENDL; } } m_last_hr_merge_time = misc_utils::get_tick_count(); diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index db92086bc..e33372b3a 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -306,6 +306,9 @@ uint64_t Blockchain::get_current_blockchain_height() const bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline, const cryptonote::test_options *test_options, difficulty_type fixed_difficulty) { LOG_PRINT_L3("Blockchain::" << __func__); + + CHECK_AND_ASSERT_MES(nettype != FAKECHAIN || test_options, false, "fake chain network type used without options"); + CRITICAL_REGION_LOCAL(m_tx_pool); CRITICAL_REGION_LOCAL1(m_blockchain_lock); @@ -2386,7 +2389,7 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context const bool bulletproof = rct::is_rct_bulletproof(tx.rct_signatures.type); if (bulletproof || !tx.rct_signatures.p.bulletproofs.empty()) { - MERROR("Bulletproofs are not allowed before v10"); + MERROR_VER("Bulletproofs are not allowed before v10"); tvc.m_invalid_output = true; return false; } @@ -2396,7 +2399,7 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context const bool borromean = rct::is_rct_borromean(tx.rct_signatures.type); if (borromean) { - MERROR("Borromean range proofs are not allowed after v10"); + MERROR_VER("Borromean range proofs are not allowed after v10"); tvc.m_invalid_output = true; return false; } diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 1646eba3f..90febd317 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -918,16 +918,19 @@ namespace cryptonote } waiter.wait(&tpool); it = tx_blobs.begin(); + std::vector already_have(tx_blobs.size(), false); for (size_t i = 0; i < tx_blobs.size(); i++, ++it) { if (!results[i].res) continue; if(m_mempool.have_tx(results[i].hash)) { LOG_PRINT_L2("tx " << results[i].hash << "already have transaction in tx_pool"); + already_have[i] = true; } else if(m_blockchain_storage.have_tx(results[i].hash)) { LOG_PRINT_L2("tx " << results[i].hash << " already have transaction in blockchain"); + already_have[i] = true; } else { @@ -949,7 +952,7 @@ namespace cryptonote std::vector tx_info; tx_info.reserve(tx_blobs.size()); for (size_t i = 0; i < tx_blobs.size(); i++) { - if (!results[i].res) + if (!results[i].res || already_have[i]) continue; tx_info.push_back({&results[i].tx, results[i].hash, tvc[i], results[i].res}); } @@ -959,6 +962,8 @@ namespace cryptonote bool ok = true; it = tx_blobs.begin(); for (size_t i = 0; i < tx_blobs.size(); i++, ++it) { + if (already_have[i]) + continue; if (!results[i].res) { ok = false; diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index 1af2cf41c..82197c940 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -298,7 +298,7 @@ namespace cryptonote CRITICAL_REGION_LOCAL1(m_blockchain); LockedTXN lock(m_blockchain); m_blockchain.add_txpool_tx(tx, meta); - if (!insert_key_images(tx, kept_by_block)) + if (!insert_key_images(tx, id, kept_by_block)) return false; m_txs_by_fee_and_receive_time.emplace(std::tuple(tx.is_deregister_tx(), fee / (double)tx_weight, receive_time), id); } @@ -338,9 +338,10 @@ namespace cryptonote { CRITICAL_REGION_LOCAL1(m_blockchain); LockedTXN lock(m_blockchain); - m_blockchain.remove_txpool_tx(get_transaction_hash(tx)); + const crypto::hash txid = get_transaction_hash(tx); + m_blockchain.remove_txpool_tx(txid); m_blockchain.add_txpool_tx(tx, meta); - if (!insert_key_images(tx, kept_by_block)) + if (!insert_key_images(tx, txid, kept_by_block)) return false; m_txs_by_fee_and_receive_time.emplace(std::tuple(tx.is_deregister_tx(), fee / (double)tx_weight, receive_time), id); } @@ -397,20 +398,26 @@ namespace cryptonote LockedTXN lock(m_blockchain); bool changed = false; - auto prune_tx = [this](sorted_tx_container::iterator &it, crypto::hash const &txid, transaction const &tx, cryptonote::blobdata const &tx_blob, bool &changed) + auto prune_tx = [this](sorted_tx_container::iterator &it, crypto::hash const &txid, txpool_tx_meta_t const &meta, bool &changed) { - const uint64_t tx_fee = std::get<1>(it->first); - const double fee_per_byte = tx_fee / tx_blob.size(); - const uint64_t tx_weight = get_transaction_weight(tx, tx_blob.size()); + cryptonote::blobdata tx_blob = m_blockchain.get_txpool_tx_blob(txid); + cryptonote::transaction_prefix tx; + if (!parse_and_validate_tx_prefix_from_blob(tx_blob, tx)) + { + return false; + } // remove first, in case this throws, so key images aren't removed - MINFO("Pruning tx " << txid << " from txpool: weight: " << tx_weight << ", fee/byte: " << fee_per_byte); + const uint64_t tx_fee = std::get<1>(it->first); + MINFO("Pruning tx " << txid << " from txpool: weight: " << meta.weight << ", fee/byte: " << tx_fee); m_blockchain.remove_txpool_tx(txid); - m_txpool_weight -= tx_weight; - remove_transaction_keyimages(tx); - MINFO("Pruned tx " << txid << " from txpool: weight: " << tx_weight << ", fee/byte: " << fee_per_byte); + m_txpool_weight -= meta.weight; + remove_transaction_keyimages(tx, txid); + MINFO("Pruned tx " << txid << " from txpool: weight: " << meta.weight << ", fee/byte: " << tx_fee); it = m_txs_by_fee_and_receive_time.erase(it); changed = true; + + return true; }; for (auto it = m_txs_by_fee_and_receive_time.begin(); it != m_txs_by_fee_and_receive_time.end(); ) @@ -437,15 +444,11 @@ namespace cryptonote continue; } - cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(txid); - cryptonote::transaction tx; - if (!parse_and_validate_tx_from_blob(txblob, tx)) + if (!prune_tx(it, txid, meta, changed)) { MERROR("Failed to parse tx from txpool"); return; } - - prune_tx(it, txid, tx, txblob, changed); } catch (const std::exception &e) { @@ -475,14 +478,12 @@ namespace cryptonote --it; continue; } - cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(txid); - cryptonote::transaction tx; - if (!parse_and_validate_tx_from_blob(txblob, tx)) + + if (!prune_tx(it, txid, meta, changed)) { MERROR("Failed to parse tx from txpool"); return; } - prune_tx(it, txid, tx, txblob, changed); } catch (const std::exception &e) { @@ -496,11 +497,10 @@ namespace cryptonote MINFO("Pool weight after pruning is larger than limit: " << m_txpool_weight << "/" << bytes); } //--------------------------------------------------------------------------------- - bool tx_memory_pool::insert_key_images(const transaction &tx, bool kept_by_block) + bool tx_memory_pool::insert_key_images(const transaction_prefix &tx, const crypto::hash &id, bool kept_by_block) { for(const auto& in: tx.vin) { - const crypto::hash id = get_transaction_hash(tx); CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, txin, false); std::unordered_set& kei_image_set = m_spent_key_images[txin.k_image]; CHECK_AND_ASSERT_MES(kept_by_block || kei_image_set.size() == 0, false, "internal error: kept_by_block=" << kept_by_block @@ -516,19 +516,17 @@ namespace cryptonote //FIXME: Can return early before removal of all of the key images. // At the least, need to make sure that a false return here // is treated properly. Should probably not return early, however. - bool tx_memory_pool::remove_transaction_keyimages(const transaction& tx) + bool tx_memory_pool::remove_transaction_keyimages(const transaction_prefix& tx, const crypto::hash &actual_hash) { CRITICAL_REGION_LOCAL(m_transactions_lock); CRITICAL_REGION_LOCAL1(m_blockchain); // ND: Speedup - // 1. Move transaction hash calcuation outside of loop. ._. - crypto::hash actual_hash = get_transaction_hash(tx); for(const txin_v& vi: tx.vin) { CHECKED_GET_SPECIFIC_VARIANT(vi, const txin_to_key, txin, false); auto it = m_spent_key_images.find(txin.k_image); CHECK_AND_ASSERT_MES(it != m_spent_key_images.end(), false, "failed to find transaction input in key images. img=" << txin.k_image << ENDL - << "transaction id = " << get_transaction_hash(tx)); + << "transaction id = " << actual_hash); std::unordered_set& key_image_set = it->second; CHECK_AND_ASSERT_MES(key_image_set.size(), false, "empty key_image set, img=" << txin.k_image << ENDL << "transaction id = " << actual_hash); @@ -581,7 +579,7 @@ namespace cryptonote // remove first, in case this throws, so key images aren't removed m_blockchain.remove_txpool_tx(id); m_txpool_weight -= tx_weight; - remove_transaction_keyimages(tx); + remove_transaction_keyimages(tx, id); } catch (const std::exception &e) { @@ -613,7 +611,7 @@ namespace cryptonote { CRITICAL_REGION_LOCAL(m_transactions_lock); CRITICAL_REGION_LOCAL1(m_blockchain); - std::unordered_set remove; + std::list> remove; m_blockchain.for_all_txpool_txes([this, &remove](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata*) { uint64_t tx_age = time(nullptr) - meta.receive_time; @@ -631,7 +629,7 @@ namespace cryptonote m_txs_by_fee_and_receive_time.erase(sorted_it); } m_timed_out_transactions.insert(txid); - remove.insert(txid); + remove.push_back(std::make_pair(txid, meta.weight)); } return true; }, false); @@ -639,13 +637,14 @@ namespace cryptonote if (!remove.empty()) { LockedTXN lock(m_blockchain); - for (const crypto::hash &txid: remove) + for (const std::pair &entry: remove) { + const crypto::hash &txid = entry.first; try { cryptonote::blobdata bd = m_blockchain.get_txpool_tx_blob(txid); - cryptonote::transaction tx; - if (!parse_and_validate_tx_from_blob(bd, tx)) + cryptonote::transaction_prefix tx; + if (!parse_and_validate_tx_prefix_from_blob(bd, tx)) { MERROR("Failed to parse tx from txpool"); // continue @@ -654,8 +653,8 @@ namespace cryptonote { // remove first, so we only remove key images if the tx removal succeeds m_blockchain.remove_txpool_tx(txid); - m_txpool_weight -= get_transaction_weight(tx, bd.size()); - remove_transaction_keyimages(tx); + m_txpool_weight -= entry.second; + remove_transaction_keyimages(tx, txid); } } catch (const std::exception &e) @@ -1162,7 +1161,7 @@ namespace cryptonote return true; } //--------------------------------------------------------------------------------- - bool tx_memory_pool::have_key_images(const std::unordered_set& k_images, const transaction& tx) + bool tx_memory_pool::have_key_images(const std::unordered_set& k_images, const transaction_prefix& tx) { for(size_t i = 0; i!= tx.vin.size(); i++) { @@ -1173,7 +1172,7 @@ namespace cryptonote return false; } //--------------------------------------------------------------------------------- - bool tx_memory_pool::append_key_images(std::unordered_set& k_images, const transaction& tx) + bool tx_memory_pool::append_key_images(std::unordered_set& k_images, const transaction_prefix& tx) { for(size_t i = 0; i!= tx.vin.size(); i++) { @@ -1420,7 +1419,7 @@ namespace cryptonote // remove tx from db first m_blockchain.remove_txpool_tx(txid); m_txpool_weight -= get_transaction_weight(tx, txblob.size()); - remove_transaction_keyimages(tx); + remove_transaction_keyimages(tx, txid); auto sorted_it = find_tx_in_sorted_container(txid); if (sorted_it == m_txs_by_fee_and_receive_time.end()) { @@ -1463,14 +1462,14 @@ namespace cryptonote bool r = m_blockchain.for_all_txpool_txes([this, &remove, kept](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd) { if (!!kept != !!meta.kept_by_block) return true; - cryptonote::transaction tx; - if (!parse_and_validate_tx_from_blob(*bd, tx)) + cryptonote::transaction_prefix tx; + if (!parse_and_validate_tx_prefix_from_blob(*bd, tx)) { MWARNING("Failed to parse tx from txpool, removing"); remove.push_back(txid); return true; } - if (!insert_key_images(tx, meta.kept_by_block)) + if (!insert_key_images(tx, txid, meta.kept_by_block)) { MFATAL("Failed to insert key images from txpool tx"); return false; diff --git a/src/cryptonote_core/tx_pool.h b/src/cryptonote_core/tx_pool.h index adb12de12..50cc8eec9 100644 --- a/src/cryptonote_core/tx_pool.h +++ b/src/cryptonote_core/tx_pool.h @@ -432,7 +432,7 @@ namespace cryptonote * * @return true on success, false on error */ - bool insert_key_images(const transaction &tx, bool kept_by_block); + bool insert_key_images(const transaction_prefix &tx, const crypto::hash &txid, bool kept_by_block); /** * @brief remove old transactions from the pool @@ -484,10 +484,11 @@ namespace cryptonote * a transaction from the pool. * * @param tx the transaction + * @param txid the transaction's hash * * @return false if any key images to be removed cannot be found, otherwise true */ - bool remove_transaction_keyimages(const transaction& tx); + bool remove_transaction_keyimages(const transaction_prefix& tx, const crypto::hash &txid); /** * @brief check if any of a transaction's spent key images are present in a given set @@ -497,7 +498,7 @@ namespace cryptonote * * @return true if any key images present in the set, otherwise false */ - static bool have_key_images(const std::unordered_set& kic, const transaction& tx); + static bool have_key_images(const std::unordered_set& kic, const transaction_prefix& tx); /** * @brief append the key images from a transaction to the given set @@ -507,7 +508,7 @@ namespace cryptonote * * @return false if any append fails, otherwise true */ - static bool append_key_images(std::unordered_set& kic, const transaction& tx); + static bool append_key_images(std::unordered_set& kic, const transaction_prefix& tx); /** * @brief check if a transaction is a valid candidate for inclusion in a block @@ -515,11 +516,11 @@ namespace cryptonote * @param txd the transaction to check (and info about it) * @param txid the txid of the transaction to check * @param txblob the transaction blob to check - * @param tx the parsed transaction, if successful + * @param tx the parsed transaction prefix, if successful * * @return true if the transaction is good to go, otherwise false */ - bool is_transaction_ready_to_go(txpool_tx_meta_t& txd, const crypto::hash &txid, const cryptonote::blobdata &txblob, transaction &tx) const; + bool is_transaction_ready_to_go(txpool_tx_meta_t& txd, const crypto::hash &txid, const cryptonote::blobdata &txblob, transaction&tx) const; /** * @brief mark all transactions double spending the one passed diff --git a/src/daemon/daemon.cpp b/src/daemon/daemon.cpp index ffacb21ed..66f1f738e 100644 --- a/src/daemon/daemon.cpp +++ b/src/daemon/daemon.cpp @@ -137,7 +137,19 @@ bool t_daemon::run(bool interactive) { throw std::runtime_error{"Can't run stopped daemon"}; } - tools::signal_handler::install(std::bind(&daemonize::t_daemon::stop_p2p, this)); + + std::atomic stop(false), shutdown(false); + boost::thread stop_thread = boost::thread([&stop, &shutdown, this] { + while (!stop) + epee::misc_utils::sleep_no_w(100); + if (shutdown) + this->stop_p2p(); + }); + epee::misc_utils::auto_scope_leave_caller scope_exit_handler = epee::misc_utils::create_scope_leave_handler([&](){ + stop = true; + stop_thread.join(); + }); + tools::signal_handler::install([&stop, &shutdown](int){ stop = shutdown = true; }); try { diff --git a/src/daemonizer/windows_daemonizer.inl b/src/daemonizer/windows_daemonizer.inl index 393528011..71f78f4e0 100644 --- a/src/daemonizer/windows_daemonizer.inl +++ b/src/daemonizer/windows_daemonizer.inl @@ -32,6 +32,7 @@ #include "common/util.h" #include "daemonizer/windows_service.h" #include "daemonizer/windows_service_runner.h" +#include "cryptonote_core/cryptonote_core.h" #include #include diff --git a/src/debug_utilities/object_sizes.cpp b/src/debug_utilities/object_sizes.cpp index 12e84d37b..e4d728cd1 100644 --- a/src/debug_utilities/object_sizes.cpp +++ b/src/debug_utilities/object_sizes.cpp @@ -30,6 +30,7 @@ #include #include "cryptonote_basic/cryptonote_basic.h" #include "cryptonote_basic/tx_extra.h" +#include "cryptonote_core/cryptonote_core.h" #include "cryptonote_core/blockchain.h" #include "p2p/p2p_protocol_defs.h" #include "net/connection_basic.hpp" diff --git a/src/device/device_io_hid.cpp b/src/device/device_io_hid.cpp index 562aca8b8..666255cb3 100644 --- a/src/device/device_io_hid.cpp +++ b/src/device/device_io_hid.cpp @@ -13,6 +13,7 @@ // #if defined(HAVE_HIDAPI) +#include #include "log.hpp" #include "device_io_hid.hpp" @@ -69,11 +70,47 @@ namespace hw { void device_io_hid::connect(void *params) { hid_conn_params *p = (struct hid_conn_params*)params; - this->connect(p->vid, p->pid, p->interface_number, p->usage_page, p->interface_OR_page); + this->connect(p->vid, p->pid, p->interface_number, p->usage_page); } - void device_io_hid::connect(unsigned int vid, unsigned int pid, unsigned int interface_number, unsigned int usage_page, bool interface_OR_page ) { - hid_device_info *hwdev_info, *hwdev_info_list; + hid_device_info *device_io_hid::find_device(hid_device_info *devices_list, boost::optional interface_number, boost::optional usage_page) { + bool select_any = !interface_number && !usage_page; + + MDEBUG( "Looking for " << + (select_any ? "any HID Device" : "HID Device with") << + (interface_number ? (" interface_number " + std::to_string(interface_number.value())) : "") << + ((interface_number && usage_page) ? " or" : "") << + (usage_page ? (" usage_page " + std::to_string(usage_page.value())) : "")); + + hid_device_info *result = nullptr; + for (; devices_list != nullptr; devices_list = devices_list->next) { + BOOST_SCOPE_EXIT(&devices_list, &result) { + MDEBUG( (result == devices_list ? "SELECTED" : "SKIPPED ") << + " HID Device" << + " path " << safe_hid_path(devices_list) << + " interface_number " << devices_list->interface_number << + " usage_page " << devices_list->usage_page); + } + BOOST_SCOPE_EXIT_END + + if (result != nullptr) { + continue; + } + + if (select_any) { + result = devices_list; + } else if (interface_number && devices_list->interface_number == interface_number.value()) { + result = devices_list; + } else if (usage_page && devices_list->usage_page == usage_page.value()) { + result = devices_list; + } + } + + return result; + } + + void device_io_hid::connect(unsigned int vid, unsigned int pid, boost::optional interface_number, boost::optional usage_page) { + hid_device_info *hwdev_info_list; hid_device *hwdev; this->disconnect(); @@ -81,17 +118,8 @@ namespace hw { hwdev_info_list = hid_enumerate(vid, pid); ASSERT_X(hwdev_info_list, "Unable to enumerate device "+std::to_string(vid)+":"+std::to_string(vid)+ ": "+ safe_hid_error(this->usb_device)); hwdev = NULL; - hwdev_info = hwdev_info_list; - while (hwdev_info) { - if ((interface_OR_page && ((usage_page == 0xffa0) || (interface_number == 0))) || - ((usage_page == 0xffa0) && (interface_number == 0)) ) { - MDEBUG("HID Device found: " << safe_hid_path(hwdev_info)); - hwdev = hid_open_path(hwdev_info->path); - break; - } else { - MDEBUG("HID Device discard: " << safe_hid_path(hwdev_info) << "("+std::to_string(hwdev_info->usage_page) << "," << std::to_string(hwdev_info->interface_number) << ")"); - } - hwdev_info = hwdev_info->next; + if (hid_device_info *device = find_device(hwdev_info_list, interface_number, usage_page)) { + hwdev = hid_open_path(device->path); } hid_free_enumeration(hwdev_info_list); ASSERT_X(hwdev, "Unable to open device "+std::to_string(pid)+":"+std::to_string(vid)); diff --git a/src/device/device_io_hid.hpp b/src/device/device_io_hid.hpp index 6fd15a1d1..bb0f0a814 100644 --- a/src/device/device_io_hid.hpp +++ b/src/device/device_io_hid.hpp @@ -29,6 +29,7 @@ #if defined(HAVE_HIDAPI) +#include #include #include "device_io.hpp" @@ -52,9 +53,8 @@ namespace hw { struct hid_conn_params { unsigned int vid; unsigned int pid; - unsigned int interface_number; - unsigned int usage_page; - bool interface_OR_page ; + int interface_number; + unsigned short usage_page; }; @@ -82,13 +82,11 @@ namespace hw { unsigned int wrapCommand(const unsigned char *command, size_t command_len, unsigned char *out, size_t out_len); unsigned int unwrapReponse(const unsigned char *data, size_t data_len, unsigned char *out, size_t out_len); + hid_device_info *find_device(hid_device_info *devices_list, boost::optional interface_number, boost::optional usage_page); public: bool hid_verbose = false; - static const unsigned int OR_SELECT = 1; - static const unsigned int AND_SELECT = 2; - static const unsigned short DEFAULT_CHANNEL = 0x0001; static const unsigned char DEFAULT_TAG = 0x01; static const unsigned int DEFAULT_PACKET_SIZE = 64; @@ -100,7 +98,7 @@ namespace hw { void init(); void connect(void *params); - void connect(unsigned int vid, unsigned int pid, unsigned int interface_number, unsigned int usage_page, bool interface_OR_page ); + void connect(unsigned int vid, unsigned int pid, boost::optional interface_number, boost::optional usage_page); bool connected() const; int exchange(unsigned char *command, unsigned int cmd_len, unsigned char *response, unsigned int max_resp_len); void disconnect(); diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp index aa43477ca..085b3c569 100644 --- a/src/device/device_ledger.cpp +++ b/src/device/device_ledger.cpp @@ -341,7 +341,7 @@ namespace hw { bool device_ledger::connect(void) { this->disconnect(); - hw_device.connect(0x2c97,0x0001, 0, 0xffa0, hw_device.OR_SELECT); + hw_device.connect(0x2c97, 0x0001, 0, 0xffa0); this->reset(); #ifdef DEBUG_HWDEVICE cryptonote::account_public_address pubkey; diff --git a/src/p2p/net_node.cpp b/src/p2p/net_node.cpp index c9ca63f43..e9d2061e8 100644 --- a/src/p2p/net_node.cpp +++ b/src/p2p/net_node.cpp @@ -29,6 +29,7 @@ // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers #include "common/command_line.h" +#include "cryptonote_core/cryptonote_core.h" #include "net_node.h" namespace nodetool diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index 5fced020f..5220eb875 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -931,7 +931,7 @@ namespace nodetool bool res = m_net_server.connect(epee::string_tools::get_ip_string_from_int32(ipv4.ip()), epee::string_tools::num_to_string_fast(ipv4.port()), m_config.m_net_config.connection_timeout, - con, m_bind_ip.empty() ? "0.0.0.0" : m_bind_ip); + con); if(!res) { @@ -996,7 +996,7 @@ namespace nodetool bool res = m_net_server.connect(epee::string_tools::get_ip_string_from_int32(ipv4.ip()), epee::string_tools::num_to_string_fast(ipv4.port()), m_config.m_net_config.connection_timeout, - con, m_bind_ip.empty() ? "0.0.0.0" : m_bind_ip); + con); if (!res) { bool is_priority = is_priority_node(na); @@ -1611,7 +1611,7 @@ namespace nodetool return false; } return true; - }, m_bind_ip.empty() ? "0.0.0.0" : m_bind_ip); + }); if(!r) { LOG_WARNING_CC(context, "Failed to call connect_async, network error."); diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 1f96f8ec0..fa984f825 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -918,6 +918,8 @@ namespace cryptonote return r; m_core.get_pool_transactions_and_spent_keys_info(res.transactions, res.spent_key_images, !request_has_rpc_origin || !m_restricted); + for (tx_info& txi : res.transactions) + txi.tx_blob = epee::string_tools::buff_to_hex_nodelimer(txi.tx_blob); res.status = CORE_RPC_STATUS_OK; return true; } @@ -1084,7 +1086,7 @@ namespace cryptonote { error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR; error_resp.message = "Internal error: failed to create block template"; - LOG_ERROR("Failed to tx pub key in coinbase extra"); + LOG_ERROR("Failed to get tx pub key in coinbase extra"); return false; } res.reserved_offset = slow_memmem((void*)block_blob.data(), block_blob.size(), &tx_pub_key, sizeof(tx_pub_key)); @@ -2164,6 +2166,8 @@ namespace cryptonote try { + // 0 is placeholder for the whole chain + const uint64_t req_to_height = req.to_height ? req.to_height : (m_core.get_current_blockchain_height() - 1); for (uint64_t amount: req.amounts) { static struct D @@ -2176,7 +2180,7 @@ namespace cryptonote } d; boost::unique_lock lock(d.mutex); - if (d.cached && amount == 0 && d.cached_from == req.from_height && d.cached_to == req.to_height) + 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, req.binary, d.cached_distribution, d.cached_base}); if (!req.cumulative) @@ -2191,23 +2195,23 @@ namespace cryptonote std::vector distribution; uint64_t start_height, base; - if (!m_core.get_output_distribution(amount, req.from_height, req.to_height, start_height, distribution, base)) + if (!m_core.get_output_distribution(amount, req.from_height, req_to_height, start_height, distribution, base)) { error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR; error_resp.message = "Failed to get rct distribution"; return false; } - if (req.to_height > 0 && req.to_height >= req.from_height) + 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 (offset <= req_to_height && req_to_height - offset + 1 < distribution.size()) + distribution.resize(req_to_height - offset + 1); } if (amount == 0) { d.cached_from = req.from_height; - d.cached_to = req.to_height; + d.cached_to = req_to_height; d.cached_distribution = distribution; d.cached_start_height = start_height; d.cached_base = base; diff --git a/src/rpc/daemon_messages.h b/src/rpc/daemon_messages.h index 8fff369df..be3138e3b 100644 --- a/src/rpc/daemon_messages.h +++ b/src/rpc/daemon_messages.h @@ -67,7 +67,7 @@ class classname \ // NOTE: when using a type with multiple template parameters, // replace any comma in the template specifier with the macro // above, or the preprocessor will eat the comma in a bad way. -#define RPC_MESSAGE_MEMBER(type, name) type name; +#define RPC_MESSAGE_MEMBER(type, name) type name = type{} namespace cryptonote diff --git a/src/serialization/serialization.h b/src/serialization/serialization.h index 5fc382a1e..2050e88e2 100644 --- a/src/serialization/serialization.h +++ b/src/serialization/serialization.h @@ -318,7 +318,7 @@ namespace serialization { * \brief self explanatory */ template - bool do_check_stream_state(Stream& s, boost::mpl::bool_) + bool do_check_stream_state(Stream& s, boost::mpl::bool_, bool noeof) { return s.good(); } @@ -329,13 +329,13 @@ namespace serialization { * \detailed Also checks to make sure that the stream is not at EOF */ template - bool do_check_stream_state(Stream& s, boost::mpl::bool_) + bool do_check_stream_state(Stream& s, boost::mpl::bool_, bool noeof) { bool result = false; if (s.good()) { std::ios_base::iostate state = s.rdstate(); - result = EOF == s.peek(); + result = noeof || EOF == s.peek(); s.clear(state); } return result; @@ -347,9 +347,9 @@ namespace serialization { * \brief calls detail::do_check_stream_state for ar */ template - bool check_stream_state(Archive& ar) + bool check_stream_state(Archive& ar, bool noeof = false) { - return detail::do_check_stream_state(ar.stream(), typename Archive::is_saving()); + return detail::do_check_stream_state(ar.stream(), typename Archive::is_saving(), noeof); } /*! \fn serialize @@ -360,6 +360,17 @@ namespace serialization { inline bool serialize(Archive &ar, T &v) { bool r = do_serialize(ar, v); - return r && check_stream_state(ar); + return r && check_stream_state(ar, false); + } + + /*! \fn serialize + * + * \brief serializes \a v into \a ar + */ + template + inline bool serialize_noeof(Archive &ar, T &v) + { + bool r = do_serialize(ar, v); + return r && check_stream_state(ar, true); } } diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 5b179d47c..77945ab5c 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -1664,7 +1664,7 @@ bool simple_wallet::blackball(const std::vector &args) uint64_t amount = std::numeric_limits::max(), offset, num_offsets; if (args.size() == 0) { - fail_msg_writer() << tr("usage: blackball / | [add]"); + fail_msg_writer() << tr("usage: mark_output_spent / | [add]"); return true; } @@ -1742,7 +1742,7 @@ bool simple_wallet::blackball(const std::vector &args) } catch (const std::exception &e) { - fail_msg_writer() << tr("Failed to blackball output: ") << e.what(); + fail_msg_writer() << tr("Failed to mark output spent: ") << e.what(); } return true; @@ -1753,7 +1753,7 @@ bool simple_wallet::unblackball(const std::vector &args) std::pair output; if (args.size() != 1) { - fail_msg_writer() << tr("usage: unblackball /"); + fail_msg_writer() << tr("usage: mark_output_unspent /"); return true; } @@ -1769,7 +1769,7 @@ bool simple_wallet::unblackball(const std::vector &args) } catch (const std::exception &e) { - fail_msg_writer() << tr("Failed to unblackball output: ") << e.what(); + fail_msg_writer() << tr("Failed to mark output unspent: ") << e.what(); } return true; @@ -1780,7 +1780,7 @@ bool simple_wallet::blackballed(const std::vector &args) std::pair output; if (args.size() != 1) { - fail_msg_writer() << tr("usage: blackballed /"); + fail_msg_writer() << tr("usage: is_output_spent /"); return true; } @@ -1793,13 +1793,13 @@ bool simple_wallet::blackballed(const std::vector &args) try { if (m_wallet->is_output_blackballed(output)) - message_writer() << tr("Blackballed: ") << output.first << "/" << output.second; + message_writer() << tr("Spent: ") << output.first << "/" << output.second; else - message_writer() << tr("not blackballed: ") << output.first << "/" << output.second; + message_writer() << tr("Not spent: ") << output.first << "/" << output.second; } catch (const std::exception &e) { - fail_msg_writer() << tr("Failed to unblackball output: ") << e.what(); + fail_msg_writer() << tr("Failed to check whether output is spent: ") << e.what(); } return true; @@ -2589,18 +2589,18 @@ simple_wallet::simple_wallet() boost::bind(&simple_wallet::save_known_rings, this, _1), tr("save_known_rings"), tr("Save known rings to the shared rings database")); - m_cmd_binder.set_handler("blackball", + m_cmd_binder.set_handler("mark_output_spent", boost::bind(&simple_wallet::blackball, this, _1), - tr("blackball / | [add]"), - tr("Blackball output(s) so they never get selected as fake outputs in a ring")); - m_cmd_binder.set_handler("unblackball", + tr("mark_output_spent / | [add]"), + tr("Mark output(s) as spent so they never get selected as fake outputs in a ring")); + m_cmd_binder.set_handler("mark_output_unspent", boost::bind(&simple_wallet::unblackball, this, _1), - tr("unblackball /"), - tr("Unblackballs an output so it may get selected as a fake output in a ring")); - m_cmd_binder.set_handler("blackballed", + tr("mark_output_unspent /"), + tr("Marks an output as unspent so it may get selected as a fake output in a ring")); + m_cmd_binder.set_handler("is_output_spent", boost::bind(&simple_wallet::blackballed, this, _1), - tr("blackballed /"), - tr("Checks whether an output is blackballed")); + tr("is_output_spent /"), + tr("Checks whether an output is marked as spent")); m_cmd_binder.set_handler("version", boost::bind(&simple_wallet::version, this, _1), tr("version"), @@ -3020,7 +3020,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm) return false; } crypto::secret_key viewkey; - if (viewkey_string.hex_to_pod(unwrap(unwrap(viewkey)))) + if (!viewkey_string.hex_to_pod(unwrap(unwrap(viewkey)))) { fail_msg_writer() << tr("failed to parse view key secret key"); return false; diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index d97412334..9b0de7806 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -777,7 +777,7 @@ bool WalletImpl::setPassword(const std::string &password) { clearStatus(); try { - m_wallet->rewrite(m_wallet->get_wallet_file(), password); + m_wallet->change_password(m_wallet->get_wallet_file(), m_password, password); m_password = password; } catch (const std::exception &e) { setStatusError(e.what()); @@ -2162,7 +2162,7 @@ bool WalletImpl::blackballOutputs(const std::vector &outputs, bool bool ret = m_wallet->set_blackballed_outputs(raw_outputs, add); if (!ret) { - setStatusError(tr("Failed to set blackballed outputs")); + setStatusError(tr("Failed to mark outputs as spent")); return false; } return true; @@ -2184,7 +2184,7 @@ bool WalletImpl::blackballOutput(const std::string &amount, const std::string &o bool ret = m_wallet->blackball_output(std::make_pair(raw_amount, raw_offset)); if (!ret) { - setStatusError(tr("Failed to blackball output")); + setStatusError(tr("Failed to mark output as spent")); return false; } return true; @@ -2206,7 +2206,7 @@ bool WalletImpl::unblackballOutput(const std::string &amount, const std::string bool ret = m_wallet->unblackball_output(std::make_pair(raw_amount, raw_offset)); if (!ret) { - setStatusError(tr("Failed to unblackball output")); + setStatusError(tr("Failed to mark output as unspent")); return false; } return true; diff --git a/src/wallet/ringdb.cpp b/src/wallet/ringdb.cpp index 0a220e32d..ce7310c52 100644 --- a/src/wallet/ringdb.cpp +++ b/src/wallet/ringdb.cpp @@ -413,13 +413,13 @@ bool ringdb::blackball_worker(const std::vector> & switch (op) { case BLACKBALL_BLACKBALL: - MDEBUG("Blackballing output " << output.first << "/" << output.second); + MDEBUG("Marking output " << output.first << "/" << output.second << " as spent"); dbr = mdb_cursor_put(cursor, &key, &data, MDB_APPENDDUP); if (dbr == MDB_KEYEXIST) dbr = 0; break; case BLACKBALL_UNBLACKBALL: - MDEBUG("Unblackballing output " << output.first << "/" << output.second); + MDEBUG("Marking output " << output.first << "/" << output.second << " as unspent"); dbr = mdb_cursor_get(cursor, &key, &data, MDB_GET_BOTH); if (dbr == 0) dbr = mdb_cursor_del(cursor, 0); diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index ba70ff6d4..e08b3aeae 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -38,6 +38,8 @@ #include #include #include +#include +#include #include "include_base_utils.h" using namespace epee; @@ -3671,6 +3673,7 @@ bool wallet2::query_device(hw::device::device_type& device_type, const std::stri if (json.Parse(account_data.c_str()).HasParseError() || !json.IsObject()) crypto::chacha8(keys_file_data.account_data.data(), keys_file_data.account_data.size(), key, keys_file_data.iv, &account_data[0]); + device_type = hw::device::device_type::SOFTWARE; // The contents should be JSON if the wallet follows the new format. if (json.Parse(account_data.c_str()).HasParseError()) { @@ -6978,6 +6981,8 @@ void wallet2::get_outs(std::vector> LOG_PRINT_L1("Selecting real output: " << td.m_global_output_index << " for " << print_money(amount)); } + std::unordered_map> picks; + // while we still need more mixins uint64_t num_usable_outs = num_outs; bool allow_blackballed = false; @@ -6992,7 +6997,7 @@ void wallet2::get_outs(std::vector> // outputs, we still need to reach the minimum ring size) if (allow_blackballed) break; - MINFO("Not enough non blackballed outputs, we'll allow blackballed ones"); + MINFO("Not enough output not marked as spent, we'll allow outputs marked as spent"); allow_blackballed = true; num_usable_outs = num_outs; } @@ -7076,11 +7081,15 @@ void wallet2::get_outs(std::vector> } seen_indices.emplace(i); - LOG_PRINT_L2("picking " << i << " as " << type); + picks[type].insert(i); req.outputs.push_back({amount, i}); ++num_found; } + for (const auto &pick: picks) + MDEBUG("picking " << pick.first << " outputs: " << + boost::join(pick.second | boost::adaptors::transformed([](uint64_t out){return std::to_string(out);}), " ")); + // if we had enough unusable outputs, we might fall off here and still // have too few outputs, so we stuff with one to keep counts good, and // we'll error out later @@ -7096,8 +7105,15 @@ void wallet2::get_outs(std::vector> [](const get_outputs_out &a, const get_outputs_out &b) { return a.index < b.index; }); } - for (auto i: req.outputs) - LOG_PRINT_L1("asking for output " << i.index << " for " << print_money(i.amount)); + if (ELPP->vRegistry()->allowed(el::Level::Debug, LOKI_DEFAULT_LOG_CATEGORY)) + { + std::map> outs; + for (const auto &i: req.outputs) + outs[i.amount].insert(i.index); + for (const auto &o: outs) + MDEBUG("asking for outputs with amount " << print_money(o.first) << ": " << + boost::join(o.second | boost::adaptors::transformed([](uint64_t out){return std::to_string(out);}), " ")); + } // get the keys for those m_daemon_rpc_mutex.lock(); diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index c6c9daa7c..93259fe52 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -2823,8 +2823,7 @@ namespace tools { try { - m_wallet->rewrite(m_wallet->get_wallet_file(), req.new_password); - m_wallet->store(); + m_wallet->change_password(m_wallet->get_wallet_file(), req.old_password, req.new_password); LOG_PRINT_L0("Wallet password changed."); } catch (const std::exception& e) diff --git a/src/wallet/wallet_rpc_server.h b/src/wallet/wallet_rpc_server.h index cb6064f20..22edc9c5c 100644 --- a/src/wallet/wallet_rpc_server.h +++ b/src/wallet/wallet_rpc_server.h @@ -36,6 +36,7 @@ #include #include "common/util.h" #include "net/http_server_impl_base.h" +#include "math_helper.h" #include "wallet_rpc_server_commands_defs.h" #include "wallet2.h" diff --git a/tests/core_tests/chaingen_main.cpp b/tests/core_tests/chaingen_main.cpp index 769e74700..9bbde73e6 100644 --- a/tests/core_tests/chaingen_main.cpp +++ b/tests/core_tests/chaingen_main.cpp @@ -122,6 +122,11 @@ int main(int argc, char* argv[]) if (run_all) { + GENERATE_AND_PLAY(gen_simple_chain_001); + GENERATE_AND_PLAY(gen_simple_chain_split_1); + GENERATE_AND_PLAY(gen_chain_switch_1); + GENERATE_AND_PLAY(gen_ring_signature_1); + GENERATE_AND_PLAY(gen_ring_signature_2); GENERATE_AND_PLAY(one_block); // Block verification tests @@ -139,6 +144,7 @@ int main(int argc, char* argv[]) GENERATE_AND_PLAY(gen_block_unlock_time_is_timestamp_in_future); GENERATE_AND_PLAY(gen_block_height_is_low); GENERATE_AND_PLAY(gen_block_height_is_high); + GENERATE_AND_PLAY(gen_block_miner_tx_has_2_in); GENERATE_AND_PLAY(gen_block_miner_tx_has_2_tx_gen_in); GENERATE_AND_PLAY(gen_block_miner_tx_with_txin_to_key); GENERATE_AND_PLAY(gen_block_miner_tx_out_is_big); @@ -180,15 +186,7 @@ int main(int argc, char* argv[]) // TODO(loki): Tests we need to fix #if 0 - GENERATE_AND_PLAY(gen_simple_chain_001); - GENERATE_AND_PLAY(gen_simple_chain_split_1); - GENERATE_AND_PLAY(gen_chain_switch_1); - GENERATE_AND_PLAY(gen_ring_signature_1); - GENERATE_AND_PLAY(gen_ring_signature_2); //GENERATE_AND_PLAY(gen_ring_signature_big); // Takes up to XXX hours (if CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW == 10) - - Block verification tests - GENERATE_AND_PLAY(gen_block_miner_tx_has_2_in); //GENERATE_AND_PLAY(gen_block_invalid_binary_format); // Takes up to 3 hours, if CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW == 500, up to 30 minutes, if CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW == 10 // Transaction verification tests @@ -282,6 +280,7 @@ int main(int argc, char* argv[]) GENERATE_AND_PLAY(gen_multisig_tx_valid_25_1_2_many_inputs); GENERATE_AND_PLAY(gen_multisig_tx_valid_48_1_234); GENERATE_AND_PLAY(gen_multisig_tx_valid_48_1_234_many_inputs); + #endif } diff --git a/tests/crypto/main.cpp b/tests/crypto/main.cpp index e5406f771..cc3b53b83 100644 --- a/tests/crypto/main.cpp +++ b/tests/crypto/main.cpp @@ -35,6 +35,7 @@ #include #include "warnings.h" +#include "misc_log_ex.h" #include "crypto/crypto.h" #include "crypto/hash.h" #include "crypto-tests.h" @@ -59,6 +60,7 @@ bool operator !=(const key_derivation &a, const key_derivation &b) { DISABLE_GCC_WARNING(maybe-uninitialized) int main(int argc, char *argv[]) { + TRY_ENTRY(); fstream input; string cmd; size_t test = 0; @@ -266,4 +268,5 @@ error: error = true; } return error ? 1 : 0; + CATCH_ENTRY_L0("main", 1); } diff --git a/tests/functional_tests/CMakeLists.txt b/tests/functional_tests/CMakeLists.txt index 4b21b945c..7a2a7fbd1 100644 --- a/tests/functional_tests/CMakeLists.txt +++ b/tests/functional_tests/CMakeLists.txt @@ -26,10 +26,6 @@ # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -if(WIN32) - set(EXTRA_LIBRARIES "${EXTRA_LIBRARIES};bcrypt") -endif() - set(functional_tests_sources main.cpp transactions_flow_test.cpp diff --git a/tests/fuzz/base58.cpp b/tests/fuzz/base58.cpp index 49516dd83..a4857bdd1 100644 --- a/tests/fuzz/base58.cpp +++ b/tests/fuzz/base58.cpp @@ -68,7 +68,9 @@ int Base58Fuzzer::run(const std::string &filename) int main(int argc, const char **argv) { + TRY_ENTRY(); Base58Fuzzer fuzzer; return run_fuzzer(argc, argv, fuzzer); + CATCH_ENTRY_L0("main", 1); } diff --git a/tests/fuzz/block.cpp b/tests/fuzz/block.cpp index 2df77b046..eed3b94b2 100644 --- a/tests/fuzz/block.cpp +++ b/tests/fuzz/block.cpp @@ -61,6 +61,8 @@ int BlockFuzzer::run(const std::string &filename) int main(int argc, const char **argv) { + TRY_ENTRY(); BlockFuzzer fuzzer; return run_fuzzer(argc, argv, fuzzer); + CATCH_ENTRY_L0("main", 1); } diff --git a/tests/fuzz/bulletproof.cpp b/tests/fuzz/bulletproof.cpp index 2f4dfd0ea..2f3a2f8d1 100644 --- a/tests/fuzz/bulletproof.cpp +++ b/tests/fuzz/bulletproof.cpp @@ -65,6 +65,8 @@ int BulletproofFuzzer::run(const std::string &filename) int main(int argc, const char **argv) { + TRY_ENTRY(); BulletproofFuzzer fuzzer; return run_fuzzer(argc, argv, fuzzer); + CATCH_ENTRY_L0("main", 1); } diff --git a/tests/fuzz/cold-outputs.cpp b/tests/fuzz/cold-outputs.cpp index 59b59810c..488a3b931 100644 --- a/tests/fuzz/cold-outputs.cpp +++ b/tests/fuzz/cold-outputs.cpp @@ -95,7 +95,9 @@ int ColdOutputsFuzzer::run(const std::string &filename) int main(int argc, const char **argv) { + TRY_ENTRY(); ColdOutputsFuzzer fuzzer; return run_fuzzer(argc, argv, fuzzer); + CATCH_ENTRY_L0("main", 1); } diff --git a/tests/fuzz/cold-transaction.cpp b/tests/fuzz/cold-transaction.cpp index da33dc318..fa3041ba3 100644 --- a/tests/fuzz/cold-transaction.cpp +++ b/tests/fuzz/cold-transaction.cpp @@ -97,6 +97,8 @@ int ColdTransactionFuzzer::run(const std::string &filename) int main(int argc, const char **argv) { + TRY_ENTRY(); ColdTransactionFuzzer fuzzer; return run_fuzzer(argc, argv, fuzzer); + CATCH_ENTRY_L0("main", 1); } diff --git a/tests/fuzz/http-client.cpp b/tests/fuzz/http-client.cpp index cd52643d9..909325832 100644 --- a/tests/fuzz/http-client.cpp +++ b/tests/fuzz/http-client.cpp @@ -92,7 +92,9 @@ int HTTPClientFuzzer::run(const std::string &filename) int main(int argc, const char **argv) { + TRY_ENTRY(); HTTPClientFuzzer fuzzer; return run_fuzzer(argc, argv, fuzzer); + CATCH_ENTRY_L0("main", 1); } diff --git a/tests/fuzz/levin.cpp b/tests/fuzz/levin.cpp index 4ced1837f..d0c5803f5 100644 --- a/tests/fuzz/levin.cpp +++ b/tests/fuzz/levin.cpp @@ -341,7 +341,9 @@ int LevinFuzzer::run(const std::string &filename) int main(int argc, const char **argv) { + TRY_ENTRY(); LevinFuzzer fuzzer; return run_fuzzer(argc, argv, fuzzer); + CATCH_ENTRY_L0("main", 1); } diff --git a/tests/fuzz/load_from_binary.cpp b/tests/fuzz/load_from_binary.cpp index 8f96c454f..89f122902 100644 --- a/tests/fuzz/load_from_binary.cpp +++ b/tests/fuzz/load_from_binary.cpp @@ -70,7 +70,9 @@ int PortableStorageFuzzer::run(const std::string &filename) int main(int argc, const char **argv) { + TRY_ENTRY(); PortableStorageFuzzer fuzzer; return run_fuzzer(argc, argv, fuzzer); + CATCH_ENTRY_L0("main", 1); } diff --git a/tests/fuzz/load_from_json.cpp b/tests/fuzz/load_from_json.cpp index b0c1a9bf3..083555f7e 100644 --- a/tests/fuzz/load_from_json.cpp +++ b/tests/fuzz/load_from_json.cpp @@ -70,7 +70,9 @@ int PortableStorageFuzzer::run(const std::string &filename) int main(int argc, const char **argv) { + TRY_ENTRY(); PortableStorageFuzzer fuzzer; return run_fuzzer(argc, argv, fuzzer); + CATCH_ENTRY_L0("main", 1); } diff --git a/tests/fuzz/parse_url.cpp b/tests/fuzz/parse_url.cpp index 8812cf9c2..fb5754a70 100644 --- a/tests/fuzz/parse_url.cpp +++ b/tests/fuzz/parse_url.cpp @@ -68,7 +68,9 @@ int ParseURLFuzzer::run(const std::string &filename) int main(int argc, const char **argv) { + TRY_ENTRY(); ParseURLFuzzer fuzzer; return run_fuzzer(argc, argv, fuzzer); + CATCH_ENTRY_L0("main", 1); } diff --git a/tests/fuzz/signature.cpp b/tests/fuzz/signature.cpp index 6dadf960d..f82ada8b4 100644 --- a/tests/fuzz/signature.cpp +++ b/tests/fuzz/signature.cpp @@ -92,6 +92,8 @@ int SignatureFuzzer::run(const std::string &filename) int main(int argc, const char **argv) { + TRY_ENTRY(); SignatureFuzzer fuzzer; return run_fuzzer(argc, argv, fuzzer); + CATCH_ENTRY_L0("main", 1); } diff --git a/tests/fuzz/transaction.cpp b/tests/fuzz/transaction.cpp index b3349c383..934bd4685 100644 --- a/tests/fuzz/transaction.cpp +++ b/tests/fuzz/transaction.cpp @@ -61,6 +61,8 @@ int TransactionFuzzer::run(const std::string &filename) int main(int argc, const char **argv) { + TRY_ENTRY(); TransactionFuzzer fuzzer; return run_fuzzer(argc, argv, fuzzer); + CATCH_ENTRY_L0("main", 1); } diff --git a/tests/net_load_tests/clt.cpp b/tests/net_load_tests/clt.cpp index a65e02cab..77cce2be7 100644 --- a/tests/net_load_tests/clt.cpp +++ b/tests/net_load_tests/clt.cpp @@ -41,6 +41,7 @@ #include "misc_language.h" #include "misc_log_ex.h" #include "storages/levin_abstract_invoke2.h" +#include "common/util.h" #include "net_load_tests.h" @@ -628,6 +629,7 @@ TEST_F(net_load_test_clt, permament_open_and_close_and_connections_closed_by_ser int main(int argc, char** argv) { + TRY_ENTRY(); tools::on_startup(); epee::debug::get_set_enable_assert(true, false); //set up logging options @@ -635,4 +637,5 @@ int main(int argc, char** argv) ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); + CATCH_ENTRY_L0("main", 1); } diff --git a/tests/net_load_tests/srv.cpp b/tests/net_load_tests/srv.cpp index 6518d9117..092c6955c 100644 --- a/tests/net_load_tests/srv.cpp +++ b/tests/net_load_tests/srv.cpp @@ -34,6 +34,7 @@ #include "include_base_utils.h" #include "misc_log_ex.h" #include "storages/levin_abstract_invoke2.h" +#include "common/util.h" #include "net_load_tests.h" @@ -215,6 +216,7 @@ namespace int main(int argc, char** argv) { + TRY_ENTRY(); tools::on_startup(); //set up logging options mlog_configure(mlog_get_default_log_path("net_load_tests_srv.log"), true); @@ -233,4 +235,5 @@ int main(int argc, char** argv) if (!tcp_server.run_server(thread_count, true)) return 2; return 0; + CATCH_ENTRY_L0("main", 1); } diff --git a/tests/unit_tests/CMakeLists.txt b/tests/unit_tests/CMakeLists.txt index c86937a8b..f53032337 100644 --- a/tests/unit_tests/CMakeLists.txt +++ b/tests/unit_tests/CMakeLists.txt @@ -61,6 +61,7 @@ set(unit_tests_sources mul_div.cpp multiexp.cpp multisig.cpp + notify.cpp parse_amount.cpp random.cpp serialization.cpp @@ -123,4 +124,8 @@ SET_PROPERTY(SOURCE memwipe.cpp PROPERTY COMPILE_FLAGS -Ofast) add_test( NAME unit_tests - COMMAND unit_tests --data-dir "${TEST_DATA_DIR}") + COMMAND unit_tests --data-dir "${TEST_DATA_DIR} --binary-dir ${CMAKE_BINARY_DIR}") + +add_executable(test_notifier test_notifier.cpp) +target_link_libraries(test_notifier ${EXTRA_LIBRARIES}) +set_property(TARGET test_notifier PROPERTY FOLDER "tests") diff --git a/tests/unit_tests/aligned.cpp b/tests/unit_tests/aligned.cpp index ad4837bec..2b733faf2 100644 --- a/tests/unit_tests/aligned.cpp +++ b/tests/unit_tests/aligned.cpp @@ -84,3 +84,24 @@ TEST(aligned, contents_smaller) aligned_free(ptr2); } +TEST(aligned, alignment) +{ + static const size_t good_alignments[] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192}; + for (size_t a = 0; a <= 8192; ++a) + { + bool good = false; + for (const auto t: good_alignments) if (a == t) good = true; + void *ptr = aligned_malloc(1, a); + if (good) + { + ASSERT_TRUE(ptr != NULL); + aligned_free(ptr); + } + else + { + ASSERT_TRUE(ptr == NULL); + } + } + + ASSERT_TRUE(aligned_malloc(1, ~0) == NULL); +} diff --git a/tests/unit_tests/notify.cpp b/tests/unit_tests/notify.cpp new file mode 100644 index 000000000..d6811c6bd --- /dev/null +++ b/tests/unit_tests/notify.cpp @@ -0,0 +1,57 @@ +// Copyright (c) 2018, 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 +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "gtest/gtest.h" + +#include + +#include "misc_language.h" +#include "string_tools.h" +#include "file_io_utils.h" +#include "common/notify.h" + +TEST(notify, works) +{ + char name_template[] = "/tmp/monero-notify-unit-test-XXXXXX"; + int fd = mkstemp(name_template); + ASSERT_TRUE(fd >= 0); + close(fd); + + const std::string spec = epee::string_tools::get_current_module_folder() + "/test_notifier " + name_template + " %s"; + + tools::Notify notify(spec.c_str()); + notify.notify("1111111111111111111111111111111111111111111111111111111111111111"); + + epee::misc_utils::sleep_no_w(100); + + std::string s; + ASSERT_TRUE(epee::file_io_utils::load_file_to_string(name_template, s)); + ASSERT_TRUE(s == "1111111111111111111111111111111111111111111111111111111111111111"); + + boost::filesystem::remove(name_template); +} diff --git a/tests/unit_tests/ringdb.cpp b/tests/unit_tests/ringdb.cpp index 0d92049ac..ab634ea82 100644 --- a/tests/unit_tests/ringdb.cpp +++ b/tests/unit_tests/ringdb.cpp @@ -136,21 +136,21 @@ TEST(ringdb, different_genesis) ASSERT_FALSE(ringdb.get_ring(KEY_2, KEY_IMAGE_1, outs2)); } -TEST(blackball, not_found) +TEST(spent_outputs, not_found) { RingDB ringdb; ASSERT_TRUE(ringdb.blackball(OUTPUT_1)); ASSERT_FALSE(ringdb.blackballed(OUTPUT_2)); } -TEST(blackball, found) +TEST(spent_outputs, found) { RingDB ringdb; ASSERT_TRUE(ringdb.blackball(OUTPUT_1)); ASSERT_TRUE(ringdb.blackballed(OUTPUT_1)); } -TEST(blackball, vector) +TEST(spent_outputs, vector) { RingDB ringdb; std::vector> outputs; @@ -174,7 +174,7 @@ TEST(blackball, vector) ASSERT_TRUE(ringdb.blackballed(std::make_pair(30, 5))); } -TEST(blackball, unblackball) +TEST(spent_outputs, mark_as_unspent) { RingDB ringdb; ASSERT_TRUE(ringdb.blackball(OUTPUT_1)); @@ -182,7 +182,7 @@ TEST(blackball, unblackball) ASSERT_FALSE(ringdb.blackballed(OUTPUT_1)); } -TEST(blackball, clear) +TEST(spent_outputs, clear) { RingDB ringdb; ASSERT_TRUE(ringdb.blackball(OUTPUT_1)); diff --git a/tests/unit_tests/test_notifier.cpp b/tests/unit_tests/test_notifier.cpp new file mode 100644 index 000000000..7fd9809c5 --- /dev/null +++ b/tests/unit_tests/test_notifier.cpp @@ -0,0 +1,54 @@ +// Copyright (c) 2018, 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 +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + if (argc < 3) + { + fprintf(stderr, "usage: %s \n", argv[0]); + return 1; + } + const char *filename = argv[1]; + const char *hash = argv[2]; + + FILE *f = fopen(filename, "a+"); + if (!f) + { + fprintf(stderr, "error opening file %s: %s\n", filename, strerror(errno)); + return 1; + } + fprintf(f, "%s", hash); + fclose(f); + + return 0; +}