aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/depends.yml22
-rw-r--r--CMakeLists.txt34
-rw-r--r--contrib/depends/packages/freebsd_base.mk4
-rw-r--r--contrib/epee/include/net/net_utils_base.h3
-rw-r--r--contrib/epee/src/CMakeLists.txt2
-rw-r--r--contrib/epee/src/net_ssl.cpp3
-rw-r--r--src/common/util.cpp8
-rw-r--r--src/p2p/net_node.inl21
-rw-r--r--src/p2p/net_peerlist.cpp12
-rw-r--r--src/p2p/net_peerlist.h26
-rw-r--r--src/rpc/CMakeLists.txt2
-rw-r--r--src/serialization/json_object.cpp18
-rw-r--r--src/wallet/api/wallet.cpp10
-rw-r--r--src/wallet/api/wallet.h2
-rw-r--r--src/wallet/api/wallet2_api.h2
-rw-r--r--src/wallet/wallet2.cpp49
-rw-r--r--tests/unit_tests/epee_boosted_tcp_server.cpp6
-rw-r--r--tests/unit_tests/epee_utils.cpp1
-rw-r--r--tests/unit_tests/node_server.cpp10
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 &note) 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());