aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--.github/workflows/build.yml1
-rw-r--r--CMakeLists.txt6
-rw-r--r--README.md14
-rw-r--r--cmake/FindLibUSB.cmake2
-rw-r--r--contrib/depends/funcs.mk5
-rw-r--r--contrib/depends/packages/hidapi.mk6
-rw-r--r--contrib/depends/packages/libusb.mk6
-rw-r--r--contrib/depends/packages/openssl.mk8
-rw-r--r--contrib/depends/patches/openssl/fix_darwin.patch60
-rw-r--r--contrib/epee/include/net/abstract_http_client.h1
-rw-r--r--contrib/epee/include/net/http_base.h12
-rw-r--r--contrib/epee/include/net/http_client.h52
-rw-r--r--contrib/epee/src/CMakeLists.txt1
-rw-r--r--contrib/epee/src/http_base.cpp71
-rw-r--r--contrib/epee/src/mlog.cpp13
-rw-r--r--contrib/epee/src/readline_buffer.cpp4
-rw-r--r--external/easylogging++/easylogging++.cc5
-rw-r--r--src/blockchain_utilities/blockchain_stats.cpp157
-rw-r--r--src/common/data_cache.h65
-rw-r--r--src/common/dns_utils.cpp17
-rw-r--r--src/common/dns_utils.h9
-rw-r--r--src/common/threadpool.h1
-rw-r--r--src/crypto/c_threads.h40
-rw-r--r--src/crypto/crypto-ops.c5
-rw-r--r--src/crypto/crypto-ops.h4
-rw-r--r--src/crypto/crypto.h8
-rw-r--r--src/crypto/hash-ops.h8
-rw-r--r--src/crypto/rx-slow-hash.c524
-rw-r--r--src/cryptonote_basic/miner.cpp5
-rw-r--r--src/cryptonote_core/blockchain.cpp45
-rw-r--r--src/cryptonote_core/blockchain.h4
-rw-r--r--src/cryptonote_core/cryptonote_tx_utils.cpp26
-rw-r--r--src/cryptonote_core/cryptonote_tx_utils.h12
-rw-r--r--src/cryptonote_core/tx_pool.cpp1
-rw-r--r--src/daemonizer/windows_service.cpp2
-rw-r--r--src/daemonizer/windows_service_runner.h3
-rw-r--r--src/net/parse.cpp8
-rw-r--r--src/net/parse.h10
-rw-r--r--src/p2p/net_node.inl38
-rw-r--r--src/ringct/rctOps.cpp6
-rw-r--r--src/ringct/rctOps.h1
-rw-r--r--src/ringct/rctSigs.cpp37
-rw-r--r--src/ringct/rctSigs.h1
-rw-r--r--src/rpc/core_rpc_server.cpp12
-rw-r--r--src/rpc/rpc_payment.cpp4
-rw-r--r--src/wallet/wallet2.cpp3
-rw-r--r--src/wallet/wallet_rpc_payments.cpp3
-rw-r--r--tests/core_tests/chaingen.h2
-rw-r--r--tests/core_tests/chaingen_serialization.h (renamed from src/common/boost_serialization_helper.h)0
-rw-r--r--tests/unit_tests/dns_resolver.cpp11
-rw-r--r--tests/unit_tests/net.cpp35
-rw-r--r--utils/gpg_keys/moneromooo.asc26
52 files changed, 774 insertions, 626 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 7cdd2d4e2..1f8e39903 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -158,6 +158,7 @@ jobs:
- name: tests
env:
CTEST_OUTPUT_ON_FAILURE: ON
+ DNS_PUBLIC: tcp://9.9.9.9
run: |
${{env.CCACHE_SETTINGS}}
${{env.BUILD_DEFAULT_LINUX}}
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c0846280c..8c088f26d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -791,7 +791,7 @@ else()
set(USE_LTO_DEFAULT false)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--stack,10485760")
if(NOT BUILD_64)
- add_definitions(-DWINVER=0x0501 -D_WIN32_WINNT=0x0501)
+ add_definitions(-DWINVER=0x0600 -D_WIN32_WINNT=0x0600)
endif()
endif()
set(C_WARNINGS "-Waggregate-return -Wnested-externs -Wold-style-definition -Wstrict-prototypes")
@@ -1136,7 +1136,9 @@ if (HIDAPI_FOUND OR LibUSB_COMPILE_TEST_PASSED)
endif()
endif()
-option(USE_READLINE "Build with GNU readline support." ON)
+if(NOT OPENBSD)
+ option(USE_READLINE "Build with GNU readline support." ON)
+endif()
if(USE_READLINE AND NOT DEPENDS)
find_package(Readline)
if(READLINE_FOUND AND GNU_READLINE_FOUND)
diff --git a/README.md b/README.md
index 0249c084a..508d822d8 100644
--- a/README.md
+++ b/README.md
@@ -140,8 +140,8 @@ Dates are provided in the format YYYY-MM-DD. The "Minimum" is the software versi
| 1978433 | 2019-11-30 | v12 | v0.15.0.0 | v0.16.0.0 | New PoW based on RandomX, only allow >= 2 outputs, change to the block median used to calculate penalty, v1 coinbases are forbidden, rct sigs in coinbase forbidden, 10 block lock time for incoming outputs
| 2210000 | 2020-10-17 | v13 | v0.17.0.0 | v0.17.3.2 | New CLSAG transaction format
| 2210720 | 2020-10-18 | v14 | v0.17.1.1 | v0.17.3.2 | forbid old MLSAG transaction format
-| 2688888 | 2022-08-13 | v15 | v0.18.0.0 | v0.18.0.0 | ringsize = 16, bulletproofs+, view tags, adjusted dynamic block weight algorithm
-| 2689608 | 2022-08-14 | v16 | v0.18.0.0 | v0.18.0.0 | forbid old v14 transaction format
+| 2688888 | 2022-08-13 | v15 | v0.18.0.0 | v0.18.1.2 | ringsize = 16, bulletproofs+, view tags, adjusted dynamic block weight algorithm
+| 2689608 | 2022-08-14 | v16 | v0.18.0.0 | v0.18.1.2 | forbid old v14 transaction format
| XXXXXXX | XXX-XX-XX | XXX | vX.XX.X.X | vX.XX.X.X | XXX |
X's indicate that these details have not been determined as of commit date.
@@ -346,7 +346,7 @@ Tested on a Raspberry Pi Zero with a clean install of minimal Raspbian Stretch (
```bash
git clone https://github.com/monero-project/monero.git
cd monero
- git checkout v0.18.0.0
+ git checkout v0.18.1.2
```
* Build:
@@ -465,10 +465,10 @@ application.
cd monero
```
-* If you would like a specific [version/tag](https://github.com/monero-project/monero/tags), do a git checkout for that version. eg. 'v0.18.0.0'. If you don't care about the version and just want binaries from master, skip this step:
+* If you would like a specific [version/tag](https://github.com/monero-project/monero/tags), do a git checkout for that version. eg. 'v0.18.1.2'. If you don't care about the version and just want binaries from master, skip this step:
```bash
- git checkout v0.18.0.0
+ git checkout v0.18.1.2
```
* If you are on a 64-bit system, run:
@@ -511,9 +511,9 @@ Monero is also available as a port or package as `monero-cli`.
You will need to add a few packages to your system. `pkg_add cmake gmake zeromq libiconv boost`.
The `doxygen` and `graphviz` packages are optional and require the xbase set.
-Running the test suite also requires `py-requests` package.
+Running the test suite also requires `py3-requests` package.
-Build monero: `env DEVELOPER_LOCAL_TOOLS=1 BOOST_ROOT=/usr/local gmake release-static`
+Build monero: `gmake`
Note: you may encounter the following error when compiling the latest version of Monero as a normal user:
diff --git a/cmake/FindLibUSB.cmake b/cmake/FindLibUSB.cmake
index 7f8a11460..f780628f8 100644
--- a/cmake/FindLibUSB.cmake
+++ b/cmake/FindLibUSB.cmake
@@ -113,7 +113,7 @@ if ( LibUSB_FOUND )
if (APPLE OR LibUSB_VERSION_1.0.16 OR STATIC)
if (APPLE)
if(DEPENDS)
- list(APPEND TEST_COMPILE_EXTRA_LIBRARIES "-framework Foundation -framework IOKit")
+ list(APPEND TEST_COMPILE_EXTRA_LIBRARIES "-framework Foundation -framework IOKit -framework Security")
else()
find_library(COREFOUNDATION CoreFoundation)
find_library(IOKIT IOKit)
diff --git a/contrib/depends/funcs.mk b/contrib/depends/funcs.mk
index 804125990..66555aad7 100644
--- a/contrib/depends/funcs.mk
+++ b/contrib/depends/funcs.mk
@@ -143,8 +143,11 @@ $(1)_config_env+=PKG_CONFIG_PATH=$($($(1)_type)_prefix)/share/pkgconfig
$(1)_config_env+=PATH="$(build_prefix)/bin:$(PATH)"
$(1)_build_env+=PATH="$(build_prefix)/bin:$(PATH)"
$(1)_stage_env+=PATH="$(build_prefix)/bin:$(PATH)"
-$(1)_autoconf=./configure --host=$($($(1)_type)_host) --disable-dependency-tracking --prefix=$($($(1)_type)_prefix) $$($(1)_config_opts) CC="$$($(1)_cc)" CXX="$$($(1)_cxx)"
+$(1)_autoconf=./configure --host=$($($(1)_type)_host) --prefix=$($($(1)_type)_prefix) $$($(1)_config_opts) CC="$$($(1)_cc)" CXX="$$($(1)_cxx)"
+ifneq ($(1),libusb)
+$(1)_autoconf += --disable-dependency-tracking
+endif
ifneq ($($(1)_nm),)
$(1)_autoconf += NM="$$($(1)_nm)"
endif
diff --git a/contrib/depends/packages/hidapi.mk b/contrib/depends/packages/hidapi.mk
index 97e204f17..64935a36a 100644
--- a/contrib/depends/packages/hidapi.mk
+++ b/contrib/depends/packages/hidapi.mk
@@ -1,8 +1,8 @@
package=hidapi
-$(package)_version=0.11.0
-$(package)_download_path=https://github.com/libusb/hidapi/archive
+$(package)_version=0.13.1
+$(package)_download_path=https://github.com/libusb/hidapi/archive/refs/tags
$(package)_file_name=$(package)-$($(package)_version).tar.gz
-$(package)_sha256_hash=391d8e52f2d6a5cf76e2b0c079cfefe25497ba1d4659131297081fc0cd744632
+$(package)_sha256_hash=476a2c9a4dc7d1fc97dd223b84338dbea3809a84caea2dcd887d9778725490e3
$(package)_linux_dependencies=libusb eudev
$(package)_patches=missing_win_include.patch
diff --git a/contrib/depends/packages/libusb.mk b/contrib/depends/packages/libusb.mk
index 348c410a7..c1d9fe6a9 100644
--- a/contrib/depends/packages/libusb.mk
+++ b/contrib/depends/packages/libusb.mk
@@ -1,8 +1,8 @@
package=libusb
-$(package)_version=1.0.22
-$(package)_download_path=https://sourceforge.net/projects/libusb/files/libusb-1.0/libusb-$($(package)_version)/
+$(package)_version=1.0.26
+$(package)_download_path=https://github.com/libusb/libusb/releases/download/v$($(package)_version)
$(package)_file_name=$(package)-$($(package)_version).tar.bz2
-$(package)_sha256_hash=75aeb9d59a4fdb800d329a545c2e6799f732362193b465ea198f2aa275518157
+$(package)_sha256_hash=12ce7a61fc9854d1d2a1ffe095f7b5fac19ddba095c259e6067a46500381b5a5
define $(package)_preprocess_cmds
autoreconf -i
diff --git a/contrib/depends/packages/openssl.mk b/contrib/depends/packages/openssl.mk
index 0d8478d49..990b85093 100644
--- a/contrib/depends/packages/openssl.mk
+++ b/contrib/depends/packages/openssl.mk
@@ -1,9 +1,8 @@
package=openssl
-$(package)_version=1.1.1l
+$(package)_version=1.1.1t
$(package)_download_path=https://www.openssl.org/source
$(package)_file_name=$(package)-$($(package)_version).tar.gz
-$(package)_sha256_hash=0b7a3e5e59c34827fe0c3a74b7ec8baef302b98fa80088d7f9153aa16fa76bd1
-$(package)_patches=fix_darwin.patch
+$(package)_sha256_hash=8dee9b24bdb1dcbf0c3d1e9b02fb8f6bf22165e807f45adeb7c9677536859d3b
define $(package)_set_vars
$(package)_config_env=AR="$($(package)_ar)" ARFLAGS=$($(package)_arflags) RANLIB="$($(package)_ranlib)" CC="$($(package)_cc)"
@@ -50,8 +49,7 @@ $(package)_config_opts_x86_64_freebsd=BSD-x86_64
endef
define $(package)_preprocess_cmds
- sed -i.old 's|"engines", "apps", "test", "util", "tools", "fuzz"|"engines", "tools"|' Configure && \
- patch -p1 < $($(package)_patch_dir)/fix_darwin.patch
+ sed -i.old 's|"engines", "apps", "test", "util", "tools", "fuzz"|"engines", "tools"|' Configure
endef
define $(package)_config_cmds
diff --git a/contrib/depends/patches/openssl/fix_darwin.patch b/contrib/depends/patches/openssl/fix_darwin.patch
deleted file mode 100644
index a917daa12..000000000
--- a/contrib/depends/patches/openssl/fix_darwin.patch
+++ /dev/null
@@ -1,60 +0,0 @@
-From 96ac8f13f4d0ee96baf5724d9f96c44c34b8606c Mon Sep 17 00:00:00 2001
-From: David Carlier <devnexen@gmail.com>
-Date: Tue, 24 Aug 2021 22:40:14 +0100
-Subject: [PATCH] Darwin platform allows to build on releases before
- Yosemite/ios 8.
-
-issue #16407 #16408
-
-Reviewed-by: Paul Dale <pauli@openssl.org>
-Reviewed-by: Tomas Mraz <tomas@openssl.org>
-(Merged from https://github.com/openssl/openssl/pull/16409)
----
- crypto/rand/rand_unix.c | 5 +----
- include/crypto/rand.h | 10 ++++++++++
- 2 files changed, 11 insertions(+), 4 deletions(-)
-
-diff --git a/crypto/rand/rand_unix.c b/crypto/rand/rand_unix.c
-index 43f1069d151d..0f4525106af7 100644
---- a/crypto/rand/rand_unix.c
-+++ b/crypto/rand/rand_unix.c
-@@ -34,9 +34,6 @@
- #if defined(__OpenBSD__)
- # include <sys/param.h>
- #endif
--#if defined(__APPLE__)
--# include <CommonCrypto/CommonRandom.h>
--#endif
-
- #if defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__)
- # include <sys/types.h>
-@@ -381,7 +378,7 @@ static ssize_t syscall_random(void *buf, size_t buflen)
- if (errno != ENOSYS)
- return -1;
- }
--# elif defined(__APPLE__)
-+# elif defined(OPENSSL_APPLE_CRYPTO_RANDOM)
- if (CCRandomGenerateBytes(buf, buflen) == kCCSuccess)
- return (ssize_t)buflen;
-
-diff --git a/include/crypto/rand.h b/include/crypto/rand.h
-index 5350d3a93119..674f840fd13c 100644
---- a/include/crypto/rand.h
-+++ b/include/crypto/rand.h
-@@ -20,6 +20,16 @@
-
- # include <openssl/rand.h>
-
-+# if defined(__APPLE__) && !defined(OPENSSL_NO_APPLE_CRYPTO_RANDOM)
-+# include <Availability.h>
-+# if (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000) || \
-+ (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 80000)
-+# define OPENSSL_APPLE_CRYPTO_RANDOM 1
-+# include <CommonCrypto/CommonCryptoError.h>
-+# include <CommonCrypto/CommonRandom.h>
-+# endif
-+# endif
-+
- /* forward declaration */
- typedef struct rand_pool_st RAND_POOL;
-
diff --git a/contrib/epee/include/net/abstract_http_client.h b/contrib/epee/include/net/abstract_http_client.h
index 5270824e1..46b3747cd 100644
--- a/contrib/epee/include/net/abstract_http_client.h
+++ b/contrib/epee/include/net/abstract_http_client.h
@@ -72,7 +72,6 @@ namespace http
virtual bool is_connected(bool *ssl = NULL) = 0;
virtual bool invoke(const boost::string_ref uri, const boost::string_ref method, const boost::string_ref body, std::chrono::milliseconds timeout, const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list()) = 0;
virtual bool invoke_get(const boost::string_ref uri, std::chrono::milliseconds timeout, const std::string& body = std::string(), const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list()) = 0;
- virtual bool invoke_post(const boost::string_ref uri, const std::string& body, std::chrono::milliseconds timeout, const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list()) = 0;
virtual uint64_t get_bytes_sent() const = 0;
virtual uint64_t get_bytes_received() const = 0;
};
diff --git a/contrib/epee/include/net/http_base.h b/contrib/epee/include/net/http_base.h
index 4af4da790..15fd30bf3 100644
--- a/contrib/epee/include/net/http_base.h
+++ b/contrib/epee/include/net/http_base.h
@@ -55,20 +55,8 @@ namespace net_utils
http_method_unknown
};
- enum http_content_type
- {
- http_content_type_text_html,
- http_content_type_image_gif,
- http_content_type_other,
- http_content_type_not_set
- };
-
typedef std::list<std::pair<std::string, std::string> > fields_list;
- std::string get_value_from_fields_list(const std::string& param_name, const net_utils::http::fields_list& fields);
-
- std::string get_value_from_uri_line(const std::string& param_name, const std::string& uri);
-
static inline void add_field(std::string& out, const boost::string_ref name, const boost::string_ref value)
{
out.append(name.data(), name.size()).append(": ");
diff --git a/contrib/epee/include/net/http_client.h b/contrib/epee/include/net/http_client.h
index 9ce30b620..8cee399cb 100644
--- a/contrib/epee/include/net/http_client.h
+++ b/contrib/epee/include/net/http_client.h
@@ -32,7 +32,6 @@
#include <boost/regex.hpp>
#include <boost/optional/optional.hpp>
#include <boost/utility/string_ref.hpp>
-//#include <mbstring.h>
#include <algorithm>
#include <cctype>
#include <functional>
@@ -48,57 +47,13 @@
#include "net_parse_helpers.h"
#include "syncobj.h"
-//#include "shlwapi.h"
-
-//#pragma comment(lib, "shlwapi.lib")
-
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "net.http"
-extern epee::critical_section gregexp_lock;
-
-
namespace epee
{
namespace net_utils
{
-
- /*struct url
- {
- public:
- void parse(const std::string& url_s)
- {
- const string prot_end("://");
- string::const_iterator prot_i = search(url_s.begin(), url_s.end(),
- prot_end.begin(), prot_end.end());
- protocol_.reserve(distance(url_s.begin(), prot_i));
- transform(url_s.begin(), prot_i,
- back_inserter(protocol_),
- ptr_fun<int,int>(tolower)); // protocol is icase
- if( prot_i == url_s.end() )
- return;
- advance(prot_i, prot_end.length());
- string::const_iterator path_i = find(prot_i, url_s.end(), '/');
- host_.reserve(distance(prot_i, path_i));
- transform(prot_i, path_i,
- back_inserter(host_),
- ptr_fun<int,int>(tolower)); // host is icase
- string::const_iterator query_i = find(path_i, url_s.end(), '?');
- path_.assign(path_i, query_i);
- if( query_i != url_s.end() )
- ++query_i;
- query_.assign(query_i, url_s.end());
- }
-
- std::string protocol_;
- std::string host_;
- std::string path_;
- std::string query_;
- };*/
-
-
-
-
//---------------------------------------------------------------------------
namespace http
{
@@ -135,7 +90,6 @@ namespace net_utils
http_response_info m_response_info;
size_t m_len_in_summary;
size_t m_len_in_remain;
- //std::string* m_ptarget_buffer;
boost::shared_ptr<i_sub_handler> m_pcontent_encoding_handler;
reciev_machine_state m_state;
chunked_state m_chunked_state;
@@ -300,12 +254,6 @@ namespace net_utils
return false;
}
//---------------------------------------------------------------------------
- inline bool invoke_post(const boost::string_ref uri, const std::string& body, std::chrono::milliseconds timeout, const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list()) override
- {
- CRITICAL_REGION_LOCAL(m_lock);
- return invoke(uri, "POST", body, timeout, ppresponse_info, additional_params);
- }
- //---------------------------------------------------------------------------
bool test(const std::string &s, std::chrono::milliseconds timeout) // TEST FUNC ONLY
{
CRITICAL_REGION_LOCAL(m_lock);
diff --git a/contrib/epee/src/CMakeLists.txt b/contrib/epee/src/CMakeLists.txt
index 808b9f09e..4e920f39c 100644
--- a/contrib/epee/src/CMakeLists.txt
+++ b/contrib/epee/src/CMakeLists.txt
@@ -37,7 +37,6 @@ monero_add_library(epee byte_slice.cpp byte_stream.cpp hex.cpp abstract_http_cli
misc_language.cpp
file_io_utils.cpp
net_parse_helpers.cpp
- http_base.cpp
${EPEE_HEADERS_PUBLIC}
)
diff --git a/contrib/epee/src/http_base.cpp b/contrib/epee/src/http_base.cpp
deleted file mode 100644
index f6d7568c5..000000000
--- a/contrib/epee/src/http_base.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution.
-// * Neither the name of the Andrey N. Sabelnikov nor the
-// names of its contributors may be used to endorse or promote products
-// derived from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
-// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-
-#include "net/http_base.h"
-#include "memwipe.h"
-#include "string_tools.h"
-
-#include <boost/regex.hpp>
-#include <string>
-#include <utility>
-
-#undef MONERO_DEFAULT_LOG_CATEGORY
-#define MONERO_DEFAULT_LOG_CATEGORY "net.http"
-
-namespace epee
-{
-namespace net_utils
-{
-namespace http
-{
- std::string get_value_from_fields_list(const std::string& param_name, const net_utils::http::fields_list& fields)
- {
- fields_list::const_iterator it = fields.begin();
- for(; it != fields.end(); ++it)
- if(!string_tools::compare_no_case(param_name, it->first))
- break;
-
- if(it==fields.end())
- return std::string();
-
- return it->second;
- }
-
- std::string get_value_from_uri_line(const std::string& param_name, const std::string& uri)
- {
- std::string buff = "([\\?|&])";
- buff += param_name + "=([^&]*)";
- boost::regex match_param(buff.c_str(), boost::regex::icase | boost::regex::normal);
- boost::smatch result;
- if(boost::regex_search(uri, result, match_param, boost::match_default) && result[0].matched)
- {
- return result[2];
- }
- return std::string();
- }
-}
-}
-}
diff --git a/contrib/epee/src/mlog.cpp b/contrib/epee/src/mlog.cpp
index 092d41777..4ca1a3632 100644
--- a/contrib/epee/src/mlog.cpp
+++ b/contrib/epee/src/mlog.cpp
@@ -338,11 +338,21 @@ bool is_stdout_a_tty()
return is_a_tty.load(std::memory_order_relaxed);
}
+static bool is_nocolor()
+{
+ static const char *no_color_var = getenv("NO_COLOR");
+ static const bool no_color = no_color_var && *no_color_var; // apparently, NO_COLOR=0 means no color too (as per no-color.org)
+ return no_color;
+}
+
void set_console_color(int color, bool bright)
{
if (!is_stdout_a_tty())
return;
+ if (is_nocolor())
+ return;
+
switch(color)
{
case console_color_default:
@@ -461,6 +471,9 @@ void reset_console_color() {
if (!is_stdout_a_tty())
return;
+ if (is_nocolor())
+ return;
+
#ifdef WIN32
HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(h_stdout, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
diff --git a/contrib/epee/src/readline_buffer.cpp b/contrib/epee/src/readline_buffer.cpp
index 1047d1696..ac68d1fdb 100644
--- a/contrib/epee/src/readline_buffer.cpp
+++ b/contrib/epee/src/readline_buffer.cpp
@@ -238,6 +238,10 @@ static char** attempted_completion(const char* text, int start, int end)
static void install_line_handler()
{
+#if RL_READLINE_VERSION >= 0x0801
+ rl_variable_bind("enable-bracketed-paste", "off");
+#endif
+
rl_attempted_completion_function = attempted_completion;
rl_callback_handler_install("", handle_line);
stifle_history(500);
diff --git a/external/easylogging++/easylogging++.cc b/external/easylogging++/easylogging++.cc
index a765ee8cc..891936b6b 100644
--- a/external/easylogging++/easylogging++.cc
+++ b/external/easylogging++/easylogging++.cc
@@ -149,6 +149,11 @@ static el::Color colorFromLevel(el::Level level)
static void setConsoleColor(el::Color color, bool bright)
{
+ static const char *no_color_var = getenv("NO_COLOR");
+ static const bool no_color = no_color_var && *no_color_var; // apparently, NO_COLOR=0 means no color too (as per no-color.org)
+ if (no_color)
+ return;
+
#if ELPP_OS_WINDOWS
HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
switch (color)
diff --git a/src/blockchain_utilities/blockchain_stats.cpp b/src/blockchain_utilities/blockchain_stats.cpp
index 3009b5024..21040a1d8 100644
--- a/src/blockchain_utilities/blockchain_stats.cpp
+++ b/src/blockchain_utilities/blockchain_stats.cpp
@@ -46,6 +46,77 @@ using namespace cryptonote;
static bool stop_requested = false;
+static bool do_inputs, do_outputs, do_ringsize, do_hours, do_emission, do_fees, do_diff;
+
+static struct tm prevtm, currtm;
+static uint64_t prevsz, currsz;
+static uint64_t prevtxs, currtxs;
+static uint64_t currblks;
+static uint64_t h;
+static uint64_t totins, totouts, totrings;
+static boost::multiprecision::uint128_t prevemission, prevfees;
+static boost::multiprecision::uint128_t emission, fees;
+static boost::multiprecision::uint128_t totdiff, mindiff, maxdiff;
+
+#define MAX_INOUT 0xffffffff
+#define MAX_RINGS 0xffffffff
+
+static uint32_t minins = MAX_INOUT, maxins;
+static uint32_t minouts = MAX_INOUT, maxouts;
+static uint32_t minrings = MAX_RINGS, maxrings;
+static uint32_t io, tottxs;
+static uint32_t txhr[24];
+
+static void doprint()
+{
+ char timebuf[64];
+
+ strftime(timebuf, sizeof(timebuf), "%Y-%m-%d", &prevtm);
+ prevtm = currtm;
+ std::cout << timebuf << "\t" << currblks << "\t" << h << "\t" << currtxs << "\t" << prevtxs + currtxs << "\t" << currsz << "\t" << prevsz + currsz;
+ prevsz += currsz;
+ currsz = 0;
+ prevtxs += currtxs;
+ currtxs = 0;
+ if (!tottxs)
+ tottxs = 1;
+ if (do_emission) {
+ std::cout << "\t" << print_money(emission) << "\t" << print_money(prevemission + emission);
+ prevemission += emission;
+ emission = 0;
+ }
+ if (do_fees) {
+ std::cout << "\t" << print_money(fees) << "\t" << print_money(prevfees + fees);
+ prevfees += fees;
+ fees = 0;
+ }
+ if (do_diff) {
+ std::cout << "\t" << (maxdiff ? mindiff : 0) << "\t" << maxdiff << "\t" << totdiff / currblks;
+ mindiff = 0; maxdiff = 0; totdiff = 0;
+ }
+ if (do_inputs) {
+ std::cout << "\t" << (maxins ? minins : 0) << "\t" << maxins << "\t" << totins * 1.0 / tottxs;
+ minins = MAX_INOUT; maxins = 0; totins = 0;
+ }
+ if (do_outputs) {
+ std::cout << "\t" << (maxouts ? minouts : 0) << "\t" << maxouts << "\t" << totouts * 1.0 / tottxs;
+ minouts = MAX_INOUT; maxouts = 0; totouts = 0;
+ }
+ if (do_ringsize) {
+ std::cout << "\t" << (maxrings ? minrings : 0) << "\t" << maxrings << "\t" << totrings * 1.0 / tottxs;
+ minrings = MAX_RINGS; maxrings = 0; totrings = 0;
+ }
+ if (do_hours) {
+ for (int i=0; i<24; i++) {
+ std::cout << "\t" << txhr[i];
+ txhr[i] = 0;
+ }
+ }
+ currblks = 0;
+ tottxs = 0;
+ std::cout << ENDL;
+}
+
int main(int argc, char* argv[])
{
TRY_ENTRY();
@@ -123,13 +194,13 @@ int main(int argc, char* argv[])
network_type net_type = opt_testnet ? TESTNET : opt_stagenet ? STAGENET : MAINNET;
block_start = command_line::get_arg(vm, arg_block_start);
block_stop = command_line::get_arg(vm, arg_block_stop);
- bool do_inputs = command_line::get_arg(vm, arg_inputs);
- bool do_outputs = command_line::get_arg(vm, arg_outputs);
- bool do_ringsize = command_line::get_arg(vm, arg_ringsize);
- bool do_hours = command_line::get_arg(vm, arg_hours);
- bool do_emission = command_line::get_arg(vm, arg_emission);
- bool do_fees = command_line::get_arg(vm, arg_fees);
- bool do_diff = command_line::get_arg(vm, arg_diff);
+ do_inputs = command_line::get_arg(vm, arg_inputs);
+ do_outputs = command_line::get_arg(vm, arg_outputs);
+ do_ringsize = command_line::get_arg(vm, arg_ringsize);
+ do_hours = command_line::get_arg(vm, arg_hours);
+ do_emission = command_line::get_arg(vm, arg_emission);
+ do_fees = command_line::get_arg(vm, arg_fees);
+ do_diff = command_line::get_arg(vm, arg_diff);
LOG_PRINT_L0("Initializing source blockchain (BlockchainDB)");
std::unique_ptr<Blockchain> core_storage;
@@ -211,25 +282,7 @@ plot 'stats.csv' index "DATA" using (timecolumn(1,"%Y-%m-%d")):4 with lines, ''
}
std::cout << ENDL;
-#define MAX_INOUT 0xffffffff
-#define MAX_RINGS 0xffffffff
-
- struct tm prevtm = {0}, currtm;
- uint64_t prevsz = 0, currsz = 0;
- uint64_t prevtxs = 0, currtxs = 0;
- uint64_t currblks = 0;
- uint64_t totins = 0, totouts = 0, totrings = 0;
- boost::multiprecision::uint128_t prevemission = 0, prevfees = 0;
- boost::multiprecision::uint128_t emission = 0, fees = 0;
- boost::multiprecision::uint128_t totdiff = 0, mindiff = 0, maxdiff = 0;
- uint32_t minins = MAX_INOUT, maxins = 0;
- uint32_t minouts = MAX_INOUT, maxouts = 0;
- uint32_t minrings = MAX_RINGS, maxrings = 0;
- uint32_t io, tottxs = 0;
- uint32_t txhr[24] = {0};
- unsigned int i;
-
- for (uint64_t h = block_start; h < block_stop; ++h)
+ for (h = block_start; h < block_stop; ++h)
{
cryptonote::blobdata bd = db->get_block_blob_from_height(h);
cryptonote::block blk;
@@ -239,7 +292,6 @@ plot 'stats.csv' index "DATA" using (timecolumn(1,"%Y-%m-%d")):4 with lines, ''
return 1;
}
time_t tt = blk.timestamp;
- char timebuf[64];
epee::misc_utils::get_gmt_time(tt, currtm);
if (!prevtm.tm_year)
prevtm = currtm;
@@ -247,54 +299,9 @@ plot 'stats.csv' index "DATA" using (timecolumn(1,"%Y-%m-%d")):4 with lines, ''
if (currtm.tm_mday > prevtm.tm_mday || (currtm.tm_mday == 1 && prevtm.tm_mday > 27))
{
// check for timestamp fudging around month ends
- if (prevtm.tm_mday == 1 && currtm.tm_mday > 27)
- goto skip;
- strftime(timebuf, sizeof(timebuf), "%Y-%m-%d", &prevtm);
- prevtm = currtm;
- std::cout << timebuf << "\t" << currblks << "\t" << h << "\t" << currtxs << "\t" << prevtxs + currtxs << "\t" << currsz << "\t" << prevsz + currsz;
- prevsz += currsz;
- currsz = 0;
- prevtxs += currtxs;
- currtxs = 0;
- if (!tottxs)
- tottxs = 1;
- if (do_emission) {
- std::cout << "\t" << print_money(emission) << "\t" << print_money(prevemission + emission);
- prevemission += emission;
- emission = 0;
- }
- if (do_fees) {
- std::cout << "\t" << print_money(fees) << "\t" << print_money(prevfees + fees);
- prevfees += fees;
- fees = 0;
- }
- if (do_diff) {
- std::cout << "\t" << (maxdiff ? mindiff : 0) << "\t" << maxdiff << "\t" << totdiff / currblks;
- mindiff = 0; maxdiff = 0; totdiff = 0;
- }
- if (do_inputs) {
- std::cout << "\t" << (maxins ? minins : 0) << "\t" << maxins << "\t" << totins * 1.0 / tottxs;
- minins = MAX_INOUT; maxins = 0; totins = 0;
- }
- if (do_outputs) {
- std::cout << "\t" << (maxouts ? minouts : 0) << "\t" << maxouts << "\t" << totouts * 1.0 / tottxs;
- minouts = MAX_INOUT; maxouts = 0; totouts = 0;
- }
- if (do_ringsize) {
- std::cout << "\t" << (maxrings ? minrings : 0) << "\t" << maxrings << "\t" << totrings * 1.0 / tottxs;
- minrings = MAX_RINGS; maxrings = 0; totrings = 0;
- }
- if (do_hours) {
- for (i=0; i<24; i++) {
- std::cout << "\t" << txhr[i];
- txhr[i] = 0;
- }
- }
- currblks = 0;
- tottxs = 0;
- std::cout << ENDL;
+ if (!(prevtm.tm_mday == 1 && currtm.tm_mday > 27))
+ doprint();
}
-skip:
currsz += bd.size();
uint64_t coinbase_amount;
uint64_t tx_fee_amount = 0;
@@ -371,6 +378,8 @@ skip:
if (stop_requested)
break;
}
+ if (currblks)
+ doprint();
core_storage->deinit();
return 0;
diff --git a/src/common/data_cache.h b/src/common/data_cache.h
new file mode 100644
index 000000000..5e70da115
--- /dev/null
+++ b/src/common/data_cache.h
@@ -0,0 +1,65 @@
+// Copyright (c) 2014-2022, The Monero Project
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are
+// permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other
+// materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its contributors may be
+// used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
+
+#pragma once
+
+#include <unordered_set>
+#include <mutex>
+
+namespace tools
+{
+ template<typename T, size_t MAX_SIZE>
+ class data_cache
+ {
+ public:
+ void add(const T& value)
+ {
+ std::lock_guard<std::mutex> lock(m);
+ if (data.insert(value).second)
+ {
+ T& old_value = buf[counter++ % MAX_SIZE];
+ data.erase(old_value);
+ old_value = value;
+ }
+ }
+
+ bool has(const T& value) const
+ {
+ std::lock_guard<std::mutex> lock(m);
+ return (data.find(value) != data.end());
+ }
+
+ private:
+ mutable std::mutex m;
+ std::unordered_set<T> data;
+ T buf[MAX_SIZE] = {};
+ size_t counter = 0;
+ };
+}
diff --git a/src/common/dns_utils.cpp b/src/common/dns_utils.cpp
index e00421f87..466224390 100644
--- a/src/common/dns_utils.cpp
+++ b/src/common/dns_utils.cpp
@@ -30,6 +30,8 @@
// check local first (in the event of static or in-source compilation of libunbound)
#include "unbound.h"
+#include <deque>
+#include <set>
#include <stdlib.h>
#include "include_base_utils.h"
#include "common/threadpool.h"
@@ -326,11 +328,6 @@ std::vector<std::string> DNSResolver::get_record(const std::string& url, int rec
dnssec_available = false;
dnssec_valid = false;
- if (!check_address_syntax(url.c_str()))
- {
- return addresses;
- }
-
// destructor takes care of cleanup
ub_result_ptr result;
@@ -413,16 +410,6 @@ DNSResolver DNSResolver::create()
return DNSResolver();
}
-bool DNSResolver::check_address_syntax(const char *addr) const
-{
- // if string doesn't contain a dot, we won't consider it a url for now.
- if (strchr(addr,'.') == NULL)
- {
- return false;
- }
- return true;
-}
-
namespace dns_utils
{
diff --git a/src/common/dns_utils.h b/src/common/dns_utils.h
index f9507b42a..81079ba30 100644
--- a/src/common/dns_utils.h
+++ b/src/common/dns_utils.h
@@ -159,15 +159,6 @@ private:
// TODO: modify this to accommodate DNSSEC
std::vector<std::string> get_record(const std::string& url, int record_type, boost::optional<std::string> (*reader)(const char *,size_t), bool& dnssec_available, bool& dnssec_valid);
- /**
- * @brief Checks a string to see if it looks like a URL
- *
- * @param addr the string to be checked
- *
- * @return true if it looks enough like a URL, false if not
- */
- bool check_address_syntax(const char *addr) const;
-
DNSResolverData *m_data;
}; // class DNSResolver
diff --git a/src/common/threadpool.h b/src/common/threadpool.h
index 53421e18b..fcf8ca945 100644
--- a/src/common/threadpool.h
+++ b/src/common/threadpool.h
@@ -31,6 +31,7 @@
#include <boost/thread/mutex.hpp>
#include <boost/thread/thread.hpp>
#include <cstddef>
+#include <deque>
#include <functional>
#include <utility>
#include <vector>
diff --git a/src/crypto/c_threads.h b/src/crypto/c_threads.h
index c5431cb8d..b4f773641 100644
--- a/src/crypto/c_threads.h
+++ b/src/crypto/c_threads.h
@@ -30,29 +30,39 @@
#pragma once
#ifdef _WIN32
+
#include <windows.h>
-#define CTHR_MUTEX_TYPE HANDLE
-#define CTHR_MUTEX_INIT NULL
-#define CTHR_MUTEX_LOCK(x) do { if (x == NULL) { \
- HANDLE p = CreateMutex(NULL, FALSE, NULL); \
- if (InterlockedCompareExchangePointer((PVOID*)&x, (PVOID)p, NULL) != NULL) \
- CloseHandle(p); \
- } WaitForSingleObject(x, INFINITE); } while(0)
-#define CTHR_MUTEX_UNLOCK(x) ReleaseMutex(x)
+
+#define CTHR_RWLOCK_TYPE SRWLOCK
+#define CTHR_RWLOCK_INIT SRWLOCK_INIT
+#define CTHR_RWLOCK_LOCK_WRITE(x) AcquireSRWLockExclusive(&x)
+#define CTHR_RWLOCK_UNLOCK_WRITE(x) ReleaseSRWLockExclusive(&x)
+#define CTHR_RWLOCK_LOCK_READ(x) AcquireSRWLockShared(&x)
+#define CTHR_RWLOCK_UNLOCK_READ(x) ReleaseSRWLockShared(&x)
+#define CTHR_RWLOCK_TRYLOCK_READ(x) TryAcquireSRWLockShared(&x)
+
#define CTHR_THREAD_TYPE HANDLE
#define CTHR_THREAD_RTYPE void
#define CTHR_THREAD_RETURN return
-#define CTHR_THREAD_CREATE(thr, func, arg) thr = (HANDLE)_beginthread(func, 0, arg)
-#define CTHR_THREAD_JOIN(thr) WaitForSingleObject(thr, INFINITE)
+#define CTHR_THREAD_CREATE(thr, func, arg) ((thr = (HANDLE)_beginthread(func, 0, arg)) != -1L)
+#define CTHR_THREAD_JOIN(thr) WaitForSingleObject((HANDLE)thr, INFINITE)
+
#else
+
#include <pthread.h>
-#define CTHR_MUTEX_TYPE pthread_mutex_t
-#define CTHR_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
-#define CTHR_MUTEX_LOCK(x) pthread_mutex_lock(&x)
-#define CTHR_MUTEX_UNLOCK(x) pthread_mutex_unlock(&x)
+
+#define CTHR_RWLOCK_TYPE pthread_rwlock_t
+#define CTHR_RWLOCK_INIT PTHREAD_RWLOCK_INITIALIZER
+#define CTHR_RWLOCK_LOCK_WRITE(x) pthread_rwlock_wrlock(&x)
+#define CTHR_RWLOCK_UNLOCK_WRITE(x) pthread_rwlock_unlock(&x)
+#define CTHR_RWLOCK_LOCK_READ(x) pthread_rwlock_rdlock(&x)
+#define CTHR_RWLOCK_UNLOCK_READ(x) pthread_rwlock_unlock(&x)
+#define CTHR_RWLOCK_TRYLOCK_READ(x) (pthread_rwlock_tryrdlock(&x) == 0)
+
#define CTHR_THREAD_TYPE pthread_t
#define CTHR_THREAD_RTYPE void *
#define CTHR_THREAD_RETURN return NULL
-#define CTHR_THREAD_CREATE(thr, func, arg) pthread_create(&thr, NULL, func, arg)
+#define CTHR_THREAD_CREATE(thr, func, arg) (pthread_create(&thr, NULL, func, arg) == 0)
#define CTHR_THREAD_JOIN(thr) pthread_join(thr, NULL)
+
#endif
diff --git a/src/crypto/crypto-ops.c b/src/crypto/crypto-ops.c
index 4b392d472..971bf663f 100644
--- a/src/crypto/crypto-ops.c
+++ b/src/crypto/crypto-ops.c
@@ -38,7 +38,6 @@ DISABLE_VS_WARNINGS(4146 4244)
/* Predeclarations */
-static void fe_mul(fe, const fe, const fe);
static void fe_sq(fe, const fe);
static void ge_madd(ge_p1p1 *, const ge_p3 *, const ge_precomp *);
static void ge_msub(ge_p1p1 *, const ge_p3 *, const ge_precomp *);
@@ -72,7 +71,7 @@ uint64_t load_4(const unsigned char *in)
h = 0
*/
-static void fe_0(fe h) {
+void fe_0(fe h) {
h[0] = 0;
h[1] = 0;
h[2] = 0;
@@ -375,7 +374,7 @@ Can get away with 11 carries, but then data flow is much deeper.
With tighter constraints on inputs can squeeze carries into int32.
*/
-static void fe_mul(fe h, const fe f, const fe g) {
+void fe_mul(fe h, const fe f, const fe g) {
int32_t f0 = f[0];
int32_t f1 = f[1];
int32_t f2 = f[2];
diff --git a/src/crypto/crypto-ops.h b/src/crypto/crypto-ops.h
index e4901e080..7a6f0789a 100644
--- a/src/crypto/crypto-ops.h
+++ b/src/crypto/crypto-ops.h
@@ -30,6 +30,8 @@
#pragma once
+#include <stdint.h>
+
/* From fe.h */
typedef int32_t fe[10];
@@ -161,5 +163,7 @@ void ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q);
void fe_add(fe h, const fe f, const fe g);
void fe_tobytes(unsigned char *, const fe);
void fe_invert(fe out, const fe z);
+void fe_mul(fe out, const fe, const fe);
+void fe_0(fe h);
int ge_p3_is_point_at_infinity_vartime(const ge_p3 *p);
diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h
index d8cd6c6a0..43ea59ac6 100644
--- a/src/crypto/crypto.h
+++ b/src/crypto/crypto.h
@@ -335,8 +335,16 @@ namespace crypto {
inline bool operator<(const public_key &p1, const public_key &p2) { return memcmp(&p1, &p2, sizeof(public_key)) < 0; }
inline bool operator>(const public_key &p1, const public_key &p2) { return p2 < p1; }
+ inline bool operator<(const key_image &p1, const key_image &p2) { return memcmp(&p1, &p2, sizeof(key_image)) < 0; }
+ inline bool operator>(const key_image &p1, const key_image &p2) { return p2 < p1; }
}
+// type conversions for easier calls to sc_add(), sc_sub(), hash functions
+inline unsigned char* to_bytes(crypto::ec_scalar &scalar) { return &reinterpret_cast<unsigned char&>(scalar); }
+inline const unsigned char* to_bytes(const crypto::ec_scalar &scalar) { return &reinterpret_cast<const unsigned char&>(scalar); }
+inline unsigned char* to_bytes(crypto::ec_point &point) { return &reinterpret_cast<unsigned char&>(point); }
+inline const unsigned char* to_bytes(const crypto::ec_point &point) { return &reinterpret_cast<const unsigned char&>(point); }
+
CRYPTO_MAKE_HASHABLE(public_key)
CRYPTO_MAKE_HASHABLE_CONSTANT_TIME(secret_key)
CRYPTO_MAKE_HASHABLE_CONSTANT_TIME(public_key_memsafe)
diff --git a/src/crypto/hash-ops.h b/src/crypto/hash-ops.h
index b7ec80d7c..9d3abc3f8 100644
--- a/src/crypto/hash-ops.h
+++ b/src/crypto/hash-ops.h
@@ -97,5 +97,9 @@ void rx_slow_hash_allocate_state(void);
void rx_slow_hash_free_state(void);
uint64_t rx_seedheight(const uint64_t height);
void rx_seedheights(const uint64_t height, uint64_t *seed_height, uint64_t *next_height);
-void rx_slow_hash(const uint64_t mainheight, const uint64_t seedheight, const char *seedhash, const void *data, size_t length, char *hash, int miners, int is_alt);
-void rx_reorg(const uint64_t split_height);
+
+void rx_set_main_seedhash(const char *seedhash, size_t max_dataset_init_threads);
+void rx_slow_hash(const char *seedhash, const void *data, size_t length, char *result_hash);
+
+void rx_set_miner_thread(uint32_t value, size_t max_dataset_init_threads);
+uint32_t rx_get_miner_thread(void);
diff --git a/src/crypto/rx-slow-hash.c b/src/crypto/rx-slow-hash.c
index 40ef96ac9..14fb56e07 100644
--- a/src/crypto/rx-slow-hash.c
+++ b/src/crypto/rx-slow-hash.c
@@ -43,32 +43,41 @@
#define RX_LOGCAT "randomx"
+// Report large page allocation failures as debug messages
+#define alloc_err_msg(x) mdebug(RX_LOGCAT, x);
+
+static CTHR_RWLOCK_TYPE main_dataset_lock = CTHR_RWLOCK_INIT;
+static CTHR_RWLOCK_TYPE main_cache_lock = CTHR_RWLOCK_INIT;
+
+static randomx_dataset *main_dataset = NULL;
+static randomx_cache *main_cache = NULL;
+static char main_seedhash[HASH_SIZE];
+static int main_seedhash_set = 0;
+
+static CTHR_RWLOCK_TYPE secondary_cache_lock = CTHR_RWLOCK_INIT;
+
+static randomx_cache *secondary_cache = NULL;
+static char secondary_seedhash[HASH_SIZE];
+static int secondary_seedhash_set = 0;
+
#if defined(_MSC_VER)
#define THREADV __declspec(thread)
#else
#define THREADV __thread
#endif
-typedef struct rx_state {
- CTHR_MUTEX_TYPE rs_mutex;
- char rs_hash[HASH_SIZE];
- uint64_t rs_height;
- randomx_cache *rs_cache;
-} rx_state;
-
-static CTHR_MUTEX_TYPE rx_mutex = CTHR_MUTEX_INIT;
-static CTHR_MUTEX_TYPE rx_dataset_mutex = CTHR_MUTEX_INIT;
+static THREADV randomx_vm *main_vm_full = NULL;
+static THREADV randomx_vm *main_vm_light = NULL;
+static THREADV randomx_vm *secondary_vm_light = NULL;
-static rx_state rx_s[2] = {{CTHR_MUTEX_INIT,{0},0,0},{CTHR_MUTEX_INIT,{0},0,0}};
+static THREADV uint32_t miner_thread = 0;
-static randomx_dataset *rx_dataset;
-static int rx_dataset_nomem;
-static int rx_dataset_nolp;
-static uint64_t rx_dataset_height;
-static THREADV randomx_vm *rx_vm = NULL;
+static bool is_main(const char* seedhash) { return main_seedhash_set && (memcmp(seedhash, main_seedhash, HASH_SIZE) == 0); }
+static bool is_secondary(const char* seedhash) { return secondary_seedhash_set && (memcmp(seedhash, secondary_seedhash, HASH_SIZE) == 0); }
static void local_abort(const char *msg)
{
+ merror(RX_LOGCAT, "%s", msg);
fprintf(stderr, "%s\n", msg);
#ifdef NDEBUG
_exit(1);
@@ -77,6 +86,16 @@ static void local_abort(const char *msg)
#endif
}
+static void hash2hex(const char* hash, char* hex) {
+ const char* d = "0123456789abcdef";
+ for (int i = 0; i < HASH_SIZE; ++i) {
+ const uint8_t b = hash[i];
+ hex[i * 2 + 0] = d[b >> 4];
+ hex[i * 2 + 1] = d[b & 15];
+ }
+ hex[HASH_SIZE * 2] = '\0';
+}
+
static inline int disabled_flags(void) {
static int flags = -1;
@@ -157,19 +176,6 @@ static unsigned int get_seedhash_epoch_blocks(void)
return blocks;
}
-void rx_reorg(const uint64_t split_height) {
- int i;
- CTHR_MUTEX_LOCK(rx_mutex);
- for (i=0; i<2; i++) {
- if (split_height <= rx_s[i].rs_height) {
- if (rx_s[i].rs_height == rx_dataset_height)
- rx_dataset_height = 1;
- rx_s[i].rs_height = 1; /* set to an invalid seed height */
- }
- }
- CTHR_MUTEX_UNLOCK(rx_mutex);
-}
-
uint64_t rx_seedheight(const uint64_t height) {
const uint64_t seedhash_epoch_lag = get_seedhash_epoch_lag();
const uint64_t seedhash_epoch_blocks = get_seedhash_epoch_blocks();
@@ -183,6 +189,103 @@ void rx_seedheights(const uint64_t height, uint64_t *seedheight, uint64_t *nexth
*nextheight = rx_seedheight(height + get_seedhash_epoch_lag());
}
+static void rx_alloc_dataset(randomx_flags flags, randomx_dataset** dataset, int ignore_env)
+{
+ if (*dataset) {
+ return;
+ }
+
+ if (disabled_flags() & RANDOMX_FLAG_FULL_MEM) {
+ static int shown = 0;
+ if (!shown) {
+ shown = 1;
+ minfo(RX_LOGCAT, "RandomX dataset is disabled by MONERO_RANDOMX_UMASK environment variable.");
+ }
+ return;
+ }
+
+ if (!ignore_env && !getenv("MONERO_RANDOMX_FULL_MEM")) {
+ static int shown = 0;
+ if (!shown) {
+ shown = 1;
+ minfo(RX_LOGCAT, "RandomX dataset is not enabled by default. Use MONERO_RANDOMX_FULL_MEM environment variable to enable it.");
+ }
+ return;
+ }
+
+ *dataset = randomx_alloc_dataset((flags | RANDOMX_FLAG_LARGE_PAGES) & ~disabled_flags());
+ if (!*dataset) {
+ alloc_err_msg("Couldn't allocate RandomX dataset using large pages");
+ *dataset = randomx_alloc_dataset(flags & ~disabled_flags());
+ if (!*dataset) {
+ merror(RX_LOGCAT, "Couldn't allocate RandomX dataset");
+ }
+ }
+}
+
+static void rx_alloc_cache(randomx_flags flags, randomx_cache** cache)
+{
+ if (*cache) {
+ return;
+ }
+
+ *cache = randomx_alloc_cache((flags | RANDOMX_FLAG_LARGE_PAGES) & ~disabled_flags());
+ if (!*cache) {
+ alloc_err_msg("Couldn't allocate RandomX cache using large pages");
+ *cache = randomx_alloc_cache(flags & ~disabled_flags());
+ if (!*cache) local_abort("Couldn't allocate RandomX cache");
+ }
+}
+
+static void rx_init_full_vm(randomx_flags flags, randomx_vm** vm)
+{
+ if (*vm || !main_dataset || (disabled_flags() & RANDOMX_FLAG_FULL_MEM)) {
+ return;
+ }
+
+ if ((flags & RANDOMX_FLAG_JIT) && !miner_thread) {
+ flags |= RANDOMX_FLAG_SECURE;
+ }
+
+ *vm = randomx_create_vm((flags | RANDOMX_FLAG_LARGE_PAGES | RANDOMX_FLAG_FULL_MEM) & ~disabled_flags(), NULL, main_dataset);
+ if (!*vm) {
+ static int shown = 0;
+ if (!shown) {
+ shown = 1;
+ alloc_err_msg("Couldn't allocate RandomX full VM using large pages (will print only once)");
+ }
+ *vm = randomx_create_vm((flags | RANDOMX_FLAG_FULL_MEM) & ~disabled_flags(), NULL, main_dataset);
+ if (!*vm) {
+ merror(RX_LOGCAT, "Couldn't allocate RandomX full VM");
+ }
+ }
+}
+
+static void rx_init_light_vm(randomx_flags flags, randomx_vm** vm, randomx_cache* cache)
+{
+ if (*vm) {
+ randomx_vm_set_cache(*vm, cache);
+ return;
+ }
+
+ if ((flags & RANDOMX_FLAG_JIT) && !miner_thread) {
+ flags |= RANDOMX_FLAG_SECURE;
+ }
+
+ flags &= ~RANDOMX_FLAG_FULL_MEM;
+
+ *vm = randomx_create_vm((flags | RANDOMX_FLAG_LARGE_PAGES) & ~disabled_flags(), cache, NULL);
+ if (!*vm) {
+ static int shown = 0;
+ if (!shown) {
+ shown = 1;
+ alloc_err_msg("Couldn't allocate RandomX light VM using large pages (will print only once)");
+ }
+ *vm = randomx_create_vm(flags & ~disabled_flags(), cache, NULL);
+ if (!*vm) local_abort("Couldn't allocate RandomX light VM");
+ }
+}
+
typedef struct seedinfo {
randomx_cache *si_cache;
unsigned long si_start;
@@ -191,187 +294,230 @@ typedef struct seedinfo {
static CTHR_THREAD_RTYPE rx_seedthread(void *arg) {
seedinfo *si = arg;
- randomx_init_dataset(rx_dataset, si->si_cache, si->si_start, si->si_count);
+ randomx_init_dataset(main_dataset, si->si_cache, si->si_start, si->si_count);
CTHR_THREAD_RETURN;
}
-static void rx_initdata(randomx_cache *rs_cache, const int miners, const uint64_t seedheight) {
- if (miners > 1) {
- unsigned long delta = randomx_dataset_item_count() / miners;
- unsigned long start = 0;
- int i;
- seedinfo *si;
- CTHR_THREAD_TYPE *st;
- si = malloc(miners * sizeof(seedinfo));
- if (si == NULL)
- local_abort("Couldn't allocate RandomX mining threadinfo");
- st = malloc(miners * sizeof(CTHR_THREAD_TYPE));
- if (st == NULL) {
- free(si);
- local_abort("Couldn't allocate RandomX mining threadlist");
- }
- for (i=0; i<miners-1; i++) {
- si[i].si_cache = rs_cache;
- si[i].si_start = start;
- si[i].si_count = delta;
- start += delta;
- }
- si[i].si_cache = rs_cache;
+static void rx_init_dataset(size_t max_threads) {
+ if (!main_dataset) {
+ return;
+ }
+
+ // leave 2 CPU cores for other tasks
+ const size_t num_threads = (max_threads < 4) ? 1 : (max_threads - 2);
+ seedinfo* si = malloc(num_threads * sizeof(seedinfo));
+ if (!si) local_abort("Couldn't allocate RandomX mining threadinfo");
+
+ const uint32_t delta = randomx_dataset_item_count() / num_threads;
+ uint32_t start = 0;
+
+ const size_t n1 = num_threads - 1;
+ for (size_t i = 0; i < n1; ++i) {
+ si[i].si_cache = main_cache;
si[i].si_start = start;
- si[i].si_count = randomx_dataset_item_count() - start;
- for (i=1; i<miners; i++) {
- CTHR_THREAD_CREATE(st[i], rx_seedthread, &si[i]);
- }
- randomx_init_dataset(rx_dataset, rs_cache, 0, si[0].si_count);
- for (i=1; i<miners; i++) {
- CTHR_THREAD_JOIN(st[i]);
+ si[i].si_count = delta;
+ start += delta;
+ }
+
+ si[n1].si_cache = main_cache;
+ si[n1].si_start = start;
+ si[n1].si_count = randomx_dataset_item_count() - start;
+
+ CTHR_THREAD_TYPE *st = malloc(num_threads * sizeof(CTHR_THREAD_TYPE));
+ if (!st) local_abort("Couldn't allocate RandomX mining threadlist");
+
+ CTHR_RWLOCK_LOCK_READ(main_cache_lock);
+ for (size_t i = 0; i < n1; ++i) {
+ if (!CTHR_THREAD_CREATE(st[i], rx_seedthread, &si[i])) {
+ local_abort("Couldn't start RandomX seed thread");
}
- free(st);
- free(si);
- } else {
- randomx_init_dataset(rx_dataset, rs_cache, 0, randomx_dataset_item_count());
}
- rx_dataset_height = seedheight;
+ rx_seedthread(&si[n1]);
+ for (size_t i = 0; i < n1; ++i) CTHR_THREAD_JOIN(st[i]);
+ CTHR_RWLOCK_UNLOCK_READ(main_cache_lock);
+
+ free(st);
+ free(si);
+
+ minfo(RX_LOGCAT, "RandomX dataset initialized");
}
-void rx_slow_hash(const uint64_t mainheight, const uint64_t seedheight, const char *seedhash, const void *data, size_t length,
- char *hash, int miners, int is_alt) {
- uint64_t s_height = rx_seedheight(mainheight);
- int toggle = (s_height & get_seedhash_epoch_blocks()) != 0;
- randomx_flags flags = enabled_flags() & ~disabled_flags();
- rx_state *rx_sp;
- randomx_cache *cache;
-
- CTHR_MUTEX_LOCK(rx_mutex);
-
- /* if alt block but with same seed as mainchain, no need for alt cache */
- if (is_alt) {
- if (s_height == seedheight && !memcmp(rx_s[toggle].rs_hash, seedhash, HASH_SIZE))
- is_alt = 0;
- } else {
- /* RPC could request an earlier block on mainchain */
- if (s_height > seedheight)
- is_alt = 1;
- /* miner can be ahead of mainchain */
- else if (s_height < seedheight)
- toggle ^= 1;
- }
-
- toggle ^= (is_alt != 0);
-
- rx_sp = &rx_s[toggle];
- CTHR_MUTEX_LOCK(rx_sp->rs_mutex);
- CTHR_MUTEX_UNLOCK(rx_mutex);
-
- cache = rx_sp->rs_cache;
- if (cache == NULL) {
- if (!(disabled_flags() & RANDOMX_FLAG_LARGE_PAGES)) {
- cache = randomx_alloc_cache(flags | RANDOMX_FLAG_LARGE_PAGES);
- if (cache == NULL) {
- mdebug(RX_LOGCAT, "Couldn't use largePages for RandomX cache");
- }
- }
- if (cache == NULL) {
- cache = randomx_alloc_cache(flags);
- if (cache == NULL)
- local_abort("Couldn't allocate RandomX cache");
- }
+typedef struct thread_info {
+ char seedhash[HASH_SIZE];
+ size_t max_threads;
+} thread_info;
+
+static CTHR_THREAD_RTYPE rx_set_main_seedhash_thread(void *arg) {
+ thread_info* info = arg;
+
+ CTHR_RWLOCK_LOCK_WRITE(main_dataset_lock);
+ CTHR_RWLOCK_LOCK_WRITE(main_cache_lock);
+
+ // Double check that seedhash wasn't already updated
+ if (is_main(info->seedhash)) {
+ CTHR_RWLOCK_UNLOCK_WRITE(main_cache_lock);
+ CTHR_RWLOCK_UNLOCK_WRITE(main_dataset_lock);
+ free(info);
+ CTHR_THREAD_RETURN;
}
- if (rx_sp->rs_height != seedheight || rx_sp->rs_cache == NULL || memcmp(seedhash, rx_sp->rs_hash, HASH_SIZE)) {
- randomx_init_cache(cache, seedhash, HASH_SIZE);
- rx_sp->rs_cache = cache;
- rx_sp->rs_height = seedheight;
- memcpy(rx_sp->rs_hash, seedhash, HASH_SIZE);
+ memcpy(main_seedhash, info->seedhash, HASH_SIZE);
+ main_seedhash_set = 1;
+
+ char buf[HASH_SIZE * 2 + 1];
+ hash2hex(main_seedhash, buf);
+ minfo(RX_LOGCAT, "RandomX new main seed hash is %s", buf);
+
+ const randomx_flags flags = enabled_flags() & ~disabled_flags();
+ rx_alloc_dataset(flags, &main_dataset, 0);
+ rx_alloc_cache(flags, &main_cache);
+
+ randomx_init_cache(main_cache, info->seedhash, HASH_SIZE);
+ minfo(RX_LOGCAT, "RandomX main cache initialized");
+
+ CTHR_RWLOCK_UNLOCK_WRITE(main_cache_lock);
+
+ // From this point, rx_slow_hash can calculate hashes in light mode, but dataset is not initialized yet
+ rx_init_dataset(info->max_threads);
+
+ CTHR_RWLOCK_UNLOCK_WRITE(main_dataset_lock);
+
+ free(info);
+ CTHR_THREAD_RETURN;
+}
+
+void rx_set_main_seedhash(const char *seedhash, size_t max_dataset_init_threads) {
+ // Early out if seedhash didn't change
+ if (is_main(seedhash)) {
+ return;
}
- if (rx_vm == NULL) {
- if ((flags & RANDOMX_FLAG_JIT) && !miners) {
- flags |= RANDOMX_FLAG_SECURE & ~disabled_flags();
- }
- if (miners && (disabled_flags() & RANDOMX_FLAG_FULL_MEM)) {
- miners = 0;
- }
- if (miners) {
- CTHR_MUTEX_LOCK(rx_dataset_mutex);
- if (!rx_dataset_nomem) {
- if (rx_dataset == NULL) {
- if (!(disabled_flags() & RANDOMX_FLAG_LARGE_PAGES)) {
- rx_dataset = randomx_alloc_dataset(RANDOMX_FLAG_LARGE_PAGES);
- if (rx_dataset == NULL) {
- mdebug(RX_LOGCAT, "Couldn't use largePages for RandomX dataset");
- }
- }
- if (rx_dataset == NULL)
- rx_dataset = randomx_alloc_dataset(RANDOMX_FLAG_DEFAULT);
- if (rx_dataset != NULL)
- rx_initdata(rx_sp->rs_cache, miners, seedheight);
- }
- }
- if (rx_dataset != NULL)
- flags |= RANDOMX_FLAG_FULL_MEM;
- else {
- miners = 0;
- if (!rx_dataset_nomem) {
- rx_dataset_nomem = 1;
- mwarning(RX_LOGCAT, "Couldn't allocate RandomX dataset for miner");
+
+ // Update main cache and dataset in the background
+ thread_info* info = malloc(sizeof(thread_info));
+ if (!info) local_abort("Couldn't allocate RandomX mining threadinfo");
+
+ memcpy(info->seedhash, seedhash, HASH_SIZE);
+ info->max_threads = max_dataset_init_threads;
+
+ CTHR_THREAD_TYPE t;
+ if (!CTHR_THREAD_CREATE(t, rx_set_main_seedhash_thread, info)) {
+ local_abort("Couldn't start RandomX seed thread");
+ }
+}
+
+void rx_slow_hash(const char *seedhash, const void *data, size_t length, char *result_hash) {
+ const randomx_flags flags = enabled_flags() & ~disabled_flags();
+ int success = 0;
+
+ // Fast path (seedhash == main_seedhash)
+ // Multiple threads can run in parallel in fast or light mode, 1-2 ms or 10-15 ms per hash per thread
+ if (is_main(seedhash)) {
+ // If CTHR_RWLOCK_TRYLOCK_READ fails it means dataset is being initialized now, so use the light mode
+ if (main_dataset && CTHR_RWLOCK_TRYLOCK_READ(main_dataset_lock)) {
+ // Double check that main_seedhash didn't change
+ if (is_main(seedhash)) {
+ rx_init_full_vm(flags, &main_vm_full);
+ if (main_vm_full) {
+ randomx_calculate_hash(main_vm_full, data, length, result_hash);
+ success = 1;
}
}
- CTHR_MUTEX_UNLOCK(rx_dataset_mutex);
- }
- if (!(disabled_flags() & RANDOMX_FLAG_LARGE_PAGES) && !rx_dataset_nolp) {
- rx_vm = randomx_create_vm(flags | RANDOMX_FLAG_LARGE_PAGES, rx_sp->rs_cache, rx_dataset);
- if(rx_vm == NULL) { //large pages failed
- mdebug(RX_LOGCAT, "Couldn't use largePages for RandomX VM");
- rx_dataset_nolp = 1;
+ CTHR_RWLOCK_UNLOCK_READ(main_dataset_lock);
+ } else {
+ CTHR_RWLOCK_LOCK_READ(main_cache_lock);
+ // Double check that main_seedhash didn't change
+ if (is_main(seedhash)) {
+ rx_init_light_vm(flags, &main_vm_light, main_cache);
+ randomx_calculate_hash(main_vm_light, data, length, result_hash);
+ success = 1;
}
+ CTHR_RWLOCK_UNLOCK_READ(main_cache_lock);
}
- if (rx_vm == NULL)
- rx_vm = randomx_create_vm(flags, rx_sp->rs_cache, rx_dataset);
- if(rx_vm == NULL) {//fallback if everything fails
- flags = RANDOMX_FLAG_DEFAULT | (miners ? RANDOMX_FLAG_FULL_MEM : 0);
- rx_vm = randomx_create_vm(flags, rx_sp->rs_cache, rx_dataset);
- }
- if (rx_vm == NULL)
- local_abort("Couldn't allocate RandomX VM");
- } else if (miners) {
- CTHR_MUTEX_LOCK(rx_dataset_mutex);
- if (rx_dataset != NULL && rx_dataset_height != seedheight)
- rx_initdata(cache, miners, seedheight);
- else if (rx_dataset == NULL) {
- /* this is a no-op if the cache hasn't changed */
- randomx_vm_set_cache(rx_vm, rx_sp->rs_cache);
+ }
+
+ if (success) {
+ return;
+ }
+
+ char buf[HASH_SIZE * 2 + 1];
+
+ // Slow path (seedhash != main_seedhash, but seedhash == secondary_seedhash)
+ // Multiple threads can run in parallel in light mode, 10-15 ms per hash per thread
+ if (!secondary_cache) {
+ CTHR_RWLOCK_LOCK_WRITE(secondary_cache_lock);
+ if (!secondary_cache) {
+ hash2hex(seedhash, buf);
+ minfo(RX_LOGCAT, "RandomX new secondary seed hash is %s", buf);
+
+ rx_alloc_cache(flags, &secondary_cache);
+ randomx_init_cache(secondary_cache, seedhash, HASH_SIZE);
+ minfo(RX_LOGCAT, "RandomX secondary cache updated");
+ memcpy(secondary_seedhash, seedhash, HASH_SIZE);
+ secondary_seedhash_set = 1;
}
- CTHR_MUTEX_UNLOCK(rx_dataset_mutex);
- } else {
- /* this is a no-op if the cache hasn't changed */
- randomx_vm_set_cache(rx_vm, rx_sp->rs_cache);
- }
- /* mainchain users can run in parallel */
- if (!is_alt)
- CTHR_MUTEX_UNLOCK(rx_sp->rs_mutex);
- randomx_calculate_hash(rx_vm, data, length, hash);
- /* altchain slot users always get fully serialized */
- if (is_alt)
- CTHR_MUTEX_UNLOCK(rx_sp->rs_mutex);
-}
+ CTHR_RWLOCK_UNLOCK_WRITE(secondary_cache_lock);
+ }
+
+ CTHR_RWLOCK_LOCK_READ(secondary_cache_lock);
+ if (is_secondary(seedhash)) {
+ rx_init_light_vm(flags, &secondary_vm_light, secondary_cache);
+ randomx_calculate_hash(secondary_vm_light, data, length, result_hash);
+ success = 1;
+ }
+ CTHR_RWLOCK_UNLOCK_READ(secondary_cache_lock);
-void rx_slow_hash_allocate_state(void) {
+ if (success) {
+ return;
+ }
+
+ // Slowest path (seedhash != main_seedhash, seedhash != secondary_seedhash)
+ // Only one thread runs at a time and updates secondary_seedhash if needed, up to 200-500 ms per hash
+ CTHR_RWLOCK_LOCK_WRITE(secondary_cache_lock);
+ if (!is_secondary(seedhash)) {
+ hash2hex(seedhash, buf);
+ minfo(RX_LOGCAT, "RandomX new secondary seed hash is %s", buf);
+
+ randomx_init_cache(secondary_cache, seedhash, HASH_SIZE);
+ minfo(RX_LOGCAT, "RandomX secondary cache updated");
+ memcpy(secondary_seedhash, seedhash, HASH_SIZE);
+ secondary_seedhash_set = 1;
+ }
+ rx_init_light_vm(flags, &secondary_vm_light, secondary_cache);
+ randomx_calculate_hash(secondary_vm_light, data, length, result_hash);
+ CTHR_RWLOCK_UNLOCK_WRITE(secondary_cache_lock);
}
-void rx_slow_hash_free_state(void) {
- if (rx_vm != NULL) {
- randomx_destroy_vm(rx_vm);
- rx_vm = NULL;
+void rx_set_miner_thread(uint32_t value, size_t max_dataset_init_threads) {
+ miner_thread = value;
+
+ // If dataset is not allocated yet, try to allocate and initialize it
+ CTHR_RWLOCK_LOCK_WRITE(main_dataset_lock);
+ if (main_dataset) {
+ CTHR_RWLOCK_UNLOCK_WRITE(main_dataset_lock);
+ return;
}
+
+ const randomx_flags flags = enabled_flags() & ~disabled_flags();
+ rx_alloc_dataset(flags, &main_dataset, 1);
+ rx_init_dataset(max_dataset_init_threads);
+
+ CTHR_RWLOCK_UNLOCK_WRITE(main_dataset_lock);
+}
+
+uint32_t rx_get_miner_thread() {
+ return miner_thread;
}
-void rx_stop_mining(void) {
- CTHR_MUTEX_LOCK(rx_dataset_mutex);
- if (rx_dataset != NULL) {
- randomx_dataset *rd = rx_dataset;
- rx_dataset = NULL;
- randomx_release_dataset(rd);
+void rx_slow_hash_allocate_state() {}
+
+static void rx_destroy_vm(randomx_vm** vm) {
+ if (*vm) {
+ randomx_destroy_vm(*vm);
+ *vm = NULL;
}
- rx_dataset_nomem = 0;
- rx_dataset_nolp = 0;
- CTHR_MUTEX_UNLOCK(rx_dataset_mutex);
+}
+
+void rx_slow_hash_free_state() {
+ rx_destroy_vm(&main_vm_full);
+ rx_destroy_vm(&main_vm_light);
+ rx_destroy_vm(&secondary_vm_light);
}
diff --git a/src/cryptonote_basic/miner.cpp b/src/cryptonote_basic/miner.cpp
index 5b0db9518..98f1555b6 100644
--- a/src/cryptonote_basic/miner.cpp
+++ b/src/cryptonote_basic/miner.cpp
@@ -82,6 +82,7 @@
using namespace epee;
#include "miner.h"
+#include "crypto/hash.h"
extern "C" void slow_hash_allocate_state();
@@ -436,7 +437,6 @@ namespace cryptonote
{
m_stop = true;
}
- extern "C" void rx_stop_mining(void);
//-----------------------------------------------------------------------------------------------------
bool miner::stop()
{
@@ -469,7 +469,6 @@ namespace cryptonote
MINFO("Mining has been stopped, " << m_threads.size() << " finished" );
m_threads.clear();
m_threads_autodetect.clear();
- rx_stop_mining();
return true;
}
//-----------------------------------------------------------------------------------------------------
@@ -524,6 +523,8 @@ namespace cryptonote
bool miner::worker_thread()
{
const uint32_t th_local_index = m_thread_index++; // atomically increment, getting value before increment
+ crypto::rx_set_miner_thread(th_local_index, tools::get_max_concurrency());
+
MLOG_SET_THREAD_NAME(std::string("[miner ") + std::to_string(th_local_index) + "]");
MGINFO("Miner thread was started ["<< th_local_index << "]");
uint32_t nonce = m_starter_nonce + th_local_index;
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp
index 07ff5f068..6cf0f5964 100644
--- a/src/cryptonote_core/blockchain.cpp
+++ b/src/cryptonote_core/blockchain.cpp
@@ -48,7 +48,6 @@
#include "file_io_utils.h"
#include "int-util.h"
#include "common/threadpool.h"
-#include "common/boost_serialization_helper.h"
#include "warnings.h"
#include "crypto/hash.h"
#include "cryptonote_core.h"
@@ -456,6 +455,14 @@ bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline
if (!update_next_cumulative_weight_limit())
return false;
}
+
+ if (m_hardfork->get_current_version() >= RX_BLOCK_VERSION)
+ {
+ const crypto::hash seedhash = get_block_id_by_height(crypto::rx_seedheight(m_db->height()));
+ if (seedhash != crypto::null_hash)
+ rx_set_main_seedhash(seedhash.data, tools::get_max_concurrency());
+ }
+
return true;
}
//------------------------------------------------------------------
@@ -570,6 +577,12 @@ void Blockchain::pop_blocks(uint64_t nblocks)
if (stop_batch)
m_db->batch_stop();
+
+ if (m_hardfork->get_current_version() >= RX_BLOCK_VERSION)
+ {
+ const crypto::hash seedhash = get_block_id_by_height(crypto::rx_seedheight(m_db->height()));
+ rx_set_main_seedhash(seedhash.data, tools::get_max_concurrency());
+ }
}
//------------------------------------------------------------------
// This function tells BlockchainDB to remove the top block from the
@@ -1239,18 +1252,20 @@ bool Blockchain::switch_to_alternative_blockchain(std::list<block_extended_info>
}
m_hardfork->reorganize_from_chain_height(split_height);
- get_block_longhash_reorg(split_height);
std::shared_ptr<tools::Notify> reorg_notify = m_reorg_notify;
if (reorg_notify)
reorg_notify->notify("%s", std::to_string(split_height).c_str(), "%h", std::to_string(m_db->height()).c_str(),
"%n", std::to_string(m_db->height() - split_height).c_str(), "%d", std::to_string(discarded_blocks).c_str(), NULL);
+ const uint64_t new_height = m_db->height();
+ const crypto::hash seedhash = get_block_id_by_height(crypto::rx_seedheight(new_height));
+
crypto::hash prev_id;
if (!get_block_hash(alt_chain.back().bl, prev_id))
MERROR("Failed to get block hash of an alternative chain's tip");
else
- send_miner_notifications(prev_id, alt_chain.back().already_generated_coins);
+ send_miner_notifications(new_height, seedhash, prev_id, alt_chain.back().already_generated_coins);
for (const auto& notifier : m_block_notifiers)
{
@@ -1262,6 +1277,9 @@ bool Blockchain::switch_to_alternative_blockchain(std::list<block_extended_info>
}
}
+ if (m_hardfork->get_current_version() >= RX_BLOCK_VERSION)
+ rx_set_main_seedhash(seedhash.data, tools::get_max_concurrency());
+
MGINFO_GREEN("REORGANIZE SUCCESS! on height: " << split_height << ", new blockchain size: " << m_db->height());
return true;
}
@@ -2001,7 +2019,7 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id
{
seedhash = get_block_id_by_height(seedheight);
}
- get_altblock_longhash(bei.bl, proof_of_work, get_current_blockchain_height(), bei.height, seedheight, seedhash);
+ get_altblock_longhash(bei.bl, proof_of_work, seedhash);
} else
{
get_block_longhash(this, bei.bl, proof_of_work, bei.height, 0);
@@ -3613,7 +3631,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
}
}
- if (!rct::verRctNonSemanticsSimple(rv))
+ if (!rct::verRctNonSemanticsSimpleCached(rv))
{
MERROR_VER("Failed to check ringct signatures!");
return false;
@@ -4552,11 +4570,15 @@ leave:
}
}
- send_miner_notifications(id, already_generated_coins);
+ const crypto::hash seedhash = get_block_id_by_height(crypto::rx_seedheight(new_height));
+ send_miner_notifications(new_height, seedhash, id, already_generated_coins);
for (const auto& notifier: m_block_notifiers)
notifier(new_height - 1, {std::addressof(bl), 1});
+ if (m_hardfork->get_current_version() >= RX_BLOCK_VERSION)
+ rx_set_main_seedhash(seedhash.data, tools::get_max_concurrency());
+
return true;
}
//------------------------------------------------------------------
@@ -5761,24 +5783,15 @@ void Blockchain::cache_block_template(const block &b, const cryptonote::account_
m_btc_valid = true;
}
-void Blockchain::send_miner_notifications(const crypto::hash &prev_id, uint64_t already_generated_coins)
+void Blockchain::send_miner_notifications(uint64_t height, const crypto::hash &seed_hash, const crypto::hash &prev_id, uint64_t already_generated_coins)
{
if (m_miner_notifiers.empty())
return;
- const uint64_t height = m_db->height();
const uint8_t major_version = m_hardfork->get_ideal_version(height);
const difficulty_type diff = get_difficulty_for_next_block();
const uint64_t median_weight = m_current_block_cumul_weight_median;
- crypto::hash seed_hash = crypto::null_hash;
- if (m_hardfork->get_current_version() >= RX_BLOCK_VERSION)
- {
- uint64_t seed_height, next_height;
- crypto::rx_seedheights(height, &seed_height, &next_height);
- seed_hash = get_block_id_by_height(seed_height);
- }
-
std::vector<tx_block_template_backlog_entry> tx_backlog;
m_tx_pool.get_block_template_backlog(tx_backlog);
diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h
index 4795fc55c..c61ce4466 100644
--- a/src/cryptonote_core/blockchain.h
+++ b/src/cryptonote_core/blockchain.h
@@ -1598,9 +1598,11 @@ namespace cryptonote
/**
* @brief sends new block notifications to ZMQ `miner_data` subscribers
*
+ * @param height current blockchain height
+ * @param seed_hash seed hash to use for mining
* @param prev_id hash of new blockchain tip
* @param already_generated_coins total coins mined by the network so far
*/
- void send_miner_notifications(const crypto::hash &prev_id, uint64_t already_generated_coins);
+ void send_miner_notifications(uint64_t height, const crypto::hash &seed_hash, const crypto::hash &prev_id, uint64_t already_generated_coins);
};
} // namespace cryptonote
diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp
index 472026217..bf58a120d 100644
--- a/src/cryptonote_core/cryptonote_tx_utils.cpp
+++ b/src/cryptonote_core/cryptonote_tx_utils.cpp
@@ -669,10 +669,10 @@ namespace cryptonote
return true;
}
//---------------------------------------------------------------
- void get_altblock_longhash(const block& b, crypto::hash& res, const uint64_t main_height, const uint64_t height, const uint64_t seed_height, const crypto::hash& seed_hash)
+ void get_altblock_longhash(const block& b, crypto::hash& res, const crypto::hash& seed_hash)
{
blobdata bd = get_block_hashing_blob(b);
- rx_slow_hash(main_height, seed_height, seed_hash.data, bd.data(), bd.size(), res.data, 0, 1);
+ rx_slow_hash(seed_hash.data, bd.data(), bd.size(), res.data);
}
bool get_block_longhash(const Blockchain *pbc, const blobdata& bd, crypto::hash& res, const uint64_t height, const int major_version, const crypto::hash *seed_hash, const int miners)
@@ -686,20 +686,16 @@ namespace cryptonote
}
if (major_version >= RX_BLOCK_VERSION)
{
- uint64_t seed_height, main_height;
crypto::hash hash;
if (pbc != NULL)
{
- seed_height = rx_seedheight(height);
+ const uint64_t seed_height = rx_seedheight(height);
hash = seed_hash ? *seed_hash : pbc->get_pending_block_id_by_height(seed_height);
- main_height = pbc->get_current_blockchain_height();
} else
{
memset(&hash, 0, sizeof(hash)); // only happens when generating genesis block
- seed_height = 0;
- main_height = 0;
}
- rx_slow_hash(main_height, seed_height, hash.data, bd.data(), bd.size(), res.data, seed_hash ? 0 : miners, !!seed_hash);
+ rx_slow_hash(hash.data, bd.data(), bd.size(), res.data);
} else {
const int pow_variant = major_version >= 7 ? major_version - 6 : 0;
crypto::cn_slow_hash(bd.data(), bd.size(), res, pow_variant, height);
@@ -713,20 +709,10 @@ namespace cryptonote
return get_block_longhash(pbc, bd, res, height, b.major_version, seed_hash, miners);
}
- bool get_block_longhash(const Blockchain *pbc, const block& b, crypto::hash& res, const uint64_t height, const int miners)
- {
- return get_block_longhash(pbc, b, res, height, NULL, miners);
- }
-
- crypto::hash get_block_longhash(const Blockchain *pbc, const block& b, const uint64_t height, const int miners)
+ crypto::hash get_block_longhash(const Blockchain *pbc, const block& b, const uint64_t height, const crypto::hash *seed_hash, const int miners)
{
crypto::hash p = crypto::null_hash;
- get_block_longhash(pbc, b, p, height, miners);
+ get_block_longhash(pbc, b, p, height, seed_hash, miners);
return p;
}
-
- void get_block_longhash_reorg(const uint64_t split_height)
- {
- rx_reorg(split_height);
- }
}
diff --git a/src/cryptonote_core/cryptonote_tx_utils.h b/src/cryptonote_core/cryptonote_tx_utils.h
index 12d6b8ce5..5f301bb89 100644
--- a/src/cryptonote_core/cryptonote_tx_utils.h
+++ b/src/cryptonote_core/cryptonote_tx_utils.h
@@ -144,14 +144,10 @@ namespace cryptonote
);
class Blockchain;
- bool get_block_longhash(const Blockchain *pb, const blobdata& bd, crypto::hash& res, const uint64_t height,
- const int major_version, const crypto::hash *seed_hash, const int miners);
- bool get_block_longhash(const Blockchain *pb, const block& b, crypto::hash& res, const uint64_t height, const int miners);
- bool get_block_longhash(const Blockchain *pb, const block& b, crypto::hash& res, const uint64_t height, const crypto::hash *seed_hash, const int miners);
- void get_altblock_longhash(const block& b, crypto::hash& res, const uint64_t main_height, const uint64_t height,
- const uint64_t seed_height, const crypto::hash& seed_hash);
- crypto::hash get_block_longhash(const Blockchain *pb, const block& b, const uint64_t height, const int miners);
- void get_block_longhash_reorg(const uint64_t split_height);
+ bool get_block_longhash(const Blockchain *pb, const blobdata& bd, crypto::hash& res, const uint64_t height, const int major_version, const crypto::hash *seed_hash, const int miners = 0);
+ bool get_block_longhash(const Blockchain *pb, const block& b, crypto::hash& res, const uint64_t height, const crypto::hash *seed_hash = nullptr, const int miners = 0);
+ crypto::hash get_block_longhash(const Blockchain *pb, const block& b, const uint64_t height, const crypto::hash *seed_hash = nullptr, const int miners = 0);
+ void get_altblock_longhash(const block& b, crypto::hash& res, const crypto::hash& seed_hash);
}
diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp
index b2a800e2b..3a058ad66 100644
--- a/src/cryptonote_core/tx_pool.cpp
+++ b/src/cryptonote_core/tx_pool.cpp
@@ -40,7 +40,6 @@
#include "blockchain.h"
#include "blockchain_db/locked_txn.h"
#include "blockchain_db/blockchain_db.h"
-#include "common/boost_serialization_helper.h"
#include "int-util.h"
#include "misc_language.h"
#include "warnings.h"
diff --git a/src/daemonizer/windows_service.cpp b/src/daemonizer/windows_service.cpp
index 846f6c071..5fcc469e9 100644
--- a/src/daemonizer/windows_service.cpp
+++ b/src/daemonizer/windows_service.cpp
@@ -196,7 +196,7 @@ bool install_service(
, 0
//, GENERIC_EXECUTE | GENERIC_READ
, SERVICE_WIN32_OWN_PROCESS
- , SERVICE_DEMAND_START
+ , SERVICE_AUTO_START
, SERVICE_ERROR_NORMAL
, full_command.c_str()
, nullptr
diff --git a/src/daemonizer/windows_service_runner.h b/src/daemonizer/windows_service_runner.h
index a8e4d3b0e..5a33b2aa7 100644
--- a/src/daemonizer/windows_service_runner.h
+++ b/src/daemonizer/windows_service_runner.h
@@ -146,9 +146,6 @@ namespace windows {
m_handler.run();
on_state_change_request_(SERVICE_CONTROL_STOP);
-
- // Ensure that the service is uninstalled
- uninstall_service(m_name);
}
static void WINAPI on_state_change_request(DWORD control_code)
diff --git a/src/net/parse.cpp b/src/net/parse.cpp
index 1df6175b4..92be492a3 100644
--- a/src/net/parse.cpp
+++ b/src/net/parse.cpp
@@ -38,7 +38,7 @@ namespace net
{
void get_network_address_host_and_port(const std::string& address, std::string& host, std::string& port)
{
- // require ipv6 address format "[addr:addr:addr:...:addr]:port"
+ // If IPv6 address format with port "[addr:addr:addr:...:addr]:port"
if (address.find(']') != std::string::npos)
{
host = address.substr(1, address.rfind(']') - 1);
@@ -47,6 +47,12 @@ namespace net
port = address.substr(address.rfind(':') + 1);
}
}
+ // Else if IPv6 address format without port e.g. "addr:addr:addr:...:addr"
+ else if (std::count(address.begin(), address.end(), ':') >= 2)
+ {
+ host = address;
+ }
+ // Else IPv4, Tor, I2P address or hostname
else
{
host = address.substr(0, address.rfind(':'));
diff --git a/src/net/parse.h b/src/net/parse.h
index 648076d7b..6ece931c6 100644
--- a/src/net/parse.h
+++ b/src/net/parse.h
@@ -38,6 +38,16 @@
namespace net
{
+ /*!
+ * \brief Takes a valid address string (IP, Tor, I2P, or DNS name) and splits it into host and port
+ *
+ * The host of an IPv6 addresses in the format "[x:x:..:x]:port" will have the braces stripped.
+ * For example, when the address is "[ffff::2023]", host will be set to "ffff::2023".
+ *
+ * \param address The address string one wants to split
+ * \param[out] host The host part of the address string. Is always set.
+ * \param[out] port The port part of the address string. Is only set when address string contains a port.
+ */
void get_network_address_host_and_port(const std::string& address, std::string& host, std::string& port);
/*!
diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl
index f33ce977d..ee6bd8b19 100644
--- a/src/p2p/net_node.inl
+++ b/src/p2p/net_node.inl
@@ -645,20 +645,10 @@ namespace nodetool
{
using namespace boost::asio;
- std::string host = addr;
+ // Split addr string into host string and port string
+ std::string host;
std::string port = std::to_string(default_port);
- size_t colon_pos = addr.find_last_of(':');
- size_t dot_pos = addr.find_last_of('.');
- size_t square_brace_pos = addr.find('[');
-
- // IPv6 will have colons regardless. IPv6 and IPv4 address:port will have a colon but also either a . or a [
- // as IPv6 addresses specified as address:port are to be specified as "[addr:addr:...:addr]:port"
- // One may also specify an IPv6 address as simply "[addr:addr:...:addr]" without the port; in that case
- // the square braces will be stripped here.
- if ((std::string::npos != colon_pos && std::string::npos != dot_pos) || std::string::npos != square_brace_pos)
- {
- net::get_network_address_host_and_port(addr, host, port);
- }
+ net::get_network_address_host_and_port(addr, host, port);
MINFO("Resolving node address: host=" << host << ", port=" << port);
io_service io_srv;
@@ -695,34 +685,32 @@ namespace nodetool
std::set<std::string> full_addrs;
if (m_nettype == cryptonote::TESTNET)
{
- full_addrs.insert("212.83.175.67:28080");
- full_addrs.insert("212.83.172.165:28080");
full_addrs.insert("176.9.0.187:28080");
full_addrs.insert("88.99.173.38:28080");
full_addrs.insert("51.79.173.165:28080");
+ full_addrs.insert("192.99.8.110:28080");
+ full_addrs.insert("37.187.74.171:28080");
}
else if (m_nettype == cryptonote::STAGENET)
{
- full_addrs.insert("162.210.173.150:38080");
full_addrs.insert("176.9.0.187:38080");
full_addrs.insert("88.99.173.38:38080");
full_addrs.insert("51.79.173.165:38080");
+ full_addrs.insert("192.99.8.110:38080");
+ full_addrs.insert("37.187.74.171:38080");
}
else if (m_nettype == cryptonote::FAKECHAIN)
{
}
else
{
- full_addrs.insert("212.83.175.67:18080");
- full_addrs.insert("212.83.172.165:18080");
full_addrs.insert("176.9.0.187:18080");
full_addrs.insert("88.198.163.90:18080");
- full_addrs.insert("95.217.25.101:18080");
- full_addrs.insert("136.244.105.131:18080");
- full_addrs.insert("104.238.221.81:18080");
full_addrs.insert("66.85.74.134:18080");
full_addrs.insert("88.99.173.38:18080");
full_addrs.insert("51.79.173.165:18080");
+ full_addrs.insert("192.99.8.110:18080");
+ full_addrs.insert("37.187.74.171:18080");
}
return full_addrs;
}
@@ -857,6 +845,8 @@ namespace nodetool
"4pixvbejrvihnkxmduo2agsnmc3rrulrqc7s3cbwwrep6h6hrzsibeqd.onion:18083",
"zbjkbsxc5munw3qusl7j2hpcmikhqocdf4pqhnhtpzw5nt5jrmofptid.onion:18083",
"qz43zul2x56jexzoqgkx2trzwcfnr6l3hbtfcfx54g4r3eahy3bssjyd.onion:18083",
+ "plowsof3t5hogddwabaeiyrno25efmzfxyro2vligremt7sxpsclfaid.onion:18083",
+ "plowsoffjexmxalw73tkjmf422gq6575fc7vicuu4javzn2ynnte6tyd.onion:18083",
};
}
return {};
@@ -865,7 +855,9 @@ namespace nodetool
{
return {
"s3l6ke4ed3df466khuebb4poienoingwof7oxtbo6j4n56sghe3a.b32.i2p:18080",
- "sel36x6fibfzujwvt4hf5gxolz6kd3jpvbjqg6o3ud2xtionyl2q.b32.i2p:18080"
+ "sel36x6fibfzujwvt4hf5gxolz6kd3jpvbjqg6o3ud2xtionyl2q.b32.i2p:18080",
+ "uqj3aphckqtjsitz7kxx5flqpwjlq5ppr3chazfued7xucv3nheq.b32.i2p:18080",
+ "vdmnehdjkpkg57nthgnjfuaqgku673r5bpbqg56ix6fyqoywgqrq.b32.i2p:18080",
};
}
return {};
@@ -2413,7 +2405,7 @@ namespace nodetool
return false;
}
return true;
- });
+ }, "0.0.0.0", m_ssl_support);
if(!r)
{
LOG_WARNING_CC(context, "Failed to call connect_async, network error.");
diff --git a/src/ringct/rctOps.cpp b/src/ringct/rctOps.cpp
index 245a3f477..5b039d907 100644
--- a/src/ringct/rctOps.cpp
+++ b/src/ringct/rctOps.cpp
@@ -671,7 +671,7 @@ namespace rct {
//Elliptic Curve Diffie Helman: encodes and decodes the amount b and mask a
// where C= aG + bH
- static key ecdhHash(const key &k)
+ key genAmountEncodingFactor(const key &k)
{
char data[38];
rct::key hash;
@@ -700,7 +700,7 @@ namespace rct {
if (v2)
{
unmasked.mask = zero();
- xor8(unmasked.amount, ecdhHash(sharedSec));
+ xor8(unmasked.amount, genAmountEncodingFactor(sharedSec));
}
else
{
@@ -715,7 +715,7 @@ namespace rct {
if (v2)
{
masked.mask = genCommitmentMask(sharedSec);
- xor8(masked.amount, ecdhHash(sharedSec));
+ xor8(masked.amount, genAmountEncodingFactor(sharedSec));
}
else
{
diff --git a/src/ringct/rctOps.h b/src/ringct/rctOps.h
index 679ed1441..da0013ee1 100644
--- a/src/ringct/rctOps.h
+++ b/src/ringct/rctOps.h
@@ -184,6 +184,7 @@ namespace rct {
//Elliptic Curve Diffie Helman: encodes and decodes the amount b and mask a
// where C= aG + bH
+ key genAmountEncodingFactor(const key &k);
key genCommitmentMask(const key &sk);
void ecdhEncode(ecdhTuple & unmasked, const key & sharedSec, bool v2);
void ecdhDecode(ecdhTuple & masked, const key & sharedSec, bool v2);
diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp
index 477a7907d..7b16f017b 100644
--- a/src/ringct/rctSigs.cpp
+++ b/src/ringct/rctSigs.cpp
@@ -30,6 +30,7 @@
#include "misc_log_ex.h"
#include "misc_language.h"
+#include "common/data_cache.h"
#include "common/perf_timer.h"
#include "common/threadpool.h"
#include "common/util.h"
@@ -1578,6 +1579,42 @@ namespace rct {
}
}
+ bool verRctNonSemanticsSimpleCached(const rctSig & rv)
+ {
+ // Hello future Monero dev! If you got this assert, read the following carefully:
+ //
+ // RCT cache assumes that this function will serialize and hash all rv's fields used for RingCT verification
+ // If you're about to add a new RCTType here, first you must check that binary_archive serialization writes all rv's fields to the binary blob
+ // If it's not the case, rewrite this function to serialize everything, even some "temporary" fields which are not serialized normally
+ CHECK_AND_ASSERT_MES_L1(rv.type <= RCTTypeBulletproofPlus, false, "Unknown RCT type. Make sure RCT cache works correctly with this type and then enable it in the code here.");
+
+ // Don't cache older (or newer) rctSig types
+ // This cache only makes sense when it caches data from mempool first,
+ // so only "current fork version-enabled" RCT types need to be cached
+ if (rv.type != RCTTypeBulletproofPlus)
+ return verRctNonSemanticsSimple(rv);
+
+ // Get the hash of rv
+ std::stringstream ss;
+ binary_archive<true> ar(ss);
+
+ ::do_serialize(ar, const_cast<rctSig&>(rv));
+
+ crypto::hash h;
+ cryptonote::get_blob_hash(ss.str(), h);
+
+ static tools::data_cache<crypto::hash, 8192> cache;
+
+ if (cache.has(h))
+ return true;
+
+ const bool res = verRctNonSemanticsSimple(rv);
+ if (res)
+ cache.add(h);
+
+ return res;
+ }
+
//RingCT protocol
//genRct:
// creates an rctSig with all data necessary to verify the rangeProofs and that the signer owns one of the
diff --git a/src/ringct/rctSigs.h b/src/ringct/rctSigs.h
index 17cfd77b9..18c7e5fe6 100644
--- a/src/ringct/rctSigs.h
+++ b/src/ringct/rctSigs.h
@@ -132,6 +132,7 @@ namespace rct {
bool verRctSemanticsSimple(const rctSig & rv);
bool verRctSemanticsSimple(const std::vector<const rctSig*> & rv);
bool verRctNonSemanticsSimple(const rctSig & rv);
+ bool verRctNonSemanticsSimpleCached(const rctSig & rv);
static inline bool verRctSimple(const rctSig & rv) { return verRctSemanticsSimple(rv) && verRctNonSemanticsSimple(rv); }
xmr_amount decodeRct(const rctSig & rv, const key & sk, unsigned int i, key & mask, hw::device &hwdev);
xmr_amount decodeRct(const rctSig & rv, const key & sk, unsigned int i, hw::device &hwdev);
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index 092cff753..56b8d1aa4 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -1072,7 +1072,17 @@ namespace cryptonote
CHECK_AND_ASSERT_MES(tx_hash == std::get<0>(tx), false, "mismatched tx hash");
e.tx_hash = *txhi++;
e.prunable_hash = epee::string_tools::pod_to_hex(std::get<2>(tx));
- if (req.split || req.prune || std::get<3>(tx).empty())
+
+ // coinbase txes do not have signatures to prune, so they appear to be pruned if looking just at prunable data being empty
+ bool pruned = std::get<3>(tx).empty();
+ if (pruned)
+ {
+ cryptonote::transaction t;
+ if (cryptonote::parse_and_validate_tx_base_from_blob(std::get<1>(tx), t) && is_coinbase(t))
+ pruned = false;
+ }
+
+ if (req.split || req.prune || pruned)
{
// use splitted form with pruned and prunable (filled only when prune=false and the daemon has it), leaving as_hex as empty
e.pruned_as_hex = string_tools::buff_to_hex_nodelimer(std::get<1>(tx));
diff --git a/src/rpc/rpc_payment.cpp b/src/rpc/rpc_payment.cpp
index 2e05f04fb..aca3e3761 100644
--- a/src/rpc/rpc_payment.cpp
+++ b/src/rpc/rpc_payment.cpp
@@ -236,10 +236,8 @@ namespace cryptonote
*(uint32_t*)(hashing_blob.data() + 39) = SWAP32LE(nonce);
if (block.major_version >= RX_BLOCK_VERSION)
{
- const uint64_t seed_height = is_current ? info.seed_height : info.previous_seed_height;
const crypto::hash &seed_hash = is_current ? info.seed_hash : info.previous_seed_hash;
- const uint64_t height = cryptonote::get_block_height(block);
- crypto::rx_slow_hash(height, seed_height, seed_hash.data, hashing_blob.data(), hashing_blob.size(), hash.data, 0, 0);
+ crypto::rx_slow_hash(seed_hash.data, hashing_blob.data(), hashing_blob.size(), hash.data);
}
else
{
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 0b1ef6d27..e61bfa9f0 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -39,7 +39,9 @@
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/join.hpp>
#include <boost/algorithm/string/predicate.hpp>
+#include <boost/archive/binary_iarchive.hpp>
#include <boost/asio/ip/address.hpp>
+#include <boost/filesystem/operations.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <openssl/evp.h>
@@ -64,7 +66,6 @@ using namespace epee;
#include "multisig/multisig_account.h"
#include "multisig/multisig_kex_msg.h"
#include "multisig/multisig_tx_builder_ringct.h"
-#include "common/boost_serialization_helper.h"
#include "common/command_line.h"
#include "common/threadpool.h"
#include "int-util.h"
diff --git a/src/wallet/wallet_rpc_payments.cpp b/src/wallet/wallet_rpc_payments.cpp
index 8474fb568..06910ebbb 100644
--- a/src/wallet/wallet_rpc_payments.cpp
+++ b/src/wallet/wallet_rpc_payments.cpp
@@ -155,8 +155,7 @@ bool wallet2::search_for_rpc_payment(uint64_t credits_target, uint32_t n_threads
const uint8_t major_version = hashing_blob[0];
if (major_version >= RX_BLOCK_VERSION)
{
- const int miners = 1;
- crypto::rx_slow_hash(height, seed_height, seed_hash.data, hashing_blob.data(), hashing_blob.size(), hash[i].data, miners, 0);
+ crypto::rx_slow_hash(seed_hash.data, hashing_blob.data(), hashing_blob.size(), hash[i].data);
}
else
{
diff --git a/tests/core_tests/chaingen.h b/tests/core_tests/chaingen.h
index d5c9edc55..1f782831f 100644
--- a/tests/core_tests/chaingen.h
+++ b/tests/core_tests/chaingen.h
@@ -44,7 +44,7 @@
#include <boost/functional/hash.hpp>
#include "include_base_utils.h"
-#include "common/boost_serialization_helper.h"
+#include "chaingen_serialization.h"
#include "common/command_line.h"
#include "common/threadpool.h"
diff --git a/src/common/boost_serialization_helper.h b/tests/core_tests/chaingen_serialization.h
index 4a903107f..4a903107f 100644
--- a/src/common/boost_serialization_helper.h
+++ b/tests/core_tests/chaingen_serialization.h
diff --git a/tests/unit_tests/dns_resolver.cpp b/tests/unit_tests/dns_resolver.cpp
index a6b733592..d56cbe45b 100644
--- a/tests/unit_tests/dns_resolver.cpp
+++ b/tests/unit_tests/dns_resolver.cpp
@@ -158,6 +158,17 @@ TEST(DNSResolver, GetTXTRecord)
EXPECT_STREQ("donate.getmonero.org", addr.c_str());
}
+TEST(DNSResolver, Localhost)
+{
+ tools::DNSResolver resolver = tools::DNSResolver::create();
+
+ bool avail, valid;
+ std::vector<std::string> ips = resolver.get_ipv4("localhost", avail, valid);
+
+ ASSERT_EQ(1, ips.size());
+ ASSERT_EQ("127.0.0.1", ips[0]);
+}
+
bool is_equal(const char *s, const std::vector<std::string> &v) { return v.size() == 1 && v[0] == s; }
TEST(DNS_PUBLIC, empty) { EXPECT_TRUE(tools::dns_utils::parse_dns_public("").empty()); }
diff --git a/tests/unit_tests/net.cpp b/tests/unit_tests/net.cpp
index 838f1af37..af0f07db0 100644
--- a/tests/unit_tests/net.cpp
+++ b/tests/unit_tests/net.cpp
@@ -938,6 +938,41 @@ TEST(get_network_address, ipv4subnet)
namespace
{
+ void na_host_and_port_test(std::string addr, std::string exp_host, std::string exp_port)
+ {
+ std::string host{"xxxxx"};
+ std::string port{"xxxxx"};
+ net::get_network_address_host_and_port(addr, host, port);
+ EXPECT_EQ(exp_host, host);
+ EXPECT_EQ(exp_port, port);
+ }
+} // anonymous namespace
+
+TEST(get_network_address_host_and_port, ipv4)
+{
+ na_host_and_port_test("9.9.9.9", "9.9.9.9", "xxxxx");
+ na_host_and_port_test("9.9.9.9:18081", "9.9.9.9", "18081");
+}
+
+TEST(get_network_address_host_and_port, ipv6)
+{
+ na_host_and_port_test("::ffff", "::ffff", "xxxxx");
+ na_host_and_port_test("[::ffff]", "::ffff", "xxxxx");
+ na_host_and_port_test("[::ffff]:00231", "::ffff", "00231");
+ na_host_and_port_test("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", "xxxxx");
+ na_host_and_port_test("[7777:7777:7777:7777:7777:7777:7777:7777]", "7777:7777:7777:7777:7777:7777:7777:7777", "xxxxx");
+ na_host_and_port_test("[7777:7777:7777:7777:7777:7777:7777:7777]:48080", "7777:7777:7777:7777:7777:7777:7777:7777", "48080");
+}
+
+TEST(get_network_address_host_and_port, hostname)
+{
+ na_host_and_port_test("localhost", "localhost", "xxxxx");
+ na_host_and_port_test("bar:29080", "bar", "29080"); // Issue https://github.com/monero-project/monero/issues/8633
+ na_host_and_port_test("xmrchain.net:18081", "xmrchain.net", "18081");
+}
+
+namespace
+{
using stream_type = boost::asio::ip::tcp;
struct io_thread
diff --git a/utils/gpg_keys/moneromooo.asc b/utils/gpg_keys/moneromooo.asc
index 959148e41..2060e99b7 100644
--- a/utils/gpg_keys/moneromooo.asc
+++ b/utils/gpg_keys/moneromooo.asc
@@ -13,18 +13,18 @@ p7gDvxXOGxzq0sqfPTWTBdCj1OPfunHbbeH8ypwBlNpwVG40fJdya+Dqjwu25qX6
Xh5vxLzeJTBmlawa97MCliPvzzJgW9qHRVCa9lLloGVYLiUOS0N+dZ/r/QARAQAB
tD5tb25lcm9tb29vLW1vbmVybyA8bW9uZXJvbW9vby1tb25lcm9AdXNlcnMubm9y
ZXBseS5naXRodWIuY29tPokCVgQTAQgAQAIbAwcLCQgHAwIBBhUIAgkKCwQWAgMB
-Ah4BAheAFiEESLCBYfva3+OTrfw+aG8HRU1s78MFAl/LzhkFCQ9bmZsACgkQaG8H
-RU1s78ON2w/+JYKglEDk3UbhYdSJ9RGGLk2nXaWMVNiAheRnOXrpC9a3b8UaGxO1
-CdOKomjSi9yCVp74K9m5fqsIRUP0B3cXAgoQ8LptnqeivpLLoo+D3Lt+Ssa0s9aQ
-+9The1k+2qIN/FDJ0EPkl0MpYgHVBXs4IYilh7mTqccC3fqBYeG2NZ1oI1G0W3fs
-4bnOf+7HImxqtEq3BQtO67xxVKvWvFxqQ9GyNN5DmQozP8O9W2rextxan1ecmxSf
-OWXbFqbLqYlN/fIRLr0gAfealRjjtjtzP5XNKX/d4cI3LbyxwZP8IORNq6hB1kio
-e3DMPBUF5C2Vg6Zgy/m5eiFVZYNUIrGfRfjX0YZoSqVjUiIM9TCs/XuddtMH329k
-gixAxmGD5stOJSbvqEJk+sFM60xBQJDnq9h689J+Z4mFfScySEMqEvFOVqv5ES7T
-Ad8xgmsWyX+x8ci+1d28lg//Uh6TxXw0AHcH3GeGu5neWkl+Q7z1r4deZ3fc77O3
-2qvYWqbK1CyOmK7YrfiDGHYb161E/snN1tXW6k2/REb2yYaHYV7YOZlMQ73xEzoM
-Sis46FQwmbpAngEmcEvHBG91AtEg24x5KBMB4QyEWb9Ld13mc6UA2MnqiK90Pgv+
-ksDrRk1NVNPinmLwkFCVjWCv768UpHhOaMOj02X+O+e+m+sCB76jA7S5Ag0EVDKb
+Ah4BAheAFiEESLCBYfva3+OTrfw+aG8HRU1s78MFAmN2cq4FCRMGPjAACgkQaG8H
+RU1s78MPwg//ZC+js6BMCHMyRLkXIjg5X4xzV7aoTPSb5QPgoObTPVvqUdg627Dd
+Ody9LFJyQDsgwektf0eCz0johtLUmy/d0rLGNJMRMEltQiGRti1x0Y/q4Dlzh0TF
+c4jpQODH3hsz6OTSb4unEki5MbFCymD5wKJIvNzHuW+tQsBLgNN8gmo6iQpXzop6
+Frh1QDHaKorymGkoSdCMz++rL6HEG9cg1koZ9Dg2xRpjdEIf5rIhjAF1/6ctWxvd
+PTcyhr341p8GgSFxLCz89mwgOKEEHSqF6f7/sLsXyKvs2J80i4fpLjcPj3rJsG9+
+21ALRHsWiJnyhs1alSxDxGdlFOhns9u9eFg9UMt8e7IP8Xoh6xzXSGgxLOkCr4x7
+pxNpnqqci49Jrm6To0uZ5kQqUBk7LURjT9xyJEez7wZKwV40xB7krHyhqFo+Ja0P
+//4Qm3ndSutK+LLVzFZHFzzM0+uuCQXaPN9thU9o9MeteqsEX8jibn49CzdVZ8Qb
+lhsiiXOkRphvc0USDLsZlhQa1BGRLzZ2cTF9VtYktWvoDFVAI/IRi76TdVOjGn2Q
+GAKj/I6Xg4apZVf+qGH5SMQQu8Zyl72gezMqs84GGadvQqI25QakwY3+V3POYVVy
+25BOf4SAljHtXRYr5iUBJlLPI7XdgV4SrORj9ZC++zY8jHB3lG1KnB25Ag0EVDKb
fgEQAMe1Md25kV27vpEDOpONP3gX3YvFJKiktKTv+x0tZNzYRGaMMh3t0qaqsvUq
HaSoC0djdGrxjzf0saZskLMjWQnI4cWj2OQQj3eypdzO0uOLM9W6SoKU5k23c1X+
e958folJ2pZycLhXWZCvZm2XSP7nWL41hXAaOWw4yUERH4tb+zt6BGoBCietwQHm
@@ -48,5 +48,5 @@ DZc98z3iS2EU3dFSCCCkrC9xupJ63hbWYzsUcox28hqqssBCFRqn9Unn4h05zhvl
YmZWTzkSzbu4/vwI08g51kfQyekeG8ho2LSTlbgyStqQhmmu+VMk6MhqqrGI4aQl
ZULb8ntkFefYwVy7jw0nxkc8jAhHrkKFPb7JR3vePfmUgfFMHjBraPWIcESgsMDA
3j6BmRzehQtWCsEg4JtSsKxcKt6kazvPDpbsyDqmfY/AVeIrFdY2ZQ==
-=BfKA
+=lTeM
-----END PGP PUBLIC KEY BLOCK-----