diff options
-rw-r--r-- | .github/workflows/depends.yml | 22 | ||||
-rw-r--r-- | CMakeLists.txt | 34 | ||||
-rw-r--r-- | contrib/depends/packages/freebsd_base.mk | 4 | ||||
-rw-r--r-- | contrib/epee/include/net/net_utils_base.h | 3 | ||||
-rw-r--r-- | contrib/epee/src/CMakeLists.txt | 2 | ||||
-rw-r--r-- | contrib/epee/src/net_ssl.cpp | 3 | ||||
-rw-r--r-- | src/common/util.cpp | 8 | ||||
-rw-r--r-- | src/p2p/net_node.inl | 21 | ||||
-rw-r--r-- | src/p2p/net_peerlist.cpp | 12 | ||||
-rw-r--r-- | src/p2p/net_peerlist.h | 26 | ||||
-rw-r--r-- | src/rpc/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/serialization/json_object.cpp | 18 | ||||
-rw-r--r-- | src/wallet/api/wallet.cpp | 10 | ||||
-rw-r--r-- | src/wallet/api/wallet.h | 2 | ||||
-rw-r--r-- | src/wallet/api/wallet2_api.h | 2 | ||||
-rw-r--r-- | src/wallet/wallet2.cpp | 49 | ||||
-rw-r--r-- | tests/unit_tests/epee_boosted_tcp_server.cpp | 6 | ||||
-rw-r--r-- | tests/unit_tests/epee_utils.cpp | 1 | ||||
-rw-r--r-- | tests/unit_tests/node_server.cpp | 10 |
19 files changed, 175 insertions, 60 deletions
diff --git a/.github/workflows/depends.yml b/.github/workflows/depends.yml index 3e0f048c7..8e4eaf177 100644 --- a/.github/workflows/depends.yml +++ b/.github/workflows/depends.yml @@ -45,15 +45,29 @@ jobs: - uses: actions/checkout@v1 with: submodules: recursive +# Most volatile cache - name: ccache uses: actions/cache@v2 with: - path: | - ~/.ccache - contrib/depends/built - contrib/depends/sdk-sources + path: ~/.ccache key: ccache-${{ matrix.toolchain.host }}-${{ github.sha }} restore-keys: ccache-${{ matrix.toolchain.host }}- +# Less volatile cache + - name: depends cache + uses: actions/cache@v2 + with: + path: contrib/depends/built + key: depends-${{ matrix.toolchain.host }}-${{ hashFiles('contrib/depends/packages/*') }} + restore-keys: | + depends-${{ matrix.toolchain.host }}-${{ hashFiles('contrib/depends/packages/*') }} + depends-${{ matrix.toolchain.host }}- +# Static cache + - name: OSX SDK cache + uses: actions/cache@v2 + with: + path: contrib/depends/sdk-sources + key: sdk-${{ matrix.toolchain.host }}-${{ matrix.toolchain.osx_sdk }} + restore-keys: sdk-${{ matrix.toolchain.host }}-${{ matrix.toolchain.osx_sdk }} - name: set apt conf run: | echo "Acquire::Retries \"3\";" | sudo tee -a /etc/apt/apt.conf.d/80-custom diff --git a/CMakeLists.txt b/CMakeLists.txt index 8240a6588..d06729931 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -605,6 +605,23 @@ add_definitions(-DAUTO_INITIALIZE_EASYLOGGINGPP) set(MONERO_GENERATED_HEADERS_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated_include") include_directories(${MONERO_GENERATED_HEADERS_DIR}) +# As of OpenBSD 6.8, -march=<anything> breaks the build +function(set_default_arch) + if (OPENBSD) + set(ARCH default) + else() + set(ARCH native) + endif() + + set(ARCH ${ARCH} CACHE STRING "CPU to build for: -march value or 'default' to not pass -march at all") +endfunction() + +if (NOT (MSVC OR ARCH)) + set_default_arch() +endif() + +CHECK_C_COMPILER_FLAG(-std=c11 HAVE_C11) + option(COVERAGE "Enable profiling for test coverage report" OFF) if(COVERAGE) message(STATUS "Building with profiling for test coverage report") @@ -684,17 +701,6 @@ endif() # Trezor support check include(CheckTrezor) -# As of OpenBSD 6.8, -march=<anything> breaks the build -function(set_default_arch) - if (OPENBSD) - set(ARCH default) - else() - set(ARCH native) - endif() - - set(ARCH ${ARCH} CACHE STRING "CPU to build for: -march value or 'default' to not pass -march at all") -endfunction() - if(MSVC) add_definitions("/bigobj /MP /W3 /GS- /D_CRT_SECURE_NO_WARNINGS /wd4996 /wd4345 /D_WIN32_WINNT=0x0600 /DWIN32_LEAN_AND_MEAN /DGTEST_HAS_TR1_TUPLE=0 /FIinline_c.h /D__SSE4_1__") # set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Dinline=__inline") @@ -707,9 +713,6 @@ if(MSVC) include_directories(SYSTEM src/platform/msc) else() include(TestCXXAcceptsFlag) - if (NOT ARCH) - set_default_arch() - endif() message(STATUS "Building on ${CMAKE_SYSTEM_PROCESSOR} for ${ARCH}") if(ARCH STREQUAL "default") set(ARCH_FLAG "") @@ -1245,9 +1248,6 @@ option(BUILD_GUI_DEPS "Build GUI dependencies." OFF) # on libunbound shipped with their distribution instead option(INSTALL_VENDORED_LIBUNBOUND "Install libunbound binary built from source vendored with this repo." OFF) - -CHECK_C_COMPILER_FLAG(-std=c11 HAVE_C11) - find_package(PythonInterp) find_program(iwyu_tool_path NAMES iwyu_tool.py iwyu_tool) if (iwyu_tool_path AND PYTHONINTERP_FOUND) diff --git a/contrib/depends/packages/freebsd_base.mk b/contrib/depends/packages/freebsd_base.mk index c6a209dcd..ad9975f8d 100644 --- a/contrib/depends/packages/freebsd_base.mk +++ b/contrib/depends/packages/freebsd_base.mk @@ -12,8 +12,8 @@ endef define $(package)_build_cmds mkdir bin &&\ - echo "exec /usr/bin/clang-8 -target x86_64-unknown-freebsd$($(package)_version) --sysroot=$(host_prefix)/native $$$$""@" > bin/clang-8 &&\ - echo "exec /usr/bin/clang++-8 -target x86_64-unknown-freebsd$($(package)_version) --sysroot=$(host_prefix)/native $$$$""@" > bin/clang++-8 &&\ + echo "#!/bin/sh\n\nexec /usr/bin/clang-8 -target x86_64-unknown-freebsd$($(package)_version) --sysroot=$(host_prefix)/native $$$$""@" > bin/clang-8 &&\ + echo "#!/bin/sh\n\nexec /usr/bin/clang++-8 -target x86_64-unknown-freebsd$($(package)_version) --sysroot=$(host_prefix)/native $$$$""@" > bin/clang++-8 &&\ chmod 755 bin/* endef diff --git a/contrib/epee/include/net/net_utils_base.h b/contrib/epee/include/net/net_utils_base.h index d86c62c17..722206ee1 100644 --- a/contrib/epee/include/net/net_utils_base.h +++ b/contrib/epee/include/net/net_utils_base.h @@ -236,6 +236,7 @@ namespace net_utils virtual address_type get_type_id() const = 0; virtual zone get_zone() const = 0; virtual bool is_blockable() const = 0; + virtual std::uint16_t port() const = 0; }; template<typename T> @@ -266,6 +267,7 @@ namespace net_utils virtual address_type get_type_id() const override { return value.get_type_id(); } virtual zone get_zone() const override { return value.get_zone(); } virtual bool is_blockable() const override { return value.is_blockable(); } + virtual std::uint16_t port() const override { return value.port(); } }; std::shared_ptr<interface> self; @@ -312,6 +314,7 @@ namespace net_utils address_type get_type_id() const { return self ? self->get_type_id() : address_type::invalid; } zone get_zone() const { return self ? self->get_zone() : zone::invalid; } bool is_blockable() const { return self ? self->is_blockable() : false; } + std::uint16_t port() const { return self ? self->port() : 0; } template<typename Type> const Type &as() const { return as_mutable<const Type>(); } BEGIN_KV_SERIALIZE_MAP() diff --git a/contrib/epee/src/CMakeLists.txt b/contrib/epee/src/CMakeLists.txt index 3c5eb49e9..07f119ba4 100644 --- a/contrib/epee/src/CMakeLists.txt +++ b/contrib/epee/src/CMakeLists.txt @@ -73,6 +73,7 @@ target_link_libraries(epee ${Boost_FILESYSTEM_LIBRARY} ${Boost_THREAD_LIBRARY} ${Boost_REGEX_LIBRARY} + ${Boost_SYSTEM_LIBRARY} ${OPENSSL_LIBRARIES} PRIVATE ${EXTRA_LIBRARIES}) @@ -81,6 +82,7 @@ if (USE_READLINE AND (GNU_READLINE_FOUND OR (DEPENDS AND NOT MINGW))) target_link_libraries(epee_readline PUBLIC easylogging + ${Boost_SYSTEM_LIBRARY} PRIVATE ${GNU_READLINE_LIBRARY}) endif() diff --git a/contrib/epee/src/net_ssl.cpp b/contrib/epee/src/net_ssl.cpp index 765dadce3..70cd0d0ad 100644 --- a/contrib/epee/src/net_ssl.cpp +++ b/contrib/epee/src/net_ssl.cpp @@ -576,7 +576,8 @@ boost::system::error_code store_ssl_keys(boost::asio::ssl::context& ssl, const b const auto ctx = ssl.native_handle(); CHECK_AND_ASSERT_MES(ctx, boost::system::error_code(EINVAL, boost::system::system_category()), "Context is null"); CHECK_AND_ASSERT_MES(base.has_filename(), boost::system::error_code(EINVAL, boost::system::system_category()), "Need filename"); - if (!(ssl_key = SSL_CTX_get0_privatekey(ctx)) || !(ssl_cert = SSL_CTX_get0_certificate(ctx))) + std::unique_ptr<SSL, decltype(&SSL_free)> dflt_SSL(SSL_new(ctx), SSL_free); + if (!dflt_SSL || !(ssl_key = SSL_get_privatekey(dflt_SSL.get())) || !(ssl_cert = SSL_get_certificate(dflt_SSL.get()))) return {EINVAL, boost::system::system_category()}; using file_closer = int(std::FILE*); diff --git a/src/common/util.cpp b/src/common/util.cpp index 445a11a75..af9843b95 100644 --- a/src/common/util.cpp +++ b/src/common/util.cpp @@ -1355,8 +1355,12 @@ std::string get_nix_version_display_string() 100743, 92152, 57565, 22533, 37564, 21823, 19980, 18277, 18402, 14344, 12142, 15842, 13677, 17631, 18294, 22270, 41422, 39296, 36688, 33512, 33831, 27582, 22276, 27516, 27317, 25505, 24426, 20566, 23045, 26766, - 28185, 26169, 27011, - 28642 // Blocks 1,990,000 to 1,999,999 in December 2019 + 28185, 26169, 27011, 28642, 34994, 34442, 30682, 34357, 31640, 41167, + 41301, 48616, 51075, 55061, 49909, 44606, 47091, 53828, 42520, 39023, + 55245, 56145, 51119, 60398, 71821, 48142, 60310, 56041, 54176, 66220, + 56336, 55248, 56656, 63305, 54029, 77136, 71902, 71618, 83587, 81068, + 69062, 54848, 53681, 53555, + 50616 // Blocks 2,400,000 to 2,409,999 in July 2021 }; const uint64_t block_range_size = 10000; diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index 8dd4b4476..cfeac3d37 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -270,9 +270,17 @@ namespace nodetool peerlist_entry pe{}; pe.adr = addr; - zone.second.m_peerlist.remove_from_peer_white(pe); - zone.second.m_peerlist.remove_from_peer_gray(pe); - zone.second.m_peerlist.remove_from_peer_anchor(addr); + if (addr.port() == 0) + { + zone.second.m_peerlist.evict_host_from_peerlist(true, pe); + zone.second.m_peerlist.evict_host_from_peerlist(false, pe); + } + else + { + zone.second.m_peerlist.remove_from_peer_white(pe); + zone.second.m_peerlist.remove_from_peer_gray(pe); + zone.second.m_peerlist.remove_from_peer_anchor(addr); + } for (const auto &c: conns) zone.second.m_net_server.get_config_object().close(c); @@ -332,6 +340,13 @@ namespace nodetool for (const auto &c: conns) zone.second.m_net_server.get_config_object().close(c); + for (int i = 0; i < 2; ++i) + zone.second.m_peerlist.filter(i == 0, [&subnet](const peerlist_entry &pe){ + if (pe.adr.get_type_id() != epee::net_utils::ipv4_network_address::get_type_id()) + return false; + return subnet.matches(pe.adr.as<const epee::net_utils::ipv4_network_address>()); + }); + conns.clear(); } diff --git a/src/p2p/net_peerlist.cpp b/src/p2p/net_peerlist.cpp index 42ab9727d..50dc6da77 100644 --- a/src/p2p/net_peerlist.cpp +++ b/src/p2p/net_peerlist.cpp @@ -289,17 +289,9 @@ namespace nodetool copy_peers(peers.anchor, m_peers_anchor.get<by_addr>()); } - void peerlist_manager::evict_host_from_white_peerlist(const peerlist_entry& pr) + void peerlist_manager::evict_host_from_peerlist(bool use_white, const peerlist_entry& pr) { - peers_indexed::index<by_time>::type& sorted_index=m_peers_white.get<by_time>(); - auto i = sorted_index.begin(); - while (i != sorted_index.end()) - { - if (i->adr.is_same_host(pr.adr)) - i = sorted_index.erase(i); - else - ++i; - } + filter(use_white, [&pr](const peerlist_entry& pe){ return pe.adr.is_same_host(pr.adr); }); } } diff --git a/src/p2p/net_peerlist.h b/src/p2p/net_peerlist.h index d8de6abe9..0662789b9 100644 --- a/src/p2p/net_peerlist.h +++ b/src/p2p/net_peerlist.h @@ -109,7 +109,7 @@ namespace nodetool bool get_white_peer_by_index(peerlist_entry& p, size_t i); bool get_gray_peer_by_index(peerlist_entry& p, size_t i); template<typename F> bool foreach(bool white, const F &f); - void evict_host_from_white_peerlist(const peerlist_entry& pr); + void evict_host_from_peerlist(bool white, const peerlist_entry& pr); bool append_with_peer_white(const peerlist_entry& pr, bool trust_last_seen = false); bool append_with_peer_gray(const peerlist_entry& pr); bool append_with_peer_anchor(const anchor_peerlist_entry& ple); @@ -120,6 +120,7 @@ namespace nodetool bool get_and_empty_anchor_peerlist(std::vector<anchor_peerlist_entry>& apl); bool remove_from_peer_anchor(const epee::net_utils::network_address& addr); bool remove_from_peer_white(const peerlist_entry& pe); + template<typename F> size_t filter(bool white, const F &f); // f returns true: drop, false: keep private: struct by_time{}; @@ -346,7 +347,7 @@ namespace nodetool if(by_addr_it_wt == m_peers_white.get<by_addr>().end()) { //put new record into white list - evict_host_from_white_peerlist(ple); + evict_host_from_peerlist(true, ple); m_peers_white.insert(ple); trim_white_peerlist(); }else @@ -520,5 +521,26 @@ namespace nodetool CATCH_ENTRY_L0("peerlist_manager::remove_from_peer_anchor()", false); } //-------------------------------------------------------------------------------------------------- + template<typename F> size_t peerlist_manager::filter(bool white, const F &f) + { + size_t filtered = 0; + TRY_ENTRY(); + CRITICAL_REGION_LOCAL(m_peerlist_lock); + peers_indexed::index<by_addr>::type& sorted_index = white ? m_peers_gray.get<by_addr>() : m_peers_white.get<by_addr>(); + auto i = sorted_index.begin(); + while (i != sorted_index.end()) + { + if (f(*i)) + { + i = sorted_index.erase(i); + ++filtered; + } + else + ++i; + } + CATCH_ENTRY_L0("peerlist_manager::filter()", filtered); + return filtered; + } + //-------------------------------------------------------------------------------------------------- } diff --git a/src/rpc/CMakeLists.txt b/src/rpc/CMakeLists.txt index aa4102481..15e433e10 100644 --- a/src/rpc/CMakeLists.txt +++ b/src/rpc/CMakeLists.txt @@ -39,7 +39,7 @@ set(rpc_sources core_rpc_server.cpp rpc_payment.cpp rpc_version_str.cpp - instanciations) + instanciations.cpp) set(daemon_messages_sources message.cpp diff --git a/src/serialization/json_object.cpp b/src/serialization/json_object.cpp index 67f042c2e..28e207ff2 100644 --- a/src/serialization/json_object.cpp +++ b/src/serialization/json_object.cpp @@ -1091,9 +1091,12 @@ void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::rctSig& }; INSERT_INTO_JSON_OBJECT(dest, type, sig.type); - INSERT_INTO_JSON_OBJECT(dest, encrypted, sig.ecdhInfo); - INSERT_INTO_JSON_OBJECT(dest, commitments, transform(sig.outPk, just_mask)); - INSERT_INTO_JSON_OBJECT(dest, fee, sig.txnFee); + if (sig.type != rct::RCTTypeNull) + { + INSERT_INTO_JSON_OBJECT(dest, encrypted, sig.ecdhInfo); + INSERT_INTO_JSON_OBJECT(dest, commitments, transform(sig.outPk, just_mask)); + INSERT_INTO_JSON_OBJECT(dest, fee, sig.txnFee); + } // prunable if (!sig.p.bulletproofs.empty() || !sig.p.rangeSigs.empty() || !sig.p.MGs.empty() || !sig.get_pseudo_outs().empty()) @@ -1122,9 +1125,12 @@ void fromJsonValue(const rapidjson::Value& val, rct::rctSig& sig) } GET_FROM_JSON_OBJECT(val, sig.type, type); - GET_FROM_JSON_OBJECT(val, sig.ecdhInfo, encrypted); - GET_FROM_JSON_OBJECT(val, sig.outPk, commitments); - GET_FROM_JSON_OBJECT(val, sig.txnFee, fee); + if (sig.type != rct::RCTTypeNull) + { + GET_FROM_JSON_OBJECT(val, sig.ecdhInfo, encrypted); + GET_FROM_JSON_OBJECT(val, sig.outPk, commitments); + GET_FROM_JSON_OBJECT(val, sig.txnFee, fee); + } // prunable const auto prunable = val.FindMember("prunable"); diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index b4fa1ea8c..0afbda705 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -2365,6 +2365,11 @@ bool WalletImpl::parse_uri(const std::string &uri, std::string &address, std::st return m_wallet->parse_uri(uri, address, payment_id, amount, tx_description, recipient_name, unknown_parameters, error); } +std::string WalletImpl::make_uri(const std::string &address, const std::string &payment_id, uint64_t amount, const std::string &tx_description, const std::string &recipient_name, std::string &error) const +{ + return m_wallet->make_uri(address, payment_id, amount, tx_description, recipient_name, error); +} + std::string WalletImpl::getDefaultDataDir() const { return tools::get_default_data_dir(); @@ -2392,6 +2397,11 @@ void WalletImpl::setOffline(bool offline) m_wallet->set_offline(offline); } +bool WalletImpl::isOffline() const +{ + return m_wallet->is_offline(); +} + void WalletImpl::hardForkInfo(uint8_t &version, uint64_t &earliest_height) const { m_wallet->get_hard_fork_info(version, earliest_height); diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h index 217f16e48..67fc2c08a 100644 --- a/src/wallet/api/wallet.h +++ b/src/wallet/api/wallet.h @@ -186,6 +186,7 @@ public: virtual std::string getCacheAttribute(const std::string &key) const override; virtual void setOffline(bool offline) override; + virtual bool isOffline() const override; virtual bool setUserNote(const std::string &txid, const std::string ¬e) override; virtual std::string getUserNote(const std::string &txid) const override; @@ -204,6 +205,7 @@ public: virtual void startRefresh() override; virtual void pauseRefresh() override; virtual bool parse_uri(const std::string &uri, std::string &address, std::string &payment_id, uint64_t &amount, std::string &tx_description, std::string &recipient_name, std::vector<std::string> &unknown_parameters, std::string &error) override; + virtual std::string make_uri(const std::string &address, const std::string &payment_id, uint64_t amount, const std::string &tx_description, const std::string &recipient_name, std::string &error) const override; virtual std::string getDefaultDataDir() const override; virtual bool lightWalletLogin(bool &isNewWallet) const override; virtual bool lightWalletImportWalletRequest(std::string &payment_id, uint64_t &fee, bool &new_request, bool &request_fulfilled, std::string &payment_address, std::string &status) override; diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h index a08033033..f9c421a93 100644 --- a/src/wallet/api/wallet2_api.h +++ b/src/wallet/api/wallet2_api.h @@ -1020,6 +1020,7 @@ struct Wallet virtual bool verifyMessageWithPublicKey(const std::string &message, const std::string &publicKey, const std::string &signature) const = 0; virtual bool parse_uri(const std::string &uri, std::string &address, std::string &payment_id, uint64_t &amount, std::string &tx_description, std::string &recipient_name, std::vector<std::string> &unknown_parameters, std::string &error) = 0; + virtual std::string make_uri(const std::string &address, const std::string &payment_id, uint64_t amount, const std::string &tx_description, const std::string &recipient_name, std::string &error) const = 0; virtual std::string getDefaultDataDir() const = 0; @@ -1034,6 +1035,7 @@ struct Wallet * \param offline - true/false */ virtual void setOffline(bool offline) = 0; + virtual bool isOffline() const = 0; //! blackballs a set of outputs virtual bool blackballOutputs(const std::vector<std::string> &outputs, bool add) = 0; diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 721a7faf8..6e8d585dc 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -144,6 +144,9 @@ using namespace cryptonote; #define IGNORE_LONG_PAYMENT_ID_FROM_BLOCK_VERSION 12 +#define DEFAULT_UNLOCK_TIME (CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE * DIFFICULTY_TARGET_V2) +#define RECENT_SPEND_WINDOW (50 * DIFFICULTY_TARGET_V2) + static const std::string MULTISIG_SIGNATURE_MAGIC = "SigMultisigPkV1"; static const std::string MULTISIG_EXTRA_INFO_MAGIC = "MultisigxV1"; @@ -1019,7 +1022,13 @@ gamma_picker::gamma_picker(const std::vector<uint64_t> &rct_offsets, double shap end = rct_offsets.data() + rct_offsets.size() - CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE; num_rct_outputs = *(end - 1); THROW_WALLET_EXCEPTION_IF(num_rct_outputs == 0, error::wallet_internal_error, "No rct outputs"); + THROW_WALLET_EXCEPTION_IF(outputs_to_consider == 0, error::wallet_internal_error, "No rct outputs to consider"); average_output_time = DIFFICULTY_TARGET_V2 * blocks_to_consider / outputs_to_consider; // this assumes constant target over the whole rct range + if (average_output_time == 0) { + // TODO: apply this to all cases; do so alongside a hard fork, where all clients will update at the same time, preventing anonymity puddle formation + average_output_time = DIFFICULTY_TARGET_V2 * blocks_to_consider / static_cast<double>(outputs_to_consider); + } + THROW_WALLET_EXCEPTION_IF(average_output_time == 0, error::wallet_internal_error, "Average seconds per output cannot be 0."); }; gamma_picker::gamma_picker(const std::vector<uint64_t> &rct_offsets): gamma_picker(rct_offsets, GAMMA_SHAPE, GAMMA_SCALE) {} @@ -1028,6 +1037,34 @@ uint64_t gamma_picker::pick() { double x = gamma(engine); x = exp(x); + + if (x > DEFAULT_UNLOCK_TIME) + { + // We are trying to select an output from the chain that appeared 'x' seconds before the + // current chain tip, where 'x' is selected from the gamma distribution recommended in Miller et al. + // (https://arxiv.org/pdf/1704.04299/). + // Our method is to get the average time delta between outputs in the recent past, estimate the number of + // outputs 'n' that would have appeared between 'chain_tip - x' and 'chain_tip', select the real output at + // 'current_num_outputs - n', then randomly select an output from the block where that output appears. + // Source code to paper: https://github.com/maltemoeser/moneropaper + // + // Due to the 'default spendable age' mechanic in Monero, 'current_num_outputs' only contains + // currently *unlocked* outputs, which means the earliest output that can be selected is not at the chain tip! + // Therefore, we must offset 'x' so it matches up with the timing of the outputs being considered. We do + // this by saying if 'x` equals the expected age of the first unlocked output (compared to the current + // chain tip - i.e. DEFAULT_UNLOCK_TIME), then select the first unlocked output. + x -= DEFAULT_UNLOCK_TIME; + } + else + { + // If the spent time suggested by the gamma is less than the unlock time, that means the gamma is suggesting an output + // that is no longer feasible to be spent (possible since the gamma was constructed when consensus rules did not enforce the + // lock time). The assumption made in this code is that an output expected spent quicker than the unlock time would likely + // be spent within RECENT_SPEND_WINDOW after allowed. So it returns an output that falls between 0 and the RECENT_SPEND_WINDOW. + // The RECENT_SPEND_WINDOW was determined with empirical analysis of observed data. + x = crypto::rand_idx(static_cast<uint64_t>(RECENT_SPEND_WINDOW)); + } + uint64_t output_index = x / average_output_time; if (output_index >= num_rct_outputs) return std::numeric_limits<uint64_t>::max(); // bad pick @@ -1213,6 +1250,7 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended, std wallet2::~wallet2() { + deinit(); } bool wallet2::has_testnet_option(const boost::program_options::variables_map& vm) @@ -3748,9 +3786,11 @@ void wallet2::detach_blockchain(uint64_t height, std::map<std::pair<uint64_t, ui //---------------------------------------------------------------------------------------------------- bool wallet2::deinit() { - m_is_initialized=false; - unlock_keys_file(); - m_account.deinit(); + if(m_is_initialized) { + m_is_initialized = false; + unlock_keys_file(); + m_account.deinit(); + } return true; } //---------------------------------------------------------------------------------------------------- @@ -8656,7 +8696,8 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>> if (req.outputs[i].index == td.m_global_output_index) if (daemon_resp.outs[i].key == boost::get<txout_to_key>(td.m_tx.vout[td.m_internal_output_index].target).key) if (daemon_resp.outs[i].mask == mask) - real_out_found = true; + if (daemon_resp.outs[i].unlocked) + real_out_found = true; } THROW_WALLET_EXCEPTION_IF(!real_out_found, error::wallet_internal_error, "Daemon response did not include the requested real output"); diff --git a/tests/unit_tests/epee_boosted_tcp_server.cpp b/tests/unit_tests/epee_boosted_tcp_server.cpp index d10b2bb33..992122dd2 100644 --- a/tests/unit_tests/epee_boosted_tcp_server.cpp +++ b/tests/unit_tests/epee_boosted_tcp_server.cpp @@ -111,8 +111,7 @@ TEST(boosted_tcp_server, worker_threads_are_exception_resistant) { boost::unique_lock<boost::mutex> lock(mtx); - ASSERT_NE(boost::cv_status::timeout, cond.wait_for(lock, boost::chrono::seconds(5))); - ASSERT_EQ(4, counter); + ASSERT_TRUE(cond.wait_for(lock, boost::chrono::seconds(5), [&counter]{ return counter == 4; })); } // Check if threads are alive @@ -125,8 +124,7 @@ TEST(boosted_tcp_server, worker_threads_are_exception_resistant) { boost::unique_lock<boost::mutex> lock(mtx); - ASSERT_NE(boost::cv_status::timeout, cond.wait_for(lock, boost::chrono::seconds(5))); - ASSERT_EQ(4, counter); + ASSERT_TRUE(cond.wait_for(lock, boost::chrono::seconds(5), [&counter]{ return counter == 4; })); } srv.send_stop_signal(); diff --git a/tests/unit_tests/epee_utils.cpp b/tests/unit_tests/epee_utils.cpp index cbe3c61b1..b83a809b7 100644 --- a/tests/unit_tests/epee_utils.cpp +++ b/tests/unit_tests/epee_utils.cpp @@ -1512,6 +1512,7 @@ TEST(NetUtils, NetworkAddress) constexpr static epee::net_utils::address_type get_type_id() noexcept { return epee::net_utils::address_type(-1); } constexpr static epee::net_utils::zone get_zone() noexcept { return epee::net_utils::zone::invalid; } constexpr static bool is_blockable() noexcept { return false; } + constexpr static uint16_t port() { return 0; } }; const epee::net_utils::network_address empty; diff --git a/tests/unit_tests/node_server.cpp b/tests/unit_tests/node_server.cpp index 2c80acda5..cab600b3d 100644 --- a/tests/unit_tests/node_server.cpp +++ b/tests/unit_tests/node_server.cpp @@ -795,9 +795,11 @@ TEST(cryptonote_protocol_handler, race_condition) workers_t workers; } check; check.work = std::make_shared<work_t>(check.io_context); - check.workers.emplace_back([&check]{ - check.io_context.run(); - }); + while (check.workers.size() < 2) { + check.workers.emplace_back([&check]{ + check.io_context.run(); + }); + } while (daemon.main.conn.size() < 1) { daemon.main.conn.emplace_back(new connection_t(check.io_context, daemon.main.shared_state, {}, {})); daemon.alt.conn.emplace_back(new connection_t(io_context, daemon.alt.shared_state, {}, {})); @@ -856,7 +858,7 @@ TEST(cryptonote_protocol_handler, race_condition) } } while (daemon.main.conn.size() < 2) { - daemon.main.conn.emplace_back(new connection_t(io_context, daemon.main.shared_state, {}, {})); + daemon.main.conn.emplace_back(new connection_t(check.io_context, daemon.main.shared_state, {}, {})); daemon.alt.conn.emplace_back(new connection_t(io_context, daemon.alt.shared_state, {}, {})); create_conn_pair(daemon.main.conn.back(), daemon.alt.conn.back()); conduct_handshake(daemon.alt.net_node, daemon.alt.conn.back()); |