diff options
61 files changed, 631 insertions, 339 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d451f8ad..bc1579db5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,13 @@ # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +list(INSERT CMAKE_MODULE_PATH 0 + "${CMAKE_SOURCE_DIR}/cmake") +include(CheckCCompilerFlag) +include(CheckCXXCompilerFlag) +include(CheckLinkerFlag) +include(CheckLibraryExists) + if (IOS) INCLUDE(CmakeLists_IOS.txt) endif() @@ -48,6 +55,31 @@ function (die msg) message(FATAL_ERROR "${BoldRed}${msg}${ColourReset}") endfunction () +function (add_c_flag_if_supported flag var) + string(REPLACE "-" "_" supported ${flag}_c) + check_c_compiler_flag(${flag} ${supported}) + if(${${supported}}) + set(${var} "${${var}} ${flag}" PARENT_SCOPE) + endif() +endfunction() + +function (add_cxx_flag_if_supported flag var) + string(REPLACE "-" "_" supported ${flag}_cxx) + check_cxx_compiler_flag(${flag} ${supported}) + if(${${supported}}) + set(${var} "${${var}} ${flag}" PARENT_SCOPE) + endif() +endfunction() + +function (add_linker_flag_if_supported flag var) + string(REPLACE "-" "_" supported ${flag}_ld) + string(REPLACE "," "_" supported ${flag}_ld) + check_linker_flag(${flag} ${supported}) + if(${${supported}}) + set(${var} "${${var}} ${flag}" PARENT_SCOPE) + endif() +endfunction() + if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE) message(STATUS "Setting default build type: ${CMAKE_BUILD_TYPE}") @@ -210,11 +242,11 @@ endif() if (BUILD_SHARED_LIBS) message(STATUS "Building internal libraries with position independent code") - set(PIC_FLAG "-fPIC") add_definitions("-DBUILD_SHARED_LIBS") else() message(STATUS "Building internal libraries as static") endif() +set(PIC_FLAG "-fPIC") if(MINGW) string(REGEX MATCH "^[^/]:/[^/]*" msys2_install_path "${CMAKE_C_COMPILER}") @@ -474,6 +506,52 @@ else() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-strict-aliasing") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-strict-aliasing") + # if those don't work for your compiler, single it out where appropriate + if(CMAKE_BUILD_TYPE STREQUAL "Release") + set(C_SECURITY_FLAGS "${C_SECURITY_FLAGS} -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1") + set(CXX_SECURITY_FLAGS "${CXX_SECURITY_FLAGS} -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1") + endif() + + # warnings + add_c_flag_if_supported(-Wformat C_SECURITY_FLAGS) + add_cxx_flag_if_supported(-Wformat CXX_SECURITY_FLAGS) + add_c_flag_if_supported(-Wformat-security C_SECURITY_FLAGS) + add_cxx_flag_if_supported(-Wformat-security CXX_SECURITY_FLAGS) + + # -fstack-protector + add_c_flag_if_supported(-fstack-protector C_SECURITY_FLAGS) + add_cxx_flag_if_supported(-fstack-protector CXX_SECURITY_FLAGS) + add_c_flag_if_supported(-fstack-protector-strong C_SECURITY_FLAGS) + add_cxx_flag_if_supported(-fstack-protector-strong CXX_SECURITY_FLAGS) + + # linker + if (NOT WIN32) + # Windows binaries die on startup with PIE + add_linker_flag_if_supported(-pie LD_SECURITY_FLAGS) + endif() + add_linker_flag_if_supported(-Wl,-z,relro LD_SECURITY_FLAGS) + add_linker_flag_if_supported(-Wl,-z,now LD_SECURITY_FLAGS) + add_linker_flag_if_supported(-Wl,-z,noexecstack noexecstack_SUPPORTED) + if (noexecstack_SUPPORTED) + set(LD_SECURITY_FLAGS "${LD_SECURITY_FLAGS} -Wl,-z,noexecstack") + set(LD_RAW_FLAGS ${LD_RAW_FLAGS} -z noexecstack) + endif() + add_linker_flag_if_supported(-Wl,-z,noexecheap noexecheap_SUPPORTED) + if (noexecheap_SUPPORTED) + set(LD_SECURITY_FLAGS "${LD_SECURITY_FLAGS} -Wl,-z,noexecheap") + set(LD_RAW_FLAGS ${LD_RAW_FLAGS} -z noexecheap) + endif() + + # some windows linker bits + if (WIN32) + add_linker_flag_if_supported(-Wl,--dynamicbase LD_SECURITY_FLAGS) + add_linker_flag_if_supported(-Wl,--nxcompat LD_SECURITY_FLAGS) + endif() + + message(STATUS "Using C security hardening flags: ${C_SECURITY_FLAGS}") + message(STATUS "Using C++ security hardening flags: ${CXX_SECURITY_FLAGS}") + message(STATUS "Using linker security hardening flags: ${LD_SECURITY_FLAGS}") + option(NO_AES "Explicitly disable AES support" ${NO_AES}) if(NO_AES) @@ -502,8 +580,9 @@ else() message(STATUS "AES support disabled") endif() - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -D_GNU_SOURCE ${MINGW_FLAG} ${STATIC_ASSERT_FLAG} ${WARNINGS} ${C_WARNINGS} ${ARCH_FLAG} ${COVERAGE_FLAGS} ${PIC_FLAG}") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -D_GNU_SOURCE ${MINGW_FLAG} ${STATIC_ASSERT_CPP_FLAG} ${WARNINGS} ${CXX_WARNINGS} ${ARCH_FLAG} ${COVERAGE_FLAGS} ${PIC_FLAG}") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -D_GNU_SOURCE ${MINGW_FLAG} ${STATIC_ASSERT_FLAG} ${WARNINGS} ${C_WARNINGS} ${ARCH_FLAG} ${COVERAGE_FLAGS} ${PIC_FLAG} ${C_SECURITY_FLAGS}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -D_GNU_SOURCE ${MINGW_FLAG} ${STATIC_ASSERT_CPP_FLAG} ${WARNINGS} ${CXX_WARNINGS} ${ARCH_FLAG} ${COVERAGE_FLAGS} ${PIC_FLAG} ${CXX_SECURITY_FLAGS}") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LD_SECURITY_FLAGS}") # With GCC 6.1.1 the compiled binary malfunctions due to aliasing. Until that # is fixed in the code (Issue #847), force compiler to be conservative. @@ -590,6 +669,7 @@ else() if(ANDROID AND NOT BUILD_GUI_DEPS STREQUAL "ON" OR IOS) #From Android 5: "only position independent executables (PIE) are supported" message(STATUS "Enabling PIE executable") + set(PIC_FLAG "") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIE") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIE") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_CXX_FLAGS} -fPIE -pie") @@ -676,7 +756,7 @@ if(NOT Boost_FOUND) die("Could not find Boost libraries, please make sure you have installed Boost or libboost-all-dev (1.58) or the equivalent") elseif(Boost_FOUND) message(STATUS "Found Boost Version: ${Boost_VERSION}") - if (Boost_VERSION VERSION_LESS 1.62 AND NOT (OPENSSL_VERSION VERSION_LESS 1.1)) + if (Boost_VERSION VERSION_LESS 106200 AND NOT (OPENSSL_VERSION VERSION_LESS 1.1)) message(FATAL_ERROR "Boost older than 1.62 is too old to link with OpenSSL 1.1 or newer. " "Update Boost or install OpenSSL 1.0 and set path to it when running cmake: " "cmake -DOPENSSL_ROOT_DIR='/usr/include/openssl-1.0;/usr/lib/openssl-1.0'") @@ -782,11 +862,7 @@ option(BUILD_GUI_DEPS "Build GUI dependencies." OFF) option(INSTALL_VENDORED_LIBUNBOUND "Install libunbound binary built from source vendored with this repo." OFF) -include(CheckCCompilerFlag) - CHECK_C_COMPILER_FLAG(-std=c11 HAVE_C11) -include(CheckLibraryExists) - check_library_exists(c memset_s "string.h" HAVE_MEMSET_S) check_library_exists(c explicit_bzero "strings.h" HAVE_EXPLICIT_BZERO) diff --git a/cmake/CheckLinkerFlag.c b/cmake/CheckLinkerFlag.c new file mode 100644 index 000000000..a0dcc168d --- /dev/null +++ b/cmake/CheckLinkerFlag.c @@ -0,0 +1,14 @@ +#ifdef __CLASSIC_C__ +int main() +{ + int ac; + char* av[]; +#else +int main(int ac, char* av[]) +{ +#endif + if (ac > 1000) { + return *av[0]; + } + return 0; +} diff --git a/cmake/CheckLinkerFlag.cmake b/cmake/CheckLinkerFlag.cmake new file mode 100644 index 000000000..a3879d0be --- /dev/null +++ b/cmake/CheckLinkerFlag.cmake @@ -0,0 +1,47 @@ +include(CheckCCompilerFlag) + +macro(CHECK_LINKER_FLAG flag VARIABLE) + if(NOT DEFINED "${VARIABLE}") + if(NOT CMAKE_REQUIRED_QUIET) + message(STATUS "Looking for ${flag} linker flag") + endif() + + set(_cle_source ${CMAKE_SOURCE_DIR}/cmake/CheckLinkerFlag.c) + + set(saved_CMAKE_C_FLAGS ${CMAKE_C_FLAGS}) + set(CMAKE_C_FLAGS "${flag}") + try_compile(${VARIABLE} + ${CMAKE_BINARY_DIR} + ${_cle_source} + COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} ${flag} + CMAKE_FLAGS + OUTPUT_VARIABLE OUTPUT) + unset(_cle_source) + set(CMAKE_C_FLAGS ${saved_CMAKE_C_FLAGS}) + unset(saved_CMAKE_C_FLAGS) + + if ("${OUTPUT}" MATCHES "warning.*ignored") + set(${VARIABLE} 0) + endif() + + if(${VARIABLE}) + if(NOT CMAKE_REQUIRED_QUIET) + message(STATUS "Looking for ${flag} linker flag - found") + endif() + set(${VARIABLE} 1 CACHE INTERNAL "Have linker flag ${flag}") + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Determining if the ${flag} linker flag is supported " + "passed with the following output:\n" + "${OUTPUT}\n\n") + else() + if(NOT CMAKE_REQUIRED_QUIET) + message(STATUS "Looking for ${flag} linker flag - not found") + endif() + set(${VARIABLE} "" CACHE INTERNAL "Have linker flag ${flag}") + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log + "Determining if the ${flag} linker flag is suppored " + "failed with the following output:\n" + "${OUTPUT}\n\n") + endif() + endif() +endmacro() diff --git a/cmake/FindReadline.cmake b/cmake/FindReadline.cmake index cdce0bfca..7a11a270a 100644 --- a/cmake/FindReadline.cmake +++ b/cmake/FindReadline.cmake @@ -36,14 +36,18 @@ find_library(Readline_LIBRARY NO_DEFAULT_PATH ) -if(Readline_INCLUDE_DIR AND Readline_LIBRARY AND Ncurses_LIBRARY) +find_library(Termcap_LIBRARY + NAMES tinfo termcap ncursesw ncurses cursesw curses +) + +if(Readline_INCLUDE_DIR AND Readline_LIBRARY) set(READLINE_FOUND TRUE) -else(Readline_INCLUDE_DIR AND Readline_LIBRARY AND Ncurses_LIBRARY) +else(Readline_INCLUDE_DIR AND Readline_LIBRARY) FIND_LIBRARY(Readline_LIBRARY NAMES readline PATHS Readline_ROOT_DIR) include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(Readline DEFAULT_MSG Readline_INCLUDE_DIR Readline_LIBRARY ) MARK_AS_ADVANCED(Readline_INCLUDE_DIR Readline_LIBRARY) -endif(Readline_INCLUDE_DIR AND Readline_LIBRARY AND Ncurses_LIBRARY) +endif(Readline_INCLUDE_DIR AND Readline_LIBRARY) mark_as_advanced( Readline_ROOT_DIR @@ -53,22 +57,25 @@ mark_as_advanced( set(CMAKE_REQUIRED_INCLUDES ${Readline_INCLUDE_DIR}) set(CMAKE_REQUIRED_LIBRARIES ${Readline_LIBRARY}) -INCLUDE(CheckCXXSourceCompiles) -CHECK_CXX_SOURCE_COMPILES( -" -#include <stdio.h> -#include <readline/readline.h> -int -main() -{ - char * s = rl_copy_text(0, 0); -} -" GNU_READLINE_FOUND) -if(NOT Readline_LIBRARY) - set(Readline_LIBRARY "") -endif() +include(CheckFunctionExists) +check_function_exists(rl_copy_text HAVE_COPY_TEXT) +check_function_exists(rl_filename_completion_function HAVE_COMPLETION_FUNCTION) + +if(NOT HAVE_COMPLETION_FUNCTION) + unset(READLINE_FOUND) + set(CMAKE_REQUIRED_LIBRARIES ${Readline_LIBRARY} ${Termcap_LIBRARY}) + check_function_exists(rl_copy_text HAVE_COPY_TEXT_TC) + check_function_exists(rl_filename_completion_function HAVE_COMPLETION_FUNCTION_TC) + set(HAVE_COMPLETION_FUNCTION ${HAVE_COMPLETION_FUNCTION_TC}) + set(HAVE_COPY_TEXT ${HAVE_COPY_TEXT_TC}) + if(HAVE_COMPLETION_FUNCTION) + set(Readline_LIBRARY ${Readline_LIBRARY} ${Termcap_LIBRARY}) + endif(HAVE_COMPLETION_FUNCTION) +endif(NOT HAVE_COMPLETION_FUNCTION) + +if(HAVE_COMPLETION_FUNCTION AND HAVE_COPY_TEXT) + set(GNU_READLINE_FOUND TRUE) + set(READLINE_FOUND TRUE) +endif(HAVE_COMPLETION_FUNCTION AND HAVE_COPY_TEXT) -if(Readline_LIBRARY AND OPENBSD) - list(APPEND EXTRA_LIBRARIES curses) -endif() diff --git a/src/common/memwipe.h b/contrib/epee/include/memwipe.h index c3b4ce8ab..c3b4ce8ab 100644 --- a/src/common/memwipe.h +++ b/contrib/epee/include/memwipe.h diff --git a/contrib/epee/include/net/http_auth.h b/contrib/epee/include/net/http_auth.h index 841cebc17..71f56b570 100644 --- a/contrib/epee/include/net/http_auth.h +++ b/contrib/epee/include/net/http_auth.h @@ -71,8 +71,8 @@ namespace net_utils std::uint32_t counter; }; - http_server_auth() : user() {} - http_server_auth(login credentials); + http_server_auth() : user(), rng() {} + http_server_auth(login credentials, std::function<void(size_t, uint8_t*)> r); //! \return Auth response, or `boost::none` iff `request` had valid auth. boost::optional<http_response_info> get_response(const http_request_info& request) @@ -81,10 +81,13 @@ namespace net_utils return do_get_response(request); return boost::none; } + private: boost::optional<http_response_info> do_get_response(const http_request_info& request); boost::optional<session> user; + + std::function<void(size_t, uint8_t*)> rng; }; //! Implements RFC 2617 digest auth. Digests from RFC 7616 can be added. diff --git a/contrib/epee/include/net/http_protocol_handler.h b/contrib/epee/include/net/http_protocol_handler.h index 652d8ff6f..b4485d1cd 100644 --- a/contrib/epee/include/net/http_protocol_handler.h +++ b/contrib/epee/include/net/http_protocol_handler.h @@ -160,6 +160,7 @@ namespace net_utils struct custum_handler_config: public http_server_config { i_http_server_handler<t_connection_context>* m_phandler; + std::function<void(size_t, uint8_t*)> rng; }; /************************************************************************/ @@ -176,7 +177,7 @@ namespace net_utils : simple_http_connection_handler<t_connection_context>(psnd_hndlr, config), m_config(config), m_conn_context(conn_context), - m_auth(m_config.m_user ? http_server_auth{*m_config.m_user} : http_server_auth{}) + m_auth(m_config.m_user ? http_server_auth{*m_config.m_user, config.rng} : http_server_auth{}) {} inline bool handle_request(const http_request_info& query_info, http_response_info& response) { diff --git a/contrib/epee/include/net/http_server_impl_base.h b/contrib/epee/include/net/http_server_impl_base.h index 8b8e31b51..1a97e610a 100644 --- a/contrib/epee/include/net/http_server_impl_base.h +++ b/contrib/epee/include/net/http_server_impl_base.h @@ -55,13 +55,14 @@ namespace epee : m_net_server(external_io_service) {} - bool init(const std::string& bind_port = "0", const std::string& bind_ip = "0.0.0.0", + bool init(std::function<void(size_t, uint8_t*)> rng, const std::string& bind_port = "0", const std::string& bind_ip = "0.0.0.0", std::vector<std::string> access_control_origins = std::vector<std::string>(), boost::optional<net_utils::http::login> user = boost::none) { //set self as callback handler m_net_server.get_config_object().m_phandler = static_cast<t_child_class*>(this); + m_net_server.get_config_object().rng = std::move(rng); //here set folder for hosting reqests m_net_server.get_config_object().m_folder = ""; diff --git a/contrib/epee/include/net/network_throttle.hpp b/contrib/epee/include/net/network_throttle.hpp index fffd22a6a..225ffee04 100644 --- a/contrib/epee/include/net/network_throttle.hpp +++ b/contrib/epee/include/net/network_throttle.hpp @@ -99,8 +99,6 @@ struct calculate_times_struct { typedef calculate_times_struct calculate_times_struct; -namespace cryptonote { class cryptonote_protocol_handler_base; } // a friend class // TODO friend not working - /*** @brief Access to simple throttles, with singlton to access global network limits */ @@ -117,7 +115,6 @@ class network_throttle_manager { static boost::mutex m_lock_get_global_throttle_inreq; static boost::mutex m_lock_get_global_throttle_out; - friend class cryptonote::cryptonote_protocol_handler_base; // FRIEND - to directly access global throttle-s. !! REMEMBER TO USE LOCKS! friend class connection_basic; // FRIEND - to directly access global throttle-s. !! REMEMBER TO USE LOCKS! friend class connection_basic_pimpl; // ditto diff --git a/contrib/epee/include/serialization/keyvalue_serialization.h b/contrib/epee/include/serialization/keyvalue_serialization.h index d4413a71b..5791e1998 100644 --- a/contrib/epee/include/serialization/keyvalue_serialization.h +++ b/contrib/epee/include/serialization/keyvalue_serialization.h @@ -31,7 +31,6 @@ #include "misc_log_ex.h" #include "enableable.h" #include "keyvalue_serialization_overloads.h" -#include "serialization/serialization.h" namespace epee { diff --git a/contrib/epee/include/storages/portable_storage_val_converters.h b/contrib/epee/include/storages/portable_storage_val_converters.h index 52aa09eba..5d9664a65 100644 --- a/contrib/epee/include/storages/portable_storage_val_converters.h +++ b/contrib/epee/include/storages/portable_storage_val_converters.h @@ -28,6 +28,7 @@ #pragma once +#include <time.h> #include <boost/regex.hpp> #include "misc_language.h" @@ -149,9 +150,8 @@ POP_WARNINGS else if (boost::regex_match (from, boost::regex("\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\dZ"))) { // Convert to unix timestamp - std::tm tm = {}; - std::istringstream ss(from); - if (ss >> std::get_time(&tm, "%Y-%m-%dT%H:%M:%S")) + struct tm tm; + if (strptime(from.c_str(), "%Y-%m-%dT%H:%M:%S", &tm)) to = std::mktime(&tm); } else ASSERT_AND_THROW_WRONG_CONVERSION(); diff --git a/contrib/epee/src/CMakeLists.txt b/contrib/epee/src/CMakeLists.txt index b6967e8fc..9d104ceeb 100644 --- a/contrib/epee/src/CMakeLists.txt +++ b/contrib/epee/src/CMakeLists.txt @@ -26,12 +26,16 @@ # 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. -add_library(epee STATIC hex.cpp http_auth.cpp mlog.cpp net_utils_base.cpp string_tools.cpp wipeable_string.cpp +add_library(epee STATIC hex.cpp http_auth.cpp mlog.cpp net_utils_base.cpp string_tools.cpp wipeable_string.cpp memwipe.c connection_basic.cpp network_throttle.cpp network_throttle-detail.cpp) if (USE_READLINE AND GNU_READLINE_FOUND) add_library(epee_readline STATIC readline_buffer.cpp) endif() +if(HAVE_C11) +SET_PROPERTY(SOURCE memwipe.c PROPERTY COMPILE_FLAGS -std=c11) +endif() + # Build and install libepee if we're building for GUI if (BUILD_GUI_DEPS) if(IOS) @@ -49,7 +53,6 @@ endif() target_link_libraries(epee PUBLIC - cncrypto easylogging ${Boost_FILESYSTEM_LIBRARY} PRIVATE diff --git a/contrib/epee/src/connection_basic.cpp b/contrib/epee/src/connection_basic.cpp index 534044a79..5848d1268 100644 --- a/contrib/epee/src/connection_basic.cpp +++ b/contrib/epee/src/connection_basic.cpp @@ -78,7 +78,6 @@ // TODO: #include "net/network_throttle-detail.hpp" -#include "cryptonote_core/cryptonote_core.h" #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "net.p2p" diff --git a/contrib/epee/src/http_auth.cpp b/contrib/epee/src/http_auth.cpp index f06f05528..5b8d892ff 100644 --- a/contrib/epee/src/http_auth.cpp +++ b/contrib/epee/src/http_auth.cpp @@ -66,7 +66,6 @@ #include <tuple> #include <type_traits> -#include "crypto/crypto.h" #include "hex.h" #include "md5_l.h" #include "string_coding.h" @@ -711,8 +710,8 @@ namespace epee { namespace http { - http_server_auth::http_server_auth(login credentials) - : user(session{std::move(credentials)}) { + http_server_auth::http_server_auth(login credentials, std::function<void(size_t, uint8_t*)> r) + : user(session{std::move(credentials)}), rng(std::move(r)) { } boost::optional<http_response_info> http_server_auth::do_get_response(const http_request_info& request) @@ -746,7 +745,7 @@ namespace epee user->counter = 0; { std::array<std::uint8_t, 16> rand_128bit{{}}; - crypto::rand(rand_128bit.size(), rand_128bit.data()); + rng(rand_128bit.size(), rand_128bit.data()); user->nonce = string_encoding::base64_encode(rand_128bit.data(), rand_128bit.size()); } return create_digest_response(user->nonce, is_stale); diff --git a/src/common/memwipe.c b/contrib/epee/src/memwipe.c index da7e9f346..da7e9f346 100644 --- a/src/common/memwipe.c +++ b/contrib/epee/src/memwipe.c diff --git a/contrib/epee/src/wipeable_string.cpp b/contrib/epee/src/wipeable_string.cpp index 894c47bbd..08a975e58 100644 --- a/contrib/epee/src/wipeable_string.cpp +++ b/contrib/epee/src/wipeable_string.cpp @@ -100,7 +100,7 @@ void wipeable_string::grow(size_t sz, size_t reserved) wipefunc(buffer.data(), old_sz * sizeof(char)); buffer.reserve(reserved); buffer.resize(sz); - memcpy(buffer.data(), tmp.get(), sz * sizeof(char)); + memcpy(buffer.data(), tmp.get(), old_sz * sizeof(char)); wipefunc(tmp.get(), old_sz * sizeof(char)); } diff --git a/external/db_drivers/liblmdb/CMakeLists.txt b/external/db_drivers/liblmdb/CMakeLists.txt index d3d3df6ad..3a09712de 100644 --- a/external/db_drivers/liblmdb/CMakeLists.txt +++ b/external/db_drivers/liblmdb/CMakeLists.txt @@ -54,3 +54,4 @@ if(${ARCH_WIDTH} EQUAL 32) target_compile_definitions(lmdb PUBLIC -DMDB_VL32) endif() +set_property(TARGET lmdb APPEND PROPERTY COMPILE_FLAGS "-fPIC") diff --git a/external/easylogging++/CMakeLists.txt b/external/easylogging++/CMakeLists.txt index 97d0bf571..8fe3fa487 100644 --- a/external/easylogging++/CMakeLists.txt +++ b/external/easylogging++/CMakeLists.txt @@ -54,4 +54,5 @@ if (BUILD_GUI_DEPS) ARCHIVE DESTINATION ${lib_folder} LIBRARY DESTINATION ${lib_folder}) endif() +set_property(TARGET easylogging APPEND PROPERTY COMPILE_FLAGS "-fPIC") diff --git a/src/blockchain_db/blockchain_db.h b/src/blockchain_db/blockchain_db.h index 88034a927..33c3341fa 100644 --- a/src/blockchain_db/blockchain_db.h +++ b/src/blockchain_db/blockchain_db.h @@ -1333,10 +1333,11 @@ public: * @brief get a txpool transaction's metadata * * @param txid the transaction id of the transation to lookup + * @param meta the metadata to return * - * @return the metadata associated with that transaction + * @return true if the tx meta was found, false otherwise */ - virtual txpool_tx_meta_t get_txpool_tx_meta(const crypto::hash& txid) const = 0; + virtual bool get_txpool_tx_meta(const crypto::hash& txid, txpool_tx_meta_t &meta) const = 0; /** * @brief get a txpool transaction's blob diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index 931bbec4b..d19399bec 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -1621,7 +1621,7 @@ void BlockchainLMDB::remove_txpool_tx(const crypto::hash& txid) } } -txpool_tx_meta_t BlockchainLMDB::get_txpool_tx_meta(const crypto::hash& txid) const +bool BlockchainLMDB::get_txpool_tx_meta(const crypto::hash& txid, txpool_tx_meta_t &meta) const { LOG_PRINT_L3("BlockchainLMDB::" << __func__); check_open(); @@ -1632,12 +1632,14 @@ txpool_tx_meta_t BlockchainLMDB::get_txpool_tx_meta(const crypto::hash& txid) co MDB_val k = {sizeof(txid), (void *)&txid}; MDB_val v; auto result = mdb_cursor_get(m_cur_txpool_meta, &k, &v, MDB_SET); + if (result == MDB_NOTFOUND) + return false; if (result != 0) throw1(DB_ERROR(lmdb_error("Error finding txpool tx meta: ", result).c_str())); - const txpool_tx_meta_t meta = *(const txpool_tx_meta_t*)v.mv_data; + meta = *(const txpool_tx_meta_t*)v.mv_data; TXN_POSTFIX_RDONLY(); - return meta; + return true; } bool BlockchainLMDB::get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata &bd) const diff --git a/src/blockchain_db/lmdb/db_lmdb.h b/src/blockchain_db/lmdb/db_lmdb.h index 85b62b5db..ecd14f11b 100644 --- a/src/blockchain_db/lmdb/db_lmdb.h +++ b/src/blockchain_db/lmdb/db_lmdb.h @@ -246,7 +246,7 @@ public: virtual uint64_t get_txpool_tx_count(bool include_unrelayed_txes = true) const; virtual bool txpool_has_tx(const crypto::hash &txid) const; virtual void remove_txpool_tx(const crypto::hash& txid); - virtual txpool_tx_meta_t get_txpool_tx_meta(const crypto::hash& txid) const; + virtual bool get_txpool_tx_meta(const crypto::hash& txid, txpool_tx_meta_t &meta) const; virtual bool get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata &bd) const; virtual cryptonote::blobdata get_txpool_tx_blob(const crypto::hash& txid) const; virtual bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata*)> f, bool include_blob = false, bool include_unrelayed_txes = true) const; diff --git a/src/blockchain_utilities/CMakeLists.txt b/src/blockchain_utilities/CMakeLists.txt index bd32e0c55..6c55e8d2d 100644 --- a/src/blockchain_utilities/CMakeLists.txt +++ b/src/blockchain_utilities/CMakeLists.txt @@ -29,9 +29,9 @@ set(blocksdat "") if(PER_BLOCK_CHECKPOINT) if(APPLE) - add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*) + add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*) else() - add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && cp ../blocks/checkpoints.dat blocks.dat && ${CMAKE_LINKER} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat) + add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && cp ../blocks/checkpoints.dat blocks.dat && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat) endif() set(blocksdat "blocksdat.o") endif() diff --git a/src/blockchain_utilities/blockchain_import.cpp b/src/blockchain_utilities/blockchain_import.cpp index 758deb7e4..edb8881e0 100644 --- a/src/blockchain_utilities/blockchain_import.cpp +++ b/src/blockchain_utilities/blockchain_import.cpp @@ -594,8 +594,8 @@ int main(int argc, char* argv[]) const command_line::arg_descriptor<std::string> arg_database = { "database", available_dbs.c_str(), default_db_type }; - const command_line::arg_descriptor<bool> arg_verify = {"verify", - "Verify blocks and transactions during import", true}; + const command_line::arg_descriptor<bool> arg_verify = {"guard-against-pwnage", + "Verify blocks and transactions during import (only disable if you exported the file yourself)", true}; const command_line::arg_descriptor<bool> arg_batch = {"batch", "Batch transactions for faster import", true}; const command_line::arg_descriptor<bool> arg_resume = {"resume", diff --git a/src/blocks/CMakeLists.txt b/src/blocks/CMakeLists.txt index 3a866af5b..9317d585b 100644 --- a/src/blocks/CMakeLists.txt +++ b/src/blocks/CMakeLists.txt @@ -30,8 +30,8 @@ if(APPLE) add_library(blocks STATIC blockexports.c) set_target_properties(blocks PROPERTIES LINKER_LANGUAGE C) else() - add_custom_command(OUTPUT blocks.o MAIN_DEPENDENCY blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocks.o blocks.dat) - add_custom_command(OUTPUT testnet_blocks.o MAIN_DEPENDENCY testnet_blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/testnet_blocks.o testnet_blocks.dat) + add_custom_command(OUTPUT blocks.o MAIN_DEPENDENCY blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocks.o blocks.dat) + add_custom_command(OUTPUT testnet_blocks.o MAIN_DEPENDENCY testnet_blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/testnet_blocks.o testnet_blocks.dat) add_library(blocks STATIC blocks.o testnet_blocks.o blockexports.c) set_target_properties(blocks PROPERTIES LINKER_LANGUAGE C) endif() diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 9e2135b61..7ce0229da 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -35,7 +35,6 @@ set(common_sources download.cpp util.cpp i18n.cpp - memwipe.c password.cpp perf_timer.cpp threadpool.cpp @@ -64,7 +63,6 @@ set(common_private_headers util.h varint.h i18n.h - memwipe.h password.h perf_timer.h stack_trace.h @@ -93,9 +91,5 @@ target_link_libraries(common ${OPENSSL_LIBRARIES} ${EXTRA_LIBRARIES}) -if(HAVE_C11) -SET_PROPERTY(SOURCE memwipe.c PROPERTY COMPILE_FLAGS -std=c11) -endif() - #monero_install_headers(common # ${common_headers}) diff --git a/src/common/password.cpp b/src/common/password.cpp index dc0856160..011123300 100644 --- a/src/common/password.cpp +++ b/src/common/password.cpp @@ -46,7 +46,7 @@ #include "readline_buffer.h" #endif -#include "common/memwipe.h" +#include "memwipe.h" namespace { diff --git a/src/common/util.cpp b/src/common/util.cpp index 2a2f50c4f..a4a435104 100644 --- a/src/common/util.cpp +++ b/src/common/util.cpp @@ -39,6 +39,7 @@ #include "wipeable_string.h" using namespace epee; +#include "crypto/crypto.h" #include "util.h" #include "memwipe.h" #include "cryptonote_config.h" diff --git a/src/crypto/CMakeLists.txt b/src/crypto/CMakeLists.txt index fd71a87e7..764b30273 100644 --- a/src/crypto/CMakeLists.txt +++ b/src/crypto/CMakeLists.txt @@ -76,6 +76,7 @@ monero_add_library(cncrypto ${crypto_private_headers}) target_link_libraries(cncrypto PUBLIC + epee ${Boost_SYSTEM_LIBRARY} PRIVATE ${EXTRA_LIBRARIES}) diff --git a/src/crypto/blake256.c b/src/crypto/blake256.c index 1e43f9c4d..95b2a6927 100644 --- a/src/crypto/blake256.c +++ b/src/crypto/blake256.c @@ -157,7 +157,7 @@ void blake256_update(state *S, const uint8_t *data, uint64_t datalen) { int left = S->buflen >> 3; int fill = 64 - left; - if (left && (((datalen >> 3) & 0x3F) >= (unsigned) fill)) { + if (left && (((datalen >> 3)) >= (unsigned) fill)) { memcpy((void *) (S->buf + left), (void *) data, fill); S->t[0] += 512; if (S->t[0] == 0) S->t[1]++; diff --git a/src/crypto/chacha.h b/src/crypto/chacha.h index a9665030d..c11e4aa2f 100644 --- a/src/crypto/chacha.h +++ b/src/crypto/chacha.h @@ -39,7 +39,7 @@ #if defined(__cplusplus) #include <memory.h> -#include "common/memwipe.h" +#include "memwipe.h" #include "hash.h" namespace crypto { diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h index 0ce5e6d7a..a929302c1 100644 --- a/src/crypto/crypto.h +++ b/src/crypto/crypto.h @@ -41,7 +41,7 @@ #include "common/pod-class.h" #include "common/util.h" -#include "common/memwipe.h" +#include "memwipe.h" #include "generic-ops.h" #include "hex.h" #include "span.h" diff --git a/src/cryptonote_basic/cryptonote_basic.h b/src/cryptonote_basic/cryptonote_basic.h index 821c21d84..c81901f4e 100644 --- a/src/cryptonote_basic/cryptonote_basic.h +++ b/src/cryptonote_basic/cryptonote_basic.h @@ -36,7 +36,6 @@ #include <cstring> // memcmp #include <sstream> #include <atomic> -#include "serialization/serialization.h" #include "serialization/variant.h" #include "serialization/vector.h" #include "serialization/binary_archive.h" diff --git a/src/cryptonote_basic/cryptonote_basic_impl.cpp b/src/cryptonote_basic/cryptonote_basic_impl.cpp index 1183fda06..929be0d5a 100644 --- a/src/cryptonote_basic/cryptonote_basic_impl.cpp +++ b/src/cryptonote_basic/cryptonote_basic_impl.cpp @@ -34,7 +34,7 @@ using namespace epee; #include "cryptonote_basic_impl.h" #include "string_tools.h" #include "serialization/binary_utils.h" -#include "serialization/vector.h" +#include "serialization/container.h" #include "cryptonote_format_utils.h" #include "cryptonote_config.h" #include "misc_language.h" diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp index 21fa63842..5f6dc3bd6 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.cpp +++ b/src/cryptonote_basic/cryptonote_format_utils.cpp @@ -35,6 +35,7 @@ using namespace epee; #include <boost/algorithm/string.hpp> #include "wipeable_string.h" #include "string_tools.h" +#include "serialization/string.h" #include "cryptonote_format_utils.h" #include "cryptonote_config.h" #include "crypto/crypto.h" diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 709c5e852..4af987c3b 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -4198,9 +4198,9 @@ uint64_t Blockchain::get_txpool_tx_count(bool include_unrelayed_txes) const return m_db->get_txpool_tx_count(include_unrelayed_txes); } -txpool_tx_meta_t Blockchain::get_txpool_tx_meta(const crypto::hash& txid) const +bool Blockchain::get_txpool_tx_meta(const crypto::hash& txid, txpool_tx_meta_t &meta) const { - return m_db->get_txpool_tx_meta(txid); + return m_db->get_txpool_tx_meta(txid, meta); } bool Blockchain::get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata &bd) const diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h index 2d5307ac0..25e573a2c 100644 --- a/src/cryptonote_core/blockchain.h +++ b/src/cryptonote_core/blockchain.h @@ -914,7 +914,7 @@ namespace cryptonote void update_txpool_tx(const crypto::hash &txid, const txpool_tx_meta_t &meta); void remove_txpool_tx(const crypto::hash &txid); uint64_t get_txpool_tx_count(bool include_unrelayed_txes = true) const; - txpool_tx_meta_t get_txpool_tx_meta(const crypto::hash& txid) const; + bool get_txpool_tx_meta(const crypto::hash& txid, txpool_tx_meta_t &meta) const; bool get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata &bd) const; cryptonote::blobdata get_txpool_tx_blob(const crypto::hash& txid) const; bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata*)>, bool include_blob = false, bool include_unrelayed_txes = true) const; diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index e6f217463..8773c1f74 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -371,7 +371,12 @@ namespace cryptonote try { LockedTXN lock(m_blockchain); - txpool_tx_meta_t meta = m_blockchain.get_txpool_tx_meta(id); + txpool_tx_meta_t meta; + if (!m_blockchain.get_txpool_tx_meta(id, meta)) + { + MERROR("Failed to find tx in txpool"); + return false; + } cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(id); if (!parse_and_validate_tx_from_blob(txblob, tx)) { @@ -514,10 +519,13 @@ namespace cryptonote { try { - txpool_tx_meta_t meta = m_blockchain.get_txpool_tx_meta(it->first); - meta.relayed = true; - meta.last_relayed_time = now; - m_blockchain.update_txpool_tx(it->first, meta); + txpool_tx_meta_t meta; + if (m_blockchain.get_txpool_tx_meta(it->first, meta)) + { + meta.relayed = true; + meta.last_relayed_time = now; + m_blockchain.update_txpool_tx(it->first, meta); + } } catch (const std::exception &e) { @@ -696,7 +704,11 @@ namespace cryptonote { try { - meta = m_blockchain.get_txpool_tx_meta(tx_id_hash); + if (!m_blockchain.get_txpool_tx_meta(tx_id_hash, meta)) + { + MERROR("Failed to get tx meta from txpool"); + return false; + } if (!meta.relayed) // Do not include that transaction if in restricted mode and it's not relayed continue; @@ -918,7 +930,13 @@ namespace cryptonote { for (const crypto::hash &txid: it->second) { - txpool_tx_meta_t meta = m_blockchain.get_txpool_tx_meta(txid); + txpool_tx_meta_t meta; + if (!m_blockchain.get_txpool_tx_meta(txid, meta)) + { + MERROR("Failed to find tx meta in txpool"); + // continue, not fatal + continue; + } if (!meta.double_spend_seen) { MDEBUG("Marking " << txid << " as double spending " << itk.k_image); @@ -998,7 +1016,12 @@ namespace cryptonote auto sorted_it = m_txs_by_fee_and_receive_time.begin(); while (sorted_it != m_txs_by_fee_and_receive_time.end()) { - txpool_tx_meta_t meta = m_blockchain.get_txpool_tx_meta(sorted_it->second); + txpool_tx_meta_t meta; + if (!m_blockchain.get_txpool_tx_meta(sorted_it->second, meta)) + { + MERROR(" failed to find tx meta"); + continue; + } LOG_PRINT_L2("Considering " << sorted_it->second << ", size " << meta.blob_size << ", current block size " << total_size << "/" << max_total_size << ", current coinbase " << print_money(best_coinbase)); // Can not exceed maximum block size diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl index 8aef31a5a..5d25d1058 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl @@ -1059,6 +1059,11 @@ skip: num_txs += block_entry.txs.size(); std::vector<tx_verification_context> tvc; m_core.handle_incoming_txs(block_entry.txs, tvc, true, true, false); + if (tvc.size() != block_entry.txs.size()) + { + LOG_ERROR_CCONTEXT("Internal error: tvc.size() != block_entry.txs.size()"); + return true; + } std::list<blobdata>::const_iterator it = block_entry.txs.begin(); for (size_t i = 0; i < tvc.size(); ++i, ++it) { diff --git a/src/daemon/CMakeLists.txt b/src/daemon/CMakeLists.txt index ad84db450..49d3bc836 100644 --- a/src/daemon/CMakeLists.txt +++ b/src/daemon/CMakeLists.txt @@ -29,9 +29,9 @@ set(blocksdat "") if(PER_BLOCK_CHECKPOINT) if(APPLE) - add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*) + add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*) else() - add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && cp ../blocks/checkpoints.dat blocks.dat && ${CMAKE_LINKER} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat) + add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && cp ../blocks/checkpoints.dat blocks.dat && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat) endif() set(blocksdat "blocksdat.o") endif() diff --git a/src/mnemonics/CMakeLists.txt b/src/mnemonics/CMakeLists.txt index 5ce2198ae..79964e873 100644 --- a/src/mnemonics/CMakeLists.txt +++ b/src/mnemonics/CMakeLists.txt @@ -57,6 +57,7 @@ monero_add_library(mnemonics ${mnemonics_private_headers}) target_link_libraries(mnemonics PUBLIC + epee easylogging ${Boost_SYSTEM_LIBRARY} PRIVATE diff --git a/src/mnemonics/electrum-words.cpp b/src/mnemonics/electrum-words.cpp index ba67952aa..f44ad40aa 100644 --- a/src/mnemonics/electrum-words.cpp +++ b/src/mnemonics/electrum-words.cpp @@ -410,7 +410,7 @@ namespace crypto std::vector<std::string> words_store; uint32_t word_list_length = word_list.size(); - // 8 bytes -> 3 words. 8 digits base 16 -> 3 digits base 1626 + // 4 bytes -> 3 words. 8 digits base 16 -> 3 digits base 1626 for (unsigned int i=0; i < len/4; i++, words += ' ') { uint32_t w1, w2, w3; diff --git a/src/p2p/CMakeLists.txt b/src/p2p/CMakeLists.txt index 123b0a272..3fc053dc7 100644 --- a/src/p2p/CMakeLists.txt +++ b/src/p2p/CMakeLists.txt @@ -46,5 +46,6 @@ target_link_libraries(p2p ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_THREAD_LIBRARY} + ${Boost_SERIALIZATION_LIBRARY} PRIVATE ${EXTRA_LIBRARIES}) diff --git a/src/ringct/rctTypes.h b/src/ringct/rctTypes.h index 5ea2dcc7c..2df797360 100644 --- a/src/ringct/rctTypes.h +++ b/src/ringct/rctTypes.h @@ -47,7 +47,7 @@ extern "C" { #include "hex.h" #include "span.h" -#include "serialization/serialization.h" +#include "serialization/vector.h" #include "serialization/debug_archive.h" #include "serialization/binary_archive.h" #include "serialization/json_archive.h" diff --git a/src/rpc/CMakeLists.txt b/src/rpc/CMakeLists.txt index 748c6b8c1..19ea93902 100644 --- a/src/rpc/CMakeLists.txt +++ b/src/rpc/CMakeLists.txt @@ -101,6 +101,7 @@ target_link_libraries(rpc_base epee ${Boost_REGEX_LIBRARY} ${Boost_THREAD_LIBRARY} + ${Boost_PROGRAM_OPTIONS_LIBRARY} PRIVATE ${EXTRA_LIBRARIES}) @@ -125,6 +126,7 @@ target_link_libraries(daemon_messages target_link_libraries(daemon_rpc_server LINK_PRIVATE + rpc cryptonote_core cryptonote_protocol daemon_messages diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index a6109cb89..4966b107d 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -106,8 +106,9 @@ namespace cryptonote if (rpc_config->login) http_login.emplace(std::move(rpc_config->login->username), std::move(rpc_config->login->password).password()); + auto rng = [](size_t len, uint8_t *ptr){ return crypto::rand(len, ptr); }; return epee::http_server_impl_base<core_rpc_server, connection_context>::init( - std::move(port), std::move(rpc_config->bind_ip), std::move(rpc_config->access_control_origins), std::move(http_login) + rng, std::move(port), std::move(rpc_config->bind_ip), std::move(rpc_config->access_control_origins), std::move(http_login) ); } //------------------------------------------------------------------------------------------------------------------------------ diff --git a/src/serialization/container.h b/src/serialization/container.h new file mode 100644 index 000000000..978a59d2a --- /dev/null +++ b/src/serialization/container.h @@ -0,0 +1,113 @@ +// Copyright (c) 2014-2017, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// 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. +// +// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers + +#pragma once + +#include "serialization.h" + +namespace serialization +{ + namespace detail + { + template <typename Archive, class T> + bool serialize_container_element(Archive& ar, T& e) + { + return ::do_serialize(ar, e); + } + + template <typename Archive> + bool serialize_container_element(Archive& ar, uint32_t& e) + { + ar.serialize_varint(e); + return true; + } + + template <typename Archive> + bool serialize_container_element(Archive& ar, uint64_t& e) + { + ar.serialize_varint(e); + return true; + } + + template <typename C> + void do_reserve(C &c, size_t N) {} + } +} + +template <template <bool> class Archive, typename C> +bool do_serialize_container(Archive<false> &ar, C &v) +{ + size_t cnt; + ar.begin_array(cnt); + if (!ar.stream().good()) + return false; + v.clear(); + + // very basic sanity check + if (ar.remaining_bytes() < cnt) { + ar.stream().setstate(std::ios::failbit); + return false; + } + + ::serialization::detail::do_reserve(v, cnt); + + for (size_t i = 0; i < cnt; i++) { + if (i > 0) + ar.delimit_array(); + typename C::value_type e; + if (!::serialization::detail::serialize_container_element(ar, e)) + return false; + ::serialization::detail::do_add(v, std::move(e)); + if (!ar.stream().good()) + return false; + } + ar.end_array(); + return true; +} + +template <template <bool> class Archive, typename C> +bool do_serialize_container(Archive<true> &ar, C &v) +{ + size_t cnt = v.size(); + ar.begin_array(cnt); + for (auto i = v.begin(); i != v.end(); ++i) + { + if (!ar.stream().good()) + return false; + if (i != v.begin()) + ar.delimit_array(); + if(!::serialization::detail::serialize_container_element(ar, const_cast<typename C::value_type&>(*i))) + return false; + if (!ar.stream().good()) + return false; + } + ar.end_array(); + return true; +} diff --git a/src/serialization/deque.h b/src/serialization/deque.h new file mode 100644 index 000000000..994d3f195 --- /dev/null +++ b/src/serialization/deque.h @@ -0,0 +1,64 @@ +// Copyright (c) 2014-2017, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// 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. +// +// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers + +#pragma once + +#include <deque> + +template <template <bool> class Archive, class T> +bool do_serialize(Archive<false> &ar, std::deque<T> &v); +template <template <bool> class Archive, class T> +bool do_serialize(Archive<true> &ar, std::deque<T> &v); + +namespace serialization +{ + namespace detail + { + template <typename T> + void do_reserve(std::deque<T> &c, size_t N) + { + c.reserve(N); + } + + template <typename T> + void do_add(std::deque<T> &c, T &&e) + { + c.emplace_back(std::move(e)); + } + } +} + +#include "serialization.h" + +template <template <bool> class Archive, class T> +bool do_serialize(Archive<false> &ar, std::deque<T> &v) { return do_serialize_container(ar, v); } +template <template <bool> class Archive, class T> +bool do_serialize(Archive<true> &ar, std::deque<T> &v) { return do_serialize_container(ar, v); } + diff --git a/src/serialization/list.h b/src/serialization/list.h index d0fb72163..d725458e7 100644 --- a/src/serialization/list.h +++ b/src/serialization/list.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2015, The Monero Project +// Copyright (c) 2014-2017, The Monero Project // // All rights reserved. // @@ -30,71 +30,29 @@ #pragma once -#include "serialization.h" +#include <list> + +template <template <bool> class Archive, class T> +bool do_serialize(Archive<false> &ar, std::list<T> &v); +template <template <bool> class Archive, class T> +bool do_serialize(Archive<true> &ar, std::list<T> &v); namespace serialization { namespace detail { - template <typename Archive, class T> - bool serialize_list_element(Archive& ar, T& e) - { - return ::do_serialize(ar, e); - } - - template <typename Archive> - bool serialize_list_element(Archive& ar, uint64_t& e) + template <typename T> + void do_add(std::list<T> &c, T &&e) { - ar.serialize_varint(e); - return true; + c.emplace_back(std::move(e)); } } } -template <template <bool> class Archive, class T> -bool do_serialize(Archive<false> &ar, std::list<T> &l) -{ - size_t cnt; - ar.begin_array(cnt); - if (!ar.stream().good()) - return false; - l.clear(); - - // very basic sanity check - if (ar.remaining_bytes() < cnt) { - ar.stream().setstate(std::ios::failbit); - return false; - } - - for (size_t i = 0; i < cnt; i++) { - if (i > 0) - ar.delimit_array(); - l.push_back(T()); - T &t = l.back(); - if (!::serialization::detail::serialize_list_element(ar, t)) - return false; - if (!ar.stream().good()) - return false; - } - ar.end_array(); - return true; -} +#include "serialization.h" template <template <bool> class Archive, class T> -bool do_serialize(Archive<true> &ar, std::list<T> &l) -{ - size_t cnt = l.size(); - ar.begin_array(cnt); - for (typename std::list<T>::iterator i = l.begin(); i != l.end(); ++i) { - if (!ar.stream().good()) - return false; - if (i != l.begin()) - ar.delimit_array(); - if(!::serialization::detail::serialize_list_element(ar, *i)) - return false; - if (!ar.stream().good()) - return false; - } - ar.end_array(); - return true; -} +bool do_serialize(Archive<false> &ar, std::list<T> &v) { return do_serialize_container(ar, v); } +template <template <bool> class Archive, class T> +bool do_serialize(Archive<true> &ar, std::list<T> &v) { return do_serialize_container(ar, v); } + diff --git a/src/serialization/serialization.h b/src/serialization/serialization.h index 9e23f0791..56496c790 100644 --- a/src/serialization/serialization.h +++ b/src/serialization/serialization.h @@ -63,15 +63,17 @@ struct is_blob_type { typedef boost::false_type type; }; template <class T> struct has_free_serializer { typedef boost::true_type type; }; -/*! \struct is_pair_type +/*! \struct is_basic_type * * \brief a descriptor for dispatching serialize */ template <class T> -struct is_pair_type { typedef boost::false_type type; }; +struct is_basic_type { typedef boost::false_type type; }; template<typename F, typename S> -struct is_pair_type<std::pair<F,S>> { typedef boost::true_type type; }; +struct is_basic_type<std::pair<F,S>> { typedef boost::true_type type; }; +template<> +struct is_basic_type<std::string> { typedef boost::true_type type; }; /*! \struct serializer * @@ -89,7 +91,7 @@ struct is_pair_type<std::pair<F,S>> { typedef boost::true_type type; }; template <class Archive, class T> struct serializer{ static bool serialize(Archive &ar, T &v) { - return serialize(ar, v, typename boost::is_integral<T>::type(), typename is_blob_type<T>::type(), typename is_pair_type<T>::type()); + return serialize(ar, v, typename boost::is_integral<T>::type(), typename is_blob_type<T>::type(), typename is_basic_type<T>::type()); } template<typename A> static bool serialize(Archive &ar, T &v, boost::false_type, boost::true_type, A a) { @@ -361,9 +363,3 @@ namespace serialization { return r && check_stream_state(ar); } } - -#include "string.h" -#include "vector.h" -#include "list.h" -#include "pair.h" -#include "set.h" diff --git a/src/serialization/set.h b/src/serialization/set.h index 54b4eb3ab..e6eff62a9 100644 --- a/src/serialization/set.h +++ b/src/serialization/set.h @@ -30,98 +30,29 @@ #pragma once -#include "serialization.h" +#include <set> template <template <bool> class Archive, class T> bool do_serialize(Archive<false> &ar, std::set<T> &v); template <template <bool> class Archive, class T> bool do_serialize(Archive<true> &ar, std::set<T> &v); -template <template <bool> class Archive, class T> -bool do_serialize(Archive<false> &ar, std::unordered_set<T> &v); -template <template <bool> class Archive, class T> -bool do_serialize(Archive<true> &ar, std::unordered_set<T> &v); namespace serialization { namespace detail { - template <typename Archive, class T> - bool serialize_set_element(Archive& ar, T& e) + template <typename T> + void do_add(std::set<T> &c, T &&e) { - return ::do_serialize(ar, e); - } - - template <typename Archive> - bool serialize_set_element(Archive& ar, uint32_t& e) - { - ar.serialize_varint(e); - return true; - } - - template <typename Archive> - bool serialize_set_element(Archive& ar, uint64_t& e) - { - ar.serialize_varint(e); - return true; + c.insert(std::move(e)); } } } -template <template <bool> class Archive, class T> -bool do_serialize_set(Archive<false> &ar, T &v) -{ - size_t cnt; - ar.begin_array(cnt); - if (!ar.stream().good()) - return false; - v.clear(); - - // very basic sanity check - if (ar.remaining_bytes() < cnt) { - ar.stream().setstate(std::ios::failbit); - return false; - } - - for (size_t i = 0; i < cnt; i++) { - if (i > 0) - ar.delimit_array(); - typename T::key_type k; - if (!::serialization::detail::serialize_set_element(ar, k)) - return false; - v.insert(std::move(k)); - if (!ar.stream().good()) - return false; - } - ar.end_array(); - return true; -} - -template <template <bool> class Archive, class T> -bool do_serialize_set(Archive<true> &ar, T &v) -{ - size_t cnt = v.size(); - ar.begin_array(cnt); - bool first = true; - for (const typename T::key_type &k: v) { - if (!ar.stream().good()) - return false; - if (!first) - ar.delimit_array(); - if(!::serialization::detail::serialize_set_element(ar, const_cast<typename T::key_type&>(k))) - return false; - if (!ar.stream().good()) - return false; - first = false; - } - ar.end_array(); - return true; -} +#include "serialization.h" template <template <bool> class Archive, class T> -bool do_serialize(Archive<false> &ar, std::set<T> &v) { return do_serialize_set(ar, v); } +bool do_serialize(Archive<false> &ar, std::set<T> &v) { return do_serialize_container(ar, v); } template <template <bool> class Archive, class T> -bool do_serialize(Archive<true> &ar, std::set<T> &v) { return do_serialize_set(ar, v); } -template <template <bool> class Archive, class T> -bool do_serialize(Archive<false> &ar, std::unordered_set<T> &v) { return do_serialize_set(ar, v); } -template <template <bool> class Archive, class T> -bool do_serialize(Archive<true> &ar, std::unordered_set<T> &v) { return do_serialize_set(ar, v); } +bool do_serialize(Archive<true> &ar, std::set<T> &v) { return do_serialize_container(ar, v); } + diff --git a/src/serialization/unordered_set.h b/src/serialization/unordered_set.h new file mode 100644 index 000000000..b277f0c4a --- /dev/null +++ b/src/serialization/unordered_set.h @@ -0,0 +1,58 @@ +// Copyright (c) 2014-2017, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// 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. +// +// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers + +#pragma once + +#include <set> + +template <template <bool> class Archive, class T> +bool do_serialize(Archive<false> &ar, std::unordered_set<T> &v); +template <template <bool> class Archive, class T> +bool do_serialize(Archive<true> &ar, std::unordered_set<T> &v); + +namespace serialization +{ + namespace detail + { + template <typename T> + void do_add(std::unordered_set<T> &c, T &&e) + { + c.insert(std::move(e)); + } + } +} + +#include "serialization.h" + +template <template <bool> class Archive, class T> +bool do_serialize(Archive<false> &ar, std::unordered_set<T> &v) { return do_serialize_container(ar, v); } +template <template <bool> class Archive, class T> +bool do_serialize(Archive<true> &ar, std::unordered_set<T> &v) { return do_serialize_container(ar, v); } + diff --git a/src/serialization/vector.h b/src/serialization/vector.h index 12fd59558..9cf3d8272 100644 --- a/src/serialization/vector.h +++ b/src/serialization/vector.h @@ -30,6 +30,7 @@ #pragma once +#include <vector> #include "serialization.h" template <template <bool> class Archive, class T> @@ -37,91 +38,28 @@ bool do_serialize(Archive<false> &ar, std::vector<T> &v); template <template <bool> class Archive, class T> bool do_serialize(Archive<true> &ar, std::vector<T> &v); -template <template <bool> class Archive, class T> -bool do_serialize(Archive<false> &ar, std::deque<T> &v); -template <template <bool> class Archive, class T> -bool do_serialize(Archive<true> &ar, std::deque<T> &v); - namespace serialization { namespace detail { - template <typename Archive, class T> - bool serialize_vector_element(Archive& ar, T& e) - { - return ::do_serialize(ar, e); - } - - template <typename Archive> - bool serialize_vector_element(Archive& ar, uint32_t& e) + template <typename T> + void do_reserve(std::vector<T> &c, size_t N) { - ar.serialize_varint(e); - return true; + c.reserve(N); } - template <typename Archive> - bool serialize_vector_element(Archive& ar, uint64_t& e) + template <typename T> + void do_add(std::vector<T> &c, T &&e) { - ar.serialize_varint(e); - return true; + c.emplace_back(std::move(e)); } } } -template <template <bool> class Archive, class T> -bool do_serialize_vd(Archive<false> &ar, T &v) -{ - size_t cnt; - ar.begin_array(cnt); - if (!ar.stream().good()) - return false; - v.clear(); - - // very basic sanity check - if (ar.remaining_bytes() < cnt) { - ar.stream().setstate(std::ios::failbit); - return false; - } - - v.reserve(cnt); - for (size_t i = 0; i < cnt; i++) { - if (i > 0) - ar.delimit_array(); - v.resize(i+1); - if (!::serialization::detail::serialize_vector_element(ar, v[i])) - return false; - if (!ar.stream().good()) - return false; - } - ar.end_array(); - return true; -} - -template <template <bool> class Archive, class T> -bool do_serialize_vd(Archive<true> &ar, T &v) -{ - size_t cnt = v.size(); - ar.begin_array(cnt); - for (size_t i = 0; i < cnt; i++) { - if (!ar.stream().good()) - return false; - if (i > 0) - ar.delimit_array(); - if(!::serialization::detail::serialize_vector_element(ar, v[i])) - return false; - if (!ar.stream().good()) - return false; - } - ar.end_array(); - return true; -} +#include "container.h" template <template <bool> class Archive, class T> -bool do_serialize(Archive<false> &ar, std::vector<T> &v) { return do_serialize_vd(ar, v); } +bool do_serialize(Archive<false> &ar, std::vector<T> &v) { return do_serialize_container(ar, v); } template <template <bool> class Archive, class T> -bool do_serialize(Archive<true> &ar, std::vector<T> &v) { return do_serialize_vd(ar, v); } +bool do_serialize(Archive<true> &ar, std::vector<T> &v) { return do_serialize_container(ar, v); } -template <template <bool> class Archive, class T> -bool do_serialize(Archive<false> &ar, std::deque<T> &v) { return do_serialize_vd(ar, v); } -template <template <bool> class Archive, class T> -bool do_serialize(Archive<true> &ar, std::deque<T> &v) { return do_serialize_vd(ar, v); } diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index f4f24ed77..b9a3e45b4 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -3307,6 +3307,13 @@ bool simple_wallet::show_incoming_transfers(const std::vector<std::string>& args { if (!parse_subaddress_indices(local_args[0], subaddr_indices)) return true; + local_args.erase(local_args.begin()); + } + + if (local_args.size() > 0) + { + fail_msg_writer() << tr("usage: incoming_transfers [available|unavailable] [verbose] [index=<N>]"); + return true; } tools::wallet2::transfer_container transfers; @@ -4528,6 +4535,12 @@ bool simple_wallet::sweep_below(const std::vector<std::string> &args_) //---------------------------------------------------------------------------------------------------- bool simple_wallet::donate(const std::vector<std::string> &args_) { + if(m_wallet->testnet()) + { + fail_msg_writer() << tr("donations are not enabled on the testnet"); + return true; + } + std::vector<std::string> local_args = args_; if(local_args.empty() || local_args.size() > 5) { @@ -6195,6 +6208,7 @@ bool simple_wallet::export_key_images(const std::vector<std::string> &args) try { + LOCK_IDLE_SCOPE(); if (!m_wallet->export_key_images(filename)) { fail_msg_writer() << tr("failed to save file ") << filename; @@ -6227,6 +6241,7 @@ bool simple_wallet::import_key_images(const std::vector<std::string> &args) } std::string filename = args[0]; + LOCK_IDLE_SCOPE(); try { uint64_t spent = 0, unspent = 0; @@ -6258,6 +6273,7 @@ bool simple_wallet::export_outputs(const std::vector<std::string> &args) if (m_wallet->ask_password() && !get_and_verify_password()) { return true; } std::string filename = args[0]; + LOCK_IDLE_SCOPE(); try { std::vector<tools::wallet2::transfer_details> outs = m_wallet->export_outputs(); @@ -6356,6 +6372,7 @@ bool simple_wallet::import_outputs(const std::vector<std::string> &args) boost::archive::binary_iarchive ar(iss); ar >> outputs; } + LOCK_IDLE_SCOPE(); size_t n_outputs = m_wallet->import_outputs(outputs); success_msg_writer() << boost::lexical_cast<std::string>(n_outputs) << " outputs imported"; } diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index c4f8f3457..2af41f588 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -53,6 +53,7 @@ using namespace epee; #include "profile_tools.h" #include "crypto/crypto.h" #include "serialization/binary_utils.h" +#include "serialization/string.h" #include "cryptonote_basic/blobdatatype.h" #include "mnemonics/electrum-words.h" #include "common/i18n.h" @@ -62,7 +63,7 @@ using namespace epee; #include "rapidjson/writer.h" #include "rapidjson/stringbuffer.h" #include "common/json_util.h" -#include "common/memwipe.h" +#include "memwipe.h" #include "common/base58.h" #include "ringct/rctSigs.h" @@ -2035,6 +2036,11 @@ void wallet2::fast_refresh(uint64_t stop_height, uint64_t &blocks_start_height, pull_hashes(0, blocks_start_height, short_chain_history, hashes); if (hashes.size() <= 3) return; + if (blocks_start_height < m_blockchain.offset()) + { + MERROR("Blocks start before blockchain offset: " << blocks_start_height << " " << m_blockchain.offset()); + return; + } if (hashes.size() + current_index < stop_height) { drop_from_short_history(short_chain_history, 3); std::list<crypto::hash>::iterator right = hashes.end(); @@ -5833,7 +5839,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry if (m_multisig) { crypto::public_key ignore = m_multisig_threshold == m_multisig_signers.size() ? crypto::null_pkey : multisig_signers.front(); - multisig_sigs.push_back({tx.rct_signatures, ignore, used_L, {}, msout}); + multisig_sigs.push_back({tx.rct_signatures, ignore, used_L, std::unordered_set<crypto::public_key>(), msout}); if (m_multisig_threshold < m_multisig_signers.size()) { @@ -5860,7 +5866,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_testnet); THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit); THROW_WALLET_EXCEPTION_IF(cryptonote::get_transaction_prefix_hash(ms_tx) != prefix_hash, error::wallet_internal_error, "Multisig txes do not share prefix"); - multisig_sigs.push_back({ms_tx.rct_signatures, multisig_signers[signer_index], new_used_L, {}, msout}); + multisig_sigs.push_back({ms_tx.rct_signatures, multisig_signers[signer_index], new_used_L, std::unordered_set<crypto::public_key>(), msout}); ms_tx.rct_signatures = tx.rct_signatures; THROW_WALLET_EXCEPTION_IF(cryptonote::get_transaction_hash(ms_tx) != cryptonote::get_transaction_hash(tx), error::wallet_internal_error, "Multisig txes differ by more than the signatures"); @@ -6159,7 +6165,8 @@ void wallet2::light_wallet_get_unspent_outs() add_tx_pub_key_to_extra(td.m_tx, tx_pub_key); td.m_key_image = unspent_key_image; - td.m_key_image_known = !m_watch_only; + td.m_key_image_known = !m_watch_only && !m_multisig; + td.m_key_image_partial = m_multisig; td.m_amount = o.amount; td.m_pk_index = 0; td.m_internal_output_index = o.index; @@ -6833,6 +6840,17 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp const size_t estimated_tx_size = estimate_tx_size(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size(), extra.size(), bulletproof); needed_fee = calculate_fee(fee_per_kb, estimated_tx_size, fee_multiplier); + uint64_t inputs = 0, outputs = needed_fee; + for (size_t idx: tx.selected_transfers) inputs += m_transfers[idx].amount(); + for (const auto &o: tx.dsts) outputs += o.amount; + + if (inputs < outputs) + { + LOG_PRINT_L2("We don't have enough for the basic fee, switching to adding_fee"); + adding_fee = true; + goto skip_tx; + } + LOG_PRINT_L2("Trying to create a tx now, with " << tx.dsts.size() << " outputs and " << tx.selected_transfers.size() << " inputs"); if (use_rct) @@ -6908,6 +6926,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp } } +skip_tx: // if unused_*_indices is empty while unused_*_indices_per_subaddr has multiple elements, and if we still have something to pay, // pop front of unused_*_indices_per_subaddr and have unused_*_indices point to the front of unused_*_indices_per_subaddr if ((!dsts.empty() && dsts[0].amount > 0) || adding_fee) @@ -6960,37 +6979,48 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_all(uint64_t below THROW_WALLET_EXCEPTION_IF(unlocked_balance(subaddr_account) == 0, error::wallet_internal_error, "No unlocked balance in the entire wallet"); - std::map<uint32_t, uint64_t> balance_per_subaddr = unlocked_balance_per_subaddress(subaddr_account); - - if (subaddr_indices.empty()) - { - // in case subaddress index wasn't specified, choose non-empty subaddress randomly (with index=0 being chosen last) - if (balance_per_subaddr.count(0) == 1 && balance_per_subaddr.size() > 1) - balance_per_subaddr.erase(0); - auto i = balance_per_subaddr.begin(); - std::advance(i, crypto::rand<size_t>() % balance_per_subaddr.size()); - subaddr_indices.insert(i->first); - } - for (uint32_t i : subaddr_indices) - LOG_PRINT_L2("Spending from subaddress index " << i); + std::map<uint32_t, std::pair<std::vector<size_t>, std::vector<size_t>>> unused_transfer_dust_indices_per_subaddr; - // gather all dust and non-dust outputs of specified subaddress + // gather all dust and non-dust outputs of specified subaddress (if any) and below specified threshold (if any) + bool fund_found = false; for (size_t i = 0; i < m_transfers.size(); ++i) { const transfer_details& td = m_transfers[i]; - if (!td.m_spent && !td.m_key_image_partial && (use_rct ? true : !td.is_rct()) && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && subaddr_indices.count(td.m_subaddr_index.minor) == 1) + if (!td.m_spent && !td.m_key_image_partial && (use_rct ? true : !td.is_rct()) && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && (subaddr_indices.empty() || subaddr_indices.count(td.m_subaddr_index.minor) == 1)) { + fund_found = true; if (below == 0 || td.amount() < below) { if ((td.is_rct()) || is_valid_decomposed_amount(td.amount())) - unused_transfers_indices.push_back(i); + unused_transfer_dust_indices_per_subaddr[td.m_subaddr_index.minor].first.push_back(i); else - unused_dust_indices.push_back(i); + unused_transfer_dust_indices_per_subaddr[td.m_subaddr_index.minor].second.push_back(i); } } } + THROW_WALLET_EXCEPTION_IF(!fund_found, error::wallet_internal_error, "No unlocked balance in the specified subaddress(es)"); + THROW_WALLET_EXCEPTION_IF(unused_transfer_dust_indices_per_subaddr.empty(), error::wallet_internal_error, "The smallest amount found is not below the specified threshold"); - THROW_WALLET_EXCEPTION_IF(unused_transfers_indices.empty() && unused_dust_indices.empty(), error::not_enough_money, 0, 0, 0); // not sure if a new error class (something like 'cant_sweep_empty'?) should be introduced + if (subaddr_indices.empty()) + { + // in case subaddress index wasn't specified, choose non-empty subaddress randomly (with index=0 being chosen last) + if (unused_transfer_dust_indices_per_subaddr.count(0) == 1 && unused_transfer_dust_indices_per_subaddr.size() > 1) + unused_transfer_dust_indices_per_subaddr.erase(0); + auto i = unused_transfer_dust_indices_per_subaddr.begin(); + std::advance(i, crypto::rand<size_t>() % unused_transfer_dust_indices_per_subaddr.size()); + unused_transfers_indices = i->second.first; + unused_dust_indices = i->second.second; + LOG_PRINT_L2("Spending from subaddress index " << i->first); + } + else + { + for (const auto& p : unused_transfer_dust_indices_per_subaddr) + { + unused_transfers_indices.insert(unused_transfers_indices.end(), p.second.first.begin(), p.second.first.end()); + unused_dust_indices.insert(unused_dust_indices.end(), p.second.second.begin(), p.second.second.end()); + LOG_PRINT_L2("Spending from subaddress index " << p.first); + } + } return create_transactions_from(address, is_subaddress, unused_transfers_indices, unused_dust_indices, fake_outs_count, unlock_time, priority, extra, trusted_daemon); } diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index 3aba76da0..fc2c43c04 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -89,6 +89,8 @@ namespace tools //------------------------------------------------------------------------------------------------------------------------------ wallet_rpc_server::~wallet_rpc_server() { + if (m_wallet) + delete m_wallet; } //------------------------------------------------------------------------------------------------------------------------------ void wallet_rpc_server::set_wallet(wallet2 *cr) @@ -229,8 +231,9 @@ namespace tools m_http_client.set_server(walvars->get_daemon_address(), walvars->get_daemon_login()); m_net_server.set_threads_prefix("RPC"); + auto rng = [](size_t len, uint8_t *ptr) { return crypto::rand(len, ptr); }; return epee::http_server_impl_base<wallet_rpc_server, connection_context>::init( - std::move(bind_port), std::move(rpc_config->bind_ip), std::move(rpc_config->access_control_origins), std::move(http_login) + rng, std::move(bind_port), std::move(rpc_config->bind_ip), std::move(rpc_config->access_control_origins), std::move(http_login) ); } //------------------------------------------------------------------------------------------------------------------------------ diff --git a/tests/gtest/cmake/internal_utils.cmake b/tests/gtest/cmake/internal_utils.cmake index 93e6dbb7c..364db5970 100644 --- a/tests/gtest/cmake/internal_utils.cmake +++ b/tests/gtest/cmake/internal_utils.cmake @@ -87,7 +87,7 @@ macro(config_compiler_and_linker) set(cxx_no_exception_flags "-D_HAS_EXCEPTIONS=0") set(cxx_no_rtti_flags "-GR-") elseif (CMAKE_COMPILER_IS_GNUCXX) - set(cxx_base_flags "-Wall -Wshadow") + set(cxx_base_flags "-Wall -Wshadow -fPIC") set(cxx_exception_flags "-fexceptions") set(cxx_no_exception_flags "-fno-exceptions") # Until version 4.3.2, GCC doesn't define a macro to indicate diff --git a/tests/unit_tests/hardfork.cpp b/tests/unit_tests/hardfork.cpp index c235f49fd..0a472a421 100644 --- a/tests/unit_tests/hardfork.cpp +++ b/tests/unit_tests/hardfork.cpp @@ -118,7 +118,7 @@ public: virtual uint64_t get_txpool_tx_count(bool include_unrelayed_txes = true) const { return 0; } virtual bool txpool_has_tx(const crypto::hash &txid) const { return false; } virtual void remove_txpool_tx(const crypto::hash& txid) {} - virtual txpool_tx_meta_t get_txpool_tx_meta(const crypto::hash& txid) const { return txpool_tx_meta_t(); } + virtual bool get_txpool_tx_meta(const crypto::hash& txid, txpool_tx_meta_t &meta) const { return false; } virtual bool get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata &bd) const { return false; } virtual cryptonote::blobdata get_txpool_tx_blob(const crypto::hash& txid) const { return ""; } virtual bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata*)>, bool include_blob = false, bool include_unrelayed_txes = false) const { return false; } diff --git a/tests/unit_tests/http.cpp b/tests/unit_tests/http.cpp index 5e427f064..0e8f9f747 100644 --- a/tests/unit_tests/http.cpp +++ b/tests/unit_tests/http.cpp @@ -60,12 +60,18 @@ #include "md5_l.h" #include "string_tools.h" +#include "crypto/crypto.h" namespace { namespace http = epee::net_utils::http; using fields = std::unordered_map<std::string, std::string>; using auth_responses = std::vector<fields>; +void rng(size_t len, uint8_t *ptr) +{ + crypto::rand(len, ptr); +} + std::string quoted(std::string str) { str.insert(str.begin(), '"'); @@ -250,13 +256,13 @@ std::string get_nc(std::uint32_t count) TEST(HTTP_Server_Auth, NotRequired) { - http::http_server_auth auth{}; + http::http_server_auth auth{}; // no rng here EXPECT_FALSE(auth.get_response(http::http_request_info{})); } TEST(HTTP_Server_Auth, MissingAuth) { - http::http_server_auth auth{{"foo", "bar"}}; + http::http_server_auth auth{{"foo", "bar"}, rng}; EXPECT_TRUE(bool(auth.get_response(http::http_request_info{}))); { http::http_request_info request{}; @@ -267,7 +273,7 @@ TEST(HTTP_Server_Auth, MissingAuth) TEST(HTTP_Server_Auth, BadSyntax) { - http::http_server_auth auth{{"foo", "bar"}}; + http::http_server_auth auth{{"foo", "bar"}, rng}; EXPECT_TRUE(bool(auth.get_response(make_request({{u8"algorithm", "fo\xFF"}})))); EXPECT_TRUE(bool(auth.get_response(make_request({{u8"cnonce", "\"000\xFF\""}})))); EXPECT_TRUE(bool(auth.get_response(make_request({{u8"cnonce \xFF =", "\"000\xFF\""}})))); @@ -277,7 +283,7 @@ TEST(HTTP_Server_Auth, BadSyntax) TEST(HTTP_Server_Auth, MD5) { http::login user{"foo", "bar"}; - http::http_server_auth auth{user}; + http::http_server_auth auth{user, rng}; const auto response = auth.get_response(make_request(fields{})); ASSERT_TRUE(bool(response)); @@ -326,7 +332,7 @@ TEST(HTTP_Server_Auth, MD5_sess) constexpr const char cnonce[] = "not a good cnonce"; http::login user{"foo", "bar"}; - http::http_server_auth auth{user}; + http::http_server_auth auth{user, rng}; const auto response = auth.get_response(make_request(fields{})); ASSERT_TRUE(bool(response)); @@ -378,7 +384,7 @@ TEST(HTTP_Server_Auth, MD5_auth) constexpr const char qop[] = "auth"; http::login user{"foo", "bar"}; - http::http_server_auth auth{user}; + http::http_server_auth auth{user, rng}; const auto response = auth.get_response(make_request(fields{})); ASSERT_TRUE(bool(response)); @@ -446,7 +452,7 @@ TEST(HTTP_Server_Auth, MD5_sess_auth) constexpr const char qop[] = "auth"; http::login user{"foo", "bar"}; - http::http_server_auth auth{user}; + http::http_server_auth auth{user, rng}; const auto response = auth.get_response(make_request(fields{})); ASSERT_TRUE(bool(response)); @@ -523,7 +529,7 @@ TEST(HTTP_Auth, DogFood) const http::login user{"some_user", "ultimate password"}; - http::http_server_auth server{user}; + http::http_server_auth server{user, rng}; http::http_client_auth client{user}; http::http_request_info request{}; diff --git a/tests/unit_tests/memwipe.cpp b/tests/unit_tests/memwipe.cpp index 2d8980ef7..59f50cef8 100644 --- a/tests/unit_tests/memwipe.cpp +++ b/tests/unit_tests/memwipe.cpp @@ -30,7 +30,7 @@ #include <stdint.h> #include "misc_log_ex.h" -#include "common/memwipe.h" +#include "memwipe.h" // Probably won't catch the optimized out case, but at least we test // it works in the normal case diff --git a/tests/unit_tests/serialization.cpp b/tests/unit_tests/serialization.cpp index 2ef1097da..8a75ac435 100644 --- a/tests/unit_tests/serialization.cpp +++ b/tests/unit_tests/serialization.cpp @@ -38,7 +38,6 @@ #include "cryptonote_basic/cryptonote_basic.h" #include "cryptonote_basic/cryptonote_basic_impl.h" #include "ringct/rctSigs.h" -#include "serialization/serialization.h" #include "serialization/binary_archive.h" #include "serialization/json_archive.h" #include "serialization/debug_archive.h" diff --git a/tests/unit_tests/varint.cpp b/tests/unit_tests/varint.cpp index 2b31cdfdf..577ad4d26 100644 --- a/tests/unit_tests/varint.cpp +++ b/tests/unit_tests/varint.cpp @@ -36,7 +36,6 @@ #include <boost/foreach.hpp> #include "cryptonote_basic/cryptonote_basic.h" #include "cryptonote_basic/cryptonote_basic_impl.h" -#include "serialization/serialization.h" #include "serialization/binary_archive.h" #include "serialization/json_archive.h" #include "serialization/debug_archive.h" |