diff options
34 files changed, 403 insertions, 91 deletions
diff --git a/cmake/FindBacktrace.cmake b/cmake/FindBacktrace.cmake new file mode 100644 index 000000000..89bbad07c --- /dev/null +++ b/cmake/FindBacktrace.cmake @@ -0,0 +1,90 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#.rst: +# FindBacktrace +# ------------- +# +# Find provider for backtrace(3). +# +# Checks if OS supports backtrace(3) via either libc or custom library. +# This module defines the following variables: +# +# ``Backtrace_HEADER`` +# The header file needed for backtrace(3). Cached. +# Could be forcibly set by user. +# ``Backtrace_INCLUDE_DIRS`` +# The include directories needed to use backtrace(3) header. +# ``Backtrace_LIBRARIES`` +# The libraries (linker flags) needed to use backtrace(3), if any. +# ``Backtrace_FOUND`` +# Is set if and only if backtrace(3) support detected. +# +# The following cache variables are also available to set or use: +# +# ``Backtrace_LIBRARY`` +# The external library providing backtrace, if any. +# ``Backtrace_INCLUDE_DIR`` +# The directory holding the backtrace(3) header. +# +# Typical usage is to generate of header file using configure_file() with the +# contents like the following:: +# +# #cmakedefine01 Backtrace_FOUND +# #if Backtrace_FOUND +# # include <${Backtrace_HEADER}> +# #endif +# +# And then reference that generated header file in actual source. + +include(CMakePushCheckState) +include(CheckSymbolExists) +include(FindPackageHandleStandardArgs) + +# List of variables to be provided to find_package_handle_standard_args() +set(_Backtrace_STD_ARGS Backtrace_INCLUDE_DIR) + +if(Backtrace_HEADER) + set(_Backtrace_HEADER_TRY "${Backtrace_HEADER}") +else(Backtrace_HEADER) + set(_Backtrace_HEADER_TRY "execinfo.h") +endif(Backtrace_HEADER) + +find_path(Backtrace_INCLUDE_DIR "${_Backtrace_HEADER_TRY}") +set(Backtrace_INCLUDE_DIRS ${Backtrace_INCLUDE_DIR}) + +if (NOT DEFINED Backtrace_LIBRARY) + # First, check if we already have backtrace(), e.g., in libc + cmake_push_check_state(RESET) + set(CMAKE_REQUIRED_INCLUDES ${Backtrace_INCLUDE_DIRS}) + set(CMAKE_REQUIRED_QUIET ${Backtrace_FIND_QUIETLY}) + check_symbol_exists("backtrace" "${_Backtrace_HEADER_TRY}" _Backtrace_SYM_FOUND) + cmake_pop_check_state() +endif() + +if(_Backtrace_SYM_FOUND) + # Avoid repeating the message() call below each time CMake is run. + if(NOT Backtrace_FIND_QUIETLY AND NOT DEFINED Backtrace_LIBRARY) + message(STATUS "backtrace facility detected in default set of libraries") + endif() + set(Backtrace_LIBRARY "" CACHE FILEPATH "Library providing backtrace(3), empty for default set of libraries") +else() + # Check for external library, for non-glibc systems + if(Backtrace_INCLUDE_DIR) + # OpenBSD has libbacktrace renamed to libexecinfo + find_library(Backtrace_LIBRARY "execinfo") + elseif() # respect user wishes + set(_Backtrace_HEADER_TRY "backtrace.h") + find_path(Backtrace_INCLUDE_DIR ${_Backtrace_HEADER_TRY}) + find_library(Backtrace_LIBRARY "backtrace") + endif() + + # Prepend list with library path as it's more common practice + set(_Backtrace_STD_ARGS Backtrace_LIBRARY ${_Backtrace_STD_ARGS}) +endif() + +set(Backtrace_LIBRARIES ${Backtrace_LIBRARY}) +set(Backtrace_HEADER "${_Backtrace_HEADER_TRY}" CACHE STRING "Header providing backtrace(3) facility") + +find_package_handle_standard_args(Backtrace FOUND_VAR Backtrace_FOUND REQUIRED_VARS ${_Backtrace_STD_ARGS}) +mark_as_advanced(Backtrace_HEADER Backtrace_INCLUDE_DIR Backtrace_LIBRARY) diff --git a/contrib/gitian/gitian-linux.yml b/contrib/gitian/gitian-linux.yml index 3bb25c314..67f174fec 100644 --- a/contrib/gitian/gitian-linux.yml +++ b/contrib/gitian/gitian-linux.yml @@ -137,7 +137,7 @@ script: | if [ -d "$EXTRA_INCLUDES" ]; then export HOST_ID_SALT="$EXTRA_INCLUDES" fi - make ${MAKEOPTS} -C ${BASEPREFIX} HOST="${i}" -j 4 V=1 + make ${MAKEOPTS} -C ${BASEPREFIX} HOST="${i}" V=1 unset HOST_ID_SALT done diff --git a/contrib/gitian/gitian-win.yml b/contrib/gitian/gitian-win.yml index fef5567f9..1eb558300 100644 --- a/contrib/gitian/gitian-win.yml +++ b/contrib/gitian/gitian-win.yml @@ -108,7 +108,7 @@ script: | if [ -d "$EXTRA_INCLUDES" ]; then export HOST_ID_SALT="$EXTRA_INCLUDES" fi - make ${MAKEOPTS} -C ${BASEPREFIX} HOST="${i}" -j 4 V=1 + make ${MAKEOPTS} -C ${BASEPREFIX} HOST="${i}" V=1 unset HOST_ID_SALT done diff --git a/external/db_drivers/liblmdb/mdb.c b/external/db_drivers/liblmdb/mdb.c index 8e67d5981..ba1315401 100644 --- a/external/db_drivers/liblmdb/mdb.c +++ b/external/db_drivers/liblmdb/mdb.c @@ -1742,6 +1742,8 @@ mdb_strerror(int err) NULL, err, 0, ptr, MSGSIZE, (va_list *)buf+MSGSIZE); return ptr; #else + if (err < 0) + return "Invalid error code"; return strerror(err); #endif } diff --git a/external/easylogging++/CMakeLists.txt b/external/easylogging++/CMakeLists.txt index 8287024c2..35fb86552 100644 --- a/external/easylogging++/CMakeLists.txt +++ b/external/easylogging++/CMakeLists.txt @@ -33,6 +33,7 @@ project(easylogging CXX) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") find_package(Threads) +find_package(Backtrace) add_library(easylogging easylogging++.cc) @@ -41,7 +42,8 @@ include_directories("${CMAKE_CURRENT_SOURCE_DIR}") include_directories("${CMAKE_CURRENT_BINARY_DIR}") target_link_libraries(easylogging PRIVATE - ${CMAKE_THREAD_LIBS_INIT}) + ${CMAKE_THREAD_LIBS_INIT} + ${Backtrace_LIBRARIES}) # GUI/libwallet install target if (BUILD_GUI_DEPS) diff --git a/src/common/combinator.h b/src/common/combinator.h index 72c6800d5..ba851bd81 100644 --- a/src/common/combinator.h +++ b/src/common/combinator.h @@ -32,6 +32,7 @@ #include <iostream> #include <vector> +#include <stdexcept> namespace tools { diff --git a/src/common/dns_utils.cpp b/src/common/dns_utils.cpp index 1a1155c7c..5e03bf897 100644 --- a/src/common/dns_utils.cpp +++ b/src/common/dns_utils.cpp @@ -33,7 +33,7 @@ #include <stdlib.h> #include "include_base_utils.h" #include "common/threadpool.h" -#include <random> +#include "crypto/crypto.h" #include <boost/thread/mutex.hpp> #include <boost/algorithm/string/join.hpp> #include <boost/optional.hpp> @@ -517,10 +517,7 @@ bool load_txt_records_from_dns(std::vector<std::string> &good_records, const std std::vector<std::vector<std::string> > records; records.resize(dns_urls.size()); - std::random_device rd; - std::mt19937 gen(rd()); - std::uniform_int_distribution<int> dis(0, dns_urls.size() - 1); - size_t first_index = dis(gen); + size_t first_index = crypto::rand_idx(dns_urls.size()); // send all requests in parallel std::deque<bool> avail(dns_urls.size(), false), valid(dns_urls.size(), false); diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h index 22b182ab0..bac456f60 100644 --- a/src/crypto/crypto.h +++ b/src/crypto/crypto.h @@ -35,6 +35,7 @@ #include <boost/optional.hpp> #include <type_traits> #include <vector> +#include <random> #include "common/pod-class.h" #include "memwipe.h" @@ -162,6 +163,32 @@ namespace crypto { return res; } + /* UniformRandomBitGenerator using crypto::rand<uint64_t>() + */ + struct random_device + { + typedef uint64_t result_type; + static constexpr result_type min() { return 0; } + static constexpr result_type max() { return result_type(-1); } + result_type operator()() const { return crypto::rand<result_type>(); } + }; + + /* Generate a random value between range_min and range_max + */ + template<typename T> + typename std::enable_if<std::is_integral<T>::value, T>::type rand_range(T range_min, T range_max) { + crypto::random_device rd; + std::uniform_int_distribution<T> dis(range_min, range_max); + return dis(rd); + } + + /* Generate a random index between 0 and sz-1 + */ + template<typename T> + typename std::enable_if<std::is_unsigned<T>::value, T>::type rand_idx(T sz) { + return crypto::rand_range<T>(0, sz-1); + } + /* Generate a new key pair */ inline secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key = secret_key(), bool recover = false) { diff --git a/src/cryptonote_basic/difficulty.cpp b/src/cryptonote_basic/difficulty.cpp index 5162e53e6..859173aa5 100644 --- a/src/cryptonote_basic/difficulty.cpp +++ b/src/cryptonote_basic/difficulty.cpp @@ -239,4 +239,19 @@ namespace cryptonote { return res.convert_to<difficulty_type>(); } + std::string hex(difficulty_type v) + { + static const char chars[] = "0123456789abcdef"; + std::string s; + while (v > 0) + { + s.push_back(chars[(v & 0xf).convert_to<unsigned>()]); + v >>= 4; + } + if (s.empty()) + s += "0"; + std::reverse(s.begin(), s.end()); + return "0x" + s; + } + } diff --git a/src/cryptonote_basic/difficulty.h b/src/cryptonote_basic/difficulty.h index f7a9376fb..02ed89e5a 100644 --- a/src/cryptonote_basic/difficulty.h +++ b/src/cryptonote_basic/difficulty.h @@ -32,6 +32,7 @@ #include <cstdint> #include <vector> +#include <string> #include <boost/multiprecision/cpp_int.hpp> #include "crypto/hash.h" @@ -58,4 +59,6 @@ namespace cryptonote bool check_hash_128(const crypto::hash &hash, difficulty_type difficulty); bool check_hash(const crypto::hash &hash, difficulty_type difficulty); difficulty_type next_difficulty(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds); + + std::string hex(difficulty_type v); } diff --git a/src/device/device.hpp b/src/device/device.hpp index 2e485b1d6..866e2c676 100644 --- a/src/device/device.hpp +++ b/src/device/device.hpp @@ -76,6 +76,7 @@ namespace hw { class i_device_callback { public: virtual void on_button_request(uint64_t code=0) {} + virtual void on_button_pressed() {} virtual boost::optional<epee::wipeable_string> on_pin_request() { return boost::none; } virtual boost::optional<epee::wipeable_string> on_passphrase_request(bool on_device) { return boost::none; } virtual void on_progress(const device_progress& event) {} diff --git a/src/device_trezor/device_trezor_base.cpp b/src/device_trezor/device_trezor_base.cpp index f3d15c5e2..58abde1d1 100644 --- a/src/device_trezor/device_trezor_base.cpp +++ b/src/device_trezor/device_trezor_base.cpp @@ -43,7 +43,7 @@ namespace trezor { const uint32_t device_trezor_base::DEFAULT_BIP44_PATH[] = {0x8000002c, 0x80000080}; - device_trezor_base::device_trezor_base(): m_callback(nullptr) { + device_trezor_base::device_trezor_base(): m_callback(nullptr), m_last_msg_type(messages::MessageType_Success) { #ifdef WITH_TREZOR_DEBUGGING m_debug = false; #endif @@ -275,6 +275,12 @@ namespace trezor { // Later if needed this generic message handler can be replaced by a pointer to // a protocol message handler which by default points to the device class which implements // the default handler. + + if (m_last_msg_type == messages::MessageType_ButtonRequest){ + on_button_pressed(); + } + m_last_msg_type = input.m_type; + switch(input.m_type){ case messages::MessageType_ButtonRequest: on_button_request(input, dynamic_cast<const messages::common::ButtonRequest*>(input.m_msg.get())); @@ -413,6 +419,11 @@ namespace trezor { resp = read_raw(); } + void device_trezor_base::on_button_pressed() + { + TREZOR_CALLBACK(on_button_pressed); + } + void device_trezor_base::on_pin_request(GenericMessage & resp, const messages::common::PinMatrixRequest * msg) { MDEBUG("on_pin_request"); diff --git a/src/device_trezor/device_trezor_base.hpp b/src/device_trezor/device_trezor_base.hpp index 8c3c14b29..c106d2099 100644 --- a/src/device_trezor/device_trezor_base.hpp +++ b/src/device_trezor/device_trezor_base.hpp @@ -98,6 +98,7 @@ namespace trezor { std::shared_ptr<messages::management::Features> m_features; // features from the last device reset boost::optional<epee::wipeable_string> m_pin; boost::optional<epee::wipeable_string> m_passphrase; + messages::MessageType m_last_msg_type; cryptonote::network_type network_type; @@ -311,6 +312,7 @@ namespace trezor { // Protocol callbacks void on_button_request(GenericMessage & resp, const messages::common::ButtonRequest * msg); + void on_button_pressed(); void on_pin_request(GenericMessage & resp, const messages::common::PinMatrixRequest * msg); void on_passphrase_request(GenericMessage & resp, const messages::common::PassphraseRequest * msg); void on_passphrase_state_request(GenericMessage & resp, const messages::common::PassphraseStateRequest * msg); diff --git a/src/device_trezor/trezor/transport.cpp b/src/device_trezor/trezor/transport.cpp index 991ba3395..dd9b0b52f 100644 --- a/src/device_trezor/trezor/transport.cpp +++ b/src/device_trezor/trezor/transport.cpp @@ -223,6 +223,11 @@ namespace trezor{ msg = msg_wrap; } + static void assert_port_number(uint32_t port) + { + CHECK_AND_ASSERT_THROW_MES(port >= 1024 && port < 65535, "Invalid port number: " << port); + } + Transport::Transport(): m_open_counter(0) { } @@ -263,6 +268,29 @@ namespace trezor{ const char * BridgeTransport::PATH_PREFIX = "bridge:"; + BridgeTransport::BridgeTransport( + boost::optional<std::string> device_path, + boost::optional<std::string> bridge_host): + m_device_path(device_path), + m_bridge_host(bridge_host ? bridge_host.get() : DEFAULT_BRIDGE), + m_response(boost::none), + m_session(boost::none), + m_device_info(boost::none) + { + const char *env_bridge_port = nullptr; + if (!bridge_host && (env_bridge_port = getenv("TREZOR_BRIDGE_PORT")) != nullptr) + { + uint16_t bridge_port; + CHECK_AND_ASSERT_THROW_MES(epee::string_tools::get_xtype_from_string(bridge_port, env_bridge_port), "Invalid bridge port: " << env_bridge_port); + assert_port_number(bridge_port); + + m_bridge_host = std::string("127.0.0.1:") + boost::lexical_cast<std::string>(env_bridge_port); + MDEBUG("Bridge host: " << m_bridge_host); + } + + m_http_client.set_server(m_bridge_host, boost::none, epee::net_utils::ssl_support_t::e_ssl_support_disabled); + } + std::string BridgeTransport::get_path() const { if (!m_device_path){ return ""; @@ -401,28 +429,40 @@ namespace trezor{ const char * UdpTransport::DEFAULT_HOST = "127.0.0.1"; const int UdpTransport::DEFAULT_PORT = 21324; + static void parse_udp_path(std::string &host, int &port, std::string path) + { + if (boost::starts_with(path, UdpTransport::PATH_PREFIX)) + { + path = path.substr(strlen(UdpTransport::PATH_PREFIX)); + } + + auto delim = path.find(':'); + if (delim == std::string::npos) { + host = path; + } else { + host = path.substr(0, delim); + port = std::stoi(path.substr(delim + 1)); + } + } + UdpTransport::UdpTransport(boost::optional<std::string> device_path, boost::optional<std::shared_ptr<Protocol>> proto) : m_io_service(), m_deadline(m_io_service) { + m_device_host = DEFAULT_HOST; m_device_port = DEFAULT_PORT; + const char *env_trezor_path = nullptr; + if (device_path) { - const std::string device_str = device_path.get(); - auto delim = device_str.find(':'); - if (delim == std::string::npos) { - m_device_host = device_str; - } else { - m_device_host = device_str.substr(0, delim); - m_device_port = std::stoi(device_str.substr(delim + 1)); - } + parse_udp_path(m_device_host, m_device_port, device_path.get()); + } else if ((env_trezor_path = getenv("TREZOR_PATH")) != nullptr && boost::starts_with(env_trezor_path, UdpTransport::PATH_PREFIX)){ + parse_udp_path(m_device_host, m_device_port, std::string(env_trezor_path)); + MDEBUG("Applied TREZOR_PATH: " << m_device_host << ":" << m_device_port); } else { m_device_host = DEFAULT_HOST; } - if (m_device_port <= 1024 || m_device_port > 65535){ - throw std::invalid_argument("Port number invalid"); - } - + assert_port_number((uint32_t)m_device_port); if (m_device_host != "localhost" && m_device_host != DEFAULT_HOST){ throw std::invalid_argument("Local endpoint allowed only"); } diff --git a/src/device_trezor/trezor/transport.hpp b/src/device_trezor/trezor/transport.hpp index 2945b3184..cde862547 100644 --- a/src/device_trezor/trezor/transport.hpp +++ b/src/device_trezor/trezor/transport.hpp @@ -163,15 +163,7 @@ namespace trezor { public: BridgeTransport( boost::optional<std::string> device_path = boost::none, - boost::optional<std::string> bridge_host = boost::none): - m_device_path(device_path), - m_bridge_host(bridge_host ? bridge_host.get() : DEFAULT_BRIDGE), - m_response(boost::none), - m_session(boost::none), - m_device_info(boost::none) - { - m_http_client.set_server(m_bridge_host, boost::none, epee::net_utils::ssl_support_t::e_ssl_support_disabled); - } + boost::optional<std::string> bridge_host = boost::none); virtual ~BridgeTransport() = default; diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index f0aef384f..7d13b3216 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -1259,7 +1259,7 @@ namespace nodetool } } else - random_index = crypto::rand<size_t>() % filtered.size(); + random_index = crypto::rand_idx(filtered.size()); CHECK_AND_ASSERT_MES(random_index < filtered.size(), false, "random_index < filtered.size() failed!!"); random_index = filtered[random_index]; @@ -1313,7 +1313,7 @@ namespace nodetool return true; size_t try_count = 0; - size_t current_index = crypto::rand<size_t>()%m_seed_nodes.size(); + size_t current_index = crypto::rand_idx(m_seed_nodes.size()); const net_server& server = m_network_zones.at(epee::net_utils::zone::public_).m_net_server; while(true) { diff --git a/src/p2p/net_peerlist.h b/src/p2p/net_peerlist.h index ebe0268d8..52814af94 100644 --- a/src/p2p/net_peerlist.h +++ b/src/p2p/net_peerlist.h @@ -398,7 +398,7 @@ namespace nodetool return false; } - size_t random_index = crypto::rand<size_t>() % m_peers_gray.size(); + size_t random_index = crypto::rand_idx(m_peers_gray.size()); peers_indexed::index<by_time>::type& by_time_index = m_peers_gray.get<by_time>(); pe = *epee::misc_utils::move_it_backward(--by_time_index.end(), random_index); diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 71bfcc950..39a8b4745 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -74,7 +74,7 @@ namespace void store_difficulty(cryptonote::difficulty_type difficulty, uint64_t &sdiff, std::string &swdiff, uint64_t &stop64) { sdiff = (difficulty << 64 >> 64).convert_to<uint64_t>(); - swdiff = difficulty.convert_to<std::string>(); + swdiff = cryptonote::hex(difficulty); stop64 = (difficulty >> 64).convert_to<uint64_t>(); } } @@ -204,6 +204,7 @@ namespace cryptonote crypto::hash hash; m_core.get_blockchain_top(res.height, hash); + ++res.height; // block height to chain height res.hash = string_tools::pod_to_hex(hash); res.status = CORE_RPC_STATUS_OK; return true; diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index db5ed32f7..2e134931f 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -5065,8 +5065,7 @@ bool simple_wallet::refresh_main(uint64_t start_height, enum ResetType reset, bo LOCK_IDLE_SCOPE(); crypto::hash transfer_hash_pre{}; - uint64_t height_pre, height_post; - + uint64_t height_pre = 0, height_post; if (reset != ResetNone) { if (reset == ResetSoftKeepKI) diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index c1303c225..032b873d6 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -249,6 +249,13 @@ struct Wallet2CallbackImpl : public tools::i_wallet2_callback } } + virtual void on_device_button_pressed() + { + if (m_listener) { + m_listener->onDeviceButtonPressed(); + } + } + virtual boost::optional<epee::wipeable_string> on_device_pin_request() { if (m_listener) { @@ -449,6 +456,11 @@ WalletImpl::~WalletImpl() close(false); // do not store wallet as part of the closing activities // Stop refresh thread stopRefresh(); + + if (m_wallet2Callback->getListener()) { + m_wallet2Callback->getListener()->onSetWallet(nullptr); + } + LOG_PRINT_L1(__FUNCTION__ << " finished"); } diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h index ee1d6ae79..0af3b1867 100644 --- a/src/wallet/api/wallet2_api.h +++ b/src/wallet/api/wallet2_api.h @@ -37,6 +37,7 @@ #include <set> #include <ctime> #include <iostream> +#include <stdexcept> // Public interface for libwallet library namespace Monero { @@ -337,6 +338,7 @@ protected: bool m_indeterminate; }; +struct Wallet; struct WalletListener { virtual ~WalletListener() = 0; @@ -381,7 +383,12 @@ struct WalletListener /** * @brief called by device if the action is required */ - virtual void onDeviceButtonRequest(uint64_t code) {} + virtual void onDeviceButtonRequest(uint64_t code) { (void)code; } + + /** + * @brief called by device if the button was pressed + */ + virtual void onDeviceButtonPressed() { } /** * @brief called by device when PIN is needed @@ -401,7 +408,12 @@ struct WalletListener /** * @brief Signalizes device operation progress */ - virtual void onDeviceProgress(const DeviceProgress & event) {}; + virtual void onDeviceProgress(const DeviceProgress & event) { (void)event; }; + + /** + * @brief If the listener is created before the wallet this enables to set created wallet object + */ + virtual void onSetWallet(Wallet * wallet) { (void)wallet; }; }; @@ -440,8 +452,8 @@ struct Wallet //! returns both error and error string atomically. suggested to use in instead of status() and errorString() virtual void statusWithErrorString(int& status, std::string& errorString) const = 0; virtual bool setPassword(const std::string &password) = 0; - virtual bool setDevicePin(const std::string &password) { return false; }; - virtual bool setDevicePassphrase(const std::string &password) { return false; }; + virtual bool setDevicePin(const std::string &pin) { (void)pin; return false; }; + virtual bool setDevicePassphrase(const std::string &passphrase) { (void)passphrase; return false; }; virtual std::string address(uint32_t accountIndex = 0, uint32_t addressIndex = 0) const = 0; std::string mainAddress() const { return address(0, 0); } virtual std::string path() const = 0; @@ -1020,9 +1032,10 @@ struct WalletManager * \param password Password of wallet file * \param nettype Network type * \param kdf_rounds Number of rounds for key derivation function + * \param listener Wallet listener to set to the wallet after creation * \return Wallet instance (Wallet::status() needs to be called to check if opened successfully) */ - virtual Wallet * openWallet(const std::string &path, const std::string &password, NetworkType nettype, uint64_t kdf_rounds = 1) = 0; + virtual Wallet * openWallet(const std::string &path, const std::string &password, NetworkType nettype, uint64_t kdf_rounds = 1, WalletListener * listener = nullptr) = 0; Wallet * openWallet(const std::string &path, const std::string &password, bool testnet = false) // deprecated { return openWallet(path, password, testnet ? TESTNET : MAINNET); @@ -1134,6 +1147,7 @@ struct WalletManager * \param restoreHeight restore from start height (0 sets to current height) * \param subaddressLookahead Size of subaddress lookahead (empty sets to some default low value) * \param kdf_rounds Number of rounds for key derivation function + * \param listener Wallet listener to set to the wallet after creation * \return Wallet instance (Wallet::status() needs to be called to check if recovered successfully) */ virtual Wallet * createWalletFromDevice(const std::string &path, @@ -1142,7 +1156,8 @@ struct WalletManager const std::string &deviceName, uint64_t restoreHeight = 0, const std::string &subaddressLookahead = "", - uint64_t kdf_rounds = 1) = 0; + uint64_t kdf_rounds = 1, + WalletListener * listener = nullptr) = 0; /*! * \brief Closes wallet. In case operation succeeded, wallet object deleted. in case operation failed, wallet object not deleted diff --git a/src/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp index f584e88ac..ef2ed2015 100644 --- a/src/wallet/api/wallet_manager.cpp +++ b/src/wallet/api/wallet_manager.cpp @@ -57,9 +57,14 @@ Wallet *WalletManagerImpl::createWallet(const std::string &path, const std::stri return wallet; } -Wallet *WalletManagerImpl::openWallet(const std::string &path, const std::string &password, NetworkType nettype, uint64_t kdf_rounds) +Wallet *WalletManagerImpl::openWallet(const std::string &path, const std::string &password, NetworkType nettype, uint64_t kdf_rounds, WalletListener * listener) { WalletImpl * wallet = new WalletImpl(nettype, kdf_rounds); + wallet->setListener(listener); + if (listener){ + listener->onSetWallet(wallet); + } + wallet->open(path, password); //Refresh addressBook wallet->addressBook()->refresh(); @@ -122,9 +127,15 @@ Wallet *WalletManagerImpl::createWalletFromDevice(const std::string &path, const std::string &deviceName, uint64_t restoreHeight, const std::string &subaddressLookahead, - uint64_t kdf_rounds) + uint64_t kdf_rounds, + WalletListener * listener) { WalletImpl * wallet = new WalletImpl(nettype, kdf_rounds); + wallet->setListener(listener); + if (listener){ + listener->onSetWallet(wallet); + } + if(restoreHeight > 0){ wallet->setRefreshFromBlockHeight(restoreHeight); } else { diff --git a/src/wallet/api/wallet_manager.h b/src/wallet/api/wallet_manager.h index 0c83d794f..235f96e17 100644 --- a/src/wallet/api/wallet_manager.h +++ b/src/wallet/api/wallet_manager.h @@ -40,7 +40,7 @@ class WalletManagerImpl : public WalletManager public: Wallet * createWallet(const std::string &path, const std::string &password, const std::string &language, NetworkType nettype, uint64_t kdf_rounds = 1) override; - Wallet * openWallet(const std::string &path, const std::string &password, NetworkType nettype, uint64_t kdf_rounds = 1) override; + Wallet * openWallet(const std::string &path, const std::string &password, NetworkType nettype, uint64_t kdf_rounds = 1, WalletListener * listener = nullptr) override; virtual Wallet * recoveryWallet(const std::string &path, const std::string &password, const std::string &mnemonic, @@ -72,7 +72,8 @@ public: const std::string &deviceName, uint64_t restoreHeight = 0, const std::string &subaddressLookahead = "", - uint64_t kdf_rounds = 1) override; + uint64_t kdf_rounds = 1, + WalletListener * listener = nullptr) override; virtual bool closeWallet(Wallet *wallet, bool store = true) override; bool walletExists(const std::string &path) override; bool verifyWalletPassword(const std::string &keys_file_name, const std::string &password, bool no_spend_key, uint64_t kdf_rounds = 1) const override; diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index dfcc61426..b288994a5 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -265,6 +265,7 @@ struct options { const command_line::arg_descriptor<std::string> hw_device = {"hw-device", tools::wallet2::tr("HW device to use"), ""}; const command_line::arg_descriptor<std::string> hw_device_derivation_path = {"hw-device-deriv-path", tools::wallet2::tr("HW device wallet derivation path (e.g., SLIP-10)"), ""}; const command_line::arg_descriptor<std::string> tx_notify = { "tx-notify" , "Run a program for each new incoming transaction, '%s' will be replaced by the transaction hash" , "" }; + const command_line::arg_descriptor<bool> no_dns = {"no-dns", tools::wallet2::tr("Do not use DNS"), false}; }; void do_prepare_file_names(const std::string& file_path, std::string& keys_file, std::string& wallet_file, std::string &mms_file) @@ -452,6 +453,9 @@ std::unique_ptr<tools::wallet2> make_basic(const boost::program_options::variabl wallet->device_name(device_name); wallet->device_derivation_path(device_derivation_path); + if (command_line::get_arg(vm, opts.no_dns)) + wallet->enable_dns(false); + try { if (!command_line::is_arg_defaulted(vm, opts.tx_notify)) @@ -992,6 +996,12 @@ void wallet_device_callback::on_button_request(uint64_t code) wallet->on_device_button_request(code); } +void wallet_device_callback::on_button_pressed() +{ + if (wallet) + wallet->on_device_button_pressed(); +} + boost::optional<epee::wipeable_string> wallet_device_callback::on_pin_request() { if (wallet) @@ -1072,7 +1082,8 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended): m_encrypt_keys_after_refresh(boost::none), m_unattended(unattended), m_devices_registered(false), - m_device_last_key_image_sync(0) + m_device_last_key_image_sync(0), + m_use_dns(true) { } @@ -1127,6 +1138,7 @@ void wallet2::init_options(boost::program_options::options_description& desc_par command_line::add_arg(desc_params, opts.hw_device); command_line::add_arg(desc_params, opts.hw_device_derivation_path); command_line::add_arg(desc_params, opts.tx_notify); + command_line::add_arg(desc_params, opts.no_dns); } std::pair<std::unique_ptr<wallet2>, tools::password_container> wallet2::make_from_json(const boost::program_options::variables_map& vm, bool unattended, const std::string& json_file, const std::function<boost::optional<tools::password_container>(const char *, bool)> &password_prompter) @@ -5773,7 +5785,7 @@ namespace { CHECK_AND_ASSERT_MES(!vec.empty(), T(), "Vector must be non-empty"); - size_t idx = crypto::rand<size_t>() % vec.size(); + size_t idx = crypto::rand_idx(vec.size()); return pop_index (vec, idx); } @@ -5876,7 +5888,7 @@ size_t wallet2::pop_best_value_from(const transfer_container &transfers, std::ve } else { - idx = crypto::rand<size_t>() % candidates.size(); + idx = crypto::rand_idx(candidates.size()); } return pop_index (unused_indices, candidates[idx]); } @@ -7565,7 +7577,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>> if (n_rct == 0) return rct_offsets[block_offset] ? rct_offsets[block_offset] - 1 : 0; MDEBUG("Picking 1/" << n_rct << " in " << (last_block_offset - first_block_offset + 1) << " blocks centered around " << block_offset + rct_start_height); - return first_rct + crypto::rand<uint64_t>() % n_rct; + return first_rct + crypto::rand_idx(n_rct); }; size_t num_selected_transfers = 0; @@ -9621,14 +9633,16 @@ bool wallet2::sanity_check(const std::vector<wallet2::pending_tx> &ptx_vector, s change -= r.second.first; MDEBUG("Adding " << cryptonote::print_money(change) << " expected change"); + // for all txes that have actual change, check change is coming back to the sending wallet for (const pending_tx &ptx: ptx_vector) - THROW_WALLET_EXCEPTION_IF(ptx.change_dts.addr != ptx_vector[0].change_dts.addr, error::wallet_internal_error, - "Change goes to several different addresses"); - const auto it = m_subaddresses.find(ptx_vector[0].change_dts.addr.m_spend_public_key); - THROW_WALLET_EXCEPTION_IF(change > 0 && it == m_subaddresses.end(), error::wallet_internal_error, "Change address is not ours"); - - required[ptx_vector[0].change_dts.addr].first += change; - required[ptx_vector[0].change_dts.addr].second = ptx_vector[0].change_dts.is_subaddress; + { + if (ptx.change_dts.amount == 0) + continue; + THROW_WALLET_EXCEPTION_IF(m_subaddresses.find(ptx.change_dts.addr.m_spend_public_key) == m_subaddresses.end(), + error::wallet_internal_error, "Change address is not ours"); + required[ptx.change_dts.addr].first += ptx.change_dts.amount; + required[ptx.change_dts.addr].second = ptx.change_dts.is_subaddress; + } for (const auto &r: required) { @@ -9694,7 +9708,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_all(uint64_t below 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()); + std::advance(i, crypto::rand_idx(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); @@ -12865,8 +12879,7 @@ uint64_t wallet2::get_segregation_fork_height() const if (m_segregation_height > 0) return m_segregation_height; - static const bool use_dns = true; - if (use_dns) + if (m_use_dns) { // All four MoneroPulse domains have DNSSEC on and valid static const std::vector<std::string> dns_urls = { @@ -12946,6 +12959,12 @@ void wallet2::on_device_button_request(uint64_t code) m_callback->on_device_button_request(code); } //---------------------------------------------------------------------------------------------------- +void wallet2::on_device_button_pressed() +{ + if (nullptr != m_callback) + m_callback->on_device_button_pressed(); +} +//---------------------------------------------------------------------------------------------------- boost::optional<epee::wipeable_string> wallet2::on_device_pin_request() { if (nullptr != m_callback) diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index c8ac7d429..39380c9df 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -105,6 +105,7 @@ namespace tools virtual void on_lw_money_spent(uint64_t height, const crypto::hash &txid, uint64_t amount) {} // Device callbacks virtual void on_device_button_request(uint64_t code) {} + virtual void on_device_button_pressed() {} virtual boost::optional<epee::wipeable_string> on_device_pin_request() { return boost::none; } virtual boost::optional<epee::wipeable_string> on_device_passphrase_request(bool on_device) { return boost::none; } virtual void on_device_progress(const hw::device_progress& event) {}; @@ -118,6 +119,7 @@ namespace tools public: wallet_device_callback(wallet2 * wallet): wallet(wallet) {}; void on_button_request(uint64_t code=0) override; + void on_button_pressed() override; boost::optional<epee::wipeable_string> on_pin_request() override; boost::optional<epee::wipeable_string> on_passphrase_request(bool on_device) override; void on_progress(const hw::device_progress& event) override; @@ -1288,6 +1290,7 @@ namespace tools void hash_m_transfer(const transfer_details & transfer, crypto::hash &hash) const; uint64_t hash_m_transfers(int64_t transfer_height, crypto::hash &hash) const; void finish_rescan_bc_keep_key_images(uint64_t transfer_height, const crypto::hash &hash); + void enable_dns(bool enable) { m_use_dns = enable; } private: /*! @@ -1378,6 +1381,7 @@ namespace tools wallet_device_callback * get_device_callback(); void on_device_button_request(uint64_t code); + void on_device_button_pressed(); boost::optional<epee::wipeable_string> on_device_pin_request(); boost::optional<epee::wipeable_string> on_device_passphrase_request(bool on_device); void on_device_progress(const hw::device_progress& event); @@ -1469,6 +1473,7 @@ namespace tools std::string m_device_name; std::string m_device_derivation_path; uint64_t m_device_last_key_image_sync; + bool m_use_dns; // Aux transaction data from device std::unordered_map<crypto::hash, std::string> m_tx_device; diff --git a/tests/core_tests/wallet_tools.cpp b/tests/core_tests/wallet_tools.cpp index 616774d18..d9cee34c1 100644 --- a/tests/core_tests/wallet_tools.cpp +++ b/tests/core_tests/wallet_tools.cpp @@ -135,7 +135,7 @@ bool wallet_tools::fill_tx_sources(tools::wallet2 * wallet, std::vector<cryptono } } - MINFO("Selected " << i << " from tx: " << dump_keys(td.m_txid.data) + MDEBUG("Selected " << i << " from tx: " << dump_keys(td.m_txid.data) << " ki: " << dump_keys(td.m_key_image.data) << " amnt: " << td.amount() << " rct: " << td.is_rct() diff --git a/tests/difficulty/difficulty.cpp b/tests/difficulty/difficulty.cpp index 9985b8710..11ce0bd73 100644 --- a/tests/difficulty/difficulty.cpp +++ b/tests/difficulty/difficulty.cpp @@ -36,6 +36,7 @@ #include <algorithm> #include <stdexcept> +#include "misc_log_ex.h" #include "cryptonote_config.h" #include "cryptonote_basic/difficulty.h" @@ -82,6 +83,8 @@ static int test_wide_difficulty(const char *filename) } int main(int argc, char *argv[]) { + TRY_ENTRY(); + if (argc < 2) { cerr << "Wrong arguments" << endl; return 1; @@ -136,4 +139,6 @@ int main(int argc, char *argv[]) { data.clear(fstream::badbit); } return 0; + + CATCH_ENTRY_L0("main", 1); } diff --git a/tests/functional_tests/blockchain.py b/tests/functional_tests/blockchain.py index 3957200d8..56164600d 100755 --- a/tests/functional_tests/blockchain.py +++ b/tests/functional_tests/blockchain.py @@ -61,8 +61,8 @@ class BlockchainTest(): prev_block = res_info.top_block_hash res_height = daemon.get_height() assert res_height.height == height - assert int(res_info.wide_cumulative_difficulty) == (res_info.cumulative_difficulty_top64 << 64) + res_info.cumulative_difficulty - cumulative_difficulty = int(res_info.wide_cumulative_difficulty) + assert int(res_info.wide_cumulative_difficulty, 16) == (res_info.cumulative_difficulty_top64 << 64) + res_info.cumulative_difficulty + cumulative_difficulty = int(res_info.wide_cumulative_difficulty, 16) # we should not see a block at height ok = False @@ -91,11 +91,11 @@ class BlockchainTest(): assert block_header.orphan_status == False assert block_header.depth == blocks - n - 1 assert block_header.prev_hash == prev_block, prev_block - assert int(block_header.wide_difficulty) == (block_header.difficulty_top64 << 64) + block_header.difficulty - assert int(block_header.wide_cumulative_difficulty) == (block_header.cumulative_difficulty_top64 << 64) + block_header.cumulative_difficulty + assert int(block_header.wide_difficulty, 16) == (block_header.difficulty_top64 << 64) + block_header.difficulty + assert int(block_header.wide_cumulative_difficulty, 16) == (block_header.cumulative_difficulty_top64 << 64) + block_header.cumulative_difficulty assert block_header.reward >= 600000000000 # tail emission - cumulative_difficulty += int(block_header.wide_difficulty) - assert cumulative_difficulty == int(block_header.wide_cumulative_difficulty) + cumulative_difficulty += int(block_header.wide_difficulty, 16) + assert cumulative_difficulty == int(block_header.wide_cumulative_difficulty, 16) assert block_header.block_size > 0 assert block_header.block_weight >= block_header.block_size assert block_header.long_term_weight > 0 @@ -123,7 +123,7 @@ class BlockchainTest(): assert res_getblocktemplate.expected_reward >= 600000000000 assert len(res_getblocktemplate.blocktemplate_blob) > 0 assert len(res_getblocktemplate.blockhashing_blob) > 0 - assert int(res_getblocktemplate.wide_difficulty) == (res_getblocktemplate.difficulty_top64 << 64) + res_getblocktemplate.difficulty + assert int(res_getblocktemplate.wide_difficulty, 16) == (res_getblocktemplate.difficulty_top64 << 64) + res_getblocktemplate.difficulty # diff etc should be the same assert res_getblocktemplate.prev_hash == res_info.top_block_hash diff --git a/tests/hash-target.cpp b/tests/hash-target.cpp index 12acc5a67..1e988c302 100644 --- a/tests/hash-target.cpp +++ b/tests/hash-target.cpp @@ -32,6 +32,7 @@ #include <cstdlib> #include <cstring> #include <limits> +#include "misc_log_ex.h" #include "crypto/hash.h" #include "cryptonote_basic/difficulty.h" @@ -39,6 +40,7 @@ using namespace std; using cryptonote::check_hash; int main(int argc, char *argv[]) { + TRY_ENTRY(); crypto::hash h; for (cryptonote::difficulty_type diff = 1;; diff += 1 + (diff >> 8)) { for (uint16_t b = 0; b < 256; b++) { @@ -83,4 +85,5 @@ int main(int argc, char *argv[]) { } } return 0; + CATCH_ENTRY_L0("main", 1); } diff --git a/tests/hash/main.cpp b/tests/hash/main.cpp index adf1bd9c4..d62098a60 100644 --- a/tests/hash/main.cpp +++ b/tests/hash/main.cpp @@ -35,6 +35,7 @@ #include <string> #include <cfenv> +#include "misc_log_ex.h" #include "warnings.h" #include "crypto/hash.h" #include "crypto/variant2_int_sqrt.h" @@ -89,6 +90,8 @@ int test_variant2_int_sqrt(); int test_variant2_int_sqrt_ref(); int main(int argc, char *argv[]) { + TRY_ENTRY(); + hash_f *f; hash_func *hf; fstream input; @@ -183,6 +186,7 @@ int main(int argc, char *argv[]) { } } return error ? 1 : 0; + CATCH_ENTRY_L0("main", 1); } #if defined(__x86_64__) || (defined(_MSC_VER) && defined(_WIN64)) diff --git a/tests/libwallet_api_tests/main.cpp b/tests/libwallet_api_tests/main.cpp index 02faae50d..c34da04b7 100644 --- a/tests/libwallet_api_tests/main.cpp +++ b/tests/libwallet_api_tests/main.cpp @@ -1139,6 +1139,8 @@ TEST_F(WalletManagerMainnetTest, RecoverAndRefreshWalletMainNetAsync) int main(int argc, char** argv) { + TRY_ENTRY(); + tools::on_startup(); // we can override default values for "TESTNET_DAEMON_ADDRESS" and "WALLETS_ROOT_DIR" @@ -1173,4 +1175,5 @@ int main(int argc, char** argv) ::testing::InitGoogleTest(&argc, argv); Monero::WalletManagerFactory::setLogLevel(Monero::WalletManagerFactory::LogLevel_Max); return RUN_ALL_TESTS(); + CATCH_ENTRY_L0("main", 1); } diff --git a/tests/trezor/daemon.cpp b/tests/trezor/daemon.cpp index 5e987793a..41af93f3f 100644 --- a/tests/trezor/daemon.cpp +++ b/tests/trezor/daemon.cpp @@ -101,6 +101,9 @@ void mock_daemon::load_params(boost::program_options::variables_map const & vm) mock_daemon::~mock_daemon() { + if(m_http_client.is_connected()) + m_http_client.disconnect(); + if (!m_terminated) { try @@ -134,11 +137,14 @@ void mock_daemon::init() if(m_http_client.is_connected()) m_http_client.disconnect(); - CHECK_AND_ASSERT_THROW_MES(m_http_client.set_server(rpc_addr(), boost::none), "RPC client init fail"); + CHECK_AND_ASSERT_THROW_MES(m_http_client.set_server(rpc_addr(), boost::none, epee::net_utils::ssl_support_t::e_ssl_support_disabled), "RPC client init fail"); } void mock_daemon::deinit() { + if(m_http_client.is_connected()) + m_http_client.disconnect(); + try { m_rpc_server.deinit(); diff --git a/tests/trezor/trezor_tests.cpp b/tests/trezor/trezor_tests.cpp index 8d5540328..31c2471ec 100644 --- a/tests/trezor/trezor_tests.cpp +++ b/tests/trezor/trezor_tests.cpp @@ -60,13 +60,14 @@ namespace #define HW_TREZOR_NAME "Trezor" #define TREZOR_ACCOUNT_ORDERING &m_miner_account, &m_alice_account, &m_bob_account, &m_eve_account -#define TREZOR_COMMON_TEST_CASE(genclass, CORE, BASE) \ +#define TREZOR_COMMON_TEST_CASE(genclass, CORE, BASE) do { \ rollback_chain(CORE, BASE.head_block()); \ { \ genclass ctest; \ BASE.fork(ctest); \ GENERATE_AND_PLAY_INSTANCE(genclass, ctest, *(CORE)); \ - } + } \ +} while(0) #define TREZOR_SETUP_CHAIN(NAME) do { \ ++tests_count; \ @@ -83,6 +84,11 @@ static device_trezor_test *ensure_trezor_test_device(); static void rollback_chain(cryptonote::core * core, const cryptonote::block & head); static void setup_chain(cryptonote::core * core, gen_trezor_base & trezor_base, std::string chain_path, bool fix_chain, const po::variables_map & vm_core); +static long get_env_long(const char * flag_name, boost::optional<long> def = boost::none){ + const char *env_data = getenv(flag_name); + return env_data ? atol(env_data) : (def ? def.get() : 0); +} + int main(int argc, char* argv[]) { TRY_ENTRY(); @@ -127,12 +133,13 @@ int main(int argc, char* argv[]) const bool heavy_tests = command_line::get_arg(vm, arg_heavy_tests); const bool fix_chain = command_line::get_arg(vm, arg_fix_chain); - hw::register_device(HW_TREZOR_NAME, ensure_trezor_test_device()); - // hw::trezor::register_all(); // We use our shim instead. + hw::register_device(HW_TREZOR_NAME, ensure_trezor_test_device()); // shim device for call tracking // Bootstrapping common chain & accounts - const uint8_t initial_hf = 9; - const uint8_t max_hf = 10; + const uint8_t initial_hf = (uint8_t)get_env_long("TEST_MIN_HF", 11); + const uint8_t max_hf = (uint8_t)get_env_long("TEST_MAX_HF", 11); + MINFO("Test versions " << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")"); + MINFO("Testing hardforks [" << (int)initial_hf << ", " << (int)max_hf << "]"); cryptonote::core core_obj(nullptr); cryptonote::core * const core = &core_obj; @@ -150,16 +157,20 @@ int main(int argc, char* argv[]) mock_daemon::default_options(vm_core); // Transaction tests - for(uint8_t hf=initial_hf; hf <= max_hf; ++hf) + for(uint8_t hf=initial_hf; hf <= max_hf + 1; ++hf) { - MDEBUG("Transaction tests for HF " << (int)hf); - if (hf > initial_hf) + if (hf > initial_hf || hf > max_hf) { daemon->stop_and_deinit(); daemon = nullptr; trezor_base.daemon(nullptr); + if (hf > max_hf) + { + break; + } } + MDEBUG("Transaction tests for HF " << (int)hf); trezor_base.set_hard_fork(hf); TREZOR_SETUP_CHAIN(std::string("HF") + std::to_string((int)hf)); @@ -196,7 +207,6 @@ int main(int argc, char* argv[]) TREZOR_COMMON_TEST_CASE(gen_trezor_many_utxo, core, trezor_base); } - daemon->stop(); core->deinit(); el::Level level = (failed_tests.empty() ? el::Level::Info : el::Level::Error); MLOG(level, "\nREPORT:"); @@ -225,6 +235,7 @@ static void rollback_chain(cryptonote::core * core, const cryptonote::block & he crypto::hash head_hash = get_block_hash(head), cur_hash{}; uint64_t height = get_block_height(head), cur_height=0; + MDEBUG("Rollbacking to " << height << " to hash " << head_hash); do { core->get_blockchain_top(cur_height, cur_hash); @@ -593,7 +604,7 @@ gen_trezor_base::gen_trezor_base(){ gen_trezor_base::gen_trezor_base(const gen_trezor_base &other): m_generator(other.m_generator), m_bt(other.m_bt), m_miner_account(other.m_miner_account), m_bob_account(other.m_bob_account), m_alice_account(other.m_alice_account), m_eve_account(other.m_eve_account), - m_hard_forks(other.m_hard_forks), m_trezor(other.m_trezor), m_rct_config(other.m_rct_config), + m_hard_forks(other.m_hard_forks), m_trezor(other.m_trezor), m_rct_config(other.m_rct_config), m_top_hard_fork(other.m_top_hard_fork), m_heavy_tests(other.m_heavy_tests), m_test_get_tx_key(other.m_test_get_tx_key), m_live_refresh_enabled(other.m_live_refresh_enabled), m_network_type(other.m_network_type), m_daemon(other.m_daemon) { @@ -625,6 +636,7 @@ void gen_trezor_base::fork(gen_trezor_base & other) other.m_events = m_events; other.m_head = m_head; other.m_hard_forks = m_hard_forks; + other.m_top_hard_fork = m_top_hard_fork; other.m_trezor_path = m_trezor_path; other.m_heavy_tests = m_heavy_tests; other.m_rct_config = m_rct_config; @@ -806,8 +818,6 @@ bool gen_trezor_base::generate(std::vector<test_event_entry>& events) // RCT transactions, wallets have to be used wallet_tools::process_transactions(m_wl_alice.get(), events, blk_5r, m_bt); wallet_tools::process_transactions(m_wl_bob.get(), events, blk_5r, m_bt); - MDEBUG("Available funds on Alice: " << get_available_funds(m_wl_alice.get())); - MDEBUG("Available funds on Bob: " << get_available_funds(m_wl_bob.get())); // Send Alice -> Bob, manually constructed. Simple TX test, precondition. cryptonote::transaction tx_1; @@ -827,7 +837,12 @@ bool gen_trezor_base::generate(std::vector<test_event_entry>& events) CHECK_AND_ASSERT_THROW_MES(resx, "tx_1 semantics failed"); CHECK_AND_ASSERT_THROW_MES(resy, "tx_1 non-semantics failed"); - REWIND_BLOCKS_HF(events, blk_6r, blk_6, m_miner_account, CUR_HF); + REWIND_BLOCKS_N_HF(events, blk_6r, blk_6, m_miner_account, 10, CUR_HF); + wallet_tools::process_transactions(m_wl_alice.get(), events, blk_6, m_bt); + wallet_tools::process_transactions(m_wl_bob.get(), events, blk_6, m_bt); + MDEBUG("Available funds on Alice: " << get_available_funds(m_wl_alice.get())); + MDEBUG("Available funds on Bob: " << get_available_funds(m_wl_bob.get())); + m_head = blk_6r; m_events = events; return true; @@ -889,15 +904,44 @@ void gen_trezor_base::load(std::vector<test_event_entry>& events) MDEBUG("Available funds on Bob: " << get_available_funds(m_wl_bob.get())); } +void gen_trezor_base::rewind_blocks(std::vector<test_event_entry>& events, size_t rewind_n, uint8_t hf) +{ + auto & generator = m_generator; // macro shortcut + REWIND_BLOCKS_N_HF(events, blk_new, m_head, m_miner_account, rewind_n, hf); + m_head = blk_new; + m_events = events; + MDEBUG("Blocks rewound: " << rewind_n << ", #blocks: " << num_blocks(events) << ", #events: " << events.size()); + + wallet_tools::process_transactions(m_wl_alice.get(), events, m_head, m_bt); + wallet_tools::process_transactions(m_wl_bob.get(), events, m_head, m_bt); +} + void gen_trezor_base::fix_hf(std::vector<test_event_entry>& events) { // If current test requires higher hard-fork, move it up const auto current_hf = m_hard_forks.back().first; - if (m_rct_config.bp_version == 2 && current_hf < 10){ + + if (current_hf > m_top_hard_fork) + { + throw std::runtime_error("Generated chain hardfork is higher than desired maximum"); + } + + if (m_rct_config.bp_version == 2 && m_top_hard_fork < 10) + { + throw std::runtime_error("Desired maximum is too low for BPv2"); + } + + if (current_hf < m_top_hard_fork) + { auto hardfork_height = num_blocks(events); - ADD_HARDFORK(m_hard_forks, 10, hardfork_height); + ADD_HARDFORK(m_hard_forks, m_top_hard_fork, hardfork_height); add_top_hfork(events, m_hard_forks); - MDEBUG("Hardfork height: " << hardfork_height); + MDEBUG("Hardfork added at height: " << hardfork_height << ", from " << (int)current_hf << " to " << (int)m_top_hard_fork); + + if (current_hf < 10) + { // buffer blocks, add 10 to apply v10 rules + rewind_blocks(events, 10, m_top_hard_fork); + } } } @@ -934,10 +978,9 @@ void gen_trezor_base::add_transactions_to_events( { // If current test requires higher hard-fork, move it up const auto current_hf = m_hard_forks.back().first; - const uint8_t tx_hf = m_rct_config.bp_version == 2 ? 10 : 9; - if (tx_hf > current_hf){ - throw std::runtime_error("Too late for HF change"); - } + const uint8_t tx_hf = m_top_hard_fork; + CHECK_AND_ASSERT_THROW_MES(tx_hf <= current_hf, "Too late for HF change: " << (int)tx_hf << " current: " << (int)current_hf); + CHECK_AND_ASSERT_THROW_MES(m_rct_config.bp_version < 2 || tx_hf >= 10, "HF too low for BPv2: " << (int)tx_hf); std::list<cryptonote::transaction> tx_list; for(const auto & tx : txs) @@ -1808,7 +1851,7 @@ bool wallet_api_tests::generate(std::vector<test_event_entry>& events) CHECK_AND_ASSERT_THROW_MES(w->init(daemon()->rpc_addr(), 0), "Wallet init fail"); CHECK_AND_ASSERT_THROW_MES(w->refresh(), "Refresh fail"); uint64_t balance = w->balance(0); - MINFO("Balance: " << balance); + MDEBUG("Balance: " << balance); CHECK_AND_ASSERT_THROW_MES(w->status() == Monero::PendingTransaction::Status_Ok, "Status nok"); auto addr = get_address(m_eve_account); diff --git a/tests/trezor/trezor_tests.h b/tests/trezor/trezor_tests.h index bed49fec4..46eb5e6a5 100644 --- a/tests/trezor/trezor_tests.h +++ b/tests/trezor/trezor_tests.h @@ -84,6 +84,8 @@ public: virtual void mine_and_test(std::vector<test_event_entry>& events); + virtual void rewind_blocks(std::vector<test_event_entry>& events, size_t rewind_n, uint8_t hf); + virtual void set_hard_fork(uint8_t hf); crypto::hash head_hash() const { return get_block_hash(m_head); } |