diff options
35 files changed, 349 insertions, 39 deletions
diff --git a/contrib/depends/Makefile b/contrib/depends/Makefile index afa61b93b..6ab602ac0 100644 --- a/contrib/depends/Makefile +++ b/contrib/depends/Makefile @@ -22,9 +22,16 @@ host_toolchain:=$(HOST)- endif ifneq ($(DEBUG),) -release_type=debug +release_type=Debug else -release_type=release +release_type=Release +endif + +ifneq ($(TESTS),) +build_tests=ON +release_type=Debug +else +build_tests=OFF endif base_build_dir=$(BASEDIR)/work/build @@ -164,6 +171,8 @@ $(host_prefix)/share/toolchain.cmake : toolchain.cmake.in $(host_prefix)/.stamp_ -e 's|@LDFLAGS@|$(strip $(host_LDFLAGS) $(host_$(release_type)_LDFLAGS))|' \ -e 's|@allow_host_packages@|$(ALLOW_HOST_PACKAGES)|' \ -e 's|@debug@|$(DEBUG)|' \ + -e 's|@release_type@|$(release_type)|' \ + -e 's|@build_tests@|$(build_tests)|' \ -e 's|@depends@|$(host_cmake)|' \ -e 's|@prefix@|$($(host_arch)_$(host_os)_prefix)|'\ -e 's|@sdk@|$(SDK_PATH)|'\ diff --git a/contrib/depends/packages/gtest.mk b/contrib/depends/packages/gtest.mk new file mode 100644 index 000000000..5df07a32e --- /dev/null +++ b/contrib/depends/packages/gtest.mk @@ -0,0 +1,38 @@ +package=gtest +$(package)_version=1.8.1 +$(package)_download_path=https://github.com/google/googletest/archive/ +$(package)_file_name=release-$($(package)_version).tar.gz +$(package)_sha256_hash=9bf1fe5182a604b4135edc1a425ae356c9ad15e9b23f9f12a02e80184c3a249c +$(package)_cxxflags=-std=c++11 +$(package)_cxxflags_linux=-fPIC + +define $(package)_config_cmds + cd googletest && \ + CC="$(host_prefix)/native/bin/$($(package)_cc)" \ + CXX="$(host_prefix)/native/bin/$($(package)_cxx)" \ + AR="$(host_prefix)/native/bin/$($(package)_ar)" \ + RANLIB="$(host_prefix)/native/bin/$($(package)_ranlib)" \ + LIBTOOL="$(host_prefix)/native/bin/$($(package)_libtool)" \ + CXXFLAGS="$($(package)_cxxflags)" \ + CCFLAGS="$($(package)_ccflags)" \ + CPPFLAGS="$($(package)_cppflags)" \ + CFLAGS="$($(package)_cflags) $($(package)_cppflags)" \ + LDLAGS="$($(package)_ldflags)" \ + cmake -DCMAKE_INSTALL_PREFIX=$(build_prefix) \ + -DTOOLCHAIN_PREFIX=$(host_toolchain) \ + -DCMAKE_AR="$(host_prefix)/native/bin/$($(package)_ar)" \ + -DCMAKE_RANLIB="$(host_prefix)/native/bin/$($(package)_ranlib)" \ + -DCMAKE_CXX_FLAGS_DEBUG=ON +endef +# -DCMAKE_TOOLCHAIN_FILE=$(HOST)/share/toolchain.cmake + +define $(package)_build_cmds + cd googletest && CC="$(host_prefix)/native/bin/$($(package)_cc)" $(MAKE) +endef + +define $(package)_stage_cmds + mkdir $($(package)_staging_prefix_dir)/lib $($(package)_staging_prefix_dir)/include &&\ + cp googletest/libgtest.a $($(package)_staging_prefix_dir)/lib/ &&\ + cp googletest/libgtest_main.a $($(package)_staging_prefix_dir)/lib/ &&\ + cp -a googletest/include/* $($(package)_staging_prefix_dir)/include/ +endef diff --git a/contrib/depends/packages/native_cctools.mk b/contrib/depends/packages/native_cctools.mk index 44d238cc4..bcfe1af6b 100644 --- a/contrib/depends/packages/native_cctools.mk +++ b/contrib/depends/packages/native_cctools.mk @@ -52,6 +52,7 @@ endef define $(package)_stage_cmds $(MAKE) DESTDIR=$($(package)_staging_dir) install && \ + cp $($(package)_extract_dir)/cctools/misc/install_name_tool $($(package)_staging_prefix_dir)/bin/ &&\ cd $($(package)_extract_dir)/toolchain && \ mkdir -p $($(package)_staging_prefix_dir)/lib/clang/$($(package)_clang_version)/include && \ mkdir -p $($(package)_staging_prefix_dir)/bin $($(package)_staging_prefix_dir)/include && \ diff --git a/contrib/depends/packages/native_cmake-unused.mk b/contrib/depends/packages/native_cmake-unused.mk new file mode 100644 index 000000000..c9ab75711 --- /dev/null +++ b/contrib/depends/packages/native_cmake-unused.mk @@ -0,0 +1,23 @@ +package=native_cmake +$(package)_version=3.14.0 +$(package)_version_dot=v3.14 +$(package)_download_path=https://cmake.org/files/$($(package)_version_dot)/ +$(package)_file_name=cmake-$($(package)_version).tar.gz +$(package)_sha256_hash=aa76ba67b3c2af1946701f847073f4652af5cbd9f141f221c97af99127e75502 + +define $(package)_set_vars +$(package)_config_opts= +endef + +define $(package)_config_cmds + ./bootstrap &&\ + ./configure $($(package)_config_opts) +endef + +define $(package)_build_cmd + $(MAKE) +endef + +define $(package)_stage_cmds + $(MAKE) DESTDIR=$($(package)_staging_dir) install +endef diff --git a/contrib/depends/packages/packages.mk b/contrib/depends/packages/packages.mk index 1db50580b..a38819337 100644 --- a/contrib/depends/packages/packages.mk +++ b/contrib/depends/packages/packages.mk @@ -7,6 +7,10 @@ darwin_packages = sodium-darwin linux_packages = eudev qt_packages = qt +ifeq ($(build_tests),ON) +packages += gtest +endif + ifeq ($(host_os),linux) packages += unwind packages += sodium diff --git a/contrib/depends/toolchain.cmake.in b/contrib/depends/toolchain.cmake.in index b0af7bd6b..6b5434751 100644 --- a/contrib/depends/toolchain.cmake.in +++ b/contrib/depends/toolchain.cmake.in @@ -1,9 +1,16 @@ # Set the system name, either Darwin, Linux, or Windows SET(CMAKE_SYSTEM_NAME @depends@) -SET(CMAKE_BUILD_TYPE release) +SET(CMAKE_BUILD_TYPE @release_type@) -SET(STATIC true) -SET(UNBOUND_STATIC true) +OPTION(STATIC "Link libraries statically" ON) +OPTION(TREZOR_DEBUG "Main trezor debugging switch" OFF) +OPTION(BUILD_TESTS "Build tests." OFF) + +SET(STATIC ON) +SET(UNBOUND_STATIC ON) + +SET(BUILD_TESTS @build_tests@) +SET(TREZOR_DEBUG @build_tests@) # where is the target environment SET(CMAKE_FIND_ROOT_PATH @prefix@ /usr) diff --git a/contrib/epee/include/net/levin_protocol_handler_async.h b/contrib/epee/include/net/levin_protocol_handler_async.h index a1ea3e680..116b3ace1 100644 --- a/contrib/epee/include/net/levin_protocol_handler_async.h +++ b/contrib/epee/include/net/levin_protocol_handler_async.h @@ -266,7 +266,7 @@ public: m_pservice_endpoint(psnd_hndlr), m_config(config), m_connection_context(conn_context), - m_cache_in_buffer(256 * 1024), + m_cache_in_buffer(4 * 1024), m_state(stream_state_head) { m_close_called = 0; diff --git a/contrib/epee/include/net/net_helper.h b/contrib/epee/include/net/net_helper.h index 89cef8134..6387c4c34 100644 --- a/contrib/epee/include/net/net_helper.h +++ b/contrib/epee/include/net/net_helper.h @@ -448,6 +448,7 @@ namespace net_utils { MTRACE("Connection err_code eof."); //connection closed there, empty + buff.clear(); return true; } diff --git a/contrib/epee/include/net/net_ssl.h b/contrib/epee/include/net/net_ssl.h index 957903ff8..5ef2ff59d 100644 --- a/contrib/epee/include/net/net_ssl.h +++ b/contrib/epee/include/net/net_ssl.h @@ -37,6 +37,8 @@ #include <boost/asio/ssl.hpp> #include <boost/system/error_code.hpp> +#define SSL_FINGERPRINT_SIZE 32 + namespace epee { namespace net_utils diff --git a/contrib/epee/include/serialization/keyvalue_serialization.h b/contrib/epee/include/serialization/keyvalue_serialization.h index fc5a21851..5459c8409 100644 --- a/contrib/epee/include/serialization/keyvalue_serialization.h +++ b/contrib/epee/include/serialization/keyvalue_serialization.h @@ -32,6 +32,9 @@ #include "enableable.h" #include "keyvalue_serialization_overloads.h" +#undef MONERO_DEFAULT_LOG_CATEGORY +#define MONERO_DEFAULT_LOG_CATEGORY "serialization" + namespace epee { /************************************************************************/ diff --git a/contrib/epee/include/serialization/keyvalue_serialization_overloads.h b/contrib/epee/include/serialization/keyvalue_serialization_overloads.h index 15c95f07a..fc8b90a2c 100644 --- a/contrib/epee/include/serialization/keyvalue_serialization_overloads.h +++ b/contrib/epee/include/serialization/keyvalue_serialization_overloads.h @@ -33,6 +33,9 @@ #include <boost/mpl/vector.hpp> #include <boost/mpl/contains_fwd.hpp> +#undef MONERO_DEFAULT_LOG_CATEGORY +#define MONERO_DEFAULT_LOG_CATEGORY "serialization" + namespace epee { namespace diff --git a/contrib/epee/src/mlog.cpp b/contrib/epee/src/mlog.cpp index 9b6b832d1..a8bfd114d 100644 --- a/contrib/epee/src/mlog.cpp +++ b/contrib/epee/src/mlog.cpp @@ -100,7 +100,7 @@ static const char *get_default_categories(int level) switch (level) { case 0: - categories = "*:WARNING,net:FATAL,net.http:FATAL,net.p2p:FATAL,net.cn:FATAL,global:INFO,verify:FATAL,stacktrace:INFO,logging:INFO,msgwriter:INFO"; + categories = "*:WARNING,net:FATAL,net.http:FATAL,net.p2p:FATAL,net.cn:FATAL,global:INFO,verify:FATAL,serialization:FATAL,stacktrace:INFO,logging:INFO,msgwriter:INFO"; break; case 1: categories = "*:INFO,global:INFO,stacktrace:INFO,logging:INFO,msgwriter:INFO,perf.*:DEBUG"; diff --git a/contrib/epee/src/net_ssl.cpp b/contrib/epee/src/net_ssl.cpp index 7bedb18ac..c17d86eca 100644 --- a/contrib/epee/src/net_ssl.cpp +++ b/contrib/epee/src/net_ssl.cpp @@ -321,7 +321,7 @@ bool ssl_options_t::has_fingerprint(boost::asio::ssl::verify_context &ctx) const unsigned int size{ 0 }; // create the digest from the certificate - if (!X509_digest(cert, EVP_sha1(), digest.data(), &size)) { + if (!X509_digest(cert, EVP_sha256(), digest.data(), &size)) { MERROR("Failed to create certificate fingerprint"); return false; } diff --git a/src/cryptonote_basic/hardfork.cpp b/src/cryptonote_basic/hardfork.cpp index d5710f727..98158a513 100644 --- a/src/cryptonote_basic/hardfork.cpp +++ b/src/cryptonote_basic/hardfork.cpp @@ -292,8 +292,7 @@ void HardFork::on_block_popped(uint64_t nblocks) const uint64_t new_chain_height = db.height(); const uint64_t old_chain_height = new_chain_height + nblocks; uint8_t version; - uint64_t height; - for (height = old_chain_height - 1; height >= new_chain_height; --height) + for (uint64_t height = old_chain_height - 1; height >= new_chain_height; --height) { version = versions.back(); last_versions[version]--; @@ -305,7 +304,7 @@ void HardFork::on_block_popped(uint64_t nblocks) // does not take voting into account for (current_fork_index = heights.size() - 1; current_fork_index > 0; --current_fork_index) - if (height >= heights[current_fork_index].height) + if (new_chain_height >= heights[current_fork_index].height) break; } diff --git a/src/cryptonote_core/tx_sanity_check.cpp b/src/cryptonote_core/tx_sanity_check.cpp index d3b225f1c..10198a3d3 100644 --- a/src/cryptonote_core/tx_sanity_check.cpp +++ b/src/cryptonote_core/tx_sanity_check.cpp @@ -34,7 +34,7 @@ #include "tx_sanity_check.h" #undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "txsanity" +#define MONERO_DEFAULT_LOG_CATEGORY "verify" namespace cryptonote { @@ -80,7 +80,7 @@ bool tx_sanity_check(Blockchain &blockchain, const cryptonote::blobdata &tx_blob if (n_available < 10000) return true; - if (rct_indices.size() < n_indices * 9 / 10) + if (rct_indices.size() < n_indices * 8 / 10) { MERROR("unique indices is only " << rct_indices.size() << "/" << n_indices); return false; diff --git a/src/daemonizer/windows_daemonizer.inl b/src/daemonizer/windows_daemonizer.inl index 701c098f6..c6cd474fd 100644 --- a/src/daemonizer/windows_daemonizer.inl +++ b/src/daemonizer/windows_daemonizer.inl @@ -61,6 +61,10 @@ namespace daemonizer "run-as-service" , "Hidden -- true if running as windows service" }; + const command_line::arg_descriptor<bool> arg_non_interactive = { + "non-interactive" + , "Run non-interactive" + }; std::string get_argument_string(int argc, char const * argv[]) { @@ -83,6 +87,7 @@ namespace daemonizer command_line::add_arg(normal_options, arg_start_service); command_line::add_arg(normal_options, arg_stop_service); command_line::add_arg(hidden_options, arg_is_service); + command_line::add_arg(hidden_options, arg_non_interactive); } inline boost::filesystem::path get_default_data_dir() @@ -177,7 +182,10 @@ namespace daemonizer else // interactive { //LOG_PRINT_L0("Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL); - return executor.run_interactive(vm); + if (command_line::has_arg(vm, arg_non_interactive)) + return executor.run_non_interactive(vm); + else + return executor.run_interactive(vm); } return false; diff --git a/src/device_trezor/device_trezor_base.cpp b/src/device_trezor/device_trezor_base.cpp index 5adadbfc4..b7adf433d 100644 --- a/src/device_trezor/device_trezor_base.cpp +++ b/src/device_trezor/device_trezor_base.cpp @@ -115,10 +115,14 @@ namespace trezor { MDEBUG("Enumerating Trezor devices..."); enumerate(trans); + sort_transports_by_env(trans); - MDEBUG("Enumeration yielded " << trans.size() << " devices"); + MDEBUG("Enumeration yielded " << trans.size() << " Trezor devices"); for (auto &cur : trans) { MDEBUG(" device: " << *(cur.get())); + } + + for (auto &cur : trans) { std::string cur_path = cur->get_path(); if (boost::starts_with(cur_path, this->name)) { MDEBUG("Device Match: " << cur_path); diff --git a/src/device_trezor/trezor/transport.cpp b/src/device_trezor/trezor/transport.cpp index dd9b0b52f..59b281f13 100644 --- a/src/device_trezor/trezor/transport.cpp +++ b/src/device_trezor/trezor/transport.cpp @@ -31,11 +31,13 @@ #include <libusb.h> #endif +#include <algorithm> #include <boost/endian/conversion.hpp> #include <boost/asio/io_service.hpp> #include <boost/asio/ip/udp.hpp> #include <boost/date_time/posix_time/posix_time_types.hpp> #include <boost/format.hpp> +#include "common/apply_permutation.h" #include "transport.hpp" #include "messages/messages-common.pb.h" @@ -95,6 +97,47 @@ namespace trezor{ return patch | (((uint64_t)minor) << bits_2) | (((uint64_t)major) << (bits_1 + bits_2)); } + typedef struct { + uint16_t trezor_type; + uint16_t id_vendor; + uint16_t id_product; + } trezor_usb_desc_t; + + static trezor_usb_desc_t TREZOR_DESC_T1 = {1, 0x534C, 0x0001}; + static trezor_usb_desc_t TREZOR_DESC_T2 = {2, 0x1209, 0x53C1}; + static trezor_usb_desc_t TREZOR_DESC_T2_BL = {3, 0x1209, 0x53C0}; + + static trezor_usb_desc_t TREZOR_DESCS[] = { + TREZOR_DESC_T1, + TREZOR_DESC_T2, + TREZOR_DESC_T2_BL, + }; + + static size_t TREZOR_DESCS_LEN = sizeof(TREZOR_DESCS)/sizeof(TREZOR_DESCS[0]); + + static ssize_t get_device_idx(uint16_t id_vendor, uint16_t id_product){ + for(size_t i = 0; i < TREZOR_DESCS_LEN; ++i){ + if (TREZOR_DESCS[i].id_vendor == id_vendor && TREZOR_DESCS[i].id_product == id_product){ + return i; + } + } + + return -1; + } + + static bool is_device_supported(ssize_t device_idx){ + CHECK_AND_ASSERT_THROW_MES(device_idx < (ssize_t)TREZOR_DESCS_LEN, "Device desc idx too big"); + if (device_idx < 0){ + return false; + } + +#ifdef TREZOR_1_SUPPORTED + return true; +#else + return TREZOR_DESCS[device_idx].trezor_type != 1; +#endif + } + // // Helpers // @@ -312,6 +355,24 @@ namespace trezor{ for(rapidjson::Value::ConstValueIterator itr = bridge_res.Begin(); itr != bridge_res.End(); ++itr){ auto element = itr->GetObject(); auto t = std::make_shared<BridgeTransport>(boost::make_optional(json_get_string(element["path"]))); + + auto itr_vendor = element.FindMember("vendor"); + auto itr_product = element.FindMember("product"); + if (itr_vendor != element.MemberEnd() && itr_product != element.MemberEnd() + && itr_vendor->value.IsNumber() && itr_product->value.IsNumber()){ + try { + const auto id_vendor = (uint16_t) itr_vendor->value.GetUint64(); + const auto id_product = (uint16_t) itr_product->value.GetUint64(); + const auto device_idx = get_device_idx(id_vendor, id_product); + if (!is_device_supported(device_idx)){ + MDEBUG("Device with idx " << device_idx << " is not supported. Vendor: " << id_vendor << ", product: " << id_product); + continue; + } + } catch(const std::exception &e){ + MERROR("Could not detect vendor & product: " << e.what()); + } + } + t->m_device_info.emplace(); t->m_device_info->CopyFrom(*itr, t->m_device_info->GetAllocator()); res.push_back(t); @@ -710,24 +771,20 @@ namespace trezor{ #ifdef WITH_DEVICE_TREZOR_WEBUSB static bool is_trezor1(libusb_device_descriptor * info){ - return info->idVendor == 0x534C && info->idProduct == 0x0001; + return info->idVendor == TREZOR_DESC_T1.id_vendor && info->idProduct == TREZOR_DESC_T1.id_product; } static bool is_trezor2(libusb_device_descriptor * info){ - return info->idVendor == 0x1209 && info->idProduct == 0x53C1; + return info->idVendor == TREZOR_DESC_T2.id_vendor && info->idProduct == TREZOR_DESC_T2.id_product; } static bool is_trezor2_bl(libusb_device_descriptor * info){ - return info->idVendor == 0x1209 && info->idProduct == 0x53C0; + return info->idVendor == TREZOR_DESC_T2_BL.id_vendor && info->idProduct == TREZOR_DESC_T2_BL.id_product; } - static uint8_t get_trezor_dev_mask(libusb_device_descriptor * info){ - uint8_t mask = 0; + static ssize_t get_trezor_dev_id(libusb_device_descriptor *info){ CHECK_AND_ASSERT_THROW_MES(info, "Empty device descriptor"); - mask |= is_trezor1(info) ? 1 : 0; - mask |= is_trezor2(info) ? 2 : 0; - mask |= is_trezor2_bl(info) ? 4 : 0; - return mask; + return get_device_idx(info->idVendor, info->idProduct); } static void set_libusb_log(libusb_context *ctx){ @@ -844,12 +901,12 @@ namespace trezor{ continue; } - const auto trezor_mask = get_trezor_dev_mask(&desc); - if (!trezor_mask){ + const auto trezor_dev_idx = get_trezor_dev_id(&desc); + if (!is_device_supported(trezor_dev_idx)){ continue; } - MTRACE("Found Trezor device: " << desc.idVendor << ":" << desc.idProduct << " mask " << (int)trezor_mask); + MTRACE("Found Trezor device: " << desc.idVendor << ":" << desc.idProduct << " dev_idx " << (int)trezor_dev_idx); auto t = std::make_shared<WebUsbTransport>(boost::make_optional(&desc)); t->m_bus_id = libusb_get_bus_number(devs[i]); @@ -909,8 +966,8 @@ namespace trezor{ continue; } - const auto trezor_mask = get_trezor_dev_mask(&desc); - if (!trezor_mask) { + const auto trezor_dev_idx = get_trezor_dev_id(&desc); + if (!is_device_supported(trezor_dev_idx)){ continue; } @@ -921,7 +978,7 @@ namespace trezor{ get_libusb_ports(devs[i], path); MTRACE("Found Trezor device: " << desc.idVendor << ":" << desc.idProduct - << ", mask: " << (int)trezor_mask + << ", dev_idx: " << (int)trezor_dev_idx << ". path: " << get_usb_path(bus_id, path)); if (bus_id == m_bus_id && path == m_port_numbers) { @@ -1110,6 +1167,39 @@ namespace trezor{ #endif } + void sort_transports_by_env(t_transport_vect & res){ + const char *env_trezor_path = getenv("TREZOR_PATH"); + if (!env_trezor_path){ + return; + } + + // Sort transports by the longest matching prefix with TREZOR_PATH + std::string trezor_path(env_trezor_path); + std::vector<size_t> match_idx(res.size()); + std::vector<size_t> path_permutation(res.size()); + + for(size_t i = 0; i < res.size(); ++i){ + auto cpath = res[i]->get_path(); + std::string * s1 = &trezor_path; + std::string * s2 = &cpath; + + // first has to be shorter in std::mismatch(). Returns first non-matching iterators. + if (s1->size() >= s2->size()){ + std::swap(s1, s2); + } + + const auto mism = std::mismatch(s1->begin(), s1->end(), s2->begin()); + match_idx[i] = mism.first - s1->begin(); + path_permutation[i] = i; + } + + std::sort(path_permutation.begin(), path_permutation.end(), [&](const size_t i0, const size_t i1) { + return match_idx[i0] > match_idx[i1]; + }); + + tools::apply_permutation(path_permutation, res); + } + std::shared_ptr<Transport> transport(const std::string & path){ if (boost::starts_with(path, BridgeTransport::PATH_PREFIX)){ return std::make_shared<BridgeTransport>(path.substr(strlen(BridgeTransport::PATH_PREFIX))); diff --git a/src/device_trezor/trezor/transport.hpp b/src/device_trezor/trezor/transport.hpp index cde862547..affd91553 100644 --- a/src/device_trezor/trezor/transport.hpp +++ b/src/device_trezor/trezor/transport.hpp @@ -303,6 +303,11 @@ namespace trezor { void enumerate(t_transport_vect & res); /** + * Sorts found transports by TREZOR_PATH environment variable. + */ + void sort_transports_by_env(t_transport_vect & res); + + /** * Transforms path to the transport */ std::shared_ptr<Transport> transport(const std::string & path); diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index c41fb37d8..97e9b482e 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -28,6 +28,7 @@ // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +#include <boost/preprocessor/stringize.hpp> #include "include_base_utils.h" #include "string_tools.h" using namespace epee; @@ -159,6 +160,14 @@ namespace cryptonote const std::vector<std::string> ssl_allowed_fingerprint_strings = command_line::get_arg(vm, arg_rpc_ssl_allowed_fingerprints); std::vector<std::vector<uint8_t>> ssl_allowed_fingerprints{ ssl_allowed_fingerprint_strings.size() }; std::transform(ssl_allowed_fingerprint_strings.begin(), ssl_allowed_fingerprint_strings.end(), ssl_allowed_fingerprints.begin(), epee::from_hex::vector); + for (const auto &fpr: ssl_allowed_fingerprints) + { + if (fpr.size() != SSL_FINGERPRINT_SIZE) + { + MERROR("SHA-256 fingerprint should be " BOOST_PP_STRINGIZE(SSL_FINGERPRINT_SIZE) " bytes long."); + return false; + } + } if (!ssl_ca_path.empty() || !ssl_allowed_fingerprints.empty()) ssl_options = epee::net_utils::ssl_options_t{std::move(ssl_allowed_fingerprints), std::move(ssl_ca_path)}; diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 831166d5f..f5b492771 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -39,6 +39,7 @@ #include <boost/algorithm/string/join.hpp> #include <boost/asio/ip/address.hpp> #include <boost/range/adaptor/transformed.hpp> +#include <boost/preprocessor/stringize.hpp> #include "include_base_utils.h" using namespace epee; @@ -131,6 +132,9 @@ using namespace cryptonote; #define GAMMA_SHAPE 19.28 #define GAMMA_SCALE (1/1.61) +#define DEFAULT_MIN_OUTPUT_COUNT 5 +#define DEFAULT_MIN_OUTPUT_VALUE (2*COIN) + static const std::string MULTISIG_SIGNATURE_MAGIC = "SigMultisigPkV1"; static const std::string MULTISIG_EXTRA_INFO_MAGIC = "MultisigxV1"; @@ -221,6 +225,8 @@ namespace add_reason(reason, "fee too low"); if (res.not_rct) add_reason(reason, "tx is not ringct"); + if (res.sanity_check_failed) + add_reason(reason, "tx sanity check failed"); if (res.not_relayed) add_reason(reason, "tx was not relayed"); return reason; @@ -338,6 +344,11 @@ std::unique_ptr<tools::wallet2> make_basic(const boost::program_options::variabl { std::vector<std::vector<uint8_t>> ssl_allowed_fingerprints{ daemon_ssl_allowed_fingerprints.size() }; std::transform(daemon_ssl_allowed_fingerprints.begin(), daemon_ssl_allowed_fingerprints.end(), ssl_allowed_fingerprints.begin(), epee::from_hex::vector); + for (const auto &fpr: daemon_ssl_allowed_fingerprints) + { + THROW_WALLET_EXCEPTION_IF(fpr.size() != SSL_FINGERPRINT_SIZE, tools::error::wallet_internal_error, + "SHA-256 fingerprint should be " BOOST_PP_STRINGIZE(SSL_FINGERPRINT_SIZE) " bytes long."); + } ssl_options = epee::net_utils::ssl_options_t{ std::move(ssl_allowed_fingerprints), std::move(daemon_ssl_ca_file) @@ -3129,6 +3140,7 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo } }); + auto scope_exit_handler_hwdev = epee::misc_utils::create_scope_leave_handler([&](){hwdev.computing_key_images(false);}); bool first = true; while(m_run.load(std::memory_order_relaxed)) { @@ -3254,7 +3266,6 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo LOG_PRINT_L1("Failed to check pending transactions"); } - hwdev.computing_key_images(false); m_first_refresh_done = true; LOG_PRINT_L1("Refresh done, blocks received: " << blocks_fetched << ", balance (all accounts): " << print_money(balance_all()) << ", unlocked: " << print_money(unlocked_balance_all())); @@ -9373,9 +9384,16 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp idx = pop_best_value(indices, tx.selected_transfers, true); // we might not want to add it if it's a large output and we don't have many left - if (m_transfers[idx].amount() >= m_min_output_value) { - if (get_count_above(m_transfers, *unused_transfers_indices, m_min_output_value) < m_min_output_count) { - LOG_PRINT_L2("Second output was not strictly needed, and we're running out of outputs above " << print_money(m_min_output_value) << ", not adding"); + uint64_t min_output_value = m_min_output_value; + uint32_t min_output_count = m_min_output_count; + if (min_output_value == 0 && min_output_count == 0) + { + min_output_value = DEFAULT_MIN_OUTPUT_VALUE; + min_output_count = DEFAULT_MIN_OUTPUT_COUNT; + } + if (m_transfers[idx].amount() >= min_output_value) { + if (get_count_above(m_transfers, *unused_transfers_indices, min_output_value) < min_output_count) { + LOG_PRINT_L2("Second output was not strictly needed, and we're running out of outputs above " << print_money(min_output_value) << ", not adding"); break; } } @@ -9534,7 +9552,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp tx.ptx = test_ptx; tx.weight = get_transaction_weight(test_tx, txBlob.size()); tx.outs = outs; - tx.needed_fee = needed_fee; + tx.needed_fee = test_ptx.fee; accumulated_fee += test_ptx.fee; accumulated_change += test_ptx.change_dts.amount; adding_fee = false; @@ -9932,7 +9950,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton tx.ptx = test_ptx; tx.weight = get_transaction_weight(test_tx, txBlob.size()); tx.outs = outs; - tx.needed_fee = needed_fee; + tx.needed_fee = test_ptx.fee; accumulated_fee += test_ptx.fee; accumulated_change += test_ptx.change_dts.amount; if (!unused_transfers_indices.empty() || !unused_dust_indices.empty()) diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index aaad82bb7..22eaffa6f 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -31,6 +31,7 @@ #include <boost/asio/ip/address.hpp> #include <boost/filesystem/operations.hpp> #include <boost/algorithm/string.hpp> +#include <boost/preprocessor/stringize.hpp> #include <cstdint> #include "include_base_utils.h" using namespace epee; @@ -254,6 +255,14 @@ namespace tools { std::vector<std::vector<uint8_t>> allowed_fingerprints{ rpc_ssl_allowed_fingerprints.size() }; std::transform(rpc_ssl_allowed_fingerprints.begin(), rpc_ssl_allowed_fingerprints.end(), allowed_fingerprints.begin(), epee::from_hex::vector); + for (const auto &fpr: rpc_ssl_allowed_fingerprints) + { + if (fpr.size() != SSL_FINGERPRINT_SIZE) + { + MERROR("SHA-256 fingerprint should be " BOOST_PP_STRINGIZE(SSL_FINGERPRINT_SIZE) " bytes long."); + return false; + } + } rpc_ssl_options = epee::net_utils::ssl_options_t{ std::move(allowed_fingerprints), std::move(rpc_ssl_ca_file) @@ -1848,6 +1857,8 @@ namespace tools rpc_transfers.tx_hash = epee::string_tools::pod_to_hex(td.m_txid); rpc_transfers.subaddr_index = {td.m_subaddr_index.major, td.m_subaddr_index.minor}; rpc_transfers.key_image = td.m_key_image_known ? epee::string_tools::pod_to_hex(td.m_key_image) : ""; + rpc_transfers.block_height = td.m_block_height; + rpc_transfers.frozen = td.m_frozen; rpc_transfers.unlocked = m_wallet->is_transfer_unlocked(td); res.transfers.push_back(rpc_transfers); } @@ -4067,9 +4078,10 @@ namespace tools { cryptonote::TESTNET, "testnet" }, { cryptonote::STAGENET, "stagenet" }, }; + if (!req.any_net_type && !m_wallet) return not_open(er); for (const auto &net_type: net_types) { - if (!req.any_net_type && net_type.type != m_wallet->nettype()) + if (!req.any_net_type && (!m_wallet || net_type.type != m_wallet->nettype())) continue; if (req.allow_openalias) { @@ -4151,6 +4163,7 @@ namespace tools { er.code = WALLET_RPC_ERROR_CODE_NO_DAEMON_CONNECTION; er.message = "SSL is enabled but no user certificate or fingerprints were provided"; + return false; } if (!m_wallet->set_daemon(req.address, boost::none, req.trusted, std::move(ssl_options))) @@ -4175,7 +4188,7 @@ namespace tools { er.code = WALLET_RPC_ERROR_CODE_INVALID_LOG_LEVEL; er.message = "Error: log level not valid"; - return true; + return false; } mlog_set_log_level(req.level); return true; diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h index 604bc4175..4504ac752 100644 --- a/src/wallet/wallet_rpc_server_commands_defs.h +++ b/src/wallet/wallet_rpc_server_commands_defs.h @@ -47,7 +47,7 @@ // advance which version they will stop working with // Don't go over 32767 for any of these #define WALLET_RPC_VERSION_MAJOR 1 -#define WALLET_RPC_VERSION_MINOR 12 +#define WALLET_RPC_VERSION_MINOR 13 #define MAKE_WALLET_RPC_VERSION(major,minor) (((major)<<16)|(minor)) #define WALLET_RPC_VERSION MAKE_WALLET_RPC_VERSION(WALLET_RPC_VERSION_MAJOR, WALLET_RPC_VERSION_MINOR) namespace tools @@ -982,6 +982,8 @@ namespace wallet_rpc std::string tx_hash; cryptonote::subaddress_index subaddr_index; std::string key_image; + uint64_t block_height; + bool frozen; bool unlocked; BEGIN_KV_SERIALIZE_MAP() @@ -991,6 +993,8 @@ namespace wallet_rpc KV_SERIALIZE(tx_hash) KV_SERIALIZE(subaddr_index) KV_SERIALIZE(key_image) + KV_SERIALIZE(block_height) + KV_SERIALIZE(frozen) KV_SERIALIZE(unlocked) END_KV_SERIALIZE_MAP() }; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index bbb0bc051..afc69ee88 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -66,6 +66,7 @@ else () # Emulate the FindGTest module's variable. set(GTEST_LIBRARIES gtest gtest_main) + set(GTEST_BOTH_LIBRARIES gtest gtest_main) include_directories(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/gtest/include") endif (GTest_FOUND) diff --git a/tests/functional_tests/blockchain.py b/tests/functional_tests/blockchain.py index 56164600d..6376b86d0 100755 --- a/tests/functional_tests/blockchain.py +++ b/tests/functional_tests/blockchain.py @@ -45,9 +45,16 @@ from framework.daemon import Daemon class BlockchainTest(): def run_test(self): + self.reset() self._test_generateblocks(5) self._test_alt_chains() + def reset(self): + print 'Resetting blockchain' + daemon = Daemon() + daemon.pop_blocks(1000) + daemon.flush_txpool() + def _test_generateblocks(self, blocks): assert blocks >= 2 diff --git a/tests/functional_tests/cold_signing.py b/tests/functional_tests/cold_signing.py index e5430f87c..59a879e0a 100755 --- a/tests/functional_tests/cold_signing.py +++ b/tests/functional_tests/cold_signing.py @@ -38,10 +38,17 @@ from framework.wallet import Wallet class ColdSigningTest(): def run_test(self): + self.reset() self.create(0) self.mine() self.transfer() + def reset(self): + print 'Resetting blockchain' + daemon = Daemon() + daemon.pop_blocks(1000) + daemon.flush_txpool() + def create(self, idx): print 'Creating hot and cold wallet' diff --git a/tests/functional_tests/functional_tests_rpc.py b/tests/functional_tests/functional_tests_rpc.py index 83b75a088..e754b4e33 100755 --- a/tests/functional_tests/functional_tests_rpc.py +++ b/tests/functional_tests/functional_tests_rpc.py @@ -98,6 +98,7 @@ FAIL = [] for test in tests: try: print('[TEST STARTED] ' + test) + sys.stdout.flush() cmd = [python, srcdir + '/' + test + ".py"] subprocess.check_call(cmd) PASS.append(test) diff --git a/tests/functional_tests/mining.py b/tests/functional_tests/mining.py index 1b189beb2..78dc68640 100755 --- a/tests/functional_tests/mining.py +++ b/tests/functional_tests/mining.py @@ -43,9 +43,16 @@ from framework.wallet import Wallet class MiningTest(): def run_test(self): + self.reset() self.create() self.mine() + def reset(self): + print 'Resetting blockchain' + daemon = Daemon() + daemon.pop_blocks(1000) + daemon.flush_txpool() + def create(self): print 'Creating wallet' wallet = Wallet() diff --git a/tests/functional_tests/multisig.py b/tests/functional_tests/multisig.py index a61f30001..476e3a02d 100755 --- a/tests/functional_tests/multisig.py +++ b/tests/functional_tests/multisig.py @@ -38,6 +38,7 @@ from framework.wallet import Wallet class MultisigTest(): def run_test(self): + self.reset() self.mine('493DsrfJPqiN3Suv9RcRDoZEbQtKZX1sNcGPA3GhkKYEEmivk8kjQrTdRdVc4ZbmzWJuE157z9NNUKmF2VDfdYDR3CziGMk', 5) self.mine('42jSRGmmKN96V2j3B8X2DbiNThBXW1tSi1rW1uwkqbyURenq3eC3yosNm8HEMdHuWwKMFGzMUB3RCTvcTaW9kHpdRPP7p5y', 5) self.mine('47fF32AdrmXG84FcPY697uZdd42pMMGiH5UpiTRTt3YX2pZC7t7wkzEMStEicxbQGRfrYvAAYxH6Fe8rnD56EaNwUgxRd53', 5) @@ -68,6 +69,12 @@ class MultisigTest(): self.import_multisig_info([0, 1, 2, 3], 6) self.check_transaction(txid) + def reset(self): + print 'Resetting blockchain' + daemon = Daemon() + daemon.pop_blocks(1000) + daemon.flush_txpool() + def mine(self, address, blocks): print("Mining some blocks") daemon = Daemon() diff --git a/tests/functional_tests/proofs.py b/tests/functional_tests/proofs.py index 0a0b6304d..844131095 100755 --- a/tests/functional_tests/proofs.py +++ b/tests/functional_tests/proofs.py @@ -38,6 +38,7 @@ from framework.wallet import Wallet class ProofsTest(): def run_test(self): + self.reset() self.mine('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 80) self.create_wallets() txid, tx_key, amount = self.transfer() @@ -45,6 +46,12 @@ class ProofsTest(): self.check_tx_proof(txid, amount) self.check_reserve_proof() + def reset(self): + print 'Resetting blockchain' + daemon = Daemon() + daemon.pop_blocks(1000) + daemon.flush_txpool() + def mine(self, address, blocks): print("Mining some blocks") daemon = Daemon() diff --git a/tests/functional_tests/transfer.py b/tests/functional_tests/transfer.py index bc2f5472b..1ff641d1f 100755 --- a/tests/functional_tests/transfer.py +++ b/tests/functional_tests/transfer.py @@ -39,6 +39,7 @@ from framework.wallet import Wallet class TransferTest(): def run_test(self): + self.reset() self.create() self.mine() self.transfer() @@ -46,6 +47,12 @@ class TransferTest(): self.check_double_spend_detection() self.sweep_single() + def reset(self): + print 'Resetting blockchain' + daemon = Daemon() + daemon.pop_blocks(1000) + daemon.flush_txpool() + def create(self): print 'Creating wallets' seeds = [ diff --git a/tests/functional_tests/txpool.py b/tests/functional_tests/txpool.py index 71109c9e5..d74395f10 100755 --- a/tests/functional_tests/txpool.py +++ b/tests/functional_tests/txpool.py @@ -38,10 +38,17 @@ from framework.wallet import Wallet class TransferTest(): def run_test(self): + self.reset() self.create() self.mine() self.check_txpool() + def reset(self): + print 'Resetting blockchain' + daemon = Daemon() + daemon.pop_blocks(1000) + daemon.flush_txpool() + def create(self): print 'Creating wallet' wallet = Wallet() diff --git a/tests/functional_tests/wallet_address.py b/tests/functional_tests/wallet_address.py index cb9c52e7a..8a55521c6 100755 --- a/tests/functional_tests/wallet_address.py +++ b/tests/functional_tests/wallet_address.py @@ -39,9 +39,11 @@ Test the following RPCs: """ from framework.wallet import Wallet +from framework.daemon import Daemon class WalletAddressTest(): def run_test(self): + self.reset() self.create() self.check_main_address() self.check_keys() @@ -49,6 +51,12 @@ class WalletAddressTest(): self.open_close() self.languages() + def reset(self): + print 'Resetting blockchain' + daemon = Daemon() + daemon.pop_blocks(1000) + daemon.flush_txpool() + def create(self): print 'Creating wallet' wallet = Wallet() diff --git a/tests/unit_tests/logging.cpp b/tests/unit_tests/logging.cpp index 12d49e2fb..056eae604 100644 --- a/tests/unit_tests/logging.cpp +++ b/tests/unit_tests/logging.cpp @@ -44,7 +44,10 @@ static void init() static void cleanup() { + // windows does not let files be deleted if still in use, so leave droppings there +#ifndef _WIN32 boost::filesystem::remove(log_filename); +#endif } static size_t nlines(const std::string &str) diff --git a/tests/unit_tests/output_distribution.cpp b/tests/unit_tests/output_distribution.cpp index 45f2c135b..2f3c78642 100644 --- a/tests/unit_tests/output_distribution.cpp +++ b/tests/unit_tests/output_distribution.cpp @@ -62,6 +62,13 @@ public: return d; } + std::vector<uint64_t> get_block_weights(uint64_t start_offset, size_t count) const override + { + std::vector<uint64_t> weights; + while (count--) weights.push_back(1); + return weights; + } + uint64_t blockchain_height; }; |